diff --git a/.github/workflows/contributors-png.yml b/.github/workflows/contributors-png.yml new file mode 100644 index 000000000..040bfe725 --- /dev/null +++ b/.github/workflows/contributors-png.yml @@ -0,0 +1,40 @@ +name: Generate Contributors PNG + +on: + push: + paths: + - '.all-contributorsrc' + +jobs: + genimage: + if: github.ref == 'refs/heads/main' && github.repository == 'processing/processing4' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Install dependencies + run: npm install canvas + + - name: Run contributors-png generator + run: node utils/contributors-png.js + + - name: Reset all changes except contributors.png + run: | + git restore --staged . + git add contributors.png + git checkout -- . + + - name: Create Pull Request + uses: peter-evans/create-pull-request@v7 + with: + commit-message: "Update contributors.png from .all-contributorsrc" + branch: update-contributors-png + title: "chore: update contributors.png from .all-contributorsrc" + body: "This PR updates the contributors.png to reflect changes in .all-contributorsrc" + add-paths: contributors.png + token: ${{ secrets.CONTRIBUTOR_PNG_ACCESS_TOKEN }} diff --git a/README.md b/README.md index c71c91901..6c19b6923 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,8 @@ For licensing information about the Processing website see the [processing-websi Copyright (c) 2015-now The Processing Foundation ## Contributors +![Grid of avatars representing contributors to the Processing4 project](contributors.png) + See [CONTRIBUTORS.md](./CONTRIBUTORS.md) for a list of all contributors to the project. This project follows the [all-contributors specification](https://github.com/all-contributors/all-contributors) and the [Emoji Key](https://all-contributors.github.io/emoji-key/) ✨ for contribution types. Detailed instructions on how to add yourself or add contribution emojis to your name are [here](https://github.com/processing/processing4/issues/839). You can also post an issue or comment on a pull request with the text: `@all-contributors please add @YOUR-USERNAME for THINGS` (where `THINGS` is a comma-separated list of entries from the [list of possible contribution types](https://all-contributors.github.io/emoji-key/)) and our nice bot will add you to [CONTRIBUTORS.md](./CONTRIBUTORS.md) automatically! diff --git a/utils/contributors-png.js b/utils/contributors-png.js new file mode 100644 index 000000000..2686f1685 --- /dev/null +++ b/utils/contributors-png.js @@ -0,0 +1,61 @@ +const { createCanvas, loadImage } = require('canvas'); +const fs = require('fs'); + +const data = fs.readFileSync('.all-contributorsrc', 'utf-8'); +const parsed = JSON.parse(data); +const contributors = parsed.contributors; + +const AVATAR_SIZE = 50; +const GAP = 4; +const COLS = 40; +const ROWS = Math.ceil(contributors.length / COLS); + +const width = COLS * AVATAR_SIZE + (COLS - 1) * GAP; +const height = ROWS * AVATAR_SIZE + (ROWS - 1) * GAP; + +const canvas = createCanvas(width, height); +const ctx = canvas.getContext('2d'); + +async function loadAvatar(url) { + try { + const res = await fetch(url); + if (!res.ok) throw new Error(`HTTP ${res.status}`); + + const buffer = Buffer.from(await res.arrayBuffer()); + return await loadImage(buffer); + } catch (err) { + return null; + } +} + +(async () => { + for (let i = 0; i < contributors.length; i++) { + const c = contributors[i]; + + const col = i % COLS; + const row = Math.floor(i / COLS); + + const x = col * (AVATAR_SIZE + GAP); + const y = row * (AVATAR_SIZE + GAP); + + const img = await loadAvatar(c.avatar_url); + + ctx.save(); + ctx.beginPath(); + ctx.arc( + x + AVATAR_SIZE / 2, + y + AVATAR_SIZE / 2, + AVATAR_SIZE / 2, + 0, + Math.PI * 2 + ); + ctx.clip(); + + if (img) { + ctx.drawImage(img, x, y, AVATAR_SIZE, AVATAR_SIZE); + } + ctx.restore(); + } + + fs.writeFileSync('contributors.png', canvas.toBuffer('image/png')); +})();