Repository: primer/octicons Branch: main Commit: b02e013361aa Files: 134 Total size: 220.5 KB Directory structure: gitextract_5k8z2tga/ ├── .changeset/ │ ├── README.md │ └── config.json ├── .github/ │ ├── CODEOWNERS │ ├── ISSUE_TEMPLATE/ │ │ ├── bug-report.md │ │ ├── config.yml │ │ └── feedback.md │ ├── actions/ │ │ ├── build_node/ │ │ │ ├── Dockerfile │ │ │ └── entrypoint.sh │ │ ├── build_ruby/ │ │ │ ├── Dockerfile │ │ │ └── entrypoint.sh │ │ ├── python/ │ │ │ └── requirements.txt │ │ └── version/ │ │ ├── Dockerfile │ │ └── entrypoint.js │ ├── dependabot.yml │ └── workflows/ │ ├── add-to-inbox.yml │ ├── check_for_changeset.yml │ ├── ci.yml │ ├── codeql.yml │ ├── optimize.yml │ ├── publish.yml │ ├── release.yml │ └── stale.yml ├── .gitignore ├── .npmrc ├── .rubocop.yml ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Gemfile ├── LICENSE ├── README.md ├── add-octicon-checklist.md ├── keywords.json ├── lib/ │ ├── octicons_gem/ │ │ ├── .npmignore │ │ ├── Gemfile │ │ ├── LICENSE │ │ ├── README.md │ │ ├── Rakefile │ │ ├── lib/ │ │ │ ├── octicons/ │ │ │ │ ├── octicon.rb │ │ │ │ └── version.rb │ │ │ └── octicons.rb │ │ ├── octicons.gemspec │ │ └── test/ │ │ ├── helper.rb │ │ ├── octicon_test.rb │ │ └── octicons_test.rb │ ├── octicons_helper/ │ │ ├── .npmignore │ │ ├── Gemfile │ │ ├── LICENSE │ │ ├── README.md │ │ ├── Rakefile │ │ ├── lib/ │ │ │ ├── octicons_helper/ │ │ │ │ ├── helper.rb │ │ │ │ ├── railtie.rb │ │ │ │ └── version.rb │ │ │ └── octicons_helper.rb │ │ ├── octicons_helper.gemspec │ │ └── test/ │ │ ├── helper.rb │ │ └── octicons_helper_test.rb │ ├── octicons_jekyll/ │ │ ├── .npmignore │ │ ├── .rubocop.yml │ │ ├── Gemfile │ │ ├── LICENSE │ │ ├── README.md │ │ ├── Rakefile │ │ ├── jekyll-octicons.gemspec │ │ ├── lib/ │ │ │ ├── jekyll-octicons/ │ │ │ │ └── version.rb │ │ │ └── jekyll-octicons.rb │ │ └── test/ │ │ ├── helper.rb │ │ └── octicon_tag_test.rb │ ├── octicons_node/ │ │ ├── .npmignore │ │ ├── LICENSE │ │ ├── README.md │ │ ├── index.js │ │ ├── index.scss │ │ ├── package.json │ │ ├── prettier.config.js │ │ └── tests/ │ │ └── index.js │ ├── octicons_react/ │ │ ├── .eslintignore │ │ ├── .eslintrc.json │ │ ├── .gitignore │ │ ├── .npmignore │ │ ├── .nvmrc │ │ ├── LICENSE │ │ ├── README.md │ │ ├── __tests__/ │ │ │ ├── __snapshots__/ │ │ │ │ └── public-api.test.js.snap │ │ │ ├── public-api.test.js │ │ │ └── tree-shaking.test.js │ │ ├── babel.config.js │ │ ├── jest.config.js │ │ ├── next.config.mjs │ │ ├── package.json │ │ ├── pages/ │ │ │ ├── _document.mjs │ │ │ └── index.mjs │ │ ├── prettier.config.js │ │ ├── rollup.config.js │ │ ├── script/ │ │ │ ├── .eslintrc.json │ │ │ ├── build.js │ │ │ └── types.js │ │ ├── src/ │ │ │ ├── __tests__/ │ │ │ │ ├── .eslintrc.json │ │ │ │ ├── __snapshots__/ │ │ │ │ │ └── octicon.js.snap │ │ │ │ └── octicon.js │ │ │ ├── createIconComponent.js │ │ │ ├── index.d.ts │ │ │ └── index.js │ │ └── ts-tests/ │ │ ├── index.tsx │ │ └── tsconfig.json │ └── octicons_styled/ │ ├── .babelrc │ ├── .eslintignore │ ├── .eslintrc.json │ ├── .gitignore │ ├── .npmignore │ ├── .nvmrc │ ├── LICENSE │ ├── README.md │ ├── package.json │ ├── prettier.config.js │ ├── rollup.config.js │ ├── script/ │ │ ├── .eslintrc.json │ │ ├── build.js │ │ └── copy.sh │ ├── src/ │ │ ├── __tests__/ │ │ │ ├── .eslintrc.json │ │ │ └── octicon.js │ │ └── utils.js │ └── ts-tests/ │ ├── index.tsx │ └── tsconfig.json ├── package.json ├── prettier.config.js ├── script/ │ ├── build.js │ ├── changeset-publish │ └── version ├── svgo.config.js └── tests/ ├── build.js ├── index.js └── snapshots/ ├── build.js.md └── build.js.snap ================================================ FILE CONTENTS ================================================ ================================================ FILE: .changeset/README.md ================================================ # Changesets Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works with multi-package repos, or single-package repos to help you version and publish your code. You can find the full documentation for it [in our repository](https://github.com/changesets/changesets) We have a quick list of common questions to get you started engaging with this project in [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) ================================================ FILE: .changeset/config.json ================================================ { "$schema": "https://unpkg.com/@changesets/config@1.6.1/schema.json", "changelog": ["@changesets/changelog-github", {"repo": "primer/octicons"}], "commit": false, "linked": [], "access": "public", "baseBranch": "main", "updateInternalDependencies": "patch", "ignore": [] } ================================================ FILE: .github/CODEOWNERS ================================================ * @primer/engineer-reviewers ================================================ FILE: .github/ISSUE_TEMPLATE/bug-report.md ================================================ --- name: 🐞 Bug report about: Report a bug in Octicons title: "[Bug] " labels: "bug, octicon" assignees: '' --- ### Describe the bug _Include a clear and concise description of what the bug is._ ### Steps to reproduce Steps to reproduce the behavior: 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' 4. See error ### Expected behavior _Include a clear and concise description of what you expected to happen if there was no bug._ ### Screenshots _Please add screenshots to help explain the problem._ ### Device details **Desktop (please complete the following information):** - OS: [e.g. iOS] - Browser [e.g. chrome, safari] - Version [e.g. 22] **Smartphone (please complete the following information):** - Device: [e.g. iPhone6] - OS: [e.g. iOS8.1] - Browser [e.g. stock browser, safari] - Version [e.g. 22] ### Additional info _Add any other information relevant to the problem here._ ================================================ FILE: .github/ISSUE_TEMPLATE/config.yml ================================================ blank_issues_enabled: true contact_links: - name: Add to the Octicon library? url: https://github.com/github/primer about: Open an issue in github/primer (for GitHub staff only!) ================================================ FILE: .github/ISSUE_TEMPLATE/feedback.md ================================================ --- name: 💬 Feedback and ideas about: Suggest improvements or give feedback on icon designs title: "[Feedback] " labels: "octicon, type: feedback" assignees: '' --- ### Describe the topic _You have an idea, feedback or suggestion for icons to add to Octicons, tell us all about it! Add as much detail as you can: what is your idea, why is it relevant, what should change, how will it improve the Octicons library?_ ### Anything else? _Include anything else you think may be relevant to understand the issue._ ================================================ FILE: .github/actions/build_node/Dockerfile ================================================ FROM node:24-slim RUN apt-get update && \ apt-get install --no-install-recommends -y \ jq && \ apt-get clean -y && \ rm -rf /var/lib/apt/lists/* ADD entrypoint.sh /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"] ================================================ FILE: .github/actions/build_node/entrypoint.sh ================================================ #!/bin/bash -l set -e PACKAGE_VERSION=$(jq '.version' --raw-output ./package.json) echo "************* Building v$PACKAGE_VERSION *************" PUBLISH_TAG=latest if [[ "$PACKAGE_VERSION" =~ ^0\.0\.0\- ]] then PUBLISH_TAG=canary elif [[ "$PACKAGE_VERSION" =~ \-rc ]] then PUBLISH_TAG=next fi cd ./lib/"$*" echo "**************** Copying assets files to build directory ****************" cp -R ../build/ . echo "**************** Installing ****************" npm install --legacy-peer-deps echo "**************** Building ****************" npm run build { echo "**************** Publishing ****************" npm version --allow-same-version "$PACKAGE_VERSION" && npm publish --tag $PUBLISH_TAG --access public } || { # Bail out of publishing exit 0 } ================================================ FILE: .github/actions/build_ruby/Dockerfile ================================================ FROM ruby:3.0 RUN apt-get update && \ apt-get install --no-install-recommends -y \ jq && \ apt-get clean -y && \ rm -rf /var/lib/apt/lists/* ADD entrypoint.sh /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"] ================================================ FILE: .github/actions/build_ruby/entrypoint.sh ================================================ #!/bin/bash -l set -e PACKAGE_VERSION=$(jq '.version' --raw-output ./package.json) PACKAGE_VERSION=$(echo $PACKAGE_VERSION | sed -e 's/^0\.0\.0./0.0.0.pre./g') PACKAGE_VERSION=$(echo $PACKAGE_VERSION | sed -e 's/-rc/.pre/g') echo "************* Building v$PACKAGE_VERSION *************" # Setup rubygems creds mkdir -p ~/.gem cat << EOF > ~/.gem/credentials --- :rubygems_api_key: ${RUBYGEMS_TOKEN} EOF chmod 0600 ~/.gem/credentials cd ./lib/$* echo "**************** Copying assets files to build directory ****************" cp -R ../build lib/ perl -pi -e "s/\"octicons\", \"[^\"]+\"/\"octicons\", \"${PACKAGE_VERSION}\"/" ./Gemfile ./*.gemspec echo "**************** Installing ****************" bundle install echo "**************** Versioning ****************" bundle exec rake version\["$PACKAGE_VERSION"\] bundle update echo "**************** Building ****************" bundle exec rake build GEM_PUSH_OUTPUT=$(gem push pkg/*.gem 2>&1) || { echo "$GEM_PUSH_OUTPUT" echo "$GEM_PUSH_OUTPUT" | grep -q "Repushing of gem versions is not allowed" || exit 1 } ================================================ FILE: .github/actions/python/requirements.txt ================================================ picosvg~=0.20.6 ================================================ FILE: .github/actions/version/Dockerfile ================================================ FROM node:10-slim WORKDIR / COPY . / RUN npm install ENTRYPOINT [ "node", "/entrypoint.js" ] ================================================ FILE: .github/actions/version/entrypoint.js ================================================ const fs = require('fs') const { resolve } = require('path') const { GITHUB_REF, GITHUB_SHA } = process.env // Octicons package const pkg = require(resolve(process.cwd(), 'package.json')) // GitHub info const branchName = GITHUB_REF.replace('refs/heads/', '') const shortSha = GITHUB_SHA.slice(0,7) let releaseMatch = null const writePackageJson = () => { fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2), 'utf8') } // If it's a release branch if (releaseMatch = branchName.match(/^release-([\d\.]+)/i)) { console.log('Versioning release candidate') console.log(`${pkg.version} => ${releaseMatch[1]}`) pkg.version = `${releaseMatch[1]}-rc.${shortSha}` writePackageJson() } // Otherwise else if (branchName != 'main') { const newVersion = `0.0.0-${shortSha}` console.log('Versioning prerelease') console.log(`${pkg.version} => ${newVersion}`) pkg.version = newVersion writePackageJson() } ================================================ FILE: .github/dependabot.yml ================================================ # To get started with Dependabot version updates, you'll need to specify which # package ecosystems to update and where the package manifests are located. # Please see the documentation for all configuration options: # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates version: 2 updates: - package-ecosystem: "npm" # See documentation for possible values directory: "/docs" # Location of package manifests schedule: interval: "daily" allow: - dependency-name: "@primer/gatsby-theme-doctocat" ================================================ FILE: .github/workflows/add-to-inbox.yml ================================================ name: Add to Inbox 📥 on: issues: types: [opened, reopened] jobs: add-to-inbox: if: ${{ github.repository == 'primer/behaviors' }} runs-on: ubuntu-latest env: ISSUE_URL: ${{ github.event.issue.html_url }} PROJECT_ID: 4503 steps: - id: get-primer-access-token uses: actions/create-github-app-token@v1 with: app-id: ${{ vars.PRIMER_ISSUE_TRIAGE_APP_ID }} private-key: ${{ secrets.PRIMER_ISSUE_TRIAGE_APP_PRIVATE_KEY }} - name: Add labels to issue run: | gh issue edit $ISSUE_URL --add-label 'rails,react' env: GH_TOKEN: ${{ steps.get-primer-access-token.outputs.token }} - id: get-github-access-token uses: actions/create-github-app-token@v1 with: app-id: ${{ vars.PRIMER_ISSUE_TRIAGE_APP_ID_FOR_GITHUB }} private-key: ${{ secrets.PRIMER_ISSUE_TRIAGE_APP_PRIVATE_KEY_FOR_GITHUB }} owner: github - name: Add issue to project run: gh project item-add $PROJECT_ID --url $ISSUE_URL --owner github env: GH_TOKEN: ${{ steps.get-github-access-token.outputs.token }} ================================================ FILE: .github/workflows/check_for_changeset.yml ================================================ name: Check for changeset on: pull_request: types: # On by default if you specify no types. - 'opened' - 'reopened' - 'synchronize' # For `skip-label` only. - 'labeled' - 'unlabeled' jobs: check-for-changeset: name: Check for changeset runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: 'Check for changeset' uses: brettcannon/check-for-changed-files@v1 with: file-pattern: '.changeset/*.md' skip-label: 'skip-changeset' failure-message: 'No changeset found. If these changes should not result in a new version, apply the ${skip-label} label to this pull request. If these changes should result in a version bump, please add a changeset https://git.io/J6QvQ' ================================================ FILE: .github/workflows/ci.yml ================================================ name: CI on: push: branches: - main pull_request: jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: node-version: 20 - run: yarn - name: Building run: yarn build - run: cp -r icons lib/build/svg - uses: actions/upload-artifact@v4 with: name: octicons-build path: ./lib/build main: name: Main project needs: build runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: node-version: 20 - uses: actions/download-artifact@v4 with: name: octicons-build path: ./lib/build - run: yarn - name: Lint run: yarn lint - name: Test run: yarn test octicons_node: name: 'npm:@primer/octicons' needs: build runs-on: ubuntu-latest defaults: run: working-directory: ./lib/octicons_node steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: node-version: 20 - uses: actions/download-artifact@v4 with: name: octicons-build path: ./lib/build - run: yarn - name: Building run: yarn build - name: Lint run: yarn lint - name: Test run: yarn test octicons_react: name: 'npm:@primer/octicons-react' needs: build runs-on: ubuntu-latest defaults: run: working-directory: ./lib/octicons_react steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: node-version: 20 - uses: actions/download-artifact@v4 with: name: octicons-build path: ./lib/build - run: yarn - name: Building run: yarn build - name: Lint run: yarn lint - name: Test run: yarn test - name: Types run: | # Run @arethetypeswrong/cli npx @arethetypeswrong/cli --pack . # Run publint npx publint@0.2.12 . --strict octicons_gem: name: 'gem:octicons' needs: build runs-on: ubuntu-latest defaults: run: working-directory: ./lib/octicons_gem steps: - uses: actions/checkout@v3 - name: Setup Ruby uses: ruby/setup-ruby@v1 with: ruby-version: 3.3 bundler-cache: true - uses: actions/download-artifact@v4 with: name: octicons-build path: ./lib/octicons_gem/lib/build - run: bundle install - name: Linting run: bundle exec rake lint - name: Testing run: bundle exec rake test - name: Build run: bundle exec rake build - uses: actions/upload-artifact@v4 with: name: octicons-gem path: ./lib/octicons_gem/pkg octicons_helper: name: 'gem:octicons_helper' needs: octicons_gem runs-on: ubuntu-latest defaults: run: working-directory: ./lib/octicons_helper steps: - uses: actions/checkout@v3 - name: Setup Ruby uses: ruby/setup-ruby@v1 with: ruby-version: 3.3 bundler-cache: true - uses: actions/download-artifact@v4 with: name: octicons-gem path: ./lib/octicons_helper/vendor/cache - name: Run bundle install run: bundle config set --local disable_checksum_validation true && bundle install - name: Linting run: bundle exec rake lint - name: Testing run: bundle exec rake test octicons_jekyll: name: 'gem:octicons_jekyll' needs: octicons_gem runs-on: ubuntu-latest defaults: run: working-directory: ./lib/octicons_jekyll steps: - uses: actions/checkout@v3 - name: Setup Ruby uses: ruby/setup-ruby@v1 with: ruby-version: 3.3 bundler-cache: true - uses: actions/download-artifact@v4 with: name: octicons-gem path: ./lib/octicons_jekyll/vendor/cache - name: Run bundle install run: bundle config set --local disable_checksum_validation true && bundle install - name: Linting run: bundle exec rake lint - name: Testing run: bundle exec rake test ================================================ FILE: .github/workflows/codeql.yml ================================================ # For most projects, this workflow file will not need changing; you simply need # to commit it to your repository. # # You may wish to alter this file to override the set of languages analyzed, # or to provide custom queries or build logic. # # ******** NOTE ******** # We have attempted to detect the languages in your repository. Please check # the `language` matrix defined below to confirm you have the correct set of # supported CodeQL languages. # name: "CodeQL" on: push: branches: [ "main" ] pull_request: # The branches below must be a subset of the branches above branches: [ "main" ] schedule: - cron: '28 7 * * 3' jobs: analyze: name: Analyze runs-on: ubuntu-latest permissions: actions: read contents: read security-events: write strategy: fail-fast: false matrix: language: [ 'javascript', 'ruby' ] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support steps: - name: Checkout repository uses: actions/checkout@v3 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@v2 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. # By default, queries listed here will override any specified in a config file. # Prefix the list here with "+" to use these queries and those in the config file. # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs # queries: security-extended,security-and-quality # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild uses: github/codeql-action/autobuild@v2 # ℹ️ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun # If the Autobuild fails above, remove it and uncomment the following three lines. # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. # - run: | # echo "Run, Build Application using script" # ./location_of_script_within_repo/buildscript.sh - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v2 ================================================ FILE: .github/workflows/optimize.yml ================================================ on: push: paths: - 'icons/**' - '.github/workflows/optimize.yml' - '.github/actions/python/requirements.txt' pull_request: paths: - 'icons/**' - '.github/workflows/optimize.yml' - '.github/actions/python/requirements.txt' name: Optimize SVGs jobs: optimize: runs-on: ubuntu-latest steps: - uses: actions/checkout@master - uses: actions/setup-python@v4 with: python-version: '3.10' cache: 'pip' - run: pip install -r .github/actions/python/requirements.txt - run: for icon in icons/*; do picosvg $icon --output_file $icon; done - uses: actions/setup-node@v3 with: node-version: 18 - run: npm install - run: npm run svgo - uses: EndBug/add-and-commit@v4 with: add: 'icons' message: 'Optimize SVGs' author_email: actions@github.com env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} ================================================ FILE: .github/workflows/publish.yml ================================================ on: release: types: [published] workflow_dispatch: permissions: id-token: write # Required for OIDC contents: read checks: write statuses: write name: Octicons Publish jobs: setup: runs-on: ubuntu-latest steps: - uses: actions/checkout@master - uses: actions/setup-node@v6 with: node-version: 24 - run: npm install - run: npm run build - run: cp -r icons lib/build/svg - uses: actions/upload-artifact@v4 with: name: octicons path: ./lib/build gem: runs-on: ubuntu-latest needs: setup steps: - uses: actions/checkout@master - uses: actions/download-artifact@v4 with: name: octicons path: ./lib/build - uses: ./.github/actions/build_ruby env: RUBYGEMS_TOKEN: ${{ secrets.RUBYGEMS_TOKEN }} with: args: octicons_gem - run: ls ./lib/octicons_gem/pkg - uses: actions/upload-artifact@v4 with: name: octicons_gem path: ./lib/octicons_gem/pkg helper: runs-on: ubuntu-latest needs: gem steps: - uses: actions/checkout@master - uses: actions/download-artifact@v4 with: name: octicons path: ./lib/build - uses: actions/download-artifact@v4 with: name: octicons_gem path: ./lib/octicons_helper/vendor/cache - uses: ./.github/actions/build_ruby env: RUBYGEMS_TOKEN: ${{ secrets.RUBYGEMS_TOKEN }} with: args: octicons_helper jekyll: runs-on: ubuntu-latest needs: gem steps: - uses: actions/checkout@master - uses: actions/download-artifact@v4 with: name: octicons path: ./lib/build - uses: actions/download-artifact@v4 with: name: octicons_gem path: ./lib/octicons_jekyll/vendor/cache - uses: ./.github/actions/build_ruby env: RUBYGEMS_TOKEN: ${{ secrets.RUBYGEMS_TOKEN }} with: args: octicons_jekyll node: runs-on: ubuntu-latest needs: setup steps: - uses: actions/checkout@master - uses: actions/download-artifact@v4 with: name: octicons path: ./lib/build - uses: ./.github/actions/build_node with: args: octicons_node react: runs-on: ubuntu-latest needs: setup steps: - uses: actions/checkout@master - uses: actions/download-artifact@v4 with: name: octicons path: ./lib/build - name: Build @primer/octicons-react uses: ./.github/actions/build_node with: args: octicons_react - name: Build @primer/styled-octicons uses: ./.github/actions/build_node with: args: octicons_styled ================================================ FILE: .github/workflows/release.yml ================================================ name: Release on: push: branches: - "main" - "next_major" jobs: release: name: Final if: ${{ github.repository == 'primer/octicons' }} runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v3 with: # This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits fetch-depth: 0 persist-credentials: false - name: Set up Node.js uses: actions/setup-node@v6 with: node-version: 24 - name: Setup Ruby uses: ruby/setup-ruby@v1 with: ruby-version: 3.2 bundler-cache: true - name: Install dependencies run: | yarn bundle install - id: get-access-token uses: camertron/github-app-installation-auth-action@v1 with: app-id: ${{ vars.PRIMER_APP_ID_SHARED }} private-key: ${{ secrets.PRIMER_APP_PRIVATE_KEY_SHARED }} client-id: ${{ vars.PRIMER_APP_CLIENT_ID_SHARED }} client-secret: ${{ secrets.PRIMER_APP_CLIENT_SECRET_SHARED }} installation-id: ${{ vars.PRIMER_APP_INSTALLATION_ID_SHARED }} - name: Create release pull request or publish to npm id: changesets uses: changesets/action@master with: title: Release Tracking version: yarn changeset:version publish: script/changeset-publish env: GITHUB_TOKEN: ${{ steps.get-access-token.outputs.access-token }} ================================================ FILE: .github/workflows/stale.yml ================================================ name: Stale on: schedule: - cron: '0 * * * *' jobs: stale: runs-on: ubuntu-latest steps: - uses: actions/stale@v4 with: # General settings days-before-stale: 60 days-before-close: 7 enable-statistics: true operations-per-run: 100 remove-stale-when-updated: true # PR specific settings delete-branch: true stale-pr-message: "Hi! This pull request has been marked as stale because it has been open with no activity for 60 days. You can comment on the pull request or remove the stale label to keep it open. If you do nothing, this pull request will be closed in 7 days." # Issue specific settings days-before-issue-stale: 180 stale-issue-message: "Hi! This issue has been marked as stale because it has been open with no activity for 180 days. You can comment on the issue or remove the stale label to keep it open. If you do nothing, this issue will be closed in 7 days." ================================================ FILE: .gitignore ================================================ *.gem /package-lock.json *.log .DS_Store .bundle .env node_modules vendor Gemfile.lock # Ignore build/export artifacts lib/**/build/ # Gatsby public .cache # Now .now ================================================ FILE: .npmrc ================================================ save-exact=true package-lock=false ================================================ FILE: .rubocop.yml ================================================ inherit_gem: rubocop-github: - config/default.yml - config/rails.yml AllCops: NewCops: enable ================================================ FILE: CHANGELOG.md ================================================ # Changelog ## 19.23.1 ### Patch Changes - [#1175](https://github.com/primer/octicons/pull/1175) [`ea8e6bb7`](https://github.com/primer/octicons/commit/ea8e6bb79894cc7e85564ee9b53d86b418738d04) Thanks [@kylewaynebenson](https://github.com/kylewaynebenson)! - - Remove set fill from svgs ## 19.23.0 ### Minor Changes - [#1165](https://github.com/primer/octicons/pull/1165) [`63bc8d01`](https://github.com/primer/octicons/commit/63bc8d01e4c51ebc34abdac1bdb861cf209f7cf0) Thanks [@kylewaynebenson](https://github.com/kylewaynebenson)! - - Addition of lockup icon - adjustments to logo and mark ## 19.22.1 ### Patch Changes - [#1169](https://github.com/primer/octicons/pull/1169) [`6567d755`](https://github.com/primer/octicons/commit/6567d755f30c18e44d8fd069abb974cf078bd2d4) Thanks [@francinelucca](https://github.com/francinelucca)! - various dep updates ## 19.22.0 ### Minor Changes - [#1157](https://github.com/primer/octicons/pull/1157) [`18e3b9fd`](https://github.com/primer/octicons/commit/18e3b9fd74c4bc85b1add3624a082fc0f6fd36c2) Thanks [@janmaarten-a11y](https://github.com/janmaarten-a11y)! - Add book-locked icon Add comment-locked icon Add issue-locked icon Add git-pull-request-locked icon ## 19.21.2 ### Patch Changes - [#1146](https://github.com/primer/octicons/pull/1146) [`41c78057`](https://github.com/primer/octicons/commit/41c780575654fe4fef3fc4e91a46c8c0e91b233b) Thanks [@rezrah](https://github.com/rezrah)! - Updated GitHub brand logos (`mark-github` and `logo-github`) to 2026 versions. ## 19.21.1 ### Patch Changes - [#1137](https://github.com/primer/octicons/pull/1137) [`97cefc9f`](https://github.com/primer/octicons/commit/97cefc9fcb19f91133cffd557cc1f308e384ffb2) Thanks [@dependabot](https://github.com/apps/dependabot)! - Bump js-yaml from 3.13.1 to 4.1.1 ## 19.21.0 ### Minor Changes - [#1132](https://github.com/primer/octicons/pull/1132) [`c5411b04`](https://github.com/primer/octicons/commit/c5411b048090e13a0e6ffafaa10efdc24a8e05b5) Thanks [@mperrotti](https://github.com/mperrotti)! - Adds icons used for Copilot Loops * [#1134](https://github.com/primer/octicons/pull/1134) [`131fbedc`](https://github.com/primer/octicons/commit/131fbedc579b6ebc07716dc02ed947a168c560f2) Thanks [@mperrotti](https://github.com/mperrotti)! - Adds icons used for Copilot Markdown text wrapping options - [#1133](https://github.com/primer/octicons/pull/1133) [`94ceabb7`](https://github.com/primer/octicons/commit/94ceabb7e1371eefd8ba26ec8eb59cf6149e7a29) Thanks [@mperrotti](https://github.com/mperrotti)! - Adds icons used for feedback dialogs ### Patch Changes - [#1135](https://github.com/primer/octicons/pull/1135) [`be5df35d`](https://github.com/primer/octicons/commit/be5df35d390439f972af3adbd9ec59d38ec4c624) Thanks [@mperrotti](https://github.com/mperrotti)! - Updates VS Code icon to closer match the real app icon ## 19.20.0 ### Minor Changes - [#1129](https://github.com/primer/octicons/pull/1129) [`68ebe53b`](https://github.com/primer/octicons/commit/68ebe53ba972e391fa2b60458e37348636e202ad) Thanks [@lukasoppermann](https://github.com/lukasoppermann)! - Added InboxFill icon ## 19.19.0 ### Minor Changes - [#1123](https://github.com/primer/octicons/pull/1123) [`1d346555`](https://github.com/primer/octicons/commit/1d34655547b0ae59211967af830d30ae919e0257) Thanks [@mperrotti](https://github.com/mperrotti)! - Adds an icon for AI chat ## 19.18.1 ### Patch Changes - [#1120](https://github.com/primer/octicons/pull/1120) [`370c72c8`](https://github.com/primer/octicons/commit/370c72c8cb511bceb4e096891ff2393e81f87fa3) Thanks [@langermank](https://github.com/langermank)! - Add vscode-32.svg, vscode-48.svg * [#1122](https://github.com/primer/octicons/pull/1122) [`dcf14c81`](https://github.com/primer/octicons/commit/dcf14c81ca32e4f1cee017a2815c66458a26b2fa) Thanks [@langermank](https://github.com/langermank)! - Add 16 vscode ## 19.18.0 ### Minor Changes - [#1117](https://github.com/primer/octicons/pull/1117) [`13014409`](https://github.com/primer/octicons/commit/13014409ff2cc07191a0d98629d088a5f994a49a) Thanks [@arisacoba](https://github.com/arisacoba)! - Add checkbox-fill-16.svg and checkbox-fill-24.svg ## 19.17.0 ### Minor Changes - [#1115](https://github.com/primer/octicons/pull/1115) [`59a4abf4`](https://github.com/primer/octicons/commit/59a4abf40334cbab7ec76e323255b44fd4ea4a95) Thanks [@CameronFoxly](https://github.com/CameronFoxly)! - Save mcp-16.svg, mcp-24.svg ## 19.16.0 ### Minor Changes - [#1107](https://github.com/primer/octicons/pull/1107) [`4073a521`](https://github.com/primer/octicons/commit/4073a52102527e8e894501314c38c6e100d4f5d0) Thanks [@CameronFoxly](https://github.com/CameronFoxly)! - Add minimize-16.svg, maximize-16.svg, maximize-24.svg, minimize-24.svg ### Patch Changes - [#1112](https://github.com/primer/octicons/pull/1112) [`36fd097f`](https://github.com/primer/octicons/commit/36fd097f885eb22118417458b6d7b5f4c8e8566c) Thanks [@lukasoppermann](https://github.com/lukasoppermann)! - Adjusted alignment of repo delete, locked and push icon in 16px and 24px ## 19.15.5 ### Patch Changes - [#1102](https://github.com/primer/octicons/pull/1102) [`02cdd0c2`](https://github.com/primer/octicons/commit/02cdd0c2229c5148380e64ae6fe9957efc9e06a2) Thanks [@CameronFoxly](https://github.com/CameronFoxly)! - Update Loop icon for visual alignment ## 19.15.4 ### Patch Changes - [#1099](https://github.com/primer/octicons/pull/1099) [`239cdee1`](https://github.com/primer/octicons/commit/239cdee1b6a2b3ada569aa25e260bf5862b52621) Thanks [@CameronFoxly](https://github.com/CameronFoxly)! - Add spaces, agents, loops, and adjust mention ## 19.15.3 ### Patch Changes - [#1097](https://github.com/primer/octicons/pull/1097) [`ce04eca0`](https://github.com/primer/octicons/commit/ce04eca0b9c33cbc3586abd57386e63d97bff7fa) Thanks [@TylerJDev](https://github.com/TylerJDev)! - Add outlined sparkle icon ## 19.15.2 ### Patch Changes - [#1070](https://github.com/primer/octicons/pull/1070) [`795101e3`](https://github.com/primer/octicons/commit/795101e3a46d6835fb2e091384033d8962ab08d1) Thanks [@smockle](https://github.com/smockle)! - Add `pause` icon ## 19.15.1 ### Patch Changes - [#1078](https://github.com/primer/octicons/pull/1078) [`8c9b6112`](https://github.com/primer/octicons/commit/8c9b611271805a436b306beebd8400b502f4f386) Thanks [@francinelucca](https://github.com/francinelucca)! - fix 24px id-badge asset [#1048](https://github.com/primer/octicons/pull/1048) * [`818a40c5`](https://github.com/primer/octicons/commit/818a40c5d5dec81ad048f3257f092f660b7c8ee5) Thanks [@jonrohan](https://github.com/jonrohan)! - Update mark-github-24 sizing [#1050](https://github.com/primer/octicons/pull/1050) ## 19.15.0 ### Minor Changes - [#1063](https://github.com/primer/octicons/pull/1063) [`6481783a`](https://github.com/primer/octicons/commit/6481783a5a7258cc4d7981a0510de56be05a2dc3) Thanks [@dylanatsmith](https://github.com/dylanatsmith)! - Add square-circle icon ## 19.14.0 ### Minor Changes - [#1037](https://github.com/primer/octicons/pull/1037) [`7402e69c`](https://github.com/primer/octicons/commit/7402e69c4d928b12340cb2430bb942ae7d96c6ba) Thanks [@jonrohan](https://github.com/jonrohan)! - Update octicons-react to use presentational attributes over inline styles for base styles * [#1047](https://github.com/primer/octicons/pull/1047) [`48198033`](https://github.com/primer/octicons/commit/481980330efce92501df9a388b27314a3f86f182) Thanks [@joshblack](https://github.com/joshblack)! - Add support for SVG props to base icons ## 19.13.0 ### Minor Changes - [#1041](https://github.com/primer/octicons/pull/1041) [`ef89a78f`](https://github.com/primer/octicons/commit/ef89a78f9c0b92a32b7476b5680c327bcd8a6d64) Thanks [@lukasoppermann](https://github.com/lukasoppermann)! - Adds sparkles icon (3 sparkles) * [#1027](https://github.com/primer/octicons/pull/1027) [`12c6fb00`](https://github.com/primer/octicons/commit/12c6fb0033c8f9dd22b5e8f93ddf3dff9bb7acb1) Thanks [@joshblack](https://github.com/joshblack)! - Update the build output to reduce number of generated assets included in the package on npm ## 19.12.0 ### Minor Changes - [#1033](https://github.com/primer/octicons/pull/1033) [`7a5ac858`](https://github.com/primer/octicons/commit/7a5ac85800359eb1ee6c98c90533c5f344e6532d) Thanks [@colebemis](https://github.com/colebemis)! - Update `thumbsup` and `thumbsdown` icons ## 19.11.0 ### Minor Changes - [#1028](https://github.com/primer/octicons/pull/1028) [`d27ea2f6`](https://github.com/primer/octicons/commit/d27ea2f6b52c5d26d4118259c86e4c91e58cfd56) Thanks [@CameronFoxly](https://github.com/CameronFoxly)! - Adding ai-model icon at 16 & 24px ## 19.10.0 ### Minor Changes - [#983](https://github.com/primer/octicons/pull/983) [`30be326a`](https://github.com/primer/octicons/commit/30be326ae23b108fd31decfd7823171150421bc4) Thanks [@lukasoppermann](https://github.com/lukasoppermann)! - Add multiple missing icons ### Patch Changes - [#1020](https://github.com/primer/octicons/pull/1020) [`449d81f1`](https://github.com/primer/octicons/commit/449d81f1b09bcbc0752ebc35d175a8b729022b55) Thanks [@joshblack](https://github.com/joshblack)! - Update types for @primer/octicons-react to explicitly include extensions for different moduleResolution settings ## 19.9.0 ### Minor Changes - [#1008](https://github.com/primer/octicons/pull/1008) [`c5786ff2`](https://github.com/primer/octicons/commit/c5786ff2f3fb9ebca2405bb8d6cc53268b12674f) Thanks [@joshblack](https://github.com/joshblack)! - Update ESM import to use mjs extension when in parent CommonJS module ### Patch Changes - [#1007](https://github.com/primer/octicons/pull/1007) [`79b93954`](https://github.com/primer/octicons/commit/79b93954c6857e81a685066c1b1205893e7161c5) Thanks [@joshblack](https://github.com/joshblack)! - Update octicons in React to no longer set `role="img"` if the icon is aria-hidden. ## 19.8.0 ### Minor Changes - [#976](https://github.com/primer/octicons/pull/976) [`15ea1e43`](https://github.com/primer/octicons/commit/15ea1e43510a55a5f77d4f4bc76f5033d6655997) Thanks [@UnicodeRogue](https://github.com/UnicodeRogue)! - Adds filter remove octicon ## 19.7.0 ### Minor Changes - [#980](https://github.com/primer/octicons/pull/980) [`5c207929`](https://github.com/primer/octicons/commit/5c207929bdda29e910f2c5b2f6df9de6ef902b84) Thanks [@gavinmn](https://github.com/gavinmn)! - Fix Feed icon alignment issue and name collision ## 19.6.0 ### Minor Changes - [#977](https://github.com/primer/octicons/pull/977) [`e2a0cbdb`](https://github.com/primer/octicons/commit/e2a0cbdbd0566301e295ea38ffb4367c4650c656) Thanks [@gavinmn](https://github.com/gavinmn)! - Add new Feed icons ## 19.5.0 ### Minor Changes - [#970](https://github.com/primer/octicons/pull/970) [`640441ee`](https://github.com/primer/octicons/commit/640441ee2935c85bb3e22022d4fb946be9b8d5c6) Thanks [@CameronFoxly](https://github.com/CameronFoxly)! - Update repo-clone and repo-pull, add 24px versions ### Patch Changes - [#966](https://github.com/primer/octicons/pull/966) [`b8a4b4dc`](https://github.com/primer/octicons/commit/b8a4b4dc47f734db7893fe50e93703f2b1d07a2a) Thanks [@gavinmn](https://github.com/gavinmn)! - Fix `pin-slash` bug ## 19.4.0 ### Minor Changes - [#962](https://github.com/primer/octicons/pull/962) [`5805622c`](https://github.com/primer/octicons/commit/5805622c1f9005a4c81a7e7fb09225f2a0e31af4) Thanks [@CameronFoxly](https://github.com/CameronFoxly)! - Edited small details on `copilot-warning` and `copilot-error` to maintain consistency with the rest of the copilot icon set. * [#961](https://github.com/primer/octicons/pull/961) [`e92cb36a`](https://github.com/primer/octicons/commit/e92cb36aedc3a9c28b8502733e8c30d01d716bb6) Thanks [@gavinmn](https://github.com/gavinmn)! - Save file-directory-symlink-16.svg, file-directory-symlink-24.svg ## 19.3.0 ### Minor Changes - [#953](https://github.com/primer/octicons/pull/953) [`d3cb9cd8`](https://github.com/primer/octicons/commit/d3cb9cd8b5186a05eb26159f9c97754bef9ea127) Thanks [@gavinmn](https://github.com/gavinmn)! - Add Tracked By states ## 19.2.0 ### Minor Changes - [#959](https://github.com/primer/octicons/pull/959) [`268b2021`](https://github.com/primer/octicons/commit/268b2021bed7b12ff878e999d8b532534b1e2dcc) Thanks [@CameronFoxly](https://github.com/CameronFoxly)! - Add pivot-column icon * [#932](https://github.com/primer/octicons/pull/932) [`ea81ec17`](https://github.com/primer/octicons/commit/ea81ec17f0d3d8e74d53e484f551166339af3a17) Thanks [@green6erry](https://github.com/green6erry)! - Add `id`, `title`, and `aria-labelledby` props to icon components - [#957](https://github.com/primer/octicons/pull/957) [`ab786838`](https://github.com/primer/octicons/commit/ab786838f7ec93523b82c2905e37b9e0c8639e43) Thanks [@CameronFoxly](https://github.com/CameronFoxly)! - Update copilot octicons for consistency * [#956](https://github.com/primer/octicons/pull/956) [`16318b6b`](https://github.com/primer/octicons/commit/16318b6b7ba9abcf75c8a17f8ea2204128f9541a) Thanks [@gavinmn](https://github.com/gavinmn)! - Add undo / redo icons ## 19.1.0 ### Minor Changes - [#933](https://github.com/primer/octicons/pull/933) [`af6edab9`](https://github.com/primer/octicons/commit/af6edab99d51f31eac23395b016dd988e34ef05d) Thanks [@stvehayes](https://github.com/stvehayes)! - Add `devices` icon * [#950](https://github.com/primer/octicons/pull/950) [`8f0edd9e`](https://github.com/primer/octicons/commit/8f0edd9e3aade3901a10d133e14f0561919c945d) Thanks [@CameronFoxly](https://github.com/CameronFoxly)! - Updates the `pin` icon with a flipped composition, and adds `pin-slash` - [#949](https://github.com/primer/octicons/pull/949) [`f6796914`](https://github.com/primer/octicons/commit/f6796914732ef96052585adbd8dcccb554bfb2d6) Thanks [@CameronFoxly](https://github.com/CameronFoxly)! - Updating `move-to-top` and `move-to-bottom` to fix logic and alignment issues. ## 19.0.0 ### Major Changes - [#943](https://github.com/primer/octicons/pull/943) [`a38ae2d2`](https://github.com/primer/octicons/commit/a38ae2d2cf0b51259be0ab9bc19052c4ddc64a09) Thanks [@broccolinisoup](https://github.com/broccolinisoup)! - Remove support for `Octicon` Update peer dependency React version to support >=16.3 Update icons to use React.forwardRef ### Minor Changes - [#937](https://github.com/primer/octicons/pull/937) [`6c94e0e8`](https://github.com/primer/octicons/commit/6c94e0e851c5c5b30cb7ddf73899cde54bf8e205) Thanks [@gavinmn](https://github.com/gavinmn)! - Add 12px `×` icon ## 18.3.0 ### Minor Changes - [#934](https://github.com/primer/octicons/pull/934) [`3707c091`](https://github.com/primer/octicons/commit/3707c0917c53eb862457673ba5aa0dfc544be434) Thanks [@gavinmn](https://github.com/gavinmn)! - Add project-template-24.svg, project-template-16.svg ## 18.2.0 ### Minor Changes - [#928](https://github.com/primer/octicons/pull/928) [`4135bc38`](https://github.com/primer/octicons/commit/4135bc38f8592906cfbe2ac6f6772aae1fe049cf) Thanks [@gavinmn](https://github.com/gavinmn)! - Add discussion state Octicons ## 18.1.0 ### Minor Changes - [#927](https://github.com/primer/octicons/pull/927) [`ffd32dd6`](https://github.com/primer/octicons/commit/ffd32dd67e7599041e3e49867e16282e486b8f36) Thanks [@gavinmn](https://github.com/gavinmn)! - Add passkey-fill-24 and passkey-fill-16 octicons ## 18.0.0 ### Major Changes - [#914](https://github.com/primer/octicons/pull/914) [`4d558ed9`](https://github.com/primer/octicons/commit/4d558ed962593dedde3d294194dce7c9419ee355) Thanks [@omerbensaadon](https://github.com/omerbensaadon)! - Update icon naming conventions for Tracks and Tracked By: - `issue-tracked-by` → `issue-tracks` - `issue-tracked-in` → `issue-tracked-by` ### Minor Changes - [#924](https://github.com/primer/octicons/pull/924) [`6b494dfe`](https://github.com/primer/octicons/commit/6b494dfe07735fd343889678bfb0d13561396dc8) Thanks [@CameronFoxly](https://github.com/CameronFoxly)! - Added missing 24px version of shield-slash-24.svg ## 17.12.0 ### Minor Changes - [#904](https://github.com/primer/octicons/pull/904) [`ad0eb569`](https://github.com/primer/octicons/commit/ad0eb5699661138ee04baf8938fbb6f291f9f060) Thanks [@CameronFoxly](https://github.com/CameronFoxly)! - Edit: Upload and download icons Add: Move to start, end, top, and bottom icons * [#918](https://github.com/primer/octicons/pull/918) [`082f722d`](https://github.com/primer/octicons/commit/082f722d1b49ce148830f0e396a5f0933afaaf2a) Thanks [@gavinmn](https://github.com/gavinmn)! - Add 24pt merge queue icon - [#919](https://github.com/primer/octicons/pull/919) [`bbff0d13`](https://github.com/primer/octicons/commit/bbff0d13c08a0cebafed32d7787ae216c9b26778) Thanks [@CameronFoxly](https://github.com/CameronFoxly)! - Save zoom-in-24.svg, zoom-out-24.svg, zoom-out-16.svg, zoom-in-16.svg ## 17.11.1 ### Patch Changes - [#905](https://github.com/primer/octicons/pull/905) [`cbbc519f`](https://github.com/primer/octicons/commit/cbbc519ffd31eaf38d5d5b1e068ad4506d0d1e27) Thanks [@gr2m](https://github.com/gr2m)! - prefix relative paths with `./` in ESM exports paths ## 17.11.0 ### Minor Changes - [#895](https://github.com/primer/octicons/pull/895) [`ce11fb3b`](https://github.com/primer/octicons/commit/ce11fb3b3c67b9c0f4f69bec14e5a962b189cba2) Thanks [@joshblack](https://github.com/joshblack)! - Update the npm package for `@primer/octicons-react` to include the `exports` field and explicitly list out files in `package.json` * [#902](https://github.com/primer/octicons/pull/902) [`4cbc043a`](https://github.com/primer/octicons/commit/4cbc043a81f81ad23f5e5bbb5dc687fe9f550877) Thanks [@gavinmn](https://github.com/gavinmn)! - Save sparkle-fill-16.svg - [#903](https://github.com/primer/octicons/pull/903) [`caf958be`](https://github.com/primer/octicons/commit/caf958be9c695ff9ee4381328a555f12b0d830fa) Thanks [@gavinmn](https://github.com/gavinmn)! - Save fiscal-host-16.svg ### Patch Changes - [#894](https://github.com/primer/octicons/pull/894) [`410831bc`](https://github.com/primer/octicons/commit/410831bc3d3aee3b816fb4172031a470b7b1e38e) Thanks [@langermank](https://github.com/langermank)! - [Bug] up/down chevron alignment fix ## 17.10.2 ### Patch Changes - [#886](https://github.com/primer/octicons/pull/886) [`b5a1530f`](https://github.com/primer/octicons/commit/b5a1530f441e5b2f7b3c874fe669c5d0d1838d9c) Thanks [@eliperkins](https://github.com/eliperkins)! - Upgrade to latest version of SVG Optimizer to remove invalid SVG paths on iOS, macOS and other native Apple target platforms. ## 17.10.1 ### Patch Changes - [#882](https://github.com/primer/octicons/pull/882) [`503bafb9`](https://github.com/primer/octicons/commit/503bafb9578ea307fed3b261a1f8f9cbaea1c346) Thanks [@manuelpuyol](https://github.com/manuelpuyol)! - Use parameter defaults instead of defaultProps * [#883](https://github.com/primer/octicons/pull/883) [`8a039a7b`](https://github.com/primer/octicons/commit/8a039a7befa6b542404f416fac3f5c9ec99099cc) Thanks [@eliperkins](https://github.com/eliperkins)! - Remove fill-rule from SVGs using picosvg as an optimization step ## 17.10.0 ### Minor Changes - [#874](https://github.com/primer/octicons/pull/874) [`3ff5aa6`](https://github.com/primer/octicons/commit/3ff5aa669d33a88048825d229656abfa459e4d64) Thanks [@gavinmn](https://github.com/gavinmn)! - Add rel-file-path-16.svg, rel-file-path-24.svg * [#878](https://github.com/primer/octicons/pull/878) [`5797f85`](https://github.com/primer/octicons/commit/5797f859859df31cd769e102fbf518ccaf9a976f) Thanks [@CameronFoxly](https://github.com/CameronFoxly)! - Save unlink-16.svg, unlink-24.svg - [#879](https://github.com/primer/octicons/pull/879) [`2fa8425`](https://github.com/primer/octicons/commit/2fa8425dab93346cd5d8b44bfc3709f0126e19fb) Thanks [@gavinmn](https://github.com/gavinmn)! - Save read-32.svg, unread-32.svg, read-48.svg, unread-48.svg * [#873](https://github.com/primer/octicons/pull/873) [`0d1b1ff`](https://github.com/primer/octicons/commit/0d1b1ffca5334c6207cf975f69459153f1d1cbfd) Thanks [@gavinmn](https://github.com/gavinmn)! - Add Goal icons - [#877](https://github.com/primer/octicons/pull/877) [`3916b29`](https://github.com/primer/octicons/commit/3916b29935d9845eec8726cc389b98281bc42b02) Thanks [@gavinmn](https://github.com/gavinmn)! - Save sponsor-tiers-16.svg, sponsor-tiers-24.svg ## 17.9.0 ### Minor Changes - [#862](https://github.com/primer/octicons/pull/862) [`e15fe00`](https://github.com/primer/octicons/commit/e15fe007224d2785878b78dec36821373c75cbf7) Thanks [@ashygee](https://github.com/ashygee)! - Add project-roadmap icons. Thanks @ohiosveryown and @gavinmn! * [#861](https://github.com/primer/octicons/pull/861) [`1a6887d`](https://github.com/primer/octicons/commit/1a6887df3423ff539f6959d0fe8bb23c17dafa70) Thanks [@ashygee](https://github.com/ashygee)! - Add project-symlink icons. Thanks @peterloveland! - [#860](https://github.com/primer/octicons/pull/860) [`8a98d2b`](https://github.com/primer/octicons/commit/8a98d2b727623aa089912721513a68e8d4c0fc3f) Thanks [@ashygee](https://github.com/ashygee)! - Save clock-fill-16.svg, clock-fill-24.svg, skip-fill-16.svg, skip-fil… Thanks @dylanatsmith! ## 17.8.0 ### Minor Changes - [#858](https://github.com/primer/octicons/pull/858) [`199f00e`](https://github.com/primer/octicons/commit/199f00e99e0fc3c5abb6e78f2255393a67c08fc6) Thanks [@heyamie](https://github.com/heyamie)! - Add diagonal arrows as 16px * [#857](https://github.com/primer/octicons/pull/857) [`da2c78f`](https://github.com/primer/octicons/commit/da2c78f103bbfd65aa046ea763325380592581a7) Thanks [@gavinmn](https://github.com/gavinmn)! - Add `issue-tracked-in` and `issue-tracked-by` icons ## 17.7.0 ### Minor Changes - [#849](https://github.com/primer/octicons/pull/849) [`f6c8d2b`](https://github.com/primer/octicons/commit/f6c8d2b37a4f38d99d5f9279f793a88a020933cf) Thanks [@broccolinisoup](https://github.com/broccolinisoup)! - Add `tabIndex` prop to React icon components ## 17.6.0 ### Minor Changes - [#848](https://github.com/primer/octicons/pull/848) [`ed25e50`](https://github.com/primer/octicons/commit/ed25e501f614afe1b43aa09c11f344d8b47a233d) Thanks [@ashygee](https://github.com/ashygee)! - Add filled alert icons - alert-fill-16 - alert-fill-24 * [#847](https://github.com/primer/octicons/pull/847) [`2f9b32e`](https://github.com/primer/octicons/commit/2f9b32e6b48cb58adac95552d6e7ddb2bf405a94) Thanks [@ashygee](https://github.com/ashygee)! - - add log-24.svg (TY @edokoa!) ### Patch Changes - [#831](https://github.com/primer/octicons/pull/831) [`57f364a`](https://github.com/primer/octicons/commit/57f364a7e234080781355cd57fcf3bdd75b05af4) Thanks [@josepmartins](https://github.com/josepmartins)! - Adjust flex wrap in UI examples.Fixes #731 ## 17.5.0 ### Minor Changes - [#827](https://github.com/primer/octicons/pull/827) [`f186ad3`](https://github.com/primer/octicons/commit/f186ad3a07bd30954088e9e63936f81dc735bbcd) Thanks [@edokoa](https://github.com/edokoa)! - Save `accessibility-inset` 16px icon * [#828](https://github.com/primer/octicons/pull/828) [`6c0d207`](https://github.com/primer/octicons/commit/6c0d20761f62dad118db48e72d6e0b20210c38cb) Thanks [@edokoa](https://github.com/edokoa)! - Save `shield-slash` 16px icon ## 17.4.1 ### Patch Changes - [#815](https://github.com/primer/octicons/pull/815) [`41c088e`](https://github.com/primer/octicons/commit/41c088e11862a2f693c7670deb3a12daa7a04089) Thanks [@ashygee](https://github.com/ashygee)! - Correct alignment for search-24 ## 17.4.0 ### Minor Changes - [#810](https://github.com/primer/octicons/pull/810) [`840f4eb`](https://github.com/primer/octicons/commit/840f4eb7d89020c36a8f8eeaa6f69042c67adc8e) Thanks [@ashygee](https://github.com/ashygee)! - - modifies tasklist icon proposed in https://github.com/github/primer/issues/746 - adds a new checkbox icon using metaphor from previous tasklist metaphor * [#807](https://github.com/primer/octicons/pull/807) [`d280148`](https://github.com/primer/octicons/commit/d280148ffaa43f3260b06ed723a059f72fc0ee3b) Thanks [@edokoa](https://github.com/edokoa)! - Add `cache` 16px icon - [#801](https://github.com/primer/octicons/pull/801) [`8e5dcfc`](https://github.com/primer/octicons/commit/8e5dcfcac8dda5c9d41ba8fb3d5b7d5d14ca3943) Thanks [@gavinmn](https://github.com/gavinmn)! - Save paperclip-16.svg, paperclip-24.svg * [#806](https://github.com/primer/octicons/pull/806) [`27575d0`](https://github.com/primer/octicons/commit/27575d0e67eb0e6557856d18535b75550a364e66) Thanks [@ashygee](https://github.com/ashygee)! - Save git-merge-queue-16.svg - [#811](https://github.com/primer/octicons/pull/811) [`a005869`](https://github.com/primer/octicons/commit/a0058690fc56e5740817e6f5060ecf0473c6fc46) Thanks [@ashygee](https://github.com/ashygee)! - Save command-palette-24.svg, command-palette-16.svg ### Patch Changes - [#803](https://github.com/primer/octicons/pull/803) [`5090b7a`](https://github.com/primer/octicons/commit/5090b7acab73dc3f0f25936fceefdeb16bc19d2f) Thanks [@ashygee](https://github.com/ashygee)! - fix table icon ## 17.3.0 ### Minor Changes - [#794](https://github.com/primer/octicons/pull/794) [`608d639`](https://github.com/primer/octicons/commit/608d6399af450f8eda444c73069b59d7fc10eaa4) Thanks [@gavinmn](https://github.com/gavinmn)! - Add `copilot` icons * [#766](https://github.com/primer/octicons/pull/766) [`8df01b5`](https://github.com/primer/octicons/commit/8df01b5031dac3bd1f11071bac9d7d699e69e4b5) Thanks [@edokoa](https://github.com/edokoa)! - Add 24px `repo-locked` icon ## 17.2.0 ### Minor Changes - [#789](https://github.com/primer/octicons/pull/789) [`d59a5e2`](https://github.com/primer/octicons/commit/d59a5e2095495c9f8a2d9ad10072782df3714522) Thanks [@ashygee](https://github.com/ashygee)! - Add file-added, file-removed, file-moved Update file to be consistent in height with other file icons ### Patch Changes - [#786](https://github.com/primer/octicons/pull/786) [`0dede7f`](https://github.com/primer/octicons/commit/0dede7f202645bde2294b354284ce0592c248815) Thanks [@ashygee](https://github.com/ashygee)! - recenter org icon ## 17.1.0 ### Minor Changes - [#756](https://github.com/primer/octicons/pull/756) [`2993d47`](https://github.com/primer/octicons/commit/2993d4733cbf3acdaf4286a1a5c17e0ced762967) Thanks [@Juliusschaeper](https://github.com/Juliusschaeper)! - Added `cloud` and `cloud-offline` icons * [#762](https://github.com/primer/octicons/pull/762) [`57105bb`](https://github.com/primer/octicons/commit/57105bbaffeb38de1bb5f8bc33e125bb3968a554) Thanks [@edokoa](https://github.com/edokoa)! - Add 16px `file-directory-open-fill` icon - [#783](https://github.com/primer/octicons/pull/783) [`47d3018`](https://github.com/primer/octicons/commit/47d30183a944383e1fb28651fe70e01f3a5dbe59) Thanks [@ashygee](https://github.com/ashygee)! - Save sliders-16.svg ## 17.0.0 ### Major Changes - [#736](https://github.com/primer/octicons/pull/736) [`ec8cab8`](https://github.com/primer/octicons/commit/ec8cab891426f759fe665a781e3129241d83de8a) Thanks [@edokoa](https://github.com/edokoa)! - This patch fixes two problems: - We're adding a non-filled `file-directory` icon to the set. - We're fixing a problem where the 16px and 24px versions of the `file-directory` icons were mismatched between `fill` and `non-fill` versions of the icon. **THIS IS A BREAKING CHANGE** and will require re-linking all the `file-directory` icon references to `file-directory-fill` ### Minor Changes - [#754](https://github.com/primer/octicons/pull/754) [`7a51cb7`](https://github.com/primer/octicons/commit/7a51cb71b108b21aeb9a1716d443df3f23deba28) Thanks [@edokoa](https://github.com/edokoa)! - Add trophy-16.svg, trophy-24.svg * [#758](https://github.com/primer/octicons/pull/758) [`0d9000c`](https://github.com/primer/octicons/commit/0d9000c50255bac736eb0fbbc1ffee839130a708) Thanks [@edokoa](https://github.com/edokoa)! - Save repo-locked-16.svg - [#755](https://github.com/primer/octicons/pull/755) [`a520a37`](https://github.com/primer/octicons/commit/a520a374a0a29f47504e1a758e5cbfa0a4033721) Thanks [@Juliusschaeper](https://github.com/Juliusschaeper)! - Second batch of feed icons: merged, forked and achievement ### Patch Changes - [#751](https://github.com/primer/octicons/pull/751) [`4e768a5`](https://github.com/primer/octicons/commit/4e768a5e427684cd92c87c6b6a0ff5a5dab1e0a4) Thanks [@Crayon2000](https://github.com/Crayon2000)! - Fix typos in build.js * [#734](https://github.com/primer/octicons/pull/734) [`afde0dd`](https://github.com/primer/octicons/commit/afde0dd4ee74ec32e6babde240b49e27d96f4d30) Thanks [@ashygee](https://github.com/ashygee)! - Modify upload-24.svg to mirror 16px version ## 16.3.1 ### Patch Changes - [#733](https://github.com/primer/octicons/pull/733) [`a57b9ca`](https://github.com/primer/octicons/commit/a57b9ca1361cde081ce2c84f15ca8999639e5792) Thanks [@edokoa](https://github.com/edokoa)! - Modify upload-24.svg to mirror 16px version ## 16.3.0 ### Minor Changes - [#715](https://github.com/primer/octicons/pull/715) [`ab991ab`](https://github.com/primer/octicons/commit/ab991ab318488efc3c02b747168a34e356fad059) Thanks [@edokoa](https://github.com/edokoa)! - Added new icons for: - `accessibility` - `apps` - `id-badge` - `log` - `repo-deleted` - `tab-external` - `webhook` * [#708](https://github.com/primer/octicons/pull/708) [`6933ac3`](https://github.com/primer/octicons/commit/6933ac32f87a2cb5efda4fb74b39d1e6199134ce) Thanks [@Juliusschaeper](https://github.com/Juliusschaeper)! - Added first batch of 16px feed icons: - `feed-discussion` - `feed-heart` - `feed-person` - `feed-repo` - `feed-rocket` - `feed-star` - `feed-tag` ## 16.2.0 ### Minor Changes - [#706](https://github.com/primer/octicons/pull/706) [`2c43706`](https://github.com/primer/octicons/commit/2c4370658663817a216895ee7831a00d413f7d4e) Thanks [@Juliusschaeper](https://github.com/Juliusschaeper)! - Add `code-of-conduct` icon ### Patch Changes - [#685](https://github.com/primer/octicons/pull/685) [`c59c097`](https://github.com/primer/octicons/commit/c59c097c23ccea6409c9e2f235b64a50b4d580dd) Thanks [@jonrohan](https://github.com/jonrohan)! - Formatting changes to the main readme file, including dark mode support. ## 16.1.1 ### Patch Changes - [#681](https://github.com/primer/octicons/pull/681) [`c394d9a`](https://github.com/primer/octicons/commit/c394d9a556666beed4912797fb78f34190796511) Thanks [@jonrohan](https://github.com/jonrohan)! - Adding changesets workflow to octicons for releasing. * [#684](https://github.com/primer/octicons/pull/684) [`9ed6154`](https://github.com/primer/octicons/commit/9ed615464cc405d9264cb933d4fe5f05ff14a219) Thanks [@ashygee](https://github.com/ashygee)! - Add 12px usage guidelines - [#677](https://github.com/primer/octicons/pull/677) [`777f229`](https://github.com/primer/octicons/commit/777f2290b4662f2d769096ac3c121e61e92a0ff2) Thanks [@benkoshy](https://github.com/benkoshy)! - update: installation instructions ## 16.1.0 ### 🚀 New features - Added first set of 12px filled icons https://github.com/primer/octicons/pull/676 ### 🐛 Bug fix - Adjusted 'no-entry' size to match other circle icons https://github.com/primer/octicons/pull/673 ## 16.0.0 ### 💥 Breaking changes - Rename 16px `select-single` icon to `single-select` https://github.com/primer/octicons/pull/665 ### 🚀 New features - `iterations` https://github.com/primer/octicons/pull/667 ### 🧽 Chores - Bump dependencies ## 15.2.0 ### 🚀 New features - Add `stack` icons https://github.com/primer/octicons/pull/659 - Add `person-fill` and `telescope-fill` icons https://github.com/primer/octicons/pull/660 ## 15.1.0 ### 🚀 New features - `bell-fill-16` https://github.com/primer/octicons/pull/657 ## 15.0.1 ### 🐛 Bug fix - Modify `duplicate` icon to differentiate from `copy` https://github.com/primer/octicons/pull/647 ## 15.0.0 ### 💥 Breaking changes - Rename `duplicate` icon to `copy` https://github.com/primer/octicons/pull/643 - Rename `clippy` icon to `paste` https://github.com/primer/octicons/pull/643 ## 14.2.2 ### 🐛 Bug fix - Update `issue-reopened` https://github.com/primer/octicons/pull/633 ## 14.2.1 ### 🐛 Bug fix - fix vectors for 24px sort icons https://github.com/primer/octicons/pull/627 (🙏 @metonym) ## 14.2.0 ### 🚀 New features - `key-asterisk-16` https://github.com/primer/octicons/pull/623 - `sort-asc` https://github.com/primer/octicons/pull/619 - `sort-desc` https://github.com/primer/octicons/pull/619 ### 🧽 Chores - Remove unused dependency on nokogiri https://github.com/primer/octicons/pull/609 (🙏 @cschlack) ## 14.1.0 ### 🚀 New features - `git-pull-request-draft` https://github.com/primer/octicons/pull/613 - `git-pull-request-closed` https://github.com/primer/octicons/pull/613 ## 14.0.0 ### 💥 Breaking changes - Remove `octoface` https://github.com/primer/octicons/pull/611 - Rename `git-fork-24` to `repo-forked-24` https://github.com/primer/octicons/pull/593 ### 🚀 New features - `number` https://github.com/primer/octicons/pull/592 - `hash` (previously `number`) https://github.com/primer/octicons/pull/592 - `diamond` https://github.com/primer/octicons/pull/616 - `single-select` https://github.com/primer/octicons/pull/612 - `rows` https://github.com/primer/octicons/pull/617 - `columns` https://github.com/primer/octicons/pull/617 - `issue-draft` https://github.com/primer/octicons/pull/614 ### 💅 Enhancements - `issue-opened` https://github.com/primer/octicons/pull/614 - `issue-closed` https://github.com/primer/octicons/pull/614 ### 🐛 Fixes - Fix 24px `arrow-up` icon https://github.com/primer/octicons/pull/594 - Prevent clipping using `overflow: visible` https://github.com/primer/octicons/pull/607 ## 13.0.0 ### 🚀 New features - `table` https://github.com/primer/octicons/pull/564 - `person-add` https://github.com/primer/octicons/pull/573 - `blocked` https://github.com/primer/octicons/pull/576 - `duplicate` https://github.com/primer/octicons/pull/576 - `dependabot`https://github.com/primer/octicons/pull/585 - `codescan` https://github.com/primer/octicons/pull/588 - `browser` https://github.com/primer/octicons/pull/575 - `sidebar` icons https://github.com/primer/octicons/pull/569 - `codespaces` https://github.com/primer/octicons/pull/587 ### 💥 Breaking changes - Remove 24px `insights` icon https://github.com/primer/octicons/pull/574 - Remove 24px `copy` icon https://github.com/primer/octicons/pull/586 ### 💅 Enhancements - Use more explicit dependencies for Rails helper https://github.com/primer/octicons/pull/565 ### 🐛 Fixes - Fix `megaphone-16` https://github.com/primer/octicons/pull/554 - Fix `circle` icon https://github.com/primer/octicons/pull/584 ## 12.1.0 ### React ### 💅 Enhancements - Add icon-specific class names to each icon component https://github.com/primer/octicons/pull/453 @FloEdelmann - Add `fill` prop to each icon component https://github.com/primer/octicons/pull/551 @macno ## 12.0.0 ### 🚀 New features - `bug` (https://github.com/primer/octicons/pull/543) - `multi-select` (https://github.com/primer/octicons/pull/534) ### 💅 Enhancements - Make octicon helper slightly faster (@jhawthorn & @seejohnrun) (#536) ### 💥 Breaking changes - Rename 16px `trashcan` icon to `trash` (@fermion 🙇) (https://github.com/primer/octicons/pull/538) ### 🧽Chores - Dependency updates (#525, #524, #523, #522, #520) ## 11.3.0 ### 🚀 New features - `number` (https://github.com/primer/octicons/pull/541) - `video` (https://github.com/primer/octicons/pull/540) ### 🐛 Fixes - Fix rendering of arrows in Safari (@aaronshekey https://github.com/primer/octicons/pull/527) ## 11.2.0 ### 🚀 New features - `strikethrough` (https://github.com/primer/octicons/pull/518) ### 🐛 Fixes - Align `plus` and `dash` icon (https://github.com/primer/octicons/pull/447) - Small edits in JS documentation (https://github.com/primer/octicons/pull/499) ### 🧽Chores - Dependency updates ## 11.1.0 ### 🚀 New features - `container` (https://github.com/primer/octicons/pull/507) - `squirrel` 24px icon (https://github.com/primer/octicons/pull/508) ### 🐛 Fixes - Corrected stroke for 24px `smiley` (https://github.com/primer/octicons/pull/509) ## 11.0.0 ### 💅 Enhancements - Cache retrieval of Octicon SVG paths (https://github.com/primer/octicons/pull/491) ### 💥 Breaking changes - Fix 24px icon names https://github.com/primer/octicons/pull/465 (@BenJetson 🙇) - `unverifed-24.svg` → `unverified-24.svg` - `file-symlink-24.svg` → `file-symlink-file-24.svg` - `fire-24.svg` → `flame-24.svg` - `eye-slash-24.svg` → `eye-closed-24.svg` - Remove 24px `settings` icon. Use `gear` instead https://github.com/primer/octicons/pull/493 ## 10.1.0 ### 🚀 New features - [`arrow-switch`](https://github.com/primer/octicons/pull/486) - [`file-badge`](https://github.com/primer/octicons/pull/464) - [`x-circle`, `x-circle-fill`, `circle`](https://github.com/primer/octicons/pull/455) ### 🐛 Fixes - Corrected positioning for `triangle-down` [#459](https://github.com/primer/octicons/pull/459) ### 🧽Chores - Dependency updates ## 10.0.0 ### All packages - We've given Octicons a new look ✨ Some icons have new names and some icons haven't been redesigned yet. The following table documents those changes. If you're using an octicon in v9.x that doesn't have an equivalent in v10.0 yet, let us know by [opening an issue](https://github.com/primer/octicons/issues/new?assignees=&labels=icon+request&template=icon-request.md&title=%5BIcon+request%5D). | v9.x | v10.0 | Notes | | ------------------------ | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | | `arrow-small-down` | `arrow-down` | | | `arrow-small-left` | `arrow-left` | | | `arrow-small-right` | `arrow-right` | | | `arrow-small-up` | `arrow-up` | | | `browser` | | [Request this icon](https://github.com/primer/octicons/issues/new?assignees=&labels=icon+request&template=icon-request.md&title=%5BIcon+request%5D) | | `bug` | | [Request this icon](https://github.com/primer/octicons/issues/new?assignees=&labels=icon+request&template=icon-request.md&title=%5BIcon+request%5D) | | `circuit-board` | `cpu` | | | `cloud-download` | `download` | | | `cloud-upload` | `upload` | | | `dashboard` | `meter` | | | `dependent` | `package-dependents` | | | `device-camera` | | [Request this icon](https://github.com/primer/octicons/issues/new?assignees=&labels=icon+request&template=icon-request.md&title=%5BIcon+request%5D) | | `file-pdf` | `file` | | | `file-symlink-directory` | `file-submodule` | | | `gist-secret` | `lock` | | | `gist` | `code-square` | | | `github-action` | | [Request this icon](https://github.com/primer/octicons/issues/new?assignees=&labels=icon+request&template=icon-request.md&title=%5BIcon+request%5D) | | `heart-outline` | `heart` | | | `internal-repo` | `repo` | | | `jersey` | `people` | | | `keyboard` | | [Request this icon](https://github.com/primer/octicons/issues/new?assignees=&labels=icon+request&template=icon-request.md&title=%5BIcon+request%5D) | | `line-arrow-down` | `arrow-down` | | | `line-arrow-left` | `arrow-left` | | | `line-arrow-right` | `arrow-right` | | | `line-arrow-up` | `arrow-up` | | | `mail-read` | `mail` | | | `no-newline` | `no-entry` | | | `paintcan` | `paintbrush` | | | `plus-small` | `plus` | | | `primitive-dot-stroke` | `dot` | | | `primitive-dot` | `dot-fill` | | | `primitive-square` | `square-fill` | | | `radio-tower` | `broadcast` | | | `repo-clone` | | [Request this icon](https://github.com/primer/octicons/issues/new?assignees=&labels=icon+request&template=icon-request.md&title=%5BIcon+request%5D) | | `repo-force-push` | `repo-push` | | | `repo-pull` | | [Request this icon](https://github.com/primer/octicons/issues/new?assignees=&labels=icon+request&template=icon-request.md&title=%5BIcon+request%5D) | | `repo-template-private` | | [Request this icon](https://github.com/primer/octicons/issues/new?assignees=&labels=icon+request&template=icon-request.md&title=%5BIcon+request%5D) | | `request-changes` | `diff` | | | `saved` | `bookmark` | | | `text-size` | `heading` or `typography` | | | `unsaved` | `bookmark-slash` | | | `watch` | `hourglass` | | | `workflow-all` | | [Request this icon](https://github.com/primer/octicons/issues/new?assignees=&labels=icon+request&template=icon-request.md&title=%5BIcon+request%5D) | - We designed a set of 24px icons—as well as 16px icons—to accommodate interfaces that need larger icons. All package implementations now choose which SVG to render based on the size passed in. ### React (@primer/octicons-react) - Icon components (e.g. `AlertIcon`, `ArrowRightIcon`, etc.) now accept `size`, `ariaLabel`, `verticalAlign`, and `className` props and can be used on their own. No need to pass them to the `Octicon` component. ```jsx ``` - Icon components will now choose the best SVG icon to render based on the `size` passed in. - The `Octicon` component is deprecated. Use icon components on their own instead: ```diff - + ``` #### BREAKING CHANGES 💥 - All icon component names now include `Icon` at the end (e.g. `Alert` → `AlertIcon`). - In order to enable tree-shaking, we removed the `iconsByName` and `getIconByName` exports. - `Octicon` no longer accepts `width` or `height` props. Use the `size` prop instead. In cases where the width and height of an icon are not equal (e.g. logos), the height will be set to the value of the `size` prop and the `width` will be scaled proportionally. - We renamed the `ariaLabel` prop to `aria-label` to be consistent with React: https://reactjs.org/docs/accessibility.html#wai-aria ```diff - + ``` - Setting `verticalAlign="top"` on the `Octicon` component or any icon component will now apply a `vertical-align: top;` style to the ``. Previously, we were translating "top" to "text-top." So setting `verticalAlign="top"` would apply a `vertical-align: text-top;` style to the ``. If you want a vertical alignment of "text-top," set the `verticalAlign` prop to `"text-top"`. - Custom icon components passed to the `Octicon` component now need to render the entire ``, not just the ``. ```diff function CirclesIcon() { return ( - + - + ) } - CirclesIcon.size = [30, 10] ``` ### JavaScript (@primer/octicons) #### BREAKING CHANGES 💥 - The structure of each icon object has been updated to allow support multiple SVGs per icon: ##### Before ```js octicons.alert // { // symbol: 'alert', // keywords: ['warning', 'triangle', 'exclamation', 'point'], // toSVG: [Function], // width: 16, // height: 16, // path: '', // options: { // version: '1.1', // width: '16', // height: '16', // viewBox: '0 0 16 16', // class: 'octicon octicon-alert', // 'aria-hidden': 'true' // }, // } ``` #### After ```js octicons.alert // { // symbol: 'alert', // keywords: ['warning', 'triangle', 'exclamation', 'point'], // toSVG: [Function] // heights: { // 16: { // width: 16, // path: '', // options: { // version: '1.1', // width: '16', // height: '16', // viewBox: '0 0 16 16', // class: 'octicon octicon-alert', // 'aria-hidden': 'true' // }, // }, // 24: ... // } // } ``` ## 9.6.0 ### features - New icon `north-star` https://github.com/primer/octicons/pull/380 ## 9.5.0 ### features - New icon `internal-repo` https://github.com/primer/octicons/pull/375 ## 9.4.0 ### features - New icons `heart-outline` `infinity` `line-arrow-up` `line-arrow-down` `line-arrow-right` `line-arrow-left` https://github.com/primer/octicons/pull/365 ### Chores - Contributing docs updates and issue template updates #367 ### Bugs - Update `heart` glyphs removing extra points https://github.com/primer/octicons/pull/365 ## 9.3.1 ### Bugfix - Workflow icon had a cutoff edge. ## 9.3.0 ### 🚀 New features - Workflow icons https://github.com/primer/octicons/pull/356 @ashygee - Allow 'unset' value for verticalAlign property https://github.com/primer/octicons/pull/354 @Fs00 ## 9.2.0 ### 🚀 New features - [x] New icons for save/unsave and primitive dot stroke https://github.com/primer/octicons/pull/351 @ashygee @colinkeany ### 🧽 Chores - [x] Migrating to new yml actions syntax https://github.com/primer/octicons/pull/332 @max & @jonrohan - [x] Update jekyll gemspec to support Jekyll 4.0 https://github.com/primer/octicons/pull/347 @ntotten ### 🐛 Bugs - [x] Octicons react isn't including className https://github.com/primer/octicons/pull/271 @pocke ## 9.1.1 ### 🐛 Bug Fix - [x] renamed the original shield icon to `shield-lock` https://github.com/primer/octicons/issues/323 @ashygee - [x] test for duplicate icons https://github.com/primer/octicons/pull/322 @jonrohan ## 9.1.0 ### 🚀 New features - [x] Adding skip icon https://github.com/primer/octicons/pull/318 @ashygee ## 9.0.0 ### 💥 Breaking changes - [x] Rename `octicons` to `@primer/octicons` https://github.com/primer/octicons/pull/311 - [x] Rename `@githubprimer/octicons-react` to `@primer/octicons-react` https://github.com/primer/octicons/pull/311 ### 🚀 New features - [x] Adding a shield icon https://github.com/primer/octicons/pull/310 @ashygee @donokuda - [x] Adding new repo icons https://github.com/primer/octicons/issues/316 @superbryntendo ## 8.5.0 - a11y aria-hidden update from @muan https://github.com/primer/octicons/pull/295 - Verified icons poor rendering. @ashygee https://github.com/primer/octicons/pull/297 - Docs update for contributing @ashygee https://github.com/primer/octicons/pull/298 ## 8.4.2 ### 💅🏼 Enhancement - Thumbs up/down icons needed some vector improvements. https://github.com/primer/octicons/pull/287 ### 🐛 Bug Fix - Node package missing `build/build.css` file. https://github.com/primer/octicons/pull/292 ## 8.4.1 ### 🐛 Bug Fix - Rollup files missing from octicons react package https://github.com/primer/octicons/issues/282 ## 8.4.0 ### 🏠 Internal - Using Actions to build and deploy Octicons https://github.com/primer/octicons/pull/276 #### Committers: 1 - Jon Rohan ([jonrohan](https://github.com/jonrohan)) ## 8.3.0 - New "changes requested" icon https://github.com/primer/octicons/pull/267 - Contrib Doc Updates https://github.com/primer/octicons/pull/256 - Updating licenses to 2019 https://github.com/primer/octicons/pull/272 ## 8.2.0 - Add `fold-up` and `fold-down` icons, courtesy of @pmarsceill ## 8.1.3 - Add `eye-closed` icon, courtesy of @colinkeany ## 8.1.2 - Patch release for failed 8.1.1 release ## 8.1.1 - Fix for `list-ordered` icon https://github.com/primer/octicons/pull/252 - In React Octicons, we set aria-hidden to false if there's an aria-label provided ## 8.1.0 - Add the `arrow-both` icon courtesy of @venetucci - TypeScript types are now available thanks to @j-f1! - Fix CI builds for outside contributors (as long as they aren't changing octicons) - Fix typo in README - Update README with `@githubprimer/octicons-react scope` - Publish release candidates from any branch beginning with `release` ## 8.0.0 - Breaking changes in `octicons_react` [#225](https://github.com/primer/octicons/pull/225) - After the initial release of octicons_react https://github.com/primer/octicons/releases/tag/v7.4.0, we needed to rename the scope of the package. Due to some deployment conflicts in our pipelines. ## 7.4.0 - This release marks the first official version of Octicons for React! Check out the `@github/octicons-react` package on npm for more info, or peruse the long-running PR [#222](https://github.com/primer/octicons/pull/222). - CI status is now reported to the `#design-ops` Slack channel - Jekyll Octicons has moved in this repo from `lib/jekyll-octicons` to `lib/octicons_jekyll` ## 7.3.0 - Fix for heart icon https://github.com/primer/octicons/pull/211 - Adding an archive icon created by @colinkeany - Fixes https://github.com/primer/octicons/issues/182 - Fixed versioning strategy https://github.com/primer/octicons/pull/#208 ## Archived releases ### Octicons_node 7.0.0 - Removing `file-text` and `mail-reply` icons. Use `file` and `reply` respectively. - Removing spritesheet calls and `toSVGUse` method. ### Octicons_gem 5.0.4 - Removing `file-text` and `mail-reply` icons. Use `file` and `reply` respectively. - Removing spritesheet calls and `to_svg_use` method. ### 6.0.1 Fixes: - Typo `kebab-veritcal` becomes `kebab-vertical` ### 6.0.0 Added: - `kebab-horizontal` and `kebab-vertical` icons - Polyfill for the `Object.assign` function Removes: - Removing a duplicate `ellipses` icon from the set. Use `ellipsis` instead. ### 5.0.1 Fixes: - projects icon renders as a block, using `fill-rule` fixes it ### 5.0.0 Adds: - `project` - `note` - `screen-full` - `screen-normal` - More node.js api endpoints for accessing icons https://github.com/primer/octicons/pull/120 - Creating a spritesheet demo https://github.com/primer/octicons/pull/121 Removes: - Deprecating support for the webfont https://github.com/primer/octicons/pull/117 - Stop checking `/build/` directory into repository https://github.com/primer/octicons/pull/118 - Removing sass as a dependency https://github.com/primer/octicons/pull/119 ### 4.4.0 Adds: - svg.json file that is accessible from node require ### 4.3.0 Fixes: - Vertical alignment on `italic` Modifies: - `person` - `organization` ### 4.2.1 Fixes: - Removing inline sourcemap from `min` versions of css. ### 4.2.0 Adds: - Keywords.json file that has an index of all octicons with alias names ### 4.1.1 (June 16, 2016) Fixes: - Putting the `$octicons-font-path` back in the scss file. ### 4.1.0 (June 6, 2016) Adds: - Installation docs https://github.com/primer/octicons/pull/94 - `grabber` - `plus-small` Modifies: - `smiley` Refines: - Renames `mail-reply` to `reply` and refines its shape. Fixes: - Revert license back to SPDX standard ### 4.0.0 (June 6, 2016) Adds: - Whole new grunt build system including svg sprite sheet. - adding css min https://github.com/primer/octicons/pull/60 - adding woff2 format https://github.com/primer/octicons/issues/3 - creates spritesheet of svg files https://github.com/primer/octicons/issues/88 Removes: - Bower support Fixes: - all svg icons include viewBox https://github.com/primer/octicons/issues/87 - license in package.json https://github.com/primer/octicons/issues/85 ### 3.5.0 (February 12, 2016) Adds: - `unverified` Refines: - `verified` ### 3.4.1 (January 24, 2016) This includes various SVG viewport refinements. Refines: - `thumbs-down` - `logo-github` ### 3.4.0 (January 22, 2016) Adds: - `verified` - `smiley` Removes: - `color-mode` Refines: - `primitive-dot` - `horizontal-rule` - `triangle-down` - `triangle-up` - `triangle-left` - `triangle-right` - `globe` - `flame` - `comment-discussion` ### 3.3.0 (November 12, 2015) Adds: - `logo-gist` Resizes all our SVG to be 16x16 instead of 1024x1024 ### 3.2.0 (November 6, 2015) Adds: - `bold` - `text-size` - `italic` - `tasklist` It also normalizes some styling in: - `list-unordered` - `list-ordered` - `quote` - `mention` - `bookmark` - `threebars` Removes - `screen-normal` - `screen-full` ### 3.1.0 (August 13, 2015) Adds - `shield` This thickens stroke widths slightly on the following icons: - `circle-slash` - `clock` - `cloud-upload` - `cloud-download` - `dashboard` - `info` - `issue-closed` - `issue` - `issue-reopened` - `history` - `question` - `search` Fills `comment-discussion` Thickens `x` to match `checkmark` ### 3.0.1 (August 10, 2015) Some files were missing in `3.0.0` ### 3.0.0 (August 10, 2015) Removes - `microscope` - `beer` - `split` - `puzzle` - `steps` - `podium` - `timer` - all `alignment` icons - all `move` icons - all `playback` icons - all `jump` icons Adds - `beaker` - `bell` - `desktop-download` - `watch` Line-weight changes, sizing normalization, and new drawings - `circle-slash` - `lock` - `cloud-upload` - `cloud-download` - `plus` - `✕` - `broadcast` - `lock` - all `repo` icons - organization - person - all `chevrons` & `triangles` - all `diff` icons - `clippy` - all `issue` and circular icons - `rss` - `ruby` - `cancel` - `settings` - `mirror` - `external-link` - `history` - `gear` - `settings` - `info` - `history` - `package` - `gist-secret` - `rocket` - `law` - `telescope` - `search` - `tag` - `normal-screen` - `iphone` - `no-new-line` - `desktop` - all `git` icons - `circuit-board` - `heart` - `home` - `briefcase` - `wiki` - `bookmark` - `briefcase` - `calendar` - `color-mode` - `comment` - `discussions` - `credit-card` - `dashboard` - `camera` - `video` - `bug` - `desktop` - `ellipses` - `eye` - all `files` & `folders` - `fold` - `unfold` - `gift` - `graph` - `hubot` - `inbox` - `jersey` - `keyboard` - `light-bulb` - `link` - `location` - `mail` - `mail-read` - `marker` - `plug` - `mute` - `pencil` - `push-pin` - `fullscreen` - `unfullscreen` - `server` - `sign-in` - `sign-out` - `tag` - `terminal` - `thumbs-up` - `thumbs-down` - `trash` - `unmute` - `versions` - `gist` - `key` - `megaphone` - `checklist` ## 2.4.1 (June 2, 2015) - Add the scss file I forgot to include ## 2.4.0 (June 2, 2015) - Add `octicons.scss` - Revert path changes to `sprockets-octicons.scss`, as they broke octicons in sprockets. ## 2.3.0 (May 28, 2015) - Add a path variable to `sprockets-octicons.scss` to be consistent with octicons.less` ## 2.2.3 (May 21, 2015) - Use SPDX license identifiers in package.json ## 2.2.2 (April 1, 2015) Fixes file icons for - `file-binary` - `file-code` - `file-media` - `file-pdf` - `file-symlink-file` - `file-text` - `file-zip` ## 2.2.1 (March 30, 2015) - Fix vector artifact and smooth curves in `mark-github` ## 2.2.0 (Feb 18, 2015) - Add two new icons: `thumbsup` and `thumbsdown` ## 2.0.1 (June 16, 2014) - Add mention of github.com/logos to the license ## 2.0.0 (June 16, 2014) - Hello world ================================================ FILE: CODE_OF_CONDUCT.md ================================================ # Contributor Covenant Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: * Using welcoming and inclusive language * Being respectful of differing viewpoints and experiences * Gracefully accepting constructive criticism * Focusing on what is best for the community * Showing empathy towards other community members Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic address, without explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at design-systems@github.com. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html [homepage]: https://www.contributor-covenant.org For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq ================================================ FILE: CONTRIBUTING.md ================================================ # Octicons Contribution Guidelines (Currently GitHub Staff only) Thank you for your interest in contributing to Octicons! We are currently only accepting submissions from GitHub staff and only include icons that are used in the GitHub UI. If you'd like to submit feedback, a bug, or an idea for improvement, please open a new issue in this repo using the appropriate [issue template](https://github.com/primer/octicons/issues/new/choose). ## Icon request and review process ### 1. Icon review request is made - Icon review requests are made using the [icon request template](https://github.com/github/primer/issues/new?assignees=&labels=octicon%2C+request%2C+needs+triage&template=02-icon-request.md&title=%5BIcon+request%5D+) in the github/primer repo (visible to GitHub staff only). - Icons in the Primer Roadmap inbox will be triaged by a maintainer from the Octicons team. Maintainers should reply with a comment on the issue and then move the issue to Primer Teams Backlog. ### 2. Working on icons - If an icon recommendation can be made async, we will discuss it in #primer-octicons or directly in the issue. - Icon review requests require a working session, we will send an invitation. - Once an icon has been assigned, it's up to assigned designer to be responsible for communicating the icon's status and drive the work forward. ### 3. Icon design, review, and communication - Once design has been started on an icon, the request issue will be moved to the **Design in Progress** column of the Primer Teams Backlog. - Designers should design the icon in Figma and when ready for review, use the [Octicons Push plugin](https://www.figma.com/community/plugin/825432045044458754/Octicons-Push) to create a PR - After a PR is created link to the PR in the icon request issue. PRs need approval from the icon requestor (stakeholder) and at least one designer on the octicons maintainer team. ### 4. Icon request completed - When an icon request PR has been approved, communicate that in the issue. - After the Octicons release, the new icons that were added will have their request issues moved to the **Done** column ## Adding or updating an icon Follow these steps to add or update an icon. ### Manually with SVG files #### 1. Clone the repository ```shell # Clone the repository git clone https://github.com/primer/octicons # Navigate to the newly cloned directory cd octicons ``` If you don't have [`write`](https://help.github.com/en/github/getting-started-with-github/access-permissions-on-github) access to the [primer/octicons](https://github.com/primer/octicons) repository, instead of cloning the repository directly, you'll need to [fork](http://help.github.com/fork-a-repo/) the project, clone your fork, and configure the remotes: ```shell # Clone your fork of the repository git clone https://github.com//octicons # Navigate to the newly cloned directory cd octicons # Assign the original repo to a remote called "upstream" git remote add upstream https://github.com/primer/octicons ``` #### 2. Create a new feature branch ```shell git checkout -b ``` #### 3. Add or update SVG files in the `/icons` directory #### 4. Add or update keywords in `keywords.json` ```diff { "mark-github": ["octocat", "brand", "github", "logo"], + "your-icon": ["foo", "bar"] } ``` #### 5. Commit and push changes ```shell git add . git commit -m git push ``` #### 6. Create a pull request Use GitHub to [create a pull request](https://help.github.com/en/desktop/contributing-to-projects/creating-a-pull-request) for your branch. In your pull request description, be sure to mention where the icon will be used and any relevant timeline information. If everything looks good, a maintainer will approve and merge the pull request when appropriate. After the pull request is merged, your icon will be available in the next Octicons release. ### Using the Octicons Push Figma plugin If you work at GitHub, you can use the [Octicons Push](https://www.figma.com/community/plugin/825432045044458754/Octicons-Push) Figma plugin to start an Octicons pull request from Figma. Here's how it works: 1. Select the icon frames you want to commit. Make sure the frames are either 16x16 or 24x24 and that you've outlined all strokes. 2. Open the Octicons Push plugin. 3. Select the branch you want to commit to. You can choose an existing branch or create a new branch. 4. Press "Commit." The plugin will then export, commit, and push the selected icons to the branch you chose. If you chose to create a new branch, the plugin will give you a link to where you can start a new pull request with your branch. After you create a pull request, a member of the Design Infrastructure team will triage and review your contribution. ![demo showing how to create a pull request using the Octicons Push Figma plugin](https://user-images.githubusercontent.com/4608155/77948730-b1a24600-727a-11ea-9c39-040be9a12963.gif) ## How changes are reviewed Here are a few questions we'll ask when reviewing new octicons. Keep these in mind as you're designing: - Where will this icon be used in the context of GitHub UI? - Is an icon necessary in that context? - Could we use an existing icon? - Is the icon trying to represent too many ideas? - Does it follow the design guidelines? ## Releasing changes Once submitted changes have been agreed upon, these instructions will guide maintainers through releasing changes. Releases are managed by 🦋 [Changesets](https://github.com/atlassian/changesets#documentation) which is a great tool for managing major/minor/patch bumps and changelogs. More info can be found in our [how we work docs](https://github.com/github/design-infrastructure/blob/main/how-we-work/engineering/changesets.md#using-changesets-to-prepare-and-publish-a-release). We have the [changeset-bot comment on new pull requests](https://github.com/changesets/bot#readme) asking contributors or maintainers to add a changeset file, which will become the markdown supported changelog entry for the change. When creating the changeset always commit into the working branch (pull request branch), not `main`. When a pull request is approved merge it into the `main` branch. The changeset action will then create a Release pull request that includes this new pull request. Once maintainers have agreed and are satisfied with the release. Merge the Release pull request. Changesets will then publish a new GitHub release to the repository with the changelog and new version number. A second action will be triggered by this release and publish the new versions to npm and rubygems. 🎉 Congratulations! The new release has been published. ## Other contributions When contributing to Octicons outside of adding a new icon or release-dependent contribution, be sure to add the `skip-changeset` label to the pull request. This will allow for the pull request to skip the changeset check and have the ability to be merged into the main branch. Examples of other contributions include adding documentation or improving a GitHub Actions workflows. ================================================ FILE: Gemfile ================================================ # frozen_string_literal: true source "https://rubygems.org" group :development, :test do gem "minitest" gem "rake" gem "rubocop-github", "0.20.0" end ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2026 GitHub Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ ![octicons cover light](https://user-images.githubusercontent.com/54012/138925195-5779c51d-ff8c-4264-a914-e64f4843893d.png#gh-light-mode-only) ![octicons cover dark](https://user-images.githubusercontent.com/54012/138925203-80e1afa1-ba54-4731-9525-3c41186663f9.png#gh-dark-mode-only)

Primer Octicons

Octicons are a set of SVG icons built by GitHub for GitHub.

## Libraries This repository contains several libraries. Each of them is in the `lib/` folder and gives access to Octicons on a different platform/language. ### JavaScript The octicons node.js library is the main JavaScript library. With [a JavaScript API](/lib/octicons_node/README.md) that can be used in a variety of applications. | Package | Version | | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------- | | **[@primer/octicons](/lib/octicons_node)**
Node.js package with JavaScript API | [![npm version](https://img.shields.io/npm/v/@primer/octicons.svg)](https://www.npmjs.org/package/@primer/octicons) | | **[@primer/octicons-react](/lib/octicons_react)**
React Octicons components | [![npm version](https://img.shields.io/npm/v/@primer/octicons-react.svg)](https://www.npmjs.org/package/@primer/octicons-react) | | **[@primer/styled-octicons](/lib/octicons_styled)**
React Octicons components with Styled System props | [![npm version](https://img.shields.io/npm/v/@primer/styled-octicons.svg)](https://www.npmjs.org/package/@primer/styled-octicons) | ### Ruby | Package | Version | | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | | **[octicons](/lib/octicons_gem)**
Ruby gem with Ruby API | [![Gem version](https://img.shields.io/gem/v/octicons.svg)](https://rubygems.org/gems/octicons) | | [octicons_helper](/lib/octicons_helper)
Rails helper for using octicons | [![Gem version](https://img.shields.io/gem/v/octicons_helper.svg)](https://rubygems.org/gems/octicons_helper) | | [jekyll-octicons](/lib/octicons_jekyll)
Jekyll plugin for using octicons | [![Gem version](https://img.shields.io/gem/v/jekyll-octicons.svg)](https://rubygems.org/gems/jekyll-octicons) | ## Contributing ### Feedback, ideas, and bug reports If you found a bug, have feedback about our Octicon Library, or an idea on how to improve it, please open a new issue in this repo using the appropriate [issue template](https://github.com/primer/octicons/issues/new/choose). ### Request an Icon Review (GitHub staff only) To request an icon review for inclusion in the Octicons Library, open an issue using the [icon review request](https://github.com/github/primer/issues/new?assignees=&labels=octicon%2C+request%2C+needs+triage&template=03-icon-request.md&title=%5BIcon+request%5D+) template in github/primer. ### Adding or updating an icon Read through our [contributing guide](./CONTRIBUTING.md#adding-or-updating-icons) if you want to add or update icons. ## License (c) GitHub, Inc. When using the GitHub logos, be sure to follow the [GitHub logo guidelines](https://github.com/logos). _Code License:_ [MIT](./LICENSE) Applies to all other files ================================================ FILE: add-octicon-checklist.md ================================================ # Add an octicon Use this checklist to add a new/updated octicon to the Figma library and the Octicons package. Read the [contributing guidelines](/CONTRIBUTING.md) for more information on the entire contribution process. ## Figma - [ ] Remove white background from icon frame - [ ] Outline all strokes of vector shape - [ ] Union shapes - [ ] Merge/flatten vector (cmd+e) - [ ] Remove any unused points - [ ] Rename vector layer "Icon" - [ ] Vector layer color set to `text/primary` - [ ] Name the icon frame to the correct icon name - Note: Octicon names should be written lower case and use `-` to separate descriptors - Note: If the icon is related to another icon or is part of a set, check the naming convention of the other icons to be consistent. (e.g. the issue icons are all prefixed as `issue-(something)`, `issue-opened`/`issue-closed`) - Note: 24px icons will end with `-24` (e.g. `issue-opened-24`) - [ ] Copy/paste into [Octicons library file](https://www.figma.com/file/1ljgTFkT5NKNRfq5hw07JQ/Octicons?node-id=0%3A1) - [ ] Convert the icons into components - [ ] Set constraints of vectors to Scale/Scale - Note: If adding multiple icons, use the ["All Constraints" plugin](https://www.figma.com/community/plugin/847224511609531534/All-Constraints) for bulk editing - [ ] Add keywords to icon component - Note: All keywords begin with the search flag `icon: ` - Note: Keywords should describe other metaphors that the icon can represent when searching - Example: The `bookmark` icon's keywords are "icon: favorite, save, bookmark" ## Octicons package - [ ] Use the [Octicons Push plugin](https://www.figma.com/community/plugin/825432045044458754/Octicons-Push) to create a pull request from Figma - [ ] Open created pull request in the browser and add details - Pull request should include - [ ] Small description with the names of the new icons - [ ] Screenshot - [ ] Link to icon request issue for tracking - [ ] Request reviewers - [ ] Original requestor (from issue) - [ ] Member of octicons team (@ashygee, @colebemis, @edokoa, @juliusschaeper) - [ ] Submit pull request ================================================ FILE: keywords.json ================================================ { "agent": ["agents", "ai", "cloud", "cloudecode", "code"], "ai-model": ["ai", "model", "llm", "models", "copilot"], "alert": ["warning", "triangle", "exclamation", "point"], "archive": ["box", "catalog"], "arrow-both": ["point", "direction", "left", "right"], "arrow-down": ["point", "direction"], "arrow-left": ["point", "direction"], "arrow-right": ["point", "direction"], "arrow-small-down": ["point", "direction", "little", "tiny"], "arrow-small-left": ["point", "direction", "little", "tiny"], "arrow-small-right": ["point", "direction", "little", "tiny"], "arrow-small-up": ["point", "direction", "little", "tiny"], "arrow-up": ["point", "direction"], "beaker": [ "experiment", "labs", "experimental", "feature", "test", "science", "education", "study", "development", "testing" ], "bell": ["notification"], "bold": ["markdown", "bold", "text"], "book": ["book", "journal", "wiki", "readme"], "book-locked": ["book", "journal", "wiki", "readme", "lock"], "bookmark": ["tab", "star"], "boolean-off": ["bool", "off", "false", "no", "0"], "boolean-on": ["bool", "on", "true", "yes", "1"], "briefcase": ["suitcase", "business"], "broadcast": ["rss", "radio", "signal"], "browser": ["window", "web"], "bug": ["insect", "issue"], "calendar": ["time", "day", "month", "year", "date", "appointment"], "check": ["mark", "yes", "confirm", "accept", "ok", "success"], "checkbox": ["box", "checkbox", "check"], "checkbox-fill": ["box", "checkbox", "check"], "checklist": ["todo", "tasks"], "chevron-down": ["triangle", "arrow"], "chevron-left": ["triangle", "arrow"], "chevron-right": ["triangle", "arrow"], "chevron-up": ["triangle", "arrow"], "circle-slash": ["no", "deny", "fail", "failure", "error", "bad"], "circuit-board": ["developer", "hardware", "electricity"], "clippy": ["copy", "paste", "save", "capture", "clipboard"], "clock": ["time", "hour", "minute", "second", "watch"], "cloud-download": ["save", "install", "get"], "cloud-upload": ["put", "export"], "code": ["brackets"], "comment": ["speak", "bubble", "chat"], "comment-ai": ["ai", "speak", "bubble", "chat"], "comment-discussion": ["converse", "talk", "chat"], "comment-locked": ["comment", "discussion", "conversation", "bubbles", "lock"], "compose": ["write", "new", "create", "pencil", "post"], "credit-card": ["money", "billing", "payments", "transactions"], "crosshairs": ["target", "focus", "center", "trigger", "aim"], "dash": ["hyphen", "range"], "dashboard": ["speed", "dial"], "database": ["disks", "data"], "dependent": ["dependency", "dependent", "file"], "desktop-download": ["clone", "download"], "device-camera": ["photo", "picture", "image", "snapshot"], "device-camera-video": ["watch", "view", "media", "stream"], "device-desktop": ["computer", "monitor"], "device-mobile": ["phone", "iphone", "cellphone"], "dice": ["lucky", "chance", "random"], "diff": ["difference", "changes", "compare"], "diff-added": ["new", "addition", "plus"], "diff-ignored": ["slash"], "diff-modified": ["dot", "changed", "updated"], "diff-removed": ["deleted", "subtracted", "dash"], "diff-renamed": ["moved", "arrow"], "ellipsis": ["dot", "read", "more", "hidden", "expand"], "exclamation": ["warning", "alert", "emphasis"], "eye": ["look", "watch", "see"], "eye-closed": ["hidden", "invisible", "concealed", ""], "file": ["file", "text", "words"], "file-binary": ["image", "video", "word", "powerpoint", "excel"], "file-check": ["file", "done", "complete", "check", "checked", "selected"], "file-code": ["text", "javascript", "html", "css", "php", "ruby", "coffeescript", "sass", "scss"], "file-directory": ["folder"], "file-media": ["image", "video", "audio"], "file-pdf": ["adobe"], "file-submodule": ["folder"], "file-symlink-directory": ["folder", "subfolder", "link", "alias"], "file-symlink-file": ["link", "alias"], "file-zip": ["compress", "archive"], "filter-remove": ["funnel", "filter", "remove", "delete"], "fiscal-host": ["safe", "money"], "flame": ["fire", "hot", "burn", "trending"], "flowchart": ["diagram", "chart", "process", "workflow", "loop", "nodes", "flow"], "focus-center": ["target", "focus", "center"], "fold": ["unfold", "hide", "collapse"], "fold-down": ["unfold", "hide", "collapse", "down"], "fold-up": ["unfold", "hide", "collapse", "up"], "gear": ["settings"], "gift": ["package", "present", "skill", "craft", "freebie"], "gist": ["gist", "github"], "gist-secret": ["gist", "secret", "private"], "git-branch": ["fork", "branch", "git", "duplicate"], "git-branch-check": ["git", "branch", "check", "checked", "selected"], "git-commit": ["save"], "git-compare": ["difference", "changes"], "git-merge": ["join"], "git-pull-request": ["review"], "git-pull-request-locked": ["pr", "pull", "git", "lock"], "github-action": ["board", "workflow", "action", "automation"], "globe": ["world", "earth", "planet", "enterprise"], "grabber": ["mover", "drag", "drop", "sort"], "graph": ["chart", "trend", "stats", "statistics"], "graph-bar-horizontal": ["chart", "barchart", "horizontal", "axis", "x-axis", "stats", "statistics"], "graph-bar-vertical": ["chart", "barchart", "vertical", "axis", "y-axis", "stats", "statistics"], "heart": ["love", "beat"], "heart-outline": ["love", "beat"], "history": ["time", "past", "revert", "back"], "home": ["welcome", "index", "house", "building"], "horizontal-rule": ["hr"], "hubot": ["robot", "bot"], "inbox": ["mail", "todo", "new", "messages"], "inbox-fill": ["mail", "todo", "new", "messages"], "infinity": ["unlimited", "infinite"], "info": ["help"], "internal-repo": ["internal, repo, repository"], "issue-closed": ["done", "complete"], "issue-locked": ["issue", "open", "new", "lock"], "issue-opened": ["new"], "issue-reopened": ["regression"], "italic": ["font", "italic", "style"], "jersey": ["team", "game", "basketball"], "kebab-horizontal": ["kebab", "dot", "menu", "more"], "kebab-vertical": ["kebab", "dot", "menu", "more"], "key": ["key", "lock", "secure", "safe"], "keyboard": ["type", "keys", "write", "shortcuts"], "law": ["legal", "bill"], "light-bulb": ["idea"], "line-arrow-down": ["arrow", "point", "direction", "down"], "line-arrow-left": ["arrow", "point", "direction", "left"], "line-arrow-right": ["arrow", "point", "direction", "right"], "line-arrow-up": ["arrow", "point", "direction", "up"], "link": ["connect", "hyperlink"], "link-external": ["out", "see", "more", "go", "to"], "list-ordered": ["numbers", "tasks", "todo", "items"], "list-unordered": ["bullet", "point", "tasks", "todo", "items"], "location": ["here", "marker"], "lock": ["secure", "safe", "protected"], "lockup-github": ["brand", "github", "logo"], "logo-gist": ["brand", "github", "logo"], "logo-github": ["brand", "github", "logo"], "loop": ["loops", "automation", "repeat", "node", "actions", "copilot"], "mail": ["email", "unread"], "mail-read": ["email", "open"], "mark-github": ["octocat", "brand", "github", "logo"], "markdown": ["markup", "style"], "maximize": ["expand", "enlarge", "arrow"], "mcp": ["model", "context", "protocol"], "megaphone": ["bullhorn", "loud", "shout", "broadcast"], "mention": ["at", "ping"], "milestone": ["marker"], "minimize": ["smaller", "shrink", "arrow"], "mirror": ["reflect"], "mortar-board": ["education", "learn", "teach"], "move-to-bottom": ["terminal", "end", "down", "end"], "move-to-end": ["terminal", "right", "finish"], "move-to-start": ["terminal", "left", "beginning"], "move-to-top": ["terminal", "up", "start", "beginning"], "mute": ["quiet", "sound", "audio", "turn", "off"], "no-newline": ["return"], "north-star": ["star", "snowflake", "asterisk"], "node": ["circle", "dot", "point", "loop", "loops"], "note": ["card", "paper", "ticket"], "octoface": ["octocat", "brand"], "organization": ["people", "group", "team"], "package": ["box", "ship"], "paintcan": ["style", "theme", "art", "color"], "pause": ["stop", "interupt", "block", "pause"], "pencil": ["edit", "change", "update", "write"], "pencil-ai": ["ai", "copilot", "edit", "change", "update", "write"], "person": ["people", "man", "woman", "human"], "pin": ["save", "star", "bookmark"], "pin-slash": ["unpin", "unsave", "unstar", "unbookmark"], "pivot-column": ["pivot", "column", "table", "project", "filter"], "play": ["play", "start", "begin", "action"], "plug": ["hook", "webhook"], "plus": ["add", "new", "more"], "plus-small": ["add", "new", "more", "small"], "primitive-dot": ["circle"], "primitive-dot-stroke": ["circle", "dot", "unread"], "primitive-square": ["box"], "project": ["board", "kanban", "columns", "scrum"], "pulse": ["graph", "trend", "line", "activity"], "question": ["help", "explain"], "quote": ["quotation"], "radio-tower": ["broadcast"], "reply": ["reply all", "back"], "repo": ["book", "journal", "repository"], "repo-clone": ["book", "journal", "repository"], "repo-force-push": ["book", "journal", "put"], "repo-forked": ["book", "journal", "copy"], "repo-pull": ["book", "journal", "get"], "repo-push": ["book", "journal", "repository", "put"], "repo-template": ["book", "new", "add", "template"], "repo-template-private": ["book", "new", "template"], "report": ["report", "abuse", "flag"], "request-changes": ["diff", "changes", "request"], "rocket": ["staff", "stafftools", "blast", "off", "space", "launch", "ship"], "rss": ["broadcast", "feed", "atom"], "ruby": ["code", "language"], "saved": ["saved", "bookmark"], "screen-full": ["fullscreen", "expand"], "screen-normal": ["fullscreen", "expand", "exit"], "search": ["magnifying", "glass"], "server": ["computers", "racks", "ops"], "settings": ["sliders", "filters", "controls", "levels"], "shield": ["security", "shield", "protection"], "shield-check": ["security", "shield", "protection", "check", "success"], "shield-lock": ["protect", "shield", "lock"], "shield-slash": ["shield", "slash", "protect", "unsafe", "unprotected", "security"], "shield-x": ["security", "shield", "protection", "fail"], "sign-in": ["door", "arrow", "direction", "enter", "log in"], "sign-out": ["door", "arrow", "direction", "leave", "log out"], "skip": ["skip", "slash"], "smiley": ["emoji", "smile", "mood", "emotion", "feedback", "happy", "4"], "smiley-frown": ["emoji", "frown", "sad", "negative", "unhappy", "mood", "emotion", "feedback", "2"], "smiley-frustrated": ["emoji", "frustrated", "negative", "angry", "mad", "pain", "mood", "emotion", "feedback", "1"], "smiley-grin": ["emoji", "grin", "mood", "ecstatic", "elated", "thrilled", "happy", "emotion", "feedback", "5"], "smiley-neutral": ["emoji", "neutral", "meh", "expressionless", "mood", "emotion", "feedback", "3"], "space": ["spaces", "context", "copilot", "attachment", "folder", "ai"], "spacing-small": ["spacing", "density", "padding", "small"], "spacing-medium": ["spacing", "density", "padding", "medium"], "spacing-large": ["spacing", "density", "padding", "large"], "sparkle": ["spark", "ai", "generate", "shine"], "split-view": ["columns", "split", "view", "panes", "sidebar"], "square-circle": ["stop", "interupt", "block", "pause"], "squirrel": ["ship", "shipit", "launch"], "star": ["save", "remember", "like"], "stop": ["block", "spam", "report"], "sync": ["cycle", "refresh", "loop"], "tag": ["release"], "tasklist": ["todo"], "telescope": ["science", "space", "look", "view", "explore"], "terminal": ["code", "ops", "shell"], "text-size": ["font", "size", "text"], "three-bars": ["hamburger", "menu", "dropdown"], "thumbsdown": ["thumb", "thumbsdown", "rejected", "dislike"], "thumbsup": ["thumb", "thumbsup", "prop", "ship", "like"], "tools": ["screwdriver", "wrench", "settings"], "trashcan": ["garbage", "rubbish", "recycle", "delete"], "triangle-down": ["arrow", "point", "direction"], "triangle-left": ["arrow", "point", "direction"], "triangle-right": ["arrow", "point", "direction"], "triangle-up": ["arrow", "point", "direction"], "unfold": ["expand", "open", "reveal"], "unmute": ["loud", "volume", "audio", "sound", "play"], "unsaved": ["unsaved", "bookmark"], "unverified": ["insecure", "untrusted", "signed"], "unwrap": ["lines", "text", "paragraph", "wordwrap", "wrap", "flow"], "verified": ["trusted", "secure", "trustworthy", "signed"], "versions": ["history", "commits"], "watch": ["wait", "hourglass", "time", "date"], "workflow": ["workflow", "actions"], "workflow-all": ["workflow", "actions"], "wrap": ["lines", "text", "paragraph", "wordwrap", "wrap", "flow"], "x": ["remove", "close", "delete"], "zap": ["electricity", "lightning", "props", "like", "star", "save"], "zoom-in": ["zoom", "in", "plus", "bigger"], "zoom-out": ["zoom", "out", "minus", "smaller"] } ================================================ FILE: lib/octicons_gem/.npmignore ================================================ * ================================================ FILE: lib/octicons_gem/Gemfile ================================================ # frozen_string_literal: true source "https://rubygems.org" gemspec group :development, :test do gem "minitest" gem "rake" gem "rubocop", "~> 1.0" gem "rubocop-github", "0.20.0" end ================================================ FILE: lib/octicons_gem/LICENSE ================================================ MIT License Copyright (c) 2026 GitHub Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: lib/octicons_gem/README.md ================================================ # octicons [![Gem version](https://img.shields.io/gem/v/octicons.svg)](https://rubygems.org/gems/octicons) ## Install Add this to your `Gemfile` ```rb gem 'octicons' ``` Then `bundle install`. If using a framework like Rails, please follow the [installation instructions](https://primer.style/view-components/#installation) in the [Primer ViewComponents](https://primer.style/view-components) documentation. ## Usage ```rb require 'octicons' icon = Octicons::Octicon.new("x") icon.to_svg # ``` ## Documentation The `Octicon` class takes two arguments. The first is the symbol of the icon, and the second is a hash of arguments representing html attributes ### `symbol` _(required)_ This is the name of the octicon you want to use. For example `alert`. [Full list of icons](/) ### Options * `:height` - When setting the height to a number, the icon will scale to that size. For example, passing `32`, will calculate the width based on the icon's natural size. * `:width` - When setting the width to a number, the icon will scale to that size. For example, passing `32`, will calculate the width based on the icon's natural size. If both `:width, :height` are passed into the options hash, then the icon will be sized exactly at those dimensions. ### Attributes Once initialized, you can read a few properties from the icon. #### `symbol` Returns the string of the symbol name ```rb icon = Octicons::Octicon.new("x") icon.symbol # "x" ``` #### `path` Path returns the string representation of the path of the icon. ```rb icon = Octicons::Octicon.new("x") icon.path # ``` #### `options` This is a hash of all the `options` that will be added to the output tag. ```rb icon = Octicons::Octicon.new("x") icon.options # {:class=>"octicon octicon-x", :viewBox=>"0 0 12 16", :version=>"1.1", :width=>12, :height=>16, :"aria-hidden"=>"true"} ``` #### `width` Width is the icon's true width. Based on the svg view box width. _Note, this doesn't change if you scale it up with size options, it only is the natural width of the icon_ #### `height` Height is the icon's true height. Based on the svg view box height. _Note, this doesn't change if you scale it up with size options, it only is the natural height of the icon_ #### `keywords` Returns an array of keywords for the icon. The data comes from the [data file in lib](../data.json). Consider contributing more aliases for the icons. ```rb icon = Octicons::Octicon.new("x") icon.keywords # ["remove", "close", "delete"] ``` ### Methods #### `to_svg` Returns a string of the svg tag ```rb icon = Octicons::Octicon.new("x") icon.to_svg # ``` ================================================ FILE: lib/octicons_gem/Rakefile ================================================ # frozen_string_literal: true require "rake/testtask" require "rubocop/rake_task" require "bundler/gem_tasks" RuboCop::RakeTask.new(:lint) do |t| t.options = ["--display-cop-names"] end Rake::TestTask.new do |t| t.libs = ["lib", "test"] t.test_files = FileList["test/*_test.rb"] end task :version, [:v] do |t, args| out = "# frozen_string_literal: true\n\nmodule Octicons\n"\ " VERSION = \"#{args[:v]}\".freeze\n"\ "end" File.open(File.expand_path("../lib/octicons/version.rb", __FILE__), "w") { |file| file.puts out } end desc "Run tests" task default: :test ================================================ FILE: lib/octicons_gem/lib/octicons/octicon.rb ================================================ # frozen_string_literal: true module Octicons class Octicon DEFAULT_HEIGHT = 16 attr_reader :path, :options, :width, :height, :symbol, :keywords def initialize(symbol, options = {}) @symbol = symbol.to_s if octicon = get_octicon(@symbol, options) @path = octicon["path"] @width = octicon["width"] @height = octicon["height"] @keywords = octicon["keywords"] @options = options.dup @options.merge!({ class: classes, viewBox: viewbox, version: "1.1" }) @options.merge!(size) @options.merge!(a11y) else raise "Couldn't find octicon symbol for #{@symbol.inspect}" end end # Returns an string representing a tag def to_svg "#{@path}" end private def html_attributes attrs = "" @options.each { |attr, value| attrs += "#{attr}=\"#{value}\" " } attrs.strip end # add some accessibility features to svg def a11y accessible = {} if @options[:"aria-label"].nil? && @options["aria-label"].nil? accessible[:"aria-hidden"] = "true" else accessible[:role] = "img" end accessible end # prepare the octicon class def classes "octicon octicon-#{@symbol} #{@options[:class]} ".strip end def viewbox "0 0 #{@width} #{@height}" end # determine the height and width of the octicon based on :size option def size size = { width: @width, height: @height } # Specific size unless @options[:width].nil? && @options[:height].nil? size[:width] = @options[:width].nil? ? calculate_width(@options[:height]) : @options[:width] size[:height] = @options[:height].nil? ? calculate_height(@options[:width]) : @options[:height] end size end def calculate_width(height) (height.to_i * @width) / @height end def calculate_height(width) (width.to_i * @height) / @width end def get_octicon(symbol, options = {}) if octicon = Octicons::OCTICON_SYMBOLS[symbol] # We're using width as an approximation for height if the height option is not passed in height = options[:height] || options[:width] || DEFAULT_HEIGHT natural_height = closest_natural_height(octicon["heights"].keys, height) return { "name" => octicon["name"], "keywords" => octicon["keywords"], "width" => octicon["heights"][natural_height.to_s]["width"].to_i, "height" => natural_height, "path" => octicon["heights"][natural_height.to_s]["path"] } end end def closest_natural_height(natural_heights, height) return natural_heights.reduce(natural_heights[0].to_i) do |acc, natural_height| natural_height.to_i <= height.to_i ? natural_height.to_i : acc end end end end ================================================ FILE: lib/octicons_gem/lib/octicons/version.rb ================================================ # frozen_string_literal: true module Octicons VERSION = "19.9.0".freeze end ================================================ FILE: lib/octicons_gem/lib/octicons.rb ================================================ # frozen_string_literal: true require "octicons/version" require "octicons/octicon" require "json" module Octicons file_data = File.read(File.join(File.dirname(__FILE__), "./build/data.json")) OCTICON_SYMBOLS = JSON.parse(file_data).freeze end ================================================ FILE: lib/octicons_gem/octicons.gemspec ================================================ # frozen_string_literal: true require File.expand_path("../lib/octicons/version", __FILE__) Gem::Specification.new do |s| s.name = "octicons" s.version = Octicons::VERSION s.summary = "GitHub's octicons gem" s.platform = Gem::Platform::RUBY s.description = "A package that distributes Octicons in a gem" s.authors = ["GitHub Inc."] s.email = ["support@github.com"] s.files = Dir["{lib}/**/*"] + ["LICENSE", "README.md"] s.homepage = "https://github.com/primer/octicons" s.license = "MIT" end ================================================ FILE: lib/octicons_gem/test/helper.rb ================================================ # frozen_string_literal: true require "minitest/autorun" require "octicons" def octicon(symbol, options = {}) Octicons::Octicon.new(symbol, options) end ================================================ FILE: lib/octicons_gem/test/octicon_test.rb ================================================ # frozen_string_literal: true require_relative "helper" describe Octicons::Octicon do it "fails when the octicon doesn't exist" do assert_raises(RuntimeError) do octicon("octicon") end end it "initialize accepts a string for an icon" do icon = octicon("x") assert icon end it "initialize accepts a symbol for an icon" do icon = octicon(:x) assert icon end it "gets keywords for the icon" do icon = octicon("mark-github") assert_equal ["octocat", "brand", "github", "logo"], icon.keywords end it "the attributes are readable" do icon = octicon("x") assert icon.path assert icon.options assert_equal "x", icon.symbol assert_equal 16, icon.width assert_equal 16, icon.height end describe "viewBox" do it "always has a viewBox" do icon = octicon("x") assert_includes icon.to_svg, "viewBox=\"0 0 16 16\"" end end describe "html_attributes" do it "includes other html attributes" do icon = octicon("x", foo: "bar", disabled: "true") assert_includes icon.to_svg, "disabled=\"true\"" assert_includes icon.to_svg, "foo=\"bar\"" end end describe "classes" do it "includes classes passed in" do icon = octicon("x", class: "text-closed") assert_includes icon.to_svg, "class=\"octicon octicon-x text-closed\"" end end describe "size" do it "always has width and height" do icon = octicon("x") assert_includes icon.to_svg, "height=\"16\"" assert_includes icon.to_svg, "width=\"16\"" end it "converts number string height to integer" do icon = octicon("x", height: "60") assert_includes icon.to_svg, "height=\"60\"" assert_includes icon.to_svg, "width=\"60\"" end it "converts number height to integer" do icon = octicon("x", height: 60) assert_includes icon.to_svg, "height=\"60\"" assert_includes icon.to_svg, "width=\"60\"" end it "converts number string width to integer" do icon = octicon("x", width: "45") assert_includes icon.to_svg, "height=\"45\"" assert_includes icon.to_svg, "width=\"45\"" end it "converts number width to integer" do icon = octicon("x", width: 45) assert_includes icon.to_svg, "height=\"45\"" assert_includes icon.to_svg, "width=\"45\"" end it "with height and width passed in" do icon = octicon("x", width: 60, height: 60) assert_includes icon.to_svg, "width=\"60\"" assert_includes icon.to_svg, "height=\"60\"" end it "chooses the correct svg given a height" do icon = octicon("x", height: 32) assert_includes icon.to_svg, "width=\"32\"" assert_includes icon.to_svg, "height=\"32\"" assert_includes icon.to_svg, "viewBox=\"0 0 24 24\"" end it "chooses the correct svg given a width" do icon = octicon("x", width: 24) assert_includes icon.to_svg, "width=\"24\"" assert_includes icon.to_svg, "height=\"24\"" assert_includes icon.to_svg, "viewBox=\"0 0 24 24\"" end it "chooses the correct svg given a height and width" do icon = octicon("x", height: 24, width: 16) assert_includes icon.to_svg, "width=\"16\"" assert_includes icon.to_svg, "height=\"24\"" assert_includes icon.to_svg, "viewBox=\"0 0 24 24\"" end end describe "a11y" do it "includes attributes for symbol keys" do icon = octicon("x", "aria-label": "Close") assert_includes icon.to_svg, "role=\"img\"" assert_includes icon.to_svg, "aria-label=\"Close\"" refute_includes icon.to_svg, "aria-hidden" end it "includes attributes for string keys" do icon = octicon("x", "aria-label" => "Close") assert_includes icon.to_svg, "role=\"img\"" assert_includes icon.to_svg, "aria-label=\"Close\"" refute_includes icon.to_svg, "aria-hidden" end it "has aria-hidden when no label is passed in" do icon = octicon("x") assert_includes icon.to_svg, "aria-hidden=\"true\"" end end end ================================================ FILE: lib/octicons_gem/test/octicons_test.rb ================================================ # frozen_string_literal: true require_relative "helper" describe Octicons do it "loads all icons on initialization" do refute_equal 0, Octicons::OCTICON_SYMBOLS.length x_icon = Octicons::OCTICON_SYMBOLS["x"] assert x_icon["name"] assert x_icon["keywords"] assert x_icon["heights"] assert x_icon["heights"]["16"] assert x_icon["heights"]["16"]["width"] assert x_icon["heights"]["16"]["path"] end end ================================================ FILE: lib/octicons_helper/.npmignore ================================================ * ================================================ FILE: lib/octicons_helper/Gemfile ================================================ # frozen_string_literal: true source "https://rubygems.org" gemspec gem "octicons", "19.9.0" gem "rails" group :development, :test do gem "minitest", "~> 5.0" gem "rake" gem "rubocop", "~> 1.0" gem "rubocop-github", "0.20.0" end ================================================ FILE: lib/octicons_helper/LICENSE ================================================ MIT License Copyright (c) 2026 GitHub Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: lib/octicons_helper/README.md ================================================ # octicons_helper [![Gem version](https://img.shields.io/gem/v/octicons_helper.svg)](https://rubygems.org/gems/octicons_helper) This rails helper lets you easily include svg octicons in your rails apps. ## Install 1. Add this to your `Gemfile` ```rb gem 'octicons_helper' ``` 3. Use this tag in your erbs ```rb <%= octicon "alert", :height => 32, :class => "right left", :"aria-label" => "hi" %> ``` We recommend including the CSS in the [`@primer/octicons`](/packages/javascript) npm module. You can also npm install that package and include `build/build.css` in your styles. ================================================ FILE: lib/octicons_helper/Rakefile ================================================ # frozen_string_literal: true require "rake/testtask" require "rubocop/rake_task" require "bundler/gem_tasks" RuboCop::RakeTask.new(:lint) do |t| t.options = ["--display-cop-names"] end task :version, [:v] do |t, args| out = "# frozen_string_literal: true\n\nmodule OcticonsHelper\n"\ " VERSION = \"#{args[:v]}\".freeze\n"\ "end" File.open(File.expand_path("../lib/octicons_helper/version.rb", __FILE__), "w") do |file| file.puts out end ["octicons_helper.gemspec", "Gemfile"].each do |filename| gs = File.read(File.expand_path("../#{filename}", __FILE__)) File.open(File.expand_path("../#{filename}", __FILE__), "w") do |file| file.puts gs.gsub(/"octicons", "[^"]+"/, "\"octicons\", \"#{args[:v]}\"") end end end Rake::TestTask.new do |t| t.libs = ["lib", "test"] t.test_files = FileList["test/*_test.rb"] t.warning = false end desc "Run tests" task default: :test ================================================ FILE: lib/octicons_helper/lib/octicons_helper/helper.rb ================================================ # frozen_string_literal: true require "octicons" require "action_view" module OcticonsHelper include ActionView::Helpers::TagHelper mattr_accessor :octicons_helper_cache, default: {} def octicon(symbol, options = {}) return "" if symbol.nil? cache_key = [symbol, options] if tag = octicons_helper_cache[cache_key] tag else icon = Octicons::Octicon.new(symbol, options) tag = content_tag(:svg, icon.path.html_safe, icon.options).freeze # rubocop:disable Rails/OutputSafety octicons_helper_cache[cache_key] = tag tag end end end ================================================ FILE: lib/octicons_helper/lib/octicons_helper/railtie.rb ================================================ # frozen_string_literal: true require "rails" module OcticonsHelper class Railtie < Rails::Railtie initializer "octicons_helper.helper" do ActionView::Base.send :include, OcticonsHelper end end end ================================================ FILE: lib/octicons_helper/lib/octicons_helper/version.rb ================================================ # frozen_string_literal: true module OcticonsHelper VERSION = "19.9.0".freeze end ================================================ FILE: lib/octicons_helper/lib/octicons_helper.rb ================================================ # frozen_string_literal: true require "octicons_helper/version" require "octicons_helper/helper" require "octicons_helper/railtie" if defined?(Rails) ================================================ FILE: lib/octicons_helper/octicons_helper.gemspec ================================================ # frozen_string_literal: true require File.expand_path("../lib/octicons_helper/version", __FILE__) Gem::Specification.new do |s| s.name = "octicons_helper" s.version = OcticonsHelper::VERSION s.summary = "Octicons rails helper" s.description = "A rails helper that makes including svg Octicons simple." s.authors = ["GitHub Inc."] s.email = ["support@github.com"] s.files = Dir["{lib}/**/*"] + ["LICENSE", "README.md"] s.homepage = "https://github.com/primer/octicons" s.license = "MIT" s.require_paths = ["lib"] s.add_dependency "octicons", "19.9.0" s.add_dependency "railties" s.add_dependency "actionview" end ================================================ FILE: lib/octicons_helper/test/helper.rb ================================================ # frozen_string_literal: true require "minitest/autorun" require "minitest/mock" require "octicons_helper" include OcticonsHelper ================================================ FILE: lib/octicons_helper/test/octicons_helper_test.rb ================================================ # frozen_string_literal: true require_relative "helper" describe OcticonsHelper do describe "rendering" do it "renders nothing when no symbol is passed in" do assert_equal "", octicon(nil) end it "renders the svg" do assert_match /.*<\/svg>/, octicon("x") end it "has a path" do assert_match / 1 "foo" end def mock.options; end Octicons::Octicon.stub :new, mock do octicon("alert") octicon("alert") end OcticonsHelper.octicons_helper_cache = {} end end end ================================================ FILE: lib/octicons_jekyll/.npmignore ================================================ * ================================================ FILE: lib/octicons_jekyll/.rubocop.yml ================================================ inherit_gem: rubocop-github: - config/default.yml Naming/FileName: Enabled: false Style/OneClassPerFile: Exclude: - "lib/jekyll-octicons/version.rb" AllCops: NewCops: enable ================================================ FILE: lib/octicons_jekyll/Gemfile ================================================ # frozen_string_literal: true source "https://rubygems.org" gemspec gem "octicons", "19.8.0" group :development, :test do gem "minitest" gem "rake" gem "rubocop", "~> 1.0" gem "rubocop-github", "0.20.0" end ================================================ FILE: lib/octicons_jekyll/LICENSE ================================================ MIT License Copyright (c) 2026 GitHub Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: lib/octicons_jekyll/README.md ================================================ # jekyll-octicons [![Gem version](https://img.shields.io/gem/v/jekyll-octicons.svg)](https://rubygems.org/gems/jekyll-octicons) The Jekyll liquid tag is a plugin that lets you include octicons in your Jekyll sites. ## Install 1. Add this to your `Gemfile` ```rb gem 'jekyll-octicons' ``` 2. Add this to your jekyll `_config.yml` ```yml plugins: - jekyll-octicons ``` 3. Use this tag in your jekyll templates ``` {% octicon alert height:32 class:"right left" aria-label:hi %} ``` We recommend including the CSS in the [`@primer/octicons`](/packages/javascript) npm module. You can also npm install that package and include `build/build.css` in your styles. ================================================ FILE: lib/octicons_jekyll/Rakefile ================================================ # frozen_string_literal: true require "rake/testtask" require "rubocop/rake_task" require "bundler/gem_tasks" RuboCop::RakeTask.new(:lint) do |t| t.options = ["--display-cop-names"] end task :version, [:v] => :environment do |t, args| out = "# frozen_string_literal: true\n\n# Prevent bundler errors\n"\ "module Liquid; class Tag; end; end\n\n"\ "module Jekyll\n"\ " class Octicons < Liquid::Tag\n"\ " VERSION = \"#{args[:v]}\".freeze\n"\ " end\n"\ "end" File.open(File.expand_path("../lib/jekyll-octicons/version.rb", __FILE__), "w") do |file| file.puts out end ["jekyll-octicons.gemspec", "Gemfile"].each do |filename| gs = File.read(File.expand_path("../#{filename}", __FILE__)) File.open(File.expand_path("../#{filename}", __FILE__), "w") do |file| file.puts gs.gsub(/"octicons", "[^"]+"/, "\"octicons\", \"#{args[:v]}\"") end end end Rake::TestTask.new do |t| t.libs = ["lib", "test"] t.test_files = FileList["test/*_test.rb"] t.warning = false end desc "Run tests" task default: :test ================================================ FILE: lib/octicons_jekyll/jekyll-octicons.gemspec ================================================ # frozen_string_literal: true require File.expand_path("../lib/jekyll-octicons/version", __FILE__) Gem::Specification.new do |s| s.name = "jekyll-octicons" s.version = Jekyll::Octicons::VERSION s.summary = "Octicons jekyll liquid tag" s.description = "A jekyll liquid plugin that makes including svg Octicons simple." s.authors = ["GitHub Inc."] s.email = ["support@github.com"] s.files = Dir["{lib}/**/*"] + ["LICENSE", "README.md"] s.homepage = "https://github.com/primer/octicons" s.license = "MIT" s.require_paths = ["lib"] s.add_dependency "jekyll", ">= 3.6", "< 5.0" s.add_dependency "octicons", "19.8.0" end ================================================ FILE: lib/octicons_jekyll/lib/jekyll-octicons/version.rb ================================================ # frozen_string_literal: true # Prevent bundler errors module Liquid; class Tag; end; end module Jekyll class Octicons < Liquid::Tag VERSION = "19.8.0".freeze end end ================================================ FILE: lib/octicons_jekyll/lib/jekyll-octicons.rb ================================================ # frozen_string_literal: true require "octicons" require "jekyll-octicons/version" require "liquid" require "jekyll/liquid_extensions" module Jekyll class Octicons < Liquid::Tag include Jekyll::LiquidExtensions # Syntax for the octicon symbol Syntax = /\A(#{Liquid::VariableSignature}+)/ # For interpolation, look for liquid variables Variable = /\{\{\s*([\w]+\.?[\w]*)\s*\}\}/i # Copied from Liquid::TagAttributes to allow dashes in tag names: # # {% octicon alert area-label:"Hello World!" %} # TagAttributes = /([\w-]+)\s*\:\s*(#{Liquid::QuotedFragment})/o def initialize(tag_name, markup, options) super @markup = markup # If there's interpolation going on, we need to do this in render prepare(markup) unless match = markup.match(Variable) end def render(context) prepare(interpolate(@markup, context)) if match = @markup.match(Variable) return nil if @symbol.nil? ::Octicons::Octicon.new(@symbol, @options).to_svg end private def interpolate(markup, context) markup.scan Variable do |variable| markup = markup.gsub(Variable, lookup_variable(context, variable.first)) end markup end def prepare(markup) @symbol = symbol(markup) @options = string_to_hash(markup) end def symbol(markup) if match = markup.match(Syntax) match[1] end end # Create a ruby hash from a string passed by the jekyll tag def string_to_hash(markup) options = {} if match = markup.match(Syntax) markup.scan(TagAttributes) do |key, value| options[key.to_sym] = value.gsub(/\A"|"\z/, "") end end options end end end Liquid::Template.register_tag("octicon", Jekyll::Octicons) ================================================ FILE: lib/octicons_jekyll/test/helper.rb ================================================ # frozen_string_literal: true require "minitest/autorun" require "jekyll-octicons" # Parse a string into a liquid template # rubocop:disable Rails/Delegate def parse(string) Liquid::Template.parse(string) end # rubocop:enable Rails/Delegate # Parse and render a string def render(string, assigns = {}) parse(string).render!(assigns) end ================================================ FILE: lib/octicons_jekyll/test/octicon_tag_test.rb ================================================ # frozen_string_literal: true require_relative "helper" describe Jekyll::Octicons do describe "parsing" do it "parses the tag options" do output = render("{% octicon mark-github height:32 class:\"left right\" aria-label:hi %}") assert_match /height="32"/, output assert_match /class="[^"]+ left right/, output assert_match /aria-label="hi"/, output end it "parses interpolation of variables" do template = render("{% assign symbol = \"mark-github\" %}{% octicon {{ symbol }} %}") assert_match /', // options: { // version: '1.1', // width: '16', // height: '16', // viewBox: '0 0 16 16', // class: 'octicon octicon-alert', // 'aria-hidden': 'true' // }, // }, // 24: ... // } // } ``` There will be a key for every icon, with [`toSVG`](#octiconsnametosvg) and other properties. _Note: `alert` in the above example can be replaced with any valid icon name. Icons with multi-word names (e.g. `arrow-right`) **cannot** be accessed using dot notation (e.g. `octicons.alert`). Instead, use bracket notation (e.g. `octicons['arrow-right']`)._ ### `octicons[name].symbol` Returns the string of the symbol name, same as the key for that icon. ```js octicons.x.symbol // "x" ``` ### `octicons[name].keywords` Returns an array of keywords for the icon. The data comes from [keywords.json](https://github.com/primer/octicons/blob/main/keywords.json). Consider contributing more aliases for the icons. ```js octicons.x.keywords // ["remove", "close", "delete"] ``` ### `octicons[name].heights` Each icon can have multiple SVGs that are designed for different sizes. The `heights` property allows you to access all the SVGs for an icon using the natural height of the SVG. ```js octicons.x.heights // { // 16: { // width: 16, // path: '', // options: { // version: '1.1', // width: '16', // height: '16', // viewBox: '0 0 16 16', // class: 'octicon octicon-alert', // 'aria-hidden': 'true' // }, // }, // 24: { // width: 24, // path: '', // options: { // version: '1.1', // width: '24', // height: '24', // viewBox: '0 0 24 24', // class: 'octicon octicon-alert', // 'aria-hidden': 'true' // }, // }, // } ``` ### `octicons[name].heights[height].width` Returns the icon's true width, based on the SVG view box width. _Note, this doesn't change if you scale it up with size options, it only is the natural width of the icon._ ### `octicons[name].heights[height].path` Returns the string representation of the path of the icon. ```js octicons.x.heights[16].path // ``` ### `octicons[name].heights[height].options` This is an object of all the attributes that will be added to the output tag. ```js octicons.x.heights[16].options // { version: '1.1', width: '12', height: '16', viewBox: '0 0 12 16', class: 'octicon octicon-x', 'aria-hidden': 'true' } ``` ### `octicons[name].toSVG()` Returns a string of the `` tag. ```js octicons.x.toSVG() // ``` The `.toSVG()` method accepts an optional `options` object. This is used to add CSS class names, accessibility options, and sizes. #### class Add more CSS classes to the `` tag. ```js octicons.x.toSVG({ "class": "close" }) // ``` #### aria-label Add accessibility `aria-label` to the icon. ```js octicons.x.toSVG({ "aria-label": "Close the window" }) // ``` #### width and height Size the SVG icon larger using `width` and `height` independently or together. `.toSVG()` will automatically choose the best SVG to render based on the width or height passed in. ```js octicons.x.toSVG({ "width": 45 }) // ``` [primer]: https://github.com/primer/primer [docs]: http://primercss.io/ [npm]: https://www.npmjs.com/ [install-npm]: https://docs.npmjs.com/getting-started/installing-node [sass]: http://sass-lang.com/ ================================================ FILE: lib/octicons_node/index.js ================================================ const data = require('./build/data.json') const objectAssign = require('object-assign') const DEFAULT_HEIGHT = 16 for (const key of Object.keys(data)) { // Returns a string representation of html attributes const htmlAttributes = (icon, defaultOptions, options) => { const attributes = [] const attrObj = objectAssign({}, defaultOptions, options) // If the user passed in options if (options) { // If any of the width or height is passed in if (options['width'] || options['height']) { attrObj['width'] = options['width'] ? options['width'] : (parseInt(options['height']) * defaultOptions['width']) / defaultOptions['height'] attrObj['height'] = options['height'] ? options['height'] : (parseInt(options['width']) * defaultOptions['height']) / defaultOptions['width'] } // If the user passed in class if (options['class']) { attrObj['class'] = `octicon octicon-${key} ${options['class']}` attrObj['class'].trim() } // If the user passed in aria-label if (options['aria-label']) { attrObj['aria-label'] = options['aria-label'] attrObj['role'] = 'img' // Un-hide the icon delete attrObj['aria-hidden'] } } for (const option of Object.keys(attrObj)) { attributes.push(`${option}="${attrObj[option]}"`) } return attributes.join(' ').trim() } // Set the symbol for easy access data[key].symbol = key // Set options for each icon height for (const height of Object.keys(data[key].heights)) { data[key].heights[height].options = { version: '1.1', width: data[key].heights[height].width, height: parseInt(height), viewBox: `0 0 ${data[key].heights[height].width} ${height}`, class: `octicon octicon-${key}`, 'aria-hidden': 'true' } } // Function to return an SVG object data[key].toSVG = function (options = {}) { const {height, width} = options const naturalHeight = closestNaturalHeight(Object.keys(data[key].heights), height || width || DEFAULT_HEIGHT) return `${ data[key].heights[naturalHeight].path }` } } // Import data into exports module.exports = data function closestNaturalHeight(naturalHeights, height) { return naturalHeights .map(naturalHeight => parseInt(naturalHeight, 10)) .reduce((acc, naturalHeight) => (naturalHeight <= height ? naturalHeight : acc), naturalHeights[0]) } ================================================ FILE: lib/octicons_node/index.scss ================================================ .octicon { display: inline-block; vertical-align: text-top; fill: currentColor; overflow: visible; } ================================================ FILE: lib/octicons_node/package.json ================================================ { "name": "@primer/octicons", "version": "19.23.1", "description": "A scalable set of icons handcrafted with <3 by GitHub.", "homepage": "https://primer.style/octicons", "author": "GitHub Inc.", "license": "MIT", "style": "index.scss", "main": "index.js", "files": [ "index.js", "index.scss", "build" ], "repository": "https://github.com/primer/octicons.git", "bugs": { "url": "https://github.com/primer/octicons/issues" }, "scripts": { "build": "\\cp -r ../build/. ./build && \\cp index.scss ./build/build.css", "lint": "eslint index.js tests/*.js", "test": "ava --verbose 'tests/*.js'" }, "keywords": [ "GitHub", "icons", "svg", "octicons" ], "dependencies": { "object-assign": "^4.1.1" }, "devDependencies": { "@github/prettier-config": "0.0.4", "ava": "^0.22.0", "eslint": "^6.5.1", "eslint-plugin-github": "4.1.3" }, "eslintConfig": { "extends": [ "plugin:github/internal", "plugin:github/recommended" ], "env": { "es6": true, "node": true }, "parserOptions": { "ecmaVersion": 2017, "requireConfigFile": false }, "rules": { "github/no-then": 0 } } } ================================================ FILE: lib/octicons_node/prettier.config.js ================================================ module.exports = require('@github/prettier-config') ================================================ FILE: lib/octicons_node/tests/index.js ================================================ import test from 'ava' import octicons from '../' test('Octicons are loaded', t => { t.truthy(octicons, "Didn't find any octicons.") t.not(Object.keys(octicons).length, 0, "Didn't find any octicons.") }) test('Octicons have svg', t => { t.truthy(octicons, "Didn't find any octicons.") for (const point of Object.keys(octicons)) { t.truthy(octicons[point].toSVG(), `The octicon "${point}" doesn't have svg`) } }) test('Octicons have default html attributes', t => { t.truthy(octicons, "Didn't find any octicons.") for (const point of Object.keys(octicons)) { const svg = octicons[point].toSVG() t.regex(svg, /version="1\.1"/, `The octicon "${point}" doesn't have the version attribute`) t.regex(svg, /aria-hidden="true"/, `The octicon "${point}" doesn't have the aria-hidden attribute`) t.regex(svg, new RegExp(`width=`), `The octicon "${point}" doesn't have the width attribute`) t.regex(svg, new RegExp(`height=`), `The octicon "${point}" doesn't have the height attribute`) t.regex(svg, new RegExp(`viewBox=`), `The octicon "${point}" doesn't have the viewBox attribute`) t.regex( svg, new RegExp(`class="octicon octicon-${octicons[point].symbol}"`), `The octicon "${point}" doesn't have the class attribute` ) } }) test('Passing in classnames will be included in output', t => { t.truthy(octicons, "Didn't find any octicons.") for (const point of Object.keys(octicons)) { const svg = octicons[point].toSVG({class: 'new-class another-class'}) t.regex( svg, new RegExp(`class="octicon octicon-${octicons[point].symbol} new-class another-class"`), `The octicon "${point}" doesn't have the class attribute` ) } }) test('Passing in aria-label will update the a11y options', t => { t.truthy(octicons, "Didn't find any octicons.") for (const point of Object.keys(octicons)) { const svg = octicons[point].toSVG({'aria-label': 'This is an icon'}) t.regex( svg, new RegExp('aria-label="This is an icon"'), `The octicon "${point}" doesn't have the aria-label attribute` ) } }) test('Passing in width will size properly', t => { const svg = octicons['x'].toSVG({height: 60}) t.regex(svg, new RegExp('width="60"'), 'The octicon "x" doesn\'t have the width attribute scaled properly') }) test('Passing in height will size properly', t => { const svg = octicons['x'].toSVG({width: 45}) t.regex(svg, new RegExp('height="45"'), 'The octicon "x" doesn\'t have the height attribute scaled properly') }) test('Passing in height will size properly', t => { const svg = octicons['x'].toSVG({width: 45}) t.regex(svg, new RegExp('height="45"'), 'The octicon "x" doesn\'t have the height attribute scaled properly') }) test('Chooses the correct svg given a height', t => { const svg = octicons['x'].toSVG({height: 32}) t.regex(svg, new RegExp('width="32"')) t.regex(svg, new RegExp('height="32"')) t.regex(svg, new RegExp('viewBox="0 0 24 24"')) }) test('Chooses the correct svg given a width', t => { const svg = octicons['x'].toSVG({width: 24}) t.regex(svg, new RegExp('width="24"')) t.regex(svg, new RegExp('height="24"')) t.regex(svg, new RegExp('viewBox="0 0 24 24"')) }) test('Chooses the correct svg given a width and height', t => { const svg = octicons['x'].toSVG({width: 16, height: 24}) t.regex(svg, new RegExp('width="16"')) t.regex(svg, new RegExp('height="24"')) t.regex(svg, new RegExp('viewBox="0 0 24 24"')) }) ================================================ FILE: lib/octicons_react/.eslintignore ================================================ src/__generated__/ ================================================ FILE: lib/octicons_react/.eslintrc.json ================================================ { "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaFeatures": { "jsx": true } }, "extends": [ "plugin:react/recommended", "plugin:jsx-a11y/recommended", "plugin:prettier/recommended", "plugin:github/recommended", "plugin:github/browser" ], "rules": { "github/no-then": 0, "import/named": 0, "react/prop-types": 0 }, "env": { "browser": true, "commonjs": true, "es6": true, "jest": true, "node": true }, "settings": { "react": { "version": "16" } } } ================================================ FILE: lib/octicons_react/.gitignore ================================================ .cache .next dist/ src/__generated__/ .tool-versions ================================================ FILE: lib/octicons_react/.npmignore ================================================ *.config.js .*.sw? .*rc .cache .eslint* .gitignore .next script src **/pages/** **/__tests__/** **/ts-tests/** ================================================ FILE: lib/octicons_react/.nvmrc ================================================ 8 ================================================ FILE: lib/octicons_react/LICENSE ================================================ MIT License Copyright (c) 2026 GitHub Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: lib/octicons_react/README.md ================================================ # @primer/octicons-react [![npm version](https://img.shields.io/npm/v/@primer/octicons-react.svg)](https://www.npmjs.org/package/@primer/octicons-react) ## Install ```shell npm install @primer/octicons-react ``` ## Usage ### Icons The `@primer/octicons-react` module exports individual icons as [named exports](https://ponyfoo.com/articles/es6-modules-in-depth#named-exports). This allows you to import only the icons that you need without blowing up your bundle: ```jsx import React from 'react' import {BeakerIcon, ZapIcon} from '@primer/octicons-react' export default function Icon({boom}) { return boom ? : } ``` If you were to compile this example with a tool that supports [tree-shaking][] (such as Webpack, Rollup, or Parcel) the resulting bundle would only include the "zap" and "beaker" icons. ### Vertical alignment By default the octicons have `vertical-align: text-bottom;` applied as inline styles. You can change the alignment via the `verticalAlign` prop, which can be either `middle`, `text-bottom`, `text-top`, or `top`. ```js import {RepoIcon} from '@primer/octicons-react' export default () => (

github/github

) ``` ### `aria-label` You have the option of adding accessibility information to the icon with the [`aria-label` attribute][aria-label] via the `aria-label` prop. ```js // Example usage import {PlusIcon} from '@primer/octicons-react' export default () => ( ) ``` ### `aria-labelledby` You have the option of adding accessibility information to the icon with the [`aria-labelledby` attribute][aria-labelledby] via the `aria-labelledby` prop. Using aria-labelledby referencing the id values of the title element provides the accessible name. ```js // Example usage import {PlusIcon} from '@primer/octicons-react' export default () => ( ) ``` ### `title` You have the option of adding accessibility information to the icon with the [`title` attribute][title] via the `title` prop. ### `id` You have the option of adding information to the icon with the [`id` attribute][id] via the `id` prop. ```js // Example usage import {PlusIcon} from '@primer/octicons-react' export default () => ( ) ``` ### `tabIndex` You can add the `tabindex` attribute to an SVG element via the `tabIndex` prop if the SVG element is intended to be interactive. `tabIndex` prop also controls the `focusable` attribute of the SVG element which is defined by SVG Tiny 1.2 and only implemented in Internet Explorer and Microsoft Edge. If there is no `tabIndex` prop is present (default behavior), it will set the `focusable` attribute to `false`. This is helpful for preventing the decorative SVG from being announced by some specialized assistive technology browsing modes which can get delayed while trying to parse the SVG markup. ```js // Example usage import {PlusIcon} from '@primer/octicons-react' export default () => ( New Item ) ``` ### Sizes The `size` prop takes `small`, `medium`, and `large` values that can be used to render octicons at standard sizes: | Prop | Rendered Size | | :-------------- | :------------------------------ | | `size='small'` | 16px height by `computed` width | | `size='medium'` | 32px height by `computed` width | | `size='large'` | 64px height by `computed` width | ```js // Example usage import {LogoGithubIcon} from '@primer/octicons-react' export default () => (

) ``` ### Fill The `fill` prop takes a string value that can be used to set the color of the icon. By default, `fill` is set to [`currentColor`](https://css-tricks.com/currentcolor/). ```js // Example usage import {LogoGithub} from '@primer/octicons-react' export default () => (

) ``` [octicons]: https://primer.style/octicons/ [primer]: https://github.com/primer/primer [docs]: http://primercss.io/ [npm]: https://www.npmjs.com/ [install-npm]: https://docs.npmjs.com/getting-started/installing-node [tree-shaking]: https://developer.mozilla.org/en-US/docs/Glossary/Tree_shaking [aria-label]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label [aria-labelledby]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-labelledby [title]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/title [id]: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/id ================================================ FILE: lib/octicons_react/__tests__/__snapshots__/public-api.test.js.snap ================================================ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`@primer/octicons-react should not update exports without a semver change 1`] = ` [ "AccessibilityIcon", "AccessibilityInsetIcon", "AgentIcon", "AiModelIcon", "AlertFillIcon", "AlertIcon", "AppsIcon", "ArchiveIcon", "ArrowBothIcon", "ArrowDownIcon", "ArrowDownLeftIcon", "ArrowDownRightIcon", "ArrowLeftIcon", "ArrowRightIcon", "ArrowSwitchIcon", "ArrowUpIcon", "ArrowUpLeftIcon", "ArrowUpRightIcon", "BeakerIcon", "BellFillIcon", "BellIcon", "BellSlashIcon", "BlockedIcon", "BoldIcon", "BookIcon", "BookLockedIcon", "BookmarkFillIcon", "BookmarkFilledIcon", "BookmarkIcon", "BookmarkSlashFillIcon", "BookmarkSlashIcon", "BooleanOffIcon", "BooleanOnIcon", "BriefcaseIcon", "BroadcastIcon", "BrowserIcon", "BugIcon", "CacheIcon", "CalendarIcon", "CheckCircleFillIcon", "CheckCircleIcon", "CheckIcon", "CheckboxFillIcon", "CheckboxIcon", "ChecklistIcon", "ChevronDownIcon", "ChevronLeftIcon", "ChevronRightIcon", "ChevronUpIcon", "CircleIcon", "CircleSlashIcon", "ClockFillIcon", "ClockIcon", "CloudIcon", "CloudOfflineIcon", "CodeIcon", "CodeOfConductIcon", "CodeReviewIcon", "CodeSquareIcon", "CodescanCheckmarkIcon", "CodescanIcon", "CodespacesIcon", "ColumnsIcon", "CommandPaletteIcon", "CommentAiIcon", "CommentDiscussionIcon", "CommentIcon", "CommentLockedIcon", "ComposeIcon", "ContainerIcon", "CopilotErrorIcon", "CopilotIcon", "CopilotWarningIcon", "CopyIcon", "CpuIcon", "CreditCardIcon", "CrossReferenceIcon", "CrosshairsIcon", "DashIcon", "DatabaseIcon", "DependabotIcon", "DesktopDownloadIcon", "DeviceCameraIcon", "DeviceCameraVideoIcon", "DeviceDesktopIcon", "DeviceMobileIcon", "DevicesIcon", "DiamondIcon", "DiceIcon", "DiffAddedIcon", "DiffIcon", "DiffIgnoredIcon", "DiffModifiedIcon", "DiffRemovedIcon", "DiffRenamedIcon", "DiscussionClosedIcon", "DiscussionDuplicateIcon", "DiscussionOutdatedIcon", "DotFillIcon", "DotIcon", "DownloadIcon", "DuplicateIcon", "EllipsisIcon", "ExclamationIcon", "EyeClosedIcon", "EyeIcon", "FeedDiscussionIcon", "FeedForkedIcon", "FeedHeartIcon", "FeedIssueClosedIcon", "FeedIssueDraftIcon", "FeedIssueOpenIcon", "FeedIssueReopenIcon", "FeedMergedIcon", "FeedPersonIcon", "FeedPlusIcon", "FeedPublicIcon", "FeedPullRequestClosedIcon", "FeedPullRequestDraftIcon", "FeedPullRequestOpenIcon", "FeedRepoIcon", "FeedRocketIcon", "FeedStarIcon", "FeedTagIcon", "FeedTrophyIcon", "FileAddedIcon", "FileBadgeIcon", "FileBinaryIcon", "FileCheckIcon", "FileCodeIcon", "FileDiffIcon", "FileDirectoryFillIcon", "FileDirectoryIcon", "FileDirectoryOpenFillIcon", "FileDirectorySymlinkIcon", "FileIcon", "FileMediaIcon", "FileMovedIcon", "FileRemovedIcon", "FileSubmoduleIcon", "FileSymlinkFileIcon", "FileZipIcon", "FilterIcon", "FilterRemoveIcon", "FiscalHostIcon", "FlameIcon", "FlowchartIcon", "FocusCenterIcon", "FoldDownIcon", "FoldIcon", "FoldUpIcon", "GearIcon", "GiftIcon", "GitBranchCheckIcon", "GitBranchIcon", "GitCommitIcon", "GitCompareIcon", "GitMergeIcon", "GitMergeQueueIcon", "GitPullRequestClosedIcon", "GitPullRequestDraftIcon", "GitPullRequestIcon", "GitPullRequestLockedIcon", "GlobeIcon", "GoalIcon", "GrabberIcon", "GraphBarHorizontalIcon", "GraphBarVerticalIcon", "GraphIcon", "HashIcon", "HeadingIcon", "HeartFillIcon", "HeartIcon", "HistoryIcon", "HomeFillIcon", "HomeIcon", "HorizontalRuleIcon", "HourglassIcon", "HubotIcon", "IdBadgeIcon", "ImageIcon", "InboxFillIcon", "InboxIcon", "InfinityIcon", "InfoIcon", "IssueClosedIcon", "IssueDraftIcon", "IssueLockedIcon", "IssueOpenedIcon", "IssueReopenedIcon", "IssueTrackedByIcon", "IssueTracksIcon", "ItalicIcon", "IterationsIcon", "KebabHorizontalIcon", "KeyAsteriskIcon", "KeyIcon", "LawIcon", "LightBulbIcon", "LinkExternalIcon", "LinkIcon", "ListOrderedIcon", "ListUnorderedIcon", "LocationIcon", "LockIcon", "LockupGithubIcon", "LogIcon", "LogoGistIcon", "LogoGithubIcon", "LoopIcon", "MailIcon", "MarkGithubIcon", "MarkdownIcon", "MaximizeIcon", "McpIcon", "MegaphoneIcon", "MentionIcon", "MeterIcon", "MilestoneIcon", "MinimizeIcon", "MirrorIcon", "MoonIcon", "MortarBoardIcon", "MoveToBottomIcon", "MoveToEndIcon", "MoveToStartIcon", "MoveToTopIcon", "MultiSelectIcon", "MuteIcon", "NoEntryFillIcon", "NoEntryIcon", "NodeIcon", "NorthStarIcon", "NoteIcon", "NumberIcon", "OrganizationIcon", "PackageDependenciesIcon", "PackageDependentsIcon", "PackageIcon", "PaintbrushIcon", "PaperAirplaneIcon", "PaperclipIcon", "PasskeyFillIcon", "PasteIcon", "PauseIcon", "PencilAiIcon", "PencilIcon", "PeopleIcon", "PersonAddIcon", "PersonFillIcon", "PersonIcon", "PinIcon", "PinSlashIcon", "PivotColumnIcon", "PlayIcon", "PlugIcon", "PlusCircleIcon", "PlusIcon", "ProjectIcon", "ProjectRoadmapIcon", "ProjectSymlinkIcon", "ProjectTemplateIcon", "PulseIcon", "QuestionIcon", "QuoteIcon", "ReadIcon", "RedoIcon", "RelFilePathIcon", "ReplyIcon", "RepoCloneIcon", "RepoDeleteIcon", "RepoDeletedIcon", "RepoForkedIcon", "RepoIcon", "RepoLockedIcon", "RepoPullIcon", "RepoPushIcon", "RepoTemplateIcon", "ReportIcon", "RocketIcon", "RowsIcon", "RssIcon", "RubyIcon", "ScreenFullIcon", "ScreenNormalIcon", "SearchIcon", "ServerIcon", "ShareAndroidIcon", "ShareIcon", "ShieldCheckIcon", "ShieldIcon", "ShieldLockIcon", "ShieldSlashIcon", "ShieldXIcon", "SidebarCollapseIcon", "SidebarExpandIcon", "SignInIcon", "SignOutIcon", "SingleSelectIcon", "SkipFillIcon", "SkipIcon", "SlidersIcon", "SmileyFrownIcon", "SmileyFrustratedIcon", "SmileyGrinIcon", "SmileyIcon", "SmileyNeutralIcon", "SortAscIcon", "SortDescIcon", "SpaceIcon", "SpacingLargeIcon", "SpacingMediumIcon", "SpacingSmallIcon", "SparkleFillIcon", "SparkleIcon", "SparklesFillIcon", "SplitViewIcon", "SponsorTiersIcon", "SquareCircleIcon", "SquareFillIcon", "SquareIcon", "SquirrelIcon", "StackIcon", "StarFillIcon", "StarIcon", "StopIcon", "StopwatchIcon", "StrikethroughIcon", "SunIcon", "SyncIcon", "TabExternalIcon", "TabIcon", "TableIcon", "TagIcon", "TasklistIcon", "TelescopeFillIcon", "TelescopeIcon", "TerminalIcon", "ThreeBarsIcon", "ThumbsdownIcon", "ThumbsupIcon", "ToolsIcon", "TrackedByClosedCompletedIcon", "TrackedByClosedNotPlannedIcon", "TrashIcon", "TriangleDownIcon", "TriangleLeftIcon", "TriangleRightIcon", "TriangleUpIcon", "TrophyIcon", "TypographyIcon", "UndoIcon", "UnfoldIcon", "UnlinkIcon", "UnlockIcon", "UnmuteIcon", "UnreadIcon", "UnverifiedIcon", "UnwrapIcon", "UploadIcon", "VerifiedIcon", "VersionsIcon", "VideoIcon", "VscodeIcon", "WebhookIcon", "WorkflowIcon", "WrapIcon", "XCircleFillIcon", "XCircleIcon", "XIcon", "ZapIcon", "ZoomInIcon", "ZoomOutIcon", ] `; ================================================ FILE: lib/octicons_react/__tests__/public-api.test.js ================================================ import * as Octicons from '../' describe('@primer/octicons-react', () => { it('should not update exports without a semver change', () => { expect(Object.keys(Octicons).sort()).toMatchSnapshot() }) }) ================================================ FILE: lib/octicons_react/__tests__/tree-shaking.test.js ================================================ const path = require('node:path') const commonjs = require('@rollup/plugin-commonjs') const {nodeResolve} = require('@rollup/plugin-node-resolve') const {rollup} = require('rollup') const virtual = require('@rollup/plugin-virtual') const packageImport = path.resolve(__dirname, '..') test('tree shaking', async () => { const bundle = await rollup({ input: '__entrypoint__', external: [], plugins: [ nodeResolve(), commonjs(), virtual({ __entrypoint__: `import { AlertIcon } from '${packageImport}'` }) ], onwarn: ({code, message}) => { if (code !== 'EMPTY_BUNDLE') { throw new Error(message) } } }) const {output} = await bundle.generate({ format: 'esm' }) for (const {code} of output) { expect(code.trim()).toBe('') } }) test('tree shaking single export', async () => { const bundle = await rollup({ input: '__entrypoint__', external: ['react'], plugins: [ nodeResolve(), commonjs(), virtual({ __entrypoint__: `export { XIcon } from '${packageImport}'` }) ] }) const {output} = await bundle.generate({ format: 'esm' }) const bundleSize = Buffer.byteLength(output[0].code.trim()) / 1000 expect(`${bundleSize}kB`).toMatchInlineSnapshot(`"6.084kB"`) }) ================================================ FILE: lib/octicons_react/babel.config.js ================================================ 'use strict' module.exports = { presets: [ [ '@babel/preset-env', { targets: { node: 'current' } } ], '@babel/preset-react' ], env: { production: { presets: ['next/babel'] } } } ================================================ FILE: lib/octicons_react/jest.config.js ================================================ 'use strict' module.exports = { moduleNameMapper: { '^rollup$': require.resolve('rollup') }, testEnvironment: 'jsdom', transform: { '^.+\\.(mjs|cjs|js|jsx)$': require.resolve('babel-jest') } } ================================================ FILE: lib/octicons_react/next.config.mjs ================================================ /** @type {import('next').NextConfig} */ const nextConfig = { reactStrictMode: true, transpilePackages: ['@primer/components'], pageExtensions: ['js', 'jsx', 'mjs', 'ts', 'tsx'], } export default nextConfig ================================================ FILE: lib/octicons_react/package.json ================================================ { "name": "@primer/octicons-react", "version": "19.23.1", "description": "A scalable set of icons handcrafted with <3 by GitHub.", "homepage": "https://primer.style/octicons", "author": "GitHub, Inc.", "license": "MIT", "type": "commonjs", "main": "dist/index.umd.js", "module": "dist/index.esm.mjs", "exports": { "types": { "import": "./dist/index.d.mts", "require": "./dist/index.d.ts" }, "import": "./dist/index.esm.mjs", "require": "./dist/index.umd.js" }, "sideEffects": false, "types": "dist/index.d.ts", "repository": "primer/octicons", "scripts": { "build": "script/build.js && script/types.js && rollup -c", "clean": "rimraf .next dist src/__generated__", "develop": "next", "lint": "eslint src pages/*.mjs script", "test": "jest", "ts-test": "tsc -P ts-tests", "posttest": "yarn ts-test" }, "files": [ "dist" ], "keywords": [ "GitHub", "icons", "svg", "octicons", "react", "primer" ], "devDependencies": { "@babel/core": "^7.22.0", "@babel/generator": "^7.22.0", "@babel/preset-env": "^7.22.0", "@babel/preset-react": "^7.22.0", "@babel/types": "^7.22.0", "@github/prettier-config": "0.0.4", "@primer/components": "27.0.0", "@rollup/plugin-babel": "5.3.1", "@rollup/plugin-commonjs": "22.0.2", "@rollup/plugin-node-resolve": "14.1.0", "@rollup/plugin-virtual": "2.1.0", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@types/react": "^18.2.0", "babel-jest": "29.0.3", "eslint": "^6.5.1", "eslint-plugin-github": "4.1.3", "eslint-plugin-jest": "^21.17.0", "eslint-plugin-jsx-a11y": "6.4.1", "eslint-plugin-react": "7.23.2", "fs-extra": "^6.0.1", "jest": "^29.0.3", "jest-environment-jsdom": "29.0.3", "next": "^16.1.5", "react": "^18.2.0", "react-dom": "^18.2.0", "rimraf": "3.0.2", "rollup": "^2.79.0", "styled-components": "^4.2.0", "typescript": "^4.8.3" }, "peerDependencies": { "react": ">=16.3" }, "engines": { "node": ">=8" } } ================================================ FILE: lib/octicons_react/pages/_document.mjs ================================================ import React from 'react' import Document, {Head, Html, Main, NextScript} from 'next/document' export default class PrimerDocument extends Document { render() { return (
) } } ================================================ FILE: lib/octicons_react/pages/index.mjs ================================================ import React from 'react' import {Box, Text} from '@primer/components' import pkg from '../package.json' // eslint-disable-next-line import/no-namespace import * as Octicons from '../' // eslint-disable-next-line no-unused-vars, import/namespace const {default: _Octicon, ...iconsByName} = Octicons export default function App() { const sizes = ['small', 'medium', 'large'] return ( {Object.keys(iconsByName).map(key => { const Icon = iconsByName[key] const iconName = Icon.displayName || key return ( ) })}
key import small, medium, large code sample
{key} {iconName} {sizes.map(size => ( ))}
                    {`
import {${iconName}} from '${pkg.name}'
export default () => <${iconName} />
                  `.trim()}
                  
) } ================================================ FILE: lib/octicons_react/prettier.config.js ================================================ module.exports = require('@github/prettier-config') ================================================ FILE: lib/octicons_react/rollup.config.js ================================================ import babel from '@rollup/plugin-babel' import commonjs from '@rollup/plugin-commonjs' import packageJson from './package.json' const dependencies = [ ...Object.keys(packageJson.peerDependencies ?? {}), ...Object.keys(packageJson.dependencies ?? {}), ...Object.keys(packageJson.devDependencies ?? {}) ] function createPackageRegex(name) { return new RegExp(`^${name}(/.*)?`) } const baseConfig = { input: 'src/index.js', external: dependencies.map(createPackageRegex), plugins: [ babel({ babelrc: false, presets: [ [ '@babel/preset-env', { modules: false } ], '@babel/preset-react' ], babelHelpers: 'bundled' }), commonjs() ] } export default [ { ...baseConfig, output: { file: `dist/index.esm.mjs`, format: 'esm' } }, { ...baseConfig, output: { file: `dist/index.umd.js`, format: 'umd', name: 'reocticons', globals: { react: 'React' } } } ] ================================================ FILE: lib/octicons_react/script/.eslintrc.json ================================================ { "env": { "node": true, "browser": false }, "rules": { "no-console": 0, "no-shadow": 0 } } ================================================ FILE: lib/octicons_react/script/build.js ================================================ #!/usr/bin/env node const octicons = require('../../build/data.json') const {default: generate} = require('@babel/generator') const t = require('@babel/types') const fse = require('fs-extra') const {join, resolve} = require('path') const srcDir = resolve(__dirname, '../src/__generated__') const iconsFile = join(srcDir, 'icons.js') const typesFile = join(srcDir, 'icons.d.ts') const GENERATED_HEADER = '/* THIS FILE IS GENERATED. DO NOT EDIT IT. */' function pascalCase(str) { return str.replace(/(^|-)([a-z])/g, (_, __, c) => c.toUpperCase()) } const icons = Object.entries(octicons) .map(([key, octicon]) => { const name = `${pascalCase(key)}Icon` // Build an object with the following structure: // // type SVGData = { // [key in string]: { // width: number, // path: React.JSXElement // }, // } // const svgData = t.objectExpression( Object.entries(octicon.heights).map(([height, icon]) => { return t.objectProperty( t.stringLiteral(height), t.objectExpression([ t.objectProperty(t.stringLiteral('width'), t.numericLiteral(icon.width)), t.objectProperty(t.stringLiteral('path'), svgToJSX(icon.ast)) ]) ) }) ) // Define the icon by using the `createIconComponent` helper and the svgData // defined above. This generates the following: // // const IconName = /*#__PURE__*/ createIconComponent('name', 'default-class-name', () => ({ // /* svgData */ // })); // const {code} = generate( t.variableDeclaration('const', [ t.variableDeclarator( t.identifier(name), t.addComment( t.callExpression(t.identifier('createIconComponent'), [ // The name of the generated icon t.stringLiteral(name), // The className used on the underlying element t.stringLiteral(`octicon octicon-${key}`), t.arrowFunctionExpression([], t.blockStatement([t.returnStatement(svgData)])) ]), 'leading', '#__PURE__' ) ) ]) ) return { key, name, octicon, code } }) .sort((a, b) => a.key.localeCompare(b.key)) function writeIcons(file) { const count = icons.length const code = `${GENERATED_HEADER} import React from 'react' import { createIconComponent } from '../createIconComponent' ${icons.map(({code}) => code).join('\n')} export { ${icons.map(({name}) => name).join(',\n ')} }` return fse.writeFile(file, code, 'utf8').then(() => { console.warn('wrote %s with %d exports', file, count) return icons }) } function writeTypes(file) { const count = icons.length const code = `${GENERATED_HEADER} import * as React from 'react' type Size = 'small' | 'medium' | 'large' interface IconProps { 'aria-label'?: string className?: string fill?: string size?: number | Size verticalAlign?: 'middle' | 'text-bottom' | 'text-top' | 'top' | 'unset' } type Icon = React.FC ${icons.map(({name}) => `declare const ${name}: Icon`).join('\n')} export { Icon, IconProps, ${icons.map(({name}) => name).join(',\n ')} }` return fse.writeFile(file, code, 'utf8').then(() => { console.warn('wrote %s with %d exports', file, count) return icons }) } fse .mkdirs(srcDir) .then(() => writeIcons(iconsFile)) .then(() => writeTypes(typesFile)) .catch(error => { console.error(error) process.exit(1) }) /** * Convert a given node from an svg AST into a JS AST of JSX Elements */ function svgToJSX(node) { if (node.type === 'element') { const children = node.children.map(svgToJSX) if (node.name === 'svg') { if (children.length === 0) { throw new Error(`No children available for icon`) } if (children.length > 1) { return t.jsxFragment(t.jsxOpeningFragment(), t.jsxClosingFragment(), children) } return children[0] } const attrs = Object.entries(node.attributes).map(([key, value]) => { if (typeof value !== 'string') { throw new Error(`Unknown value type: ${value}`) } return t.jsxAttribute(t.jsxIdentifier(key), t.stringLiteral(value)) }) const openingElement = t.jsxOpeningElement(t.jsxIdentifier(node.name), attrs, children.length === 0) const closingElement = t.jsxClosingElement(t.jsxIdentifier(node.name)) if (children.length > 0) { return t.jsxElement(openingElement, closingElement, children, false) } return t.jsxElement(openingElement, closingElement, [], true) } throw new Error(`Unknown type: ${node.type}`) } ================================================ FILE: lib/octicons_react/script/types.js ================================================ #!/usr/bin/env node const fse = require('fs-extra') const {join, resolve} = require('path') const srcDir = resolve(__dirname, '../src/__generated__') const iconsSrc = join(srcDir, 'icons.d.ts') const indexSrc = join(srcDir, '../index.d.ts') const destDir = resolve(__dirname, '../dist') const iconsDest = join(destDir, 'icons.d.ts') const indexDest = join(destDir, 'index.d.ts') async function main() { await fse.copy(iconsSrc, iconsDest) let contents = await fse.readFile(indexSrc, 'utf8') contents = contents.replace(/.\/__generated__\//g, './') await fse.writeFile(indexDest, contents, 'utf8') await fse.writeFile(join(destDir, 'index.d.mts'), contents, 'utf8') } main().catch(error => { console.error(error) process.exitCode = 1 }) ================================================ FILE: lib/octicons_react/src/__tests__/.eslintrc.json ================================================ { "rules": { "github/unescaped-html-literal": 0 } } ================================================ FILE: lib/octicons_react/src/__tests__/__snapshots__/octicon.js.snap ================================================ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`An icon component matches snapshot 1`] = ` `; ================================================ FILE: lib/octicons_react/src/__tests__/octicon.js ================================================ import '@testing-library/jest-dom' import {render, screen} from '@testing-library/react' import React from 'react' import {AlertIcon} from '../index' describe('An icon component', () => { it('matches snapshot', () => { const {container} = render() expect(container.querySelector('svg')).toMatchSnapshot() }) it('defaults to `aria-hidden="true"` if no label is present', () => { const {container} = render() expect(container.querySelector('svg')).toHaveAttribute('aria-hidden', 'true') }) it('sets `role="img"` if `aria-label` is provided', () => { render() expect(screen.getByLabelText('Alert')).toHaveAttribute('role', 'img') }) it('sets `role="img"` if `aria-labelledby` is provided', () => { render( <> Alert ) expect(screen.getByLabelText('Alert')).toHaveAttribute('role', 'img') }) it('sets aria-hidden="false" if ariaLabel prop is present', () => { const {container} = render() expect(container.querySelector('svg')).not.toHaveAttribute('aria-hidden') expect(container.querySelector('svg')).toHaveAttribute('aria-label', 'icon') }) it('set the focusable prop to false if tabIndex prop is not present', () => { const {container} = render() expect(container.querySelector('svg')).toHaveAttribute('focusable', 'false') }) it('sets focusable prop to true if tabIndex prop is present and greater than 0', () => { const {container} = render() expect(container.querySelector('svg')).toHaveAttribute('tabindex', '0') expect(container.querySelector('svg')).toHaveAttribute('focusable', 'true') }) it('sets focusable prop to false if tabIndex prop is -1', () => { const {container} = render() expect(container.querySelector('svg')).toHaveAttribute('tabindex', '-1') expect(container.querySelector('svg')).toHaveAttribute('focusable', 'false') }) it('respects the className prop', () => { const {container} = render() expect(container.querySelector('svg')).toHaveAttribute('class', 'octicon octicon-alert foo') }) it('respects the fill prop', () => { const {container} = render() expect(container.querySelector('svg')).toHaveAttribute('fill', '#f00') }) it('respects the verticalAlign prop', () => { const {container} = render() expect(container.querySelector('svg')).toHaveStyle({verticalAlign: 'middle'}) }) it('supports additional props on the outermost element', () => { const {container} = render() expect(container.firstChild).toHaveAttribute('data-testid', 'icon') }) describe('size props', () => { it('respects size="small"', () => { const {container} = render() expect(container.querySelector('svg')).toHaveAttribute('width', '16') expect(container.querySelector('svg')).toHaveAttribute('height', '16') }) it('respects size="medium"', () => { const {container} = render() expect(container.querySelector('svg')).toHaveAttribute('width', '32') expect(container.querySelector('svg')).toHaveAttribute('height', '32') }) it('respects size="large"', () => { const {container} = render() expect(container.querySelector('svg')).toHaveAttribute('width', '64') expect(container.querySelector('svg')).toHaveAttribute('height', '64') }) it('respects size={number}', () => { const {container} = render() expect(container.querySelector('svg')).toHaveAttribute('width', '128') expect(container.querySelector('svg')).toHaveAttribute('height', '128') }) it('chooses the correct SVG given a size <24', () => { const {container} = render() expect(container.querySelector('svg')).toHaveAttribute('viewBox', '0 0 16 16') expect(container.querySelector('svg')).toHaveAttribute('width', '20') expect(container.querySelector('svg')).toHaveAttribute('height', '20') }) it('chooses the correct SVG given a size >=24', () => { const {container} = render() expect(container.querySelector('svg')).toHaveAttribute('viewBox', '0 0 24 24') expect(container.querySelector('svg')).toHaveAttribute('width', '24') expect(container.querySelector('svg')).toHaveAttribute('height', '24') }) }) }) ================================================ FILE: lib/octicons_react/src/createIconComponent.js ================================================ import React from 'react' const sizeMap = { small: 16, medium: 32, large: 64 } export function createIconComponent(name, defaultClassName, getSVGData) { const svgDataByHeight = getSVGData() const heights = Object.keys(svgDataByHeight) const Icon = React.forwardRef( ( { 'aria-label': ariaLabel, 'aria-labelledby': arialabelledby, tabIndex, className = '', fill = 'currentColor', size = 16, verticalAlign = 'text-bottom', id, title, style, ...rest }, forwardedRef ) => { const height = sizeMap[size] || size const naturalHeight = closestNaturalHeight(heights, height) const naturalWidth = svgDataByHeight[naturalHeight].width const width = height * (naturalWidth / naturalHeight) const path = svgDataByHeight[naturalHeight].path const labelled = ariaLabel || arialabelledby const role = labelled ? 'img' : undefined return ( = 0 ? 'true' : 'false'} aria-label={ariaLabel} aria-labelledby={arialabelledby} className={`${defaultClassName} ${className}`.trim()} role={role} viewBox={`0 0 ${naturalWidth} ${naturalHeight}`} width={width} height={height} fill={fill} id={id} display="inline-block" overflow="visible" style={{ verticalAlign, ...style }} > {title ? {title} : null} {path} ) } ) Icon.displayName = name return Icon } function closestNaturalHeight(naturalHeights, height) { return naturalHeights .map(naturalHeight => parseInt(naturalHeight, 10)) .reduce((acc, naturalHeight) => (naturalHeight <= height ? naturalHeight : acc), naturalHeights[0]) } ================================================ FILE: lib/octicons_react/src/index.d.ts ================================================ // eslint-disable-next-line import/no-namespace import * as React from 'react' // eslint-disable-next-line prettier/prettier import {Icon} from './__generated__/icons.js' type Size = 'small' | 'medium' | 'large' export interface OcticonProps extends React.ComponentPropsWithoutRef<'svg'> { 'aria-label'?: string 'aria-labelledby'?: string tabIndex?: number children?: React.ReactElement className?: string title?: string | React.ReactElement id?: string fill?: string icon?: Icon | React.ReactNode size?: number | Size /** @deprecated use v-align utilities instead */ verticalAlign?: 'middle' | 'text-bottom' | 'text-top' | 'top' | 'unset' } export * from './__generated__/icons.js' ================================================ FILE: lib/octicons_react/src/index.js ================================================ export * from './__generated__/icons' ================================================ FILE: lib/octicons_react/ts-tests/index.tsx ================================================ import * as React from 'react' import {MarkGithubIcon, PlusIcon, RepoIcon} from '../src' function TestOcticons() { return (
) } ================================================ FILE: lib/octicons_react/ts-tests/tsconfig.json ================================================ { "$schema": "http://json.schemastore.org/tsconfig", "compileOnSave": false, "compilerOptions": { "module": "commonjs", "noEmit": true, "noImplicitAny": true, "jsx": "react", "lib": ["es2015"], "skipLibCheck": true } } ================================================ FILE: lib/octicons_styled/.babelrc ================================================ { "presets": ["env", "stage-0", "react"], "env": { "production": { "presets": ["next/babel"] } } } ================================================ FILE: lib/octicons_styled/.eslintignore ================================================ src/__generated__/ ================================================ FILE: lib/octicons_styled/.eslintrc.json ================================================ { "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaFeatures": { "jsx": true } }, "extends": [ "plugin:react/recommended", "plugin:jsx-a11y/recommended", "plugin:prettier/recommended", "plugin:github/recommended", "plugin:github/browser" ], "rules": { "github/no-then": 0, "import/named": 0, "react/prop-types": 0 }, "env": { "browser": true, "commonjs": true, "es6": true, "jest": true, "node": true }, "settings": { "react": { "version": "16" } } } ================================================ FILE: lib/octicons_styled/.gitignore ================================================ .cache .next dist/ src/__generated__/ ================================================ FILE: lib/octicons_styled/.npmignore ================================================ *.config.js .*.sw? .*rc .cache .eslint* .gitignore .next script src ================================================ FILE: lib/octicons_styled/.nvmrc ================================================ 8 ================================================ FILE: lib/octicons_styled/LICENSE ================================================ MIT License Copyright (c) 2026 GitHub Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: lib/octicons_styled/README.md ================================================ # @primer/styled-octicons [![npm version](https://img.shields.io/npm/v/@primer/styled-octicons.svg)](https://www.npmjs.org/package/@primer/styled-octicons) The `@primer/styled-octicons` package wraps icon components from [`@primer/octicons-react`](/packages/react) with [system props](https://primer.style/components/system-props), making them easier to style in projects that use [styled system](https://styled-system.com/)—like [Primer React](https://primer.style/components). ## Install ```shell npm install @primer/styled-octicons ``` ## Usage `@primer/styled-octicons` exports each icons as a named export. This allows you to import only the icons you need: ```jsx import {AlertIcon} from '@primer/styled-octicons' export () => ( ) ``` ## System props All icon components in `@primer/styled-octicons` get `color` and `space` system props as well as the `sx` prop. Read the Primer React [System Props](https://primer.style/components/system-props) documentation for a full list of available props. ## Props In addition to system props, icon components in `@primer/styled-octicons` accept the same props as components in `@primer/octicons-react`: | Name | Type | Default | Description | | :- | :- | :-: | :- | | aria-label | String | | Sets the [`aria-label`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-label_attribute) attribute of the ``. If no `aria-label` is defined, `aria-hidden` will be set to `true`. | | className | String | | Sets the `class` attribute on the ``. | | size | Number \| `"small"` \| `"medium"` \| `"large"` | `16` | The height of the icon. Width will be scaled proportionally. | | verticalAlign | `"middle"` \| `"text-bottom"` \| `"text-top"` \| `"top"` \| `"unset"` | `"text-bottom"` | The vertical alignment of the ``. | ================================================ FILE: lib/octicons_styled/package.json ================================================ { "name": "@primer/styled-octicons", "version": "16.1.0", "description": "A scalable set of icons handcrafted with <3 by GitHub.", "homepage": "https://primer.style/octicons", "author": "GitHub, Inc.", "license": "MIT", "main": "dist/index.umd.js", "module": "dist/index.esm.js", "sideEffects": false, "types": "dist/index.d.ts", "repository": "primer/octicons", "files": [ "dist" ], "scripts": { "build": "script/build.js && npm run rollup && script/copy.sh", "ts-test": "tsc -P ts-tests", "test": "jest", "posttest": "npm run ts-test", "lint": "eslint src script", "rollup": "rollup -c --bundleConfigAsCjs" }, "keywords": [ "GitHub", "icons", "svg", "octicons", "react", "primer" ], "dependencies": { "@styled-system/css": "^5.1.5", "@styled-system/prop-types": "^5.1.5", "@types/styled-system": "^5.1.9", "@types/styled-system__css": "^5.0.8", "styled-system": "^5.1.5" }, "peerDependencies": { "react": ">=15", "styled-components": "4.x || 5.x" }, "devDependencies": { "@babel/core": "7.24.7", "@babel/preset-env": "7.24.7", "@babel/preset-react": "7.24.7", "@github/prettier-config": "0.0.4", "@rollup/plugin-babel": "6.0.4", "@testing-library/jest-dom": "^5.3.0", "@testing-library/react": "^10.0.2", "@types/react": "^16.4.6", "eslint": "^6.5.1", "eslint-plugin-github": "4.1.3", "eslint-plugin-jest": "^21.17.0", "eslint-plugin-jsx-a11y": "6.4.1", "eslint-plugin-react": "7.23.2", "fs-extra": "^6.0.1", "jest": "^23.2.0", "jest-styled-components": "^7.0.2", "next": "^16.1.7", "react": "^16.4.0", "react-dom": "^16.4.1", "rollup": "^4.18.0", "styled-components": "^5.1.0", "typescript": "^3.7.5" }, "engines": { "node": ">=8" } } ================================================ FILE: lib/octicons_styled/prettier.config.js ================================================ module.exports = require('@github/prettier-config') ================================================ FILE: lib/octicons_styled/rollup.config.js ================================================ import babel from '@rollup/plugin-babel' // eslint-disable-next-line import/no-namespace import * as octicons from '../octicons_react/dist/index.esm' const icons = Object.keys(octicons).filter(name => name !== 'default') export default [ { input: 'src/__generated__/index.js', plugins: [ babel({ babelrc: false, presets: [[require.resolve('@babel/preset-env'), {modules: false}], require.resolve('@babel/preset-react')], babelHelpers: 'inline' }) ], output: { file: 'dist/index.umd.js', format: 'umd', name: 'reocticons' } }, { input: Object.fromEntries(icons.map(name => [`icons/${name}`, `src/__generated__/icons/${name}.js`])), plugins: [ babel({ babelrc: false, presets: [[require.resolve('@babel/preset-env'), {modules: false}], require.resolve('@babel/preset-react')], babelHelpers: 'bundled' }) ], output: { dir: 'dist', format: 'esm' } } ] ================================================ FILE: lib/octicons_styled/script/.eslintrc.json ================================================ { "env": { "node": true, "browser": false }, "rules": { "no-console": 0 } } ================================================ FILE: lib/octicons_styled/script/build.js ================================================ #!/usr/bin/env node const path = require('path') const fs = require('fs-extra') const octicons = require('../../octicons_react') const GENERATED_HEADER = '/* THIS FILE IS GENERATED. DO NOT EDIT IT. */' const generatedDir = path.join(__dirname, '../src/__generated__') const iconsDir = path.join(generatedDir, 'icons') fs.ensureDirSync(iconsDir) const icons = Object.keys(octicons).filter(name => name !== 'default') const initialTypeDefinitions = `${GENERATED_HEADER} import * as React from 'react' import * as StyledSystem from 'styled-system' import {SystemStyleObject} from '@styled-system/css' type Size = 'small' | 'medium' | 'large' export interface IconProps extends StyledSystem.ColorProps, StyledSystem.SpaceProps { 'aria-label'?: string className?: string size?: number | Size verticalAlign?: 'middle' | 'text-bottom' | 'text-top' | 'top' | 'unset' sx?: SystemStyleObject } export type Icon = React.FC ` fs.writeFileSync(path.join(generatedDir, 'index.js'), '', 'utf-8') fs.writeFileSync(path.join(generatedDir, 'index.d.ts'), initialTypeDefinitions, 'utf-8') for (const name of icons) { const location = path.join(iconsDir, `${name}.js`) const code = `${GENERATED_HEADER} import styled from 'styled-components' import * as styledSystem from 'styled-system' import {${name}} from '../../../../octicons_react/dist/index.esm' import {COMMON, sx} from '../../utils' const Styled${name} = styled(${name})(COMMON, sx) export default Styled${name} ` fs.writeFileSync(location, code, 'utf-8') console.log('Successfully built', name) const exportString = `export { default as ${name} } from './icons/${name}';\r\n` fs.appendFileSync(path.join(generatedDir, 'index.js'), exportString, 'utf-8') const exportTypeString = `export const ${name}: Icon;\n` fs.appendFileSync(path.join(generatedDir, 'index.d.ts'), exportTypeString, 'utf-8') } ================================================ FILE: lib/octicons_styled/script/copy.sh ================================================ #!/bin/bash cp src/__generated__/index.d.ts dist/index.d.ts cp src/__generated__/index.js dist/index.esm.js ================================================ FILE: lib/octicons_styled/src/__tests__/.eslintrc.json ================================================ { "rules": { "github/unescaped-html-literal": 0 } } ================================================ FILE: lib/octicons_styled/src/__tests__/octicon.js ================================================ import '@testing-library/jest-dom' import {render} from '@testing-library/react' import 'jest-styled-components' import React from 'react' import {ThemeProvider} from 'styled-components' import {AlertIcon} from '../__generated__/index' describe('An icon component', () => { it('sets aria-hidden="false" if ariaLabel prop is present', () => { const {container} = render() expect(container.querySelector('svg')).toHaveAttribute('aria-hidden', 'false') expect(container.querySelector('svg')).toHaveAttribute('aria-label', 'icon') }) it('respects the className prop', () => { const {container} = render() expect(container.querySelector('svg')).toHaveClass('foo') }) it('respects the verticalAlign prop', () => { const {container} = render() expect(container.querySelector('svg')).toHaveStyle({verticalAlign: 'middle'}) }) describe('size props', () => { it('respects size="small"', () => { const {container} = render() expect(container.querySelector('svg')).toHaveAttribute('width', '16') expect(container.querySelector('svg')).toHaveAttribute('height', '16') }) it('respects size="medium"', () => { const {container} = render() expect(container.querySelector('svg')).toHaveAttribute('width', '32') expect(container.querySelector('svg')).toHaveAttribute('height', '32') }) it('respects size="large"', () => { const {container} = render() expect(container.querySelector('svg')).toHaveAttribute('width', '64') expect(container.querySelector('svg')).toHaveAttribute('height', '64') }) it('respects size={number}', () => { const {container} = render() expect(container.querySelector('svg')).toHaveAttribute('width', '128') expect(container.querySelector('svg')).toHaveAttribute('height', '128') }) it('chooses the correct SVG given a size <24', () => { const {container} = render() expect(container.querySelector('svg')).toHaveAttribute('viewBox', '0 0 16 16') expect(container.querySelector('svg')).toHaveAttribute('width', '20') expect(container.querySelector('svg')).toHaveAttribute('height', '20') }) it('chooses the correct SVG given a size >=24', () => { const {container} = render() expect(container.querySelector('svg')).toHaveAttribute('viewBox', '0 0 24 24') expect(container.querySelector('svg')).toHaveAttribute('width', '24') expect(container.querySelector('svg')).toHaveAttribute('height', '24') }) }) describe('system props', () => { it('respects the color prop', () => { const theme = {colors: {red: ['#ffeef0', '#ffdce0']}} const {container} = render( ) expect(container.querySelector('svg')).toHaveStyleRule('color', '#ffdce0') }) it('respects space props', () => { const theme = {space: [0, 4, 8, 16, 24, 32, 40, 48]} const {container} = render( ) expect(container.querySelector('svg')).toHaveStyleRule('margin-top', '4px') expect(container.querySelector('svg')).toHaveStyleRule('margin-left', '8px') expect(container.querySelector('svg')).toHaveStyleRule('margin-right', '16px') expect(container.querySelector('svg')).toHaveStyleRule('margin-bottom', '24px') }) it('respects sx props', () => { const theme = {colors: {red: ['#ffeef0', '#ffdce0']}} const {container} = render( ) expect(container.querySelector('svg')).toHaveStyleRule('color', '#ffeef0') }) }) }) ================================================ FILE: lib/octicons_styled/src/utils.js ================================================ // eslint-disable-next-line import/no-namespace import * as styledSystem from 'styled-system' import css from '@styled-system/css' export const COMMON = styledSystem.compose(styledSystem.space, styledSystem.color) export const sx = props => css(props.sx) ================================================ FILE: lib/octicons_styled/ts-tests/index.tsx ================================================ import * as React from 'react' import {RepoIcon} from '../src/__generated__' function TestOcticons() { return (
) } ================================================ FILE: lib/octicons_styled/ts-tests/tsconfig.json ================================================ { "$schema": "http://json.schemastore.org/tsconfig", "compileOnSave": false, "compilerOptions": { "module": "commonjs", "noEmit": true, "noImplicitAny": true, "jsx": "react", "lib": ["es2015"], "skipLibCheck": true } } ================================================ FILE: package.json ================================================ { "name": "@primer/octicons", "version": "19.23.1", "publishConfig": { "registry": "no registry, don't publish from this package.json." }, "scripts": { "build": "script/build.js --input icons/**/*.svg --output lib/build/data.json", "changeset:version": "changeset version && script/version", "lint": "eslint tests", "svgo": "svgo icons --config svgo.config.js", "test": "ava -v tests/*.js", "version": "script/version" }, "devDependencies": { "@changesets/changelog-github": "0.4.1", "@changesets/cli": "2.17.0", "@github/prettier-config": "0.0.6", "ava": "2.1.0", "braces": "3.0.3", "cheerio": "1.0.0-rc.3", "eslint": "8.57.1", "eslint-plugin-github": "5.0.2", "eslint-plugin-prettier": "5.2.1", "execa": "4.0.0", "fs-extra": "7.0.1", "globby": "11.0.0", "js-yaml": "3.14.2", "prettier": "3.4.1", "lodash.merge": "4.6.2", "svgo": "3.3.3", "svgson": "5.2.1", "trim-newlines": "3.0.1", "yargs": "15.1.0" }, "eslintConfig": { "extends": [ "plugin:github/internal", "plugin:github/recommended" ], "env": { "es6": true, "node": true }, "parserOptions": { "ecmaVersion": 2017, "requireConfigFile": false }, "rules": { "github/no-then": 0, "eslint-comments/no-use": 0 } }, "packageManager": "yarn@1.22.1" } ================================================ FILE: prettier.config.js ================================================ module.exports = require('@github/prettier-config') ================================================ FILE: script/build.js ================================================ #!/usr/bin/env node /* eslint-env node */ const fs = require('fs-extra') const path = require('path') const globby = require('globby') const cheerio = require('cheerio') const {parseSync} = require('svgson') const trimNewlines = require('trim-newlines') const yargs = require('yargs') const merge = require('lodash.merge') const keywords = require('../keywords.json') // This script generates a JSON file that contains // information about input SVG files. const {argv} = yargs .usage('Usage: $0 --input --output ') .example('$0 --input icons/**/*.svg --output build/data.json') .option('input', { alias: 'i', type: 'array', demandOption: true, describe: 'Input SVG files' }) .option('output', { alias: 'o', type: 'string', describe: 'Output JSON file. Defaults to stdout if no output file is provided.' }) // The `argv.input` array could contain globs (e.g. "**/*.svg"). const filepaths = globby.sync(argv.input) const svgFilepaths = filepaths.filter(filepath => path.parse(filepath).ext === '.svg') if (svgFilepaths.length === 0) { // eslint-disable-next-line no-console console.error('No input SVG file(s) found') process.exit(1) } let exitCode = 0 const icons = svgFilepaths.map(filepath => { try { const filename = path.parse(filepath).base const filenamePattern = /(.+)-([0-9]+).svg$/ if (!filenamePattern.test(filename)) { throw new Error( `${filename}: Invalid filename. Please append the height of the SVG to the end of the filename (e.g. alert-16.svg).` ) } const [, name, height] = filename.match(filenamePattern) const svg = fs.readFileSync(path.resolve(filepath), 'utf8') const svgElement = cheerio.load(svg)('svg') const svgWidth = parseInt(svgElement.attr('width')) const svgHeight = parseInt(svgElement.attr('height')) const svgViewBox = svgElement.attr('viewBox') const svgPath = trimNewlines(svgElement.html()).trim() const ast = parseSync(svg, { camelcase: true }) if (!svgWidth) { throw new Error(`${filename}: Missing width attribute.`) } if (!svgHeight) { throw new Error(`${filename}: Missing height attribute.`) } if (!svgViewBox) { throw new Error(`${filename}: Missing viewBox attribute.`) } if (svgHeight !== parseInt(height)) { throw new Error(`${filename}: Height in filename does not match height attribute of SVG`) } const viewBoxPattern = /0 0 ([0-9]+) ([0-9]+)/ if (!viewBoxPattern.test(svgViewBox)) { throw new Error( `${filename}: Invalid viewBox attribute. The viewBox attribute should be in the following format: "0 0 "` ) } const [, viewBoxWidth, viewBoxHeight] = svgViewBox.match(viewBoxPattern) if (svgWidth !== parseInt(viewBoxWidth)) { throw new Error(`${filename}: width attribute and viewBox width do not match.`) } if (svgHeight !== parseInt(viewBoxHeight)) { throw new Error(`${filename}: height attribute and viewBox height do not match.`) } return { name, keywords: keywords[name] || [], width: svgWidth, height: svgHeight, path: svgPath, ast } } catch (error) { // eslint-disable-next-line no-console console.error(error) // Instead of exiting immediately, we set exitCode to 1 and continue // iterating through the rest of the SVGs. This allows us to identify all // the SVGs that have errors, not just the first one. An exit code of 1 // indicates that an error occurred. // Reference: https://nodejs.org/api/process.html#process_exit_codes exitCode = 1 return null } }) // Exit early if any errors occurred. if (exitCode !== 0) { process.exit(exitCode) } const iconsByName = icons.reduce( (acc, icon) => merge(acc, { [icon.name]: { name: icon.name, keywords: icon.keywords, heights: { [icon.height]: { width: icon.width, path: icon.path, ast: icon.ast } } } }), {} ) if (argv.output) { fs.outputJsonSync(path.resolve(argv.output), iconsByName) } else { process.stdout.write(JSON.stringify(iconsByName)) } ================================================ FILE: script/changeset-publish ================================================ #!/bin/bash # This is a hack to make the changeset action think we npm published, so that it creates the github release # Get the current version PACKAGE_VERSION=$(jq '.version' --raw-output ./package.json) # Check if the remote has the current version as a git tag # If it doesn't, we echo "New tag:" which is what the changeset action expects https://github.com/changesets/action/blob/b98cec97583b917ff1dc6179dd4d230d3e439894/src/run.ts#L123 git ls-remote --exit-code --tags origin "v$PACKAGE_VERSION" || echo "New tag:" ================================================ FILE: script/version ================================================ #!/bin/bash PACKAGE_VERSION=$(jq '.version' --raw-output ./package.json) echo $PACKAGE_VERSION echo "Versioning Octicons node package" cd lib/octicons_node/ npm -f --no-git-tag-version --allow-same-version version $PACKAGE_VERSION echo "Versioning Octicons react package" cd ../octicons_react/ npm -f --no-git-tag-version --allow-same-version version $PACKAGE_VERSION echo "Versioning Octicons ruby gem" cd ../octicons_gem/ rake version\["$PACKAGE_VERSION"\] echo "Versioning Octicons rails helper gem" cd ../octicons_helper/ rake version\["$PACKAGE_VERSION"\] echo "Versioning Octicons jekyll plugin gem" cd ../octicons_jekyll/ rake version\["$PACKAGE_VERSION"\] cd ../../ git add lib/ ================================================ FILE: svgo.config.js ================================================ /* eslint-disable import/no-commonjs,filenames/match-regex */ module.exports = { multipass: true, plugins: [ { name: 'preset-default', params: { overrides: { removeViewBox: false } } }, 'removeStyleElement', { name: 'removeAttrs', params: { attrs: ['xmlns:xlink', 'id', 'class', 'data-name', 'fill', 'transform', 'href', 'clip-path', 'clip-rule'] } } ] } ================================================ FILE: tests/build.js ================================================ /* eslint-disable import/no-commonjs */ const path = require('path') const test = require('ava') const execa = require('execa') test('builds an object with the correct shape', t => { return execa( path.resolve(__dirname, '../script/build.js'), ['--input', 'icons/icon-a-16.svg', './icons/icon-a-24.svg', './icons/icon-b-16.svg'], {cwd: __dirname}, ).then(({stdout}) => { const icons = JSON.parse(stdout) t.snapshot(icons) }) }) test('fails when input argument is missing', t => { return execa(path.resolve(__dirname, '../script/build.js')) .then(() => { t.fail() // Test should fail if execa() call doesn't throw an error }) .catch(error => { t.is(error.exitCode, 1) t.false(error.killed) }) }) test('fails when input file does not exist', t => { return execa(path.resolve(__dirname, '../script/build.js'), ['--input', 'fake-16.svg']) .then(() => { t.fail() // Test should fail if execa() call doesn't throw an error }) .catch(error => { t.is(error.exitCode, 1) t.false(error.killed) }) }) test('fails when filename is missing a height', t => { return execa(path.resolve(__dirname, '../script/build.js'), ['--input', 'tests/icons/missing-height.svg']) .then(() => { t.fail() // Test should fail if execa() call doesn't throw an error }) .catch(error => { t.is(error.exitCode, 1) t.false(error.killed) }) }) test('fails when height in filename does not match height attribute of SVG', t => { return execa(path.resolve(__dirname, '../script/build.js'), ['--input', 'tests/icons/height-mismatch-24.svg']) .then(() => { t.fail() // Test should fail if execa() call doesn't throw an error }) .catch(error => { t.is(error.exitCode, 1) t.false(error.killed) }) }) test('fails when height attribute is missing', t => { return execa(path.resolve(__dirname, '../script/build.js'), ['--input', 'tests/icons/missing-height-attr-16.svg']) .then(() => { t.fail() // Test should fail if execa() call doesn't throw an error }) .catch(error => { t.is(error.exitCode, 1) t.false(error.killed) }) }) test('fails when width attribute is missing', t => { return execa(path.resolve(__dirname, '../script/build.js'), ['--input', 'tests/icons/missing-width-attr-16.svg']) .then(() => { t.fail() // Test should fail if execa() call doesn't throw an error }) .catch(error => { t.is(error.exitCode, 1) t.false(error.killed) }) }) test('fails when viewBox attribute is missing', t => { return execa(path.resolve(__dirname, '../script/build.js'), ['--input', 'tests/icons/missing-viewbox-attr-16.svg']) .then(() => { t.fail() // Test should fail if execa() call doesn't throw an error }) .catch(error => { t.is(error.exitCode, 1) t.false(error.killed) }) }) test('fails when height attribute is invalid', t => { return execa(path.resolve(__dirname, '../script/build.js'), ['--input', 'tests/icons/invalid-height-attr-16.svg']) .then(() => { t.fail() // Test should fail if execa() call doesn't throw an error }) .catch(error => { t.is(error.exitCode, 1) t.false(error.killed) }) }) test('fails when width attribute is invalid', t => { return execa(path.resolve(__dirname, '../script/build.js'), ['--input', 'tests/icons/invalid-width-attr-16.svg']) .then(() => { t.fail() // Test should fail if execa() call doesn't throw an error }) .catch(error => { t.is(error.exitCode, 1) t.false(error.killed) }) }) test('fails when viewBox attribute is invalid', t => { return execa(path.resolve(__dirname, '../script/build.js'), ['--input', 'tests/icons/invalid-viewbox-attr-16.svg']) .then(() => { t.fail() // Test should fail if execa() call doesn't throw an error }) .catch(error => { t.is(error.exitCode, 1) t.false(error.killed) }) }) test('fails when viewBox width does not match width attribute', t => { return execa(path.resolve(__dirname, '../script/build.js'), ['--input', 'tests/icons/viewbox-width-mismatch-16.svg']) .then(() => { t.fail() // Test should fail if execa() call doesn't throw an error }) .catch(error => { t.is(error.exitCode, 1) t.false(error.killed) }) }) test('fails when viewBox height does not match height attribute', t => { return execa(path.resolve(__dirname, '../script/build.js'), ['--input', 'tests/icons/viewbox-height-mismatch-16.svg']) .then(() => { t.fail() // Test should fail if execa() call doesn't throw an error }) .catch(error => { t.is(error.exitCode, 1) t.false(error.killed) }) }) test('ignores non-SVG input files', t => { return execa(path.resolve(__dirname, '../script/build.js'), ['--input', 'tests/build.js']) .then(() => { t.fail() // Test should fail if execa() call doesn't throw an error }) .catch(error => { t.is(error.exitCode, 1) t.false(error.killed) }) }) ================================================ FILE: tests/index.js ================================================ /* eslint-disable import/no-commonjs */ /* eslint-disable i18n-text/no-en */ const test = require('ava') const fs = require('fs-extra') const globby = require('globby') const year = new Date().getFullYear() const yearRegex = new RegExp(`Copyright \\(c\\) ${year} GitHub Inc\\.`) const octiconsLib = fs.readdirSync('./lib/build/svg') const octiconsData = require('../lib/build/data.json') test(`LICENSE files have the current year ${year}`, t => { return globby(['**/LICENSE', '!**/node_modules/**/LICENSE', '!**/vendor/**/LICENSE']).then(paths => { t.plan(paths.length) return paths.map(path => { const license = fs.readFileSync(path, 'utf8') return t.regex(license, yearRegex, `The license "${path}" does not include the current year ${year}`) }) }) }) test('SVG icons exist', t => { t.not(octiconsLib.length, 0, `We didn't find any svg files`) }) test('Data file exist', t => { t.not(octiconsData.length, 0, `We didn't find any data files`) }) const names = {} for (const octicon of Object.values(octiconsData)) { test(`No duplicate ${octicon.name} icon`, t => { if (names[octicon.name]) { t.fail( `Found duplicate '${octicon.name}' icons in the figma file. Please rename one of them. https://www.figma.com/file/${octicon.file}?node-id=${octicon.id}`, ) } else { names[octicon.name] = octicon t.pass() } }) } ================================================ FILE: tests/snapshots/build.js.md ================================================ # Snapshot report for `tests/build.js` The actual snapshot is saved in `build.js.snap`. Generated by [AVA](https://ava.li). ## builds an object with the correct shape > Snapshot 1 { 'icon-a': { heights: { 16: { ast: { attributes: { height: '16', viewBox: '0 0 16 16', width: '16', xmlns: 'http://www.w3.org/2000/svg', }, children: [ { attributes: { clipRule: 'evenodd', d: 'M8.22048 1.75358C8.1263 1.57738 7.87369 1.57738 7.77951 1.75359L1.69787 13.1321C1.60886 13.2987 1.72953 13.5 1.91835 13.5H14.0816C14.2705 13.5 14.3911 13.2987 14.3021 13.1321L8.22048 1.75358ZM6.45662 1.04652C7.11588 -0.186933 8.88412 -0.186935 9.54338 1.04652L15.625 12.4251C16.2481 13.5908 15.4034 15 14.0816 15H1.91835C0.596554 15 -0.248093 13.5908 0.374974 12.4251L6.45662 1.04652ZM9 11C9 11.5523 8.55229 12 8 12C7.44772 12 7 11.5523 7 11C7 10.4477 7.44772 10 8 10C8.55229 10 9 10.4477 9 11ZM8.75 5.75C8.75 5.33579 8.41421 5 8 5C7.58579 5 7.25 5.33579 7.25 5.75V8.25C7.25 8.66421 7.58579 9 8 9C8.41421 9 8.75 8.66421 8.75 8.25V5.75Z', fillRule: 'evenodd', }, children: [], name: 'path', type: 'element', value: '', }, ], name: 'svg', type: 'element', value: '', }, path: '', width: 16, }, 24: { ast: { attributes: { height: '24', viewBox: '0 0 24 24', width: '24', xmlns: 'http://www.w3.org/2000/svg', }, children: [ { attributes: { d: 'M13 17.5C13 18.0523 12.5523 18.5 12 18.5C11.4477 18.5 11 18.0523 11 17.5C11 16.9477 11.4477 16.5 12 16.5C12.5523 16.5 13 16.9477 13 17.5Z', }, children: [], name: 'path', type: 'element', value: '', }, { attributes: { d: 'M12.75 9.25C12.75 8.83579 12.4142 8.5 12 8.5C11.5858 8.5 11.25 8.83579 11.25 9.25V13.75C11.25 14.1642 11.5858 14.5 12 14.5C12.4142 14.5 12.75 14.1642 12.75 13.75V9.25Z', }, children: [], name: 'path', type: 'element', value: '', }, { attributes: { clipRule: 'evenodd', d: 'M9.83587 3.24404C10.7985 1.57946 13.2015 1.57946 14.1642 3.24404L23.1306 18.7484C24.0944 20.4151 22.8917 22.5 20.9664 22.5H3.03364C1.10834 22.5 -0.0943731 20.4151 0.869482 18.7484L9.83587 3.24404ZM12.8657 3.99498C12.4806 3.32915 11.5194 3.32915 11.1344 3.99498L2.16798 19.4994C1.78244 20.166 2.26352 21 3.03364 21H20.9664C21.7365 21 22.2176 20.166 21.8321 19.4994L12.8657 3.99498Z', fillRule: 'evenodd', }, children: [], name: 'path', type: 'element', value: '', }, ], name: 'svg', type: 'element', value: '', }, path: '', width: 24, }, }, keywords: [], name: 'icon-a', }, 'icon-b': { heights: { 16: { ast: { attributes: { height: '16', viewBox: '0 0 14 16', width: '14', xmlns: 'http://www.w3.org/2000/svg', }, children: [ { attributes: { d: 'M13 2H1v2h12V2zM0 4a1 1 0 001 1v9a1 1 0 001 1h10a1 1 0 001-1V5a1 1 0 001-1V2a1 1 0 00-1-1H1a1 1 0 00-1 1v2zm2 1h10v9H2V5zm2 3h6V7H4v1z', fillRule: 'evenodd', }, children: [], name: 'path', type: 'element', value: '', }, ], name: 'svg', type: 'element', value: '', }, path: '', width: 14, }, }, keywords: [], name: 'icon-b', }, }