diff --git a/.github/workflows/optimize-images.yml b/.github/workflows/optimize-images.yml new file mode 100644 index 0000000000..1cb6143b6e --- /dev/null +++ b/.github/workflows/optimize-images.yml @@ -0,0 +1,72 @@ +name: Optimize images + +# **What it does**: Optimize images. +# **Why we have it**: Reduce bandwidth needs. +# **Who does it impact**: Docs engineering. + +on: + workflow_dispatch: + pull_request: + paths: + - '**/*.png' + +permissions: + contents: write + pull-requests: write + +jobs: + optimize-images-on-pr: + # We can't make commits on forks + if: github.repository == 'github/docs-internal' + runs-on: ubuntu-latest + steps: + - name: Check out repo on head ref + uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + with: + ref: ${{ github.head_ref }} + # Need to specify a PAT here because otherwise GITHUB_TOKEN is used + # by default. Workflows won't trigger in that case because actions + # performed with GITHUB_TOKEN don't trigger other workflows. + token: ${{ secrets.DOCUBOT_REPO_PAT }} + + - name: Check out base ref + run: git fetch --no-tags --depth=1 origin $GITHUB_BASE_REF + + - name: Install the Optipng package + run: sudo apt-get update && sudo apt-get -y install optipng + + - name: Run optipng on new or changed images + run: | + set -e # exit when any command fails + + echo "Ensure we can view $GITHUB_BASE_REF" + git checkout $GITHUB_BASE_REF + + echo "Ensure we can view $GITHUB_HEAD_REF" + git checkout $GITHUB_HEAD_REF + + echo "List the files that changed" + git diff --name-only --diff-filter=d $GITHUB_BASE_REF $GITHUB_HEAD_REF + + echo "Run optipng on pngs in from the diff" + git diff --name-only -z --diff-filter=d $GITHUB_BASE_REF $GITHUB_HEAD_REF -- '*.png' | xargs -0 optipng -nx + + - name: Make a commit and a push + run: | + echo "If there's no changes, exit" + if [[ ! `git status --porcelain` ]] + then + echo "No changes found" + exit 0 + fi + + echo "Make a commit" + git config user.name github-actions + git config user.email github-actions@github.com + git add "*.png" + git commit --message="Optimize images" + + echo "Push up changes" + git push + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/repo-sync.yml b/.github/workflows/repo-sync.yml index 455b27031e..29e20b6895 100644 --- a/.github/workflows/repo-sync.yml +++ b/.github/workflows/repo-sync.yml @@ -1,17 +1,11 @@ -# The docs.github.com project has two repositories: github/docs (public) and github/docs-internal (private) -# -# This GitHub Actions workflow keeps the `main` branch of those two repos in sync. -# -# For more details, see https://github.com/repo-sync/repo-sync#how-it-works - name: Repo Sync -# **What it does**: -# Syncs docs and docs-internal. -# **Why we have it**: -# To keep the open-source repository up-to-date, while still having an internal -# repository for sensitive work. +# **What it does**: GitHub Docs has two repositories: github/docs (public) and github/docs-internal (private). +# This GitHub Actions workflow keeps the `main` branch of those two repos in sync. +# **Why we have it**: To keep the open-source repository up-to-date +# while still having an internal repository for sensitive work. # **Who does it impact**: Open-source. +# For more details, see https://github.com/repo-sync/repo-sync#how-it-works on: workflow_dispatch: @@ -31,18 +25,6 @@ jobs: - name: Check out repo uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - # Set up npm and run npm ci to get custom husky githooks error - # messages if they exist. We could also remove these steps - # because currently we have no hooks with customer error messages. - # See pull #32064 where they were removed. - - name: Setup Node.js - uses: actions/setup-node@8c91899e586c5b171469028077307d293428b516 - with: - node-version-file: 'package.json' - cache: npm - - name: Install dependencies - run: npm ci - - name: Sync repo to branch uses: repo-sync/github-sync@3832fe8e2be32372e1b3970bbae8e7079edeec88 env: @@ -53,41 +35,64 @@ jobs: destination_branch: repo-sync github_token: ${{ secrets.OCTOMERGER_PAT_WITH_REPO_AND_WORKFLOW_SCOPE }} - - name: Create pull request - uses: repo-sync/pull-request@65785d95a5a466e46a9d0708933a3bd51bbf9dde - env: - GITHUB_TOKEN: ${{ secrets.OCTOMERGER_PAT_WITH_REPO_AND_WORKFLOW_SCOPE }} + - name: Find or create pull request + id: pull-request + uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 with: - source_branch: repo-sync - destination_branch: main - pr_title: 'repo sync' - pr_body: "This is an automated pull request to sync changes between the public and private repos.\n\n:robot: This pull request should be merged (not squashed) to preserve continuity across repos, so please let a bot do the merging!" - pr_label: automated-reposync-pr - github_token: ${{ secrets.OCTOMERGER_PAT_WITH_REPO_AND_WORKFLOW_SCOPE }} - # This will exit 0 if there's no difference between `repo-sync` - # and `main`. And if so, no PR will be created. - pr_allow_empty: false + github-token: ${{ secrets.OCTOMERGER_PAT_WITH_REPO_AND_WORKFLOW_SCOPE }} + result-encoding: string + script: | + const { owner, repo } = context.repo + const head = 'repo-sync' + const base = 'main' + const label = 'automated-reposync-pr' - - name: Find pull request - uses: juliangruber/find-pull-request-action@3a4c7c62101755c3778d397dcb6a760a558992f1 - id: find-pull-request - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - branch: repo-sync - base: main - author: Octomerger - state: open + // Check if a pull request already exists + let { data: pulls } = await github.rest.pulls.list({ owner, repo, head, base }) + let foundPull = pulls.find(pr => pr.labels.some(xlabel => xlabel.name === label)) + if (foundPull) { + console.log('Found pull request and will not create a new one', foundPull.html_url) + return foundPull.number + } + + const body = ` + This is an automated pull request to sync changes between the public and private repos. + Our bot will merge this pull request automatically. + To preserve continuity across repos, _do not squash_ this pull request. + ` + console.log('Create a new pull request') + let { data: pull } = await github.rest.pulls.create({ + owner, + repo, + head, + base, + title: 'Repo sync', + body, + }) + + console.log('Add label', label) + await github.rest.issues.addLabels({ + owner, + repo, + issue_number: pull.number, + labels: [label] + }) + + console.log('Created pull request successfully', pull.html_url) + return pull.number # Because we get far too much spam ;_; - name: Lock conversations - if: ${{ github.repository == 'github/docs' && steps.find-pull-request.outputs.number }} + if: ${{ github.repository == 'github/docs' && steps.pull-request.outputs.result }} uses: actions/github-script@98814c53be79b1d30f795b907e553d8679345975 + env: + PR_NUMBER: ${{ steps.pull-request.outputs.result }} with: script: | try { await github.rest.issues.lock({ ...context.repo, - issue_number: parseInt(${{ steps.find-pull-request.outputs.number }}), + issue_number: parseInt(process.env.PR_NUMBER), lock_reason: 'spam' }) console.log('Locked the pull request to prevent spam!') @@ -96,10 +101,13 @@ jobs: console.error(`Failed to lock the pull request. Error: ${error}`) } - # There are cases where the branch becomes out-of-date in between the time this workflow began and when the pull request is created/updated + # There are cases where the branch becomes out-of-date in between the time this workflow began + # and when the pull request is created/updated - name: Update branch - if: ${{ steps.find-pull-request.outputs.number }} + if: ${{ steps.pull-request.outputs.result }} uses: actions/github-script@98814c53be79b1d30f795b907e553d8679345975 + env: + PR_NUMBER: ${{ steps.pull-request.outputs.result }} with: github-token: ${{ secrets.OCTOMERGER_PAT_WITH_REPO_AND_WORKFLOW_SCOPE }} script: | @@ -109,9 +117,10 @@ jobs: }) console.log(`heads/main sha: ${mainHeadSha.data.object.sha}`) + const pull_number = parseInt(process.env.PR_NUMBER) const pull = await github.rest.pulls.get({ ...context.repo, - pull_number: parseInt(${{ steps.find-pull-request.outputs.number }}) + pull_number, }) console.log(`Pull request base sha: ${pull.data.base.sha}`) @@ -119,7 +128,7 @@ jobs: try { const updateBranch = await github.rest.pulls.updateBranch({ ...context.repo, - pull_number: parseInt(${{ steps.find-pull-request.outputs.number }}) + pull_number, }) console.log(updateBranch.data.message) } catch (error) { @@ -129,7 +138,7 @@ jobs: try { const updateBranch = await github.rest.pulls.updateBranch({ ...context.repo, - pull_number: parseInt(${{ steps.find-pull-request.outputs.number }}) + pull_number, }) console.log(updateBranch.data.message) } catch (error) { @@ -147,11 +156,11 @@ jobs: } - name: Check pull request file count after updating - if: ${{ steps.find-pull-request.outputs.number }} + if: ${{ steps.pull-request.outputs.result }} uses: actions/github-script@98814c53be79b1d30f795b907e553d8679345975 id: pr-files env: - PR_NUMBER: ${{ steps.find-pull-request.outputs.number }} + PR_NUMBER: ${{ steps.pull-request.outputs.result }} with: github-token: ${{ secrets.OCTOMERGER_PAT_WITH_REPO_AND_WORKFLOW_SCOPE }} result-encoding: string @@ -165,24 +174,26 @@ jobs: # Sometimes after updating the branch, there aren't any remaining files changed. # If not, we should close the PR instead of merging it and triggering deployments. - name: Close the pull request if no files remain - if: ${{ steps.find-pull-request.outputs.number && steps.pr-files.outputs.count == '0' }} + if: ${{ steps.pull-request.outputs.result && steps.pr-files.outputs.count == '0' }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR_NUMBER: ${{ steps.pull-request.outputs.result }} run: | - gh pr close ${{ steps.find-pull-request.outputs.number }} --repo $GITHUB_REPOSITORY + gh pr close $PR_NUMBER --repo $GITHUB_REPOSITORY - name: Approve pull request - if: ${{ steps.find-pull-request.outputs.number && steps.pr-files.outputs.count != '0' }} + if: ${{ steps.steps.pull-request.outputs.result && steps.pr-files.outputs.count != '0' }} uses: juliangruber/approve-pull-request-action@dcc4effb325c0b503408619918d56e40653dcc91 with: github-token: ${{ secrets.GITHUB_TOKEN }} - number: ${{ steps.find-pull-request.outputs.number }} + number: ${{ steps.pull-request.outputs.result }} + # Admin merge to avoid being squashed in the merge queue - name: Admin merge the pull request - if: ${{ steps.find-pull-request.outputs.number && steps.pr-files.outputs.count != '0' }} + if: ${{ steps.pull-request.outputs.result && steps.pr-files.outputs.count != '0' }} env: GITHUB_TOKEN: ${{ secrets.OCTOMERGER_PAT_WITH_REPO_AND_WORKFLOW_SCOPE }} - PR_NUMBER: ${{ steps.find-pull-request.outputs.number }} + PR_NUMBER: ${{ steps.pull-request.outputs.result }} run: | gh pr merge $PR_NUMBER --admin --merge @@ -193,4 +204,4 @@ jobs: channel: ${{ secrets.DOCS_ALERTS_SLACK_CHANNEL_ID }} bot-token: ${{ secrets.SLACK_DOCS_BOT_TOKEN }} color: failure - text: The last repo-sync run for ${{github.repository}} failed. See https://github.com/${{github.repository}}/actions?query=workflow%3A%22Repo+Sync%22 + text: The last repo-sync run for ${{github.repository}} failed. See https://github.com/${{github.repository}}/actions/workflows/repo-sync.yml diff --git a/assets/images/enterprise/repository/blame-button.png b/assets/images/enterprise/repository/blame-button.png index c85abf3c96..84a45cbb76 100644 Binary files a/assets/images/enterprise/repository/blame-button.png and b/assets/images/enterprise/repository/blame-button.png differ diff --git a/assets/images/enterprise/repository/edit-file-edit-button.png b/assets/images/enterprise/repository/edit-file-edit-button.png index af6fe2bac0..6cc0c7b0ea 100644 Binary files a/assets/images/enterprise/repository/edit-file-edit-button.png and b/assets/images/enterprise/repository/edit-file-edit-button.png differ diff --git a/assets/images/enterprise/repository/edit-readme-preview-changes.png b/assets/images/enterprise/repository/edit-readme-preview-changes.png index 2ffbb4f120..fd0cd78ba7 100644 Binary files a/assets/images/enterprise/repository/edit-readme-preview-changes.png and b/assets/images/enterprise/repository/edit-readme-preview-changes.png differ diff --git a/assets/images/enterprise/repository/git-blame.png b/assets/images/enterprise/repository/git-blame.png index 6b0b20a0b3..8381756ab1 100644 Binary files a/assets/images/enterprise/repository/git-blame.png and b/assets/images/enterprise/repository/git-blame.png differ diff --git a/assets/images/enterprise/repository/new-file-preview.png b/assets/images/enterprise/repository/new-file-preview.png index 6e6008acc0..75be4b4fa9 100644 Binary files a/assets/images/enterprise/repository/new-file-preview.png and b/assets/images/enterprise/repository/new-file-preview.png differ diff --git a/assets/images/enterprise/repository/raw-file-button.png b/assets/images/enterprise/repository/raw-file-button.png index 3a84eaf6c9..b3711c7197 100644 Binary files a/assets/images/enterprise/repository/raw-file-button.png and b/assets/images/enterprise/repository/raw-file-button.png differ diff --git a/assets/images/enterprise/site-admin-settings/dependabot-alerts-setup-dropdown.png b/assets/images/enterprise/site-admin-settings/dependabot-alerts-setup-dropdown.png index 6713c80d55..019c7a16a6 100644 Binary files a/assets/images/enterprise/site-admin-settings/dependabot-alerts-setup-dropdown.png and b/assets/images/enterprise/site-admin-settings/dependabot-alerts-setup-dropdown.png differ diff --git a/assets/images/github-apps/authorize_app.png b/assets/images/github-apps/authorize_app.png index d25cf67a1d..df6794516b 100644 Binary files a/assets/images/github-apps/authorize_app.png and b/assets/images/github-apps/authorize_app.png differ diff --git a/assets/images/github-apps/install_app.png b/assets/images/github-apps/install_app.png index 2170708b45..d60adaa213 100644 Binary files a/assets/images/github-apps/install_app.png and b/assets/images/github-apps/install_app.png differ diff --git a/assets/images/help/actions/arc-diagram.png b/assets/images/help/actions/arc-diagram.png index 56668357be..fbbcbdea43 100644 Binary files a/assets/images/help/actions/arc-diagram.png and b/assets/images/help/actions/arc-diagram.png differ diff --git a/assets/images/help/billing/update_payment_method_org.png b/assets/images/help/billing/update_payment_method_org.png index c1ea49d7db..9d64630c1f 100644 Binary files a/assets/images/help/billing/update_payment_method_org.png and b/assets/images/help/billing/update_payment_method_org.png differ diff --git a/assets/images/help/billing/update_payment_method_personal_account.png b/assets/images/help/billing/update_payment_method_personal_account.png index 4b10174d29..872c6312db 100644 Binary files a/assets/images/help/billing/update_payment_method_personal_account.png and b/assets/images/help/billing/update_payment_method_personal_account.png differ diff --git a/assets/images/help/billing/view-payment-history-link-personal-account.png b/assets/images/help/billing/view-payment-history-link-personal-account.png index 95446c0a01..72538a65ba 100644 Binary files a/assets/images/help/billing/view-payment-history-link-personal-account.png and b/assets/images/help/billing/view-payment-history-link-personal-account.png differ diff --git a/assets/images/help/branches/branch-selection-dropdown.png b/assets/images/help/branches/branch-selection-dropdown.png index 99bd9ae7ae..33fb446fb6 100644 Binary files a/assets/images/help/branches/branch-selection-dropdown.png and b/assets/images/help/branches/branch-selection-dropdown.png differ diff --git a/assets/images/help/branches/file-tree-view-branch-dropdown.png b/assets/images/help/branches/file-tree-view-branch-dropdown.png index 195f47e278..8ec099ae1f 100644 Binary files a/assets/images/help/branches/file-tree-view-branch-dropdown.png and b/assets/images/help/branches/file-tree-view-branch-dropdown.png differ diff --git a/assets/images/help/codespaces/settings-sync-config-ok.png b/assets/images/help/codespaces/settings-sync-config-ok.png index 8e0e0f3e15..fa3a8098e7 100644 Binary files a/assets/images/help/codespaces/settings-sync-config-ok.png and b/assets/images/help/codespaces/settings-sync-config-ok.png differ diff --git a/assets/images/help/codespaces/who-will-pay-vscode.png b/assets/images/help/codespaces/who-will-pay-vscode.png index 3a86713eb7..afd3e7bdb0 100644 Binary files a/assets/images/help/codespaces/who-will-pay-vscode.png and b/assets/images/help/codespaces/who-will-pay-vscode.png differ diff --git a/assets/images/help/codespaces/who-will-pay.png b/assets/images/help/codespaces/who-will-pay.png index 1623308231..e8cae40624 100644 Binary files a/assets/images/help/codespaces/who-will-pay.png and b/assets/images/help/codespaces/who-will-pay.png differ diff --git a/assets/images/help/copilot/copilot-cancel-trial.png b/assets/images/help/copilot/copilot-cancel-trial.png index c4890901a8..b27cd72b5b 100644 Binary files a/assets/images/help/copilot/copilot-cancel-trial.png and b/assets/images/help/copilot/copilot-cancel-trial.png differ diff --git a/assets/images/help/desktop/ahead-tab.png b/assets/images/help/desktop/ahead-tab.png index 4c1c7b079d..23d35b76af 100644 Binary files a/assets/images/help/desktop/ahead-tab.png and b/assets/images/help/desktop/ahead-tab.png differ diff --git a/assets/images/help/desktop/view-pr-on-github.png b/assets/images/help/desktop/view-pr-on-github.png index 25210219a7..3d921bcdc1 100644 Binary files a/assets/images/help/desktop/view-pr-on-github.png and b/assets/images/help/desktop/view-pr-on-github.png differ diff --git a/assets/images/help/gist/starring-a-gist.png b/assets/images/help/gist/starring-a-gist.png index 506a35fb48..766d6d6ced 100644 Binary files a/assets/images/help/gist/starring-a-gist.png and b/assets/images/help/gist/starring-a-gist.png differ diff --git a/assets/images/help/graphs/activity-view-compare-changes.png b/assets/images/help/graphs/activity-view-compare-changes.png index e9b0798bd8..f9546151da 100644 Binary files a/assets/images/help/graphs/activity-view-compare-changes.png and b/assets/images/help/graphs/activity-view-compare-changes.png differ diff --git a/assets/images/help/graphs/activity-view-embedded-link.png b/assets/images/help/graphs/activity-view-embedded-link.png index 37a72e4888..f4d510c47a 100644 Binary files a/assets/images/help/graphs/activity-view-embedded-link.png and b/assets/images/help/graphs/activity-view-embedded-link.png differ diff --git a/assets/images/help/graphs/activity-view-icon.png b/assets/images/help/graphs/activity-view-icon.png index 061ff2bf45..715b43b109 100644 Binary files a/assets/images/help/graphs/activity-view-icon.png and b/assets/images/help/graphs/activity-view-icon.png differ diff --git a/assets/images/help/projects-v2/filter-for-templates.png b/assets/images/help/projects-v2/filter-for-templates.png index 1efef61ef7..c6dc0475af 100644 Binary files a/assets/images/help/projects-v2/filter-for-templates.png and b/assets/images/help/projects-v2/filter-for-templates.png differ diff --git a/assets/images/help/repository/add-files-buttons.png b/assets/images/help/repository/add-files-buttons.png index 59859ce17d..0845ddf997 100644 Binary files a/assets/images/help/repository/add-files-buttons.png and b/assets/images/help/repository/add-files-buttons.png differ diff --git a/assets/images/help/repository/choose-commit-email-address.png b/assets/images/help/repository/choose-commit-email-address.png index d6d4b45634..fe23d8b225 100644 Binary files a/assets/images/help/repository/choose-commit-email-address.png and b/assets/images/help/repository/choose-commit-email-address.png differ diff --git a/assets/images/help/repository/delete-file-button.png b/assets/images/help/repository/delete-file-button.png index fd6a43b46b..d7c4c56e0c 100644 Binary files a/assets/images/help/repository/delete-file-button.png and b/assets/images/help/repository/delete-file-button.png differ diff --git a/assets/images/help/repository/file-tree-view-branch-dropdown-expanded.png b/assets/images/help/repository/file-tree-view-branch-dropdown-expanded.png index 2f334c4eb7..61f3dba11f 100644 Binary files a/assets/images/help/repository/file-tree-view-branch-dropdown-expanded.png and b/assets/images/help/repository/file-tree-view-branch-dropdown-expanded.png differ diff --git a/assets/images/help/repository/fork_button.png b/assets/images/help/repository/fork_button.png index c8fb42e0f4..f4190488b6 100644 Binary files a/assets/images/help/repository/fork_button.png and b/assets/images/help/repository/fork_button.png differ diff --git a/assets/images/help/repository/https-url-clone-cli.png b/assets/images/help/repository/https-url-clone-cli.png index 8c245d429b..2a57eb0637 100644 Binary files a/assets/images/help/repository/https-url-clone-cli.png and b/assets/images/help/repository/https-url-clone-cli.png differ diff --git a/assets/images/help/repository/new-branch.png b/assets/images/help/repository/new-branch.png index 6f6932c6cb..38c1462e07 100644 Binary files a/assets/images/help/repository/new-branch.png and b/assets/images/help/repository/new-branch.png differ diff --git a/assets/images/help/repository/upload-files-button.png b/assets/images/help/repository/upload-files-button.png index a4371a54ad..53680709b4 100644 Binary files a/assets/images/help/repository/upload-files-button.png and b/assets/images/help/repository/upload-files-button.png differ diff --git a/assets/images/help/settings/scheduled-reminders-org-choice.png b/assets/images/help/settings/scheduled-reminders-org-choice.png index bd7d9e4d07..fd92e11191 100644 Binary files a/assets/images/help/settings/scheduled-reminders-org-choice.png and b/assets/images/help/settings/scheduled-reminders-org-choice.png differ diff --git a/assets/images/help/writing/inline-backtick-math-markdown-rendering.png b/assets/images/help/writing/inline-backtick-math-markdown-rendering.png index c911d17ab1..f5d062228e 100644 Binary files a/assets/images/help/writing/inline-backtick-math-markdown-rendering.png and b/assets/images/help/writing/inline-backtick-math-markdown-rendering.png differ diff --git a/assets/images/help/writing/inline-math-markdown-rendering.png b/assets/images/help/writing/inline-math-markdown-rendering.png index 2f8636c8f0..2ca1c7a476 100644 Binary files a/assets/images/help/writing/inline-math-markdown-rendering.png and b/assets/images/help/writing/inline-math-markdown-rendering.png differ diff --git a/assets/images/help/writing/math-expression-as-a-block-rendering.png b/assets/images/help/writing/math-expression-as-a-block-rendering.png index e99e9b1d92..d7594b0228 100644 Binary files a/assets/images/help/writing/math-expression-as-a-block-rendering.png and b/assets/images/help/writing/math-expression-as-a-block-rendering.png differ diff --git a/assets/images/site/apple-touch-icon-114x114.png b/assets/images/site/apple-touch-icon-114x114.png index 8520369396..1792a42831 100644 Binary files a/assets/images/site/apple-touch-icon-114x114.png and b/assets/images/site/apple-touch-icon-114x114.png differ diff --git a/assets/images/site/apple-touch-icon-120x120.png b/assets/images/site/apple-touch-icon-120x120.png index fbaa2a6ff4..95903a6f89 100644 Binary files a/assets/images/site/apple-touch-icon-120x120.png and b/assets/images/site/apple-touch-icon-120x120.png differ diff --git a/assets/images/site/apple-touch-icon-144x144.png b/assets/images/site/apple-touch-icon-144x144.png index b9eb51f7ea..a7df9a401a 100644 Binary files a/assets/images/site/apple-touch-icon-144x144.png and b/assets/images/site/apple-touch-icon-144x144.png differ diff --git a/assets/images/site/apple-touch-icon-152x152.png b/assets/images/site/apple-touch-icon-152x152.png index 751d286a52..191e190e73 100644 Binary files a/assets/images/site/apple-touch-icon-152x152.png and b/assets/images/site/apple-touch-icon-152x152.png differ diff --git a/assets/images/site/apple-touch-icon-180x180.png b/assets/images/site/apple-touch-icon-180x180.png index 12b4fb0b23..29ab743018 100644 Binary files a/assets/images/site/apple-touch-icon-180x180.png and b/assets/images/site/apple-touch-icon-180x180.png differ diff --git a/assets/images/site/apple-touch-icon-192x192.png b/assets/images/site/apple-touch-icon-192x192.png index 9ecc7c51e3..e23ec12299 100644 Binary files a/assets/images/site/apple-touch-icon-192x192.png and b/assets/images/site/apple-touch-icon-192x192.png differ diff --git a/assets/images/site/apple-touch-icon-512x512.png b/assets/images/site/apple-touch-icon-512x512.png index 8d76a12f5e..280a5e3dc5 100644 Binary files a/assets/images/site/apple-touch-icon-512x512.png and b/assets/images/site/apple-touch-icon-512x512.png differ diff --git a/assets/images/site/apple-touch-icon-57x57.png b/assets/images/site/apple-touch-icon-57x57.png index b6f3340bd7..23f6fc2430 100644 Binary files a/assets/images/site/apple-touch-icon-57x57.png and b/assets/images/site/apple-touch-icon-57x57.png differ diff --git a/assets/images/site/apple-touch-icon-60x60.png b/assets/images/site/apple-touch-icon-60x60.png index 695434160d..81be8bc982 100644 Binary files a/assets/images/site/apple-touch-icon-60x60.png and b/assets/images/site/apple-touch-icon-60x60.png differ diff --git a/assets/images/site/apple-touch-icon-72x72.png b/assets/images/site/apple-touch-icon-72x72.png index 678617e170..b69474e6a7 100644 Binary files a/assets/images/site/apple-touch-icon-72x72.png and b/assets/images/site/apple-touch-icon-72x72.png differ diff --git a/assets/images/site/apple-touch-icon-76x76.png b/assets/images/site/apple-touch-icon-76x76.png index a71c93f36c..be3506dc41 100644 Binary files a/assets/images/site/apple-touch-icon-76x76.png and b/assets/images/site/apple-touch-icon-76x76.png differ diff --git a/components/ui/MarkdownContent/stylesheets/code.scss b/components/ui/MarkdownContent/stylesheets/code.scss index 8816450846..ff3bd837fd 100644 --- a/components/ui/MarkdownContent/stylesheets/code.scss +++ b/components/ui/MarkdownContent/stylesheets/code.scss @@ -10,7 +10,7 @@ overflow: auto; } - [class~="code-extra"] { + [class~="code-example"] { margin-top: 1.5rem; pre, diff --git a/lib/render-content/create-processor.js b/lib/render-content/create-processor.js index eee1179705..7e567b2419 100644 --- a/lib/render-content/create-processor.js +++ b/lib/render-content/create-processor.js @@ -14,7 +14,6 @@ import erb from 'highlight.js/lib/languages/erb' import powershell from 'highlight.js/lib/languages/powershell' import graphql from 'highlight.js/lib/languages/graphql' import html from 'rehype-stringify' -import remarkCodeExtra from 'remark-code-extra' import codeHeader from './plugins/code-header.js' import rewriteLocalLinks from './plugins/rewrite-local-links.js' import rewriteImgSources from './plugins/rewrite-asset-urls.js' @@ -34,7 +33,6 @@ export default function createProcessor(context) { .use(process.env.COMMONMARK ? gfm : null) // Markdown AST below vvv .use(parseInfoString) - .use(remarkCodeExtra, { transform: codeHeader }) .use(emoji) // Markdown AST above ^^^ .use(remark2rehype, { allowDangerousHtml: true }) @@ -42,6 +40,7 @@ export default function createProcessor(context) { .use(slug) .use(useEnglishHeadings, context) .use(headingLinks) + .use(codeHeader) .use(annotate) .use(highlight, { languages: { graphql, dockerfile, http, groovy, erb, powershell }, diff --git a/lib/render-content/plugins/annotate.js b/lib/render-content/plugins/annotate.js index ba2d9e13de..dcd1f42b3e 100644 --- a/lib/render-content/plugins/annotate.js +++ b/lib/render-content/plugins/annotate.js @@ -35,6 +35,7 @@ import { visit } from 'unist-util-visit' import { h } from 'hastscript' import { fromMarkdown } from 'mdast-util-from-markdown' import { toHast } from 'mdast-util-to-hast' +// import { header } from './code-header.js' const languages = yaml.load(fs.readFileSync('./data/variables/code-languages.yml', 'utf8')) @@ -71,7 +72,7 @@ function createAnnotatedNode(node) { const rows = chunk(groups, 2) // Render the HTML - return template({ lang, rows }) + return template({ lang, code, rows }) } function validate(lang, code) { @@ -116,10 +117,11 @@ function matchComment(lang) { return (line) => regex.test(line) } -function template({ lang, rows }) { +function template({ lang, code, rows }) { return h( 'div', { class: 'annotate' }, + // header(lang, code), rows.map(([note, code]) => h('div', { className: 'annotate-row' }, [ h( diff --git a/lib/render-content/plugins/code-header.js b/lib/render-content/plugins/code-header.js index 1c98fbd9c1..b005a040d0 100644 --- a/lib/render-content/plugins/code-header.js +++ b/lib/render-content/plugins/code-header.js @@ -1,105 +1,42 @@ +/** + * Adds a bar above code blocks that shows the language and a copy button + */ + +import yaml from 'js-yaml' +import fs from 'fs' +import { visit } from 'unist-util-visit' import { h } from 'hastscript' import octicons from '@primer/octicons' import { parse } from 'parse5' import { fromParse5 } from 'hast-util-from-parse5' -const LANGUAGE_MAP = { - asp: 'ASP', - aspx: 'ASP', - 'aspx-vb': 'ASP', - as3: 'ActionScript', - apache: 'ApacheConf', - nasm: 'Assembly', - bat: 'Batchfile', - 'c#': 'C#', - csharp: 'C#', - c: 'C', - 'c++': 'C++', - cpp: 'C++', - chpl: 'Chapel', - coffee: 'CoffeeScript', - 'coffee-script': 'CoffeeScript', - cfm: 'ColdFusion', - 'common-lisp': 'Common Lisp', - lisp: 'Common Lisp', - dpatch: 'Darcs Patch', - dart: 'Dart', - elisp: 'Emacs Lisp', - emacs: 'Emacs Lisp', - 'emacs-lisp': 'Emacs Lisp', - pot: 'Gettext Catalog', - html: 'HTML', - xhtml: 'HTML', - 'html+erb': 'HTML+ERB', - erb: 'HTML+ERB', - irc: 'IRC log', - json: 'JSON', - jsp: 'Java Server Pages', - java: 'Java', - javascript: 'JavaScript', - js: 'JavaScript', - lhs: 'Literate Haskell', - 'literate-haskell': 'Literate Haskell', - objc: 'Objective-C', - openedge: 'OpenEdge ABL', - progress: 'OpenEdge ABL', - abl: 'OpenEdge ABL', - pir: 'Parrot Internal Representation', - posh: 'PowerShell', - puppet: 'Puppet', - 'pure-data': 'Pure Data', - raw: 'Raw token data', - rb: 'Ruby', - ruby: 'Ruby', - r: 'R', - scheme: 'Scheme', - bash: 'Shell', - sh: 'Shell', - shell: 'Shell', - zsh: 'Shell', - supercollider: 'SuperCollider', - tex: 'TeX', - ts: 'TypeScript', - vim: 'Vim script', - viml: 'Vim script', - rst: 'reStructuredText', - xbm: 'X BitMap', - xpm: 'X PixMap', - yaml: 'YAML', - yml: 'YAML', +const languages = yaml.load(fs.readFileSync('./data/variables/code-languages.yml', 'utf8')) - // Unofficial languages - shellsession: 'Shell', - jsx: 'JSX', +const matcher = (node) => + node.type === 'element' && + node.tagName === 'pre' && + // For now, limit to ones with the copy meta, + // but we may enable for all examples later. + getPreMeta(node).copy && + // Don't add this header for annotated examples. + !getPreMeta(node).annotate + +export default function codeHeader() { + return (tree) => { + visit(tree, matcher, (node, index, parent) => { + parent.children[index] = wrapCodeExample(node) + }) + } } -const COPY_REGEX = /\{:copy\}$/ +function wrapCodeExample(node) { + const lang = node.children[0].properties.className?.[0].replace('language-', '') + const code = node.children[0].children[0].value + return h('div', { className: 'code-example' }, [header(lang, code), node]) +} -/** - * Adds a bar above code blocks that shows the language and a copy button - */ -export default function addCodeHeader(node) { - // Check if the language matches `lang{:copy}` - const hasCopy = node.lang && COPY_REGEX.test(node.lang) - - if (hasCopy) { - // js{:copy} => js - node.lang = node.lang.replace(COPY_REGEX, '') - } else { - // It doesn't have the copy annotation, so don't add the header - return - } - - // Display the language using the above map of `{ [shortCode]: language }` - const language = LANGUAGE_MAP[node.lang] || node.lang || 'Code' - - const btnIconHtml = octicons.copy.toSVG() - const btnIconAst = parse(String(btnIconHtml), { sourceCodeLocationInfo: true }) - const btnIcon = fromParse5(btnIconAst, { file: btnIconHtml }) - - // Need to create the header using Markdown AST utilities, to fit - // into the Unified processor ecosystem. - const header = h( +export function header(lang, code) { + return h( 'header', { class: [ @@ -109,24 +46,35 @@ export default function addCodeHeader(node) { 'p-2', 'text-small', 'rounded-top-1', - 'border', + 'border-top', + 'border-left', + 'border-right', ], }, [ - h('span', language), + h('span', languages[lang]?.name), h( 'button', { class: ['js-btn-copy', 'btn', 'btn-sm', 'tooltipped', 'tooltipped-nw'], - 'data-clipboard-text': node.value, + 'data-clipboard-text': code, 'aria-label': 'Copy code to clipboard', }, - btnIcon + btnIcon() ), ] ) - - return { - before: [header], - } +} + +function btnIcon() { + const btnIconHtml = octicons.copy.toSVG() + const btnIconAst = parse(String(btnIconHtml), { sourceCodeLocationInfo: true }) + const btnIcon = fromParse5(btnIconAst, { file: btnIconHtml }) + return btnIcon +} + +function getPreMeta(node) { + // Here's why this monstrosity works: + // https://github.com/syntax-tree/mdast-util-to-hast/blob/c87cd606731c88a27dbce4bfeaab913a9589bf83/lib/handlers/code.js#L40-L42 + return node.children[0]?.data?.meta || {} } diff --git a/lib/render-content/plugins/parse-info-string.js b/lib/render-content/plugins/parse-info-string.js index 920d3cdf6b..4b27c40e90 100644 --- a/lib/render-content/plugins/parse-info-string.js +++ b/lib/render-content/plugins/parse-info-string.js @@ -7,17 +7,26 @@ import { visit } from 'unist-util-visit' -const matcher = (node) => node.type === 'code' && node.lang && node.meta +const matcher = (node) => node.type === 'code' && node.lang export default function parseInfoString() { return (tree) => { visit(tree, matcher, (node) => { node.meta = strToObj(node.meta) + + // Temporary, change {:copy} to ` copy` to avoid conflict in styles. + // We may end up enabling copy on all code examples later. + const copyTag = '{:copy}' + if (node.lang.includes(copyTag)) { + node.meta.copy = true + node.lang = node.lang.replace(copyTag, '') + } }) } } function strToObj(str) { + if (!str) return {} return Object.fromEntries( str .split(/\s+/g) diff --git a/package-lock.json b/package-lock.json index d65fcc3508..327c1a76c6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -73,7 +73,6 @@ "rehype-raw": "^6.1.1", "rehype-slug": "^5.0.1", "rehype-stringify": "^9.0.3", - "remark-code-extra": "^1.0.1", "remark-gemoji-to-emoji": "^1.1.0", "remark-gfm": "^3.0.1", "remark-parse": "^10.0.1", @@ -16424,31 +16423,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/remark-code-extra": { - "version": "1.0.1", - "license": "MIT", - "dependencies": { - "unist-util-visit": "^1.4.1" - } - }, - "node_modules/remark-code-extra/node_modules/unist-util-is": { - "version": "3.0.0", - "license": "MIT" - }, - "node_modules/remark-code-extra/node_modules/unist-util-visit": { - "version": "1.4.1", - "license": "MIT", - "dependencies": { - "unist-util-visit-parents": "^2.0.0" - } - }, - "node_modules/remark-code-extra/node_modules/unist-util-visit-parents": { - "version": "2.1.2", - "license": "MIT", - "dependencies": { - "unist-util-is": "^3.0.0" - } - }, "node_modules/remark-gemoji-to-emoji": { "version": "1.1.0", "license": "MIT", @@ -30242,29 +30216,6 @@ "unified": "^10.0.0" } }, - "remark-code-extra": { - "version": "1.0.1", - "requires": { - "unist-util-visit": "^1.4.1" - }, - "dependencies": { - "unist-util-is": { - "version": "3.0.0" - }, - "unist-util-visit": { - "version": "1.4.1", - "requires": { - "unist-util-visit-parents": "^2.0.0" - } - }, - "unist-util-visit-parents": { - "version": "2.1.2", - "requires": { - "unist-util-is": "^3.0.0" - } - } - } - }, "remark-gemoji-to-emoji": { "version": "1.1.0", "requires": { diff --git a/package.json b/package.json index 0a1ad992c3..30a70c1c2d 100644 --- a/package.json +++ b/package.json @@ -120,7 +120,6 @@ "rehype-raw": "^6.1.1", "rehype-slug": "^5.0.1", "rehype-stringify": "^9.0.3", - "remark-code-extra": "^1.0.1", "remark-gemoji-to-emoji": "^1.1.0", "remark-gfm": "^3.0.1", "remark-parse": "^10.0.1", diff --git a/src/codeql-cli/scripts/convert-markdown-for-docs.js b/src/codeql-cli/scripts/convert-markdown-for-docs.js index 4e535c1d29..41eb4caec3 100644 --- a/src/codeql-cli/scripts/convert-markdown-for-docs.js +++ b/src/codeql-cli/scripts/convert-markdown-for-docs.js @@ -86,7 +86,8 @@ export async function convertContentToDocs(content, frontmatterDefaults = {}) { visitParents(ast, matcher, (node, ancestors) => { // Add the copy button to the example command if (node.type === 'code' && node.value.startsWith(`codeql ${frontmatter.title}`)) { - node.lang = 'shell{:copy}' + node.lang = 'shell' + node.meta = 'copy' } // This is the beginning of a secondary options section. For example, diff --git a/tests/unit/render-content.js b/tests/unit/render-content.js index 94ee37bc93..98525ea3b6 100644 --- a/tests/unit/render-content.js +++ b/tests/unit/render-content.js @@ -248,12 +248,12 @@ $resourceGroupName = "octocat-testgroup" test('does not autoguess code block language', async () => { const template = nl(` \`\`\` -some code -\`\`\`\ +var a = 1 +\`\`\` `) const html = await renderContent(template) const $ = cheerio.load(html, { xmlMode: true }) - expect($.html().includes('
some code\n
')).toBeTruthy() + expect($.html().includes('var a = 1')).toBeTruthy() }) test('renders a line break in a table', async () => { @@ -267,15 +267,15 @@ some code ) }) - test('renders a copy button for code blocks with {:copy} annotation', async () => { + test('renders a copy button for code blocks with language specified', async () => { const template = nl(` -\`\`\`js{:copy} -some code -\`\`\`\ +\`\`\`javascript copy +var a = 1 +\`\`\` `) const html = await renderContent(template) const $ = cheerio.load(html) const el = $('button.js-btn-copy') - expect(el.data('clipboard-text')).toBe('some code') + expect(el.data('clipboard-text')).toBe('var a = 1\n') }) })