From bd86e027aa25f15bd031df87f63ab25805e4d78e Mon Sep 17 00:00:00 2001 From: Josh Black Date: Thu, 12 Oct 2023 11:01:11 -0500 Subject: [PATCH 01/27] chore: restore default changeset behavior (#3801) * chore: restore default changeset behavior * chore: add @types/semver --------- Co-authored-by: Josh Black --- .github/workflows/changesets.yml | 24 --- .github/workflows/check_for_changeset.yml | 25 +++ package-lock.json | 215 ++++++++-------------- package.json | 3 +- 4 files changed, 99 insertions(+), 168 deletions(-) delete mode 100644 .github/workflows/changesets.yml create mode 100644 .github/workflows/check_for_changeset.yml diff --git a/.github/workflows/changesets.yml b/.github/workflows/changesets.yml deleted file mode 100644 index 614167cc9afd..000000000000 --- a/.github/workflows/changesets.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: Changesets -'on': - pull_request: - types: [opened, synchronize, reopened, labeled, unlabeled] - -jobs: - validate: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Set up Node.js - uses: actions/setup-node@v3 - with: - node-version: 18 - cache: 'npm' - - name: Install dependencies - run: npm ci - # This step generates the generated/components.json file expected by the - # validator action - - name: Build - run: npm run build - - uses: gr2m/primer-release-changesets-validator-action@v1 diff --git a/.github/workflows/check_for_changeset.yml b/.github/workflows/check_for_changeset.yml new file mode 100644 index 000000000000..098aaa5d2a6c --- /dev/null +++ b/.github/workflows/check_for_changeset.yml @@ -0,0 +1,25 @@ +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' diff --git a/package-lock.json b/package-lock.json index bb122433c98a..15b7a0a9a229 100644 --- a/package-lock.json +++ b/package-lock.json @@ -51,6 +51,7 @@ "@babel/preset-react": "7.22.15", "@babel/preset-typescript": "7.22.15", "@changesets/changelog-github": "0.4.8", + "@changesets/cli": "2.26.2", "@github/markdownlint-github": "^0.3.0", "@github/prettier-config": "0.0.6", "@playwright/test": "1.37.0", @@ -92,6 +93,7 @@ "@types/node": "18.16.19", "@types/react": "18.2.21", "@types/react-dom": "18.2.6", + "@types/semver": "7.5.3", "@typescript-eslint/eslint-plugin": "5.59.6", "@typescript-eslint/parser": "5.62.0", "ajv": "8.12.0", @@ -151,7 +153,6 @@ "postcss-custom-properties-fallback": "1.0.2", "postcss-preset-env": "9.0.0", "prettier": "3.0.1", - "primer-changesets-cli": "2.2.1", "react": "18.2.0", "react-dnd": "14.0.4", "react-dnd-html5-backend": "14.0.2", @@ -2317,13 +2318,13 @@ "dev": true }, "node_modules/@changesets/apply-release-plan": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/@changesets/apply-release-plan/-/apply-release-plan-6.1.3.tgz", - "integrity": "sha512-ECDNeoc3nfeAe1jqJb5aFQX7CqzQhD2klXRez2JDb/aVpGUbX673HgKrnrgJRuQR/9f2TtLoYIzrGB9qwD77mg==", + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@changesets/apply-release-plan/-/apply-release-plan-6.1.4.tgz", + "integrity": "sha512-FMpKF1fRlJyCZVYHr3CbinpZZ+6MwvOtWUuO8uo+svcATEoc1zRDcj23pAurJ2TZ/uVz1wFHH6K3NlACy0PLew==", "dev": true, "dependencies": { "@babel/runtime": "^7.20.1", - "@changesets/config": "^2.3.0", + "@changesets/config": "^2.3.1", "@changesets/get-version-range-type": "^0.3.2", "@changesets/git": "^2.0.0", "@changesets/types": "^5.2.1", @@ -2334,7 +2335,7 @@ "outdent": "^0.5.0", "prettier": "^2.7.1", "resolve-from": "^5.0.0", - "semver": "^5.4.1" + "semver": "^7.5.3" } }, "node_modules/@changesets/apply-release-plan/node_modules/prettier": { @@ -2352,36 +2353,18 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/@changesets/apply-release-plan/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, "node_modules/@changesets/assemble-release-plan": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/@changesets/assemble-release-plan/-/assemble-release-plan-5.2.3.tgz", - "integrity": "sha512-g7EVZCmnWz3zMBAdrcKhid4hkHT+Ft1n0mLussFMcB1dE2zCuwcvGoy9ec3yOgPGF4hoMtgHaMIk3T3TBdvU9g==", + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/@changesets/assemble-release-plan/-/assemble-release-plan-5.2.4.tgz", + "integrity": "sha512-xJkWX+1/CUaOUWTguXEbCDTyWJFECEhmdtbkjhn5GVBGxdP/JwaHBIU9sW3FR6gD07UwZ7ovpiPclQZs+j+mvg==", "dev": true, "dependencies": { "@babel/runtime": "^7.20.1", "@changesets/errors": "^0.1.4", - "@changesets/get-dependents-graph": "^1.3.5", + "@changesets/get-dependents-graph": "^1.3.6", "@changesets/types": "^5.2.1", "@manypkg/get-packages": "^1.1.3", - "semver": "^5.4.1" - } - }, - "node_modules/@changesets/assemble-release-plan/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" + "semver": "^7.5.3" } }, "node_modules/@changesets/changelog-git": { @@ -2404,14 +2387,58 @@ "dotenv": "^8.1.0" } }, + "node_modules/@changesets/cli": { + "version": "2.26.2", + "resolved": "https://registry.npmjs.org/@changesets/cli/-/cli-2.26.2.tgz", + "integrity": "sha512-dnWrJTmRR8bCHikJHl9b9HW3gXACCehz4OasrXpMp7sx97ECuBGGNjJhjPhdZNCvMy9mn4BWdplI323IbqsRig==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.20.1", + "@changesets/apply-release-plan": "^6.1.4", + "@changesets/assemble-release-plan": "^5.2.4", + "@changesets/changelog-git": "^0.1.14", + "@changesets/config": "^2.3.1", + "@changesets/errors": "^0.1.4", + "@changesets/get-dependents-graph": "^1.3.6", + "@changesets/get-release-plan": "^3.0.17", + "@changesets/git": "^2.0.0", + "@changesets/logger": "^0.0.5", + "@changesets/pre": "^1.0.14", + "@changesets/read": "^0.5.9", + "@changesets/types": "^5.2.1", + "@changesets/write": "^0.2.3", + "@manypkg/get-packages": "^1.1.3", + "@types/is-ci": "^3.0.0", + "@types/semver": "^7.5.0", + "ansi-colors": "^4.1.3", + "chalk": "^2.1.0", + "enquirer": "^2.3.0", + "external-editor": "^3.1.0", + "fs-extra": "^7.0.1", + "human-id": "^1.0.2", + "is-ci": "^3.0.1", + "meow": "^6.0.0", + "outdent": "^0.5.0", + "p-limit": "^2.2.0", + "preferred-pm": "^3.0.0", + "resolve-from": "^5.0.0", + "semver": "^7.5.3", + "spawndamnit": "^2.0.0", + "term-size": "^2.1.0", + "tty-table": "^4.1.5" + }, + "bin": { + "changeset": "bin.js" + } + }, "node_modules/@changesets/config": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@changesets/config/-/config-2.3.0.tgz", - "integrity": "sha512-EgP/px6mhCx8QeaMAvWtRrgyxW08k/Bx2tpGT+M84jEdX37v3VKfh4Cz1BkwrYKuMV2HZKeHOh8sHvja/HcXfQ==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@changesets/config/-/config-2.3.1.tgz", + "integrity": "sha512-PQXaJl82CfIXddUOppj4zWu+987GCw2M+eQcOepxN5s+kvnsZOwjEJO3DH9eVy+OP6Pg/KFEWdsECFEYTtbg6w==", "dev": true, "dependencies": { "@changesets/errors": "^0.1.4", - "@changesets/get-dependents-graph": "^1.3.5", + "@changesets/get-dependents-graph": "^1.3.6", "@changesets/logger": "^0.0.5", "@changesets/types": "^5.2.1", "@manypkg/get-packages": "^1.1.3", @@ -2429,25 +2456,16 @@ } }, "node_modules/@changesets/get-dependents-graph": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@changesets/get-dependents-graph/-/get-dependents-graph-1.3.5.tgz", - "integrity": "sha512-w1eEvnWlbVDIY8mWXqWuYE9oKhvIaBhzqzo4ITSJY9hgoqQ3RoBqwlcAzg11qHxv/b8ReDWnMrpjpKrW6m1ZTA==", + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/@changesets/get-dependents-graph/-/get-dependents-graph-1.3.6.tgz", + "integrity": "sha512-Q/sLgBANmkvUm09GgRsAvEtY3p1/5OCzgBE5vX3vgb5CvW0j7CEljocx5oPXeQSNph6FXulJlXV3Re/v3K3P3Q==", "dev": true, "dependencies": { "@changesets/types": "^5.2.1", "@manypkg/get-packages": "^1.1.3", "chalk": "^2.1.0", "fs-extra": "^7.0.1", - "semver": "^5.4.1" - } - }, - "node_modules/@changesets/get-dependents-graph/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" + "semver": "^7.5.3" } }, "node_modules/@changesets/get-github-info": { @@ -2461,14 +2479,14 @@ } }, "node_modules/@changesets/get-release-plan": { - "version": "3.0.16", - "resolved": "https://registry.npmjs.org/@changesets/get-release-plan/-/get-release-plan-3.0.16.tgz", - "integrity": "sha512-OpP9QILpBp1bY2YNIKFzwigKh7Qe9KizRsZomzLe6pK8IUo8onkAAVUD8+JRKSr8R7d4+JRuQrfSSNlEwKyPYg==", + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/@changesets/get-release-plan/-/get-release-plan-3.0.17.tgz", + "integrity": "sha512-6IwKTubNEgoOZwDontYc2x2cWXfr6IKxP3IhKeK+WjyD6y3M4Gl/jdQvBw+m/5zWILSOCAaGLu2ZF6Q+WiPniw==", "dev": true, "dependencies": { "@babel/runtime": "^7.20.1", - "@changesets/assemble-release-plan": "^5.2.3", - "@changesets/config": "^2.3.0", + "@changesets/assemble-release-plan": "^5.2.4", + "@changesets/config": "^2.3.1", "@changesets/pre": "^1.0.14", "@changesets/read": "^0.5.9", "@changesets/types": "^5.2.1", @@ -7653,12 +7671,6 @@ "integrity": "sha512-6sfo1qTulpVbkxECP+AVrHV9OoJqhzCsfTNp5NIG+enM4HyM3HvZCO798WShIXBN0+QtDIcutJCjsVYnQP5rIQ==", "dev": true }, - "node_modules/@storybook/builder-webpack5/node_modules/@types/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", - "dev": true - }, "node_modules/@storybook/builder-webpack5/node_modules/fs-extra": { "version": "11.1.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", @@ -7792,12 +7804,6 @@ "url": "https://opencollective.com/storybook" } }, - "node_modules/@storybook/cli/node_modules/@types/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", - "dev": true - }, "node_modules/@storybook/cli/node_modules/agent-base": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz", @@ -8933,12 +8939,6 @@ "integrity": "sha512-6sfo1qTulpVbkxECP+AVrHV9OoJqhzCsfTNp5NIG+enM4HyM3HvZCO798WShIXBN0+QtDIcutJCjsVYnQP5rIQ==", "dev": true }, - "node_modules/@storybook/core-server/node_modules/@types/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", - "dev": true - }, "node_modules/@storybook/core-server/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -9421,12 +9421,6 @@ "integrity": "sha512-6sfo1qTulpVbkxECP+AVrHV9OoJqhzCsfTNp5NIG+enM4HyM3HvZCO798WShIXBN0+QtDIcutJCjsVYnQP5rIQ==", "dev": true }, - "node_modules/@storybook/preset-react-webpack/node_modules/@types/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", - "dev": true - }, "node_modules/@storybook/preset-react-webpack/node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -12566,9 +12560,9 @@ "integrity": "sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA==" }, "node_modules/@types/semver": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-6.2.3.tgz", - "integrity": "sha512-KQf+QAMWKMrtBMsB8/24w53tEsxllMj6TuA80TT/5igJalLI/zm0L3oXRbIAl4Ohfc85gyHX/jhMwsVkmhLU4A==", + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.3.tgz", + "integrity": "sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==", "dev": true }, "node_modules/@types/serve-static": { @@ -12935,12 +12929,6 @@ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/@types/semver": { - "version": "7.3.13", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", - "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", - "dev": true - }, "node_modules/@typescript-eslint/visitor-keys": { "version": "5.59.6", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.6.tgz", @@ -18678,12 +18666,6 @@ "eslint": "^8.0.1" } }, - "node_modules/eslint-plugin-primer-react/node_modules/@types/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", - "dev": true - }, "node_modules/eslint-plugin-primer-react/node_modules/@typescript-eslint/eslint-plugin": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.2.1.tgz", @@ -34441,59 +34423,6 @@ "node": ">= 0.8" } }, - "node_modules/primer-changesets-cli": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/primer-changesets-cli/-/primer-changesets-cli-2.2.1.tgz", - "integrity": "sha512-k+/gXOw+2+Bwve1ZaquQII1eqOn/S7hzrNWYZ0nCF/ZD+4/LIPe7ekRpDFwcUT3ufWlN3HRXkAX+7CDL7KSd3A==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.20.1", - "@changesets/apply-release-plan": "^6.1.3", - "@changesets/assemble-release-plan": "^5.2.3", - "@changesets/changelog-git": "^0.1.14", - "@changesets/config": "^2.3.0", - "@changesets/errors": "^0.1.4", - "@changesets/get-dependents-graph": "^1.3.5", - "@changesets/get-release-plan": "^3.0.16", - "@changesets/git": "^2.0.0", - "@changesets/logger": "^0.0.5", - "@changesets/pre": "^1.0.14", - "@changesets/read": "^0.5.9", - "@changesets/types": "^5.2.1", - "@changesets/write": "^0.2.3", - "@manypkg/get-packages": "^1.1.3", - "@types/is-ci": "^3.0.0", - "@types/semver": "^6.0.0", - "ansi-colors": "^4.1.3", - "chalk": "^2.1.0", - "enquirer": "^2.3.0", - "external-editor": "^3.1.0", - "fs-extra": "^7.0.1", - "human-id": "^1.0.2", - "is-ci": "^3.0.1", - "meow": "^6.0.0", - "outdent": "^0.5.0", - "p-limit": "^2.2.0", - "preferred-pm": "^3.0.0", - "resolve-from": "^5.0.0", - "semver": "^5.4.1", - "spawndamnit": "^2.0.0", - "term-size": "^2.1.0", - "tty-table": "^4.1.5" - }, - "bin": { - "changeset": "bin.js" - } - }, - "node_modules/primer-changesets-cli/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, "node_modules/prismjs": { "version": "1.28.0", "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.28.0.tgz", diff --git a/package.json b/package.json index 009eda6ced58..08c42ecc6da7 100644 --- a/package.json +++ b/package.json @@ -136,6 +136,7 @@ "@babel/preset-react": "7.22.15", "@babel/preset-typescript": "7.22.15", "@changesets/changelog-github": "0.4.8", + "@changesets/cli": "2.26.2", "@github/markdownlint-github": "^0.3.0", "@github/prettier-config": "0.0.6", "@playwright/test": "1.37.0", @@ -177,6 +178,7 @@ "@types/node": "18.16.19", "@types/react": "18.2.21", "@types/react-dom": "18.2.6", + "@types/semver": "7.5.3", "@typescript-eslint/eslint-plugin": "5.59.6", "@typescript-eslint/parser": "5.62.0", "ajv": "8.12.0", @@ -236,7 +238,6 @@ "postcss-custom-properties-fallback": "1.0.2", "postcss-preset-env": "9.0.0", "prettier": "3.0.1", - "primer-changesets-cli": "2.2.1", "react": "18.2.0", "react-dnd": "14.0.4", "react-dnd-html5-backend": "14.0.2", From 30b7deed3ad00b3f5c4604d355cb13f58cb7ed1d Mon Sep 17 00:00:00 2001 From: Josh Black Date: Thu, 12 Oct 2023 11:36:20 -0500 Subject: [PATCH 02/27] test: get all public exports from package entrypoints (#3733) * test: add experiment for getting all public exports * chore: try to add ts types * test: add support for additional export members * test: update snapshots * Delete script/get-exports.mjs --------- Co-authored-by: Josh Black --- package-lock.json | 7 +- package.json | 1 + .../__snapshots__/exports.test.ts.snap | 347 +++++++++- src/__tests__/exports.test.ts | 607 +++++++++++++++++- 4 files changed, 935 insertions(+), 27 deletions(-) diff --git a/package-lock.json b/package-lock.json index 15b7a0a9a229..f279a87a2a8d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -45,6 +45,7 @@ "@babel/cli": "7.22.10", "@babel/core": "7.22.5", "@babel/eslint-parser": "7.21.3", + "@babel/parser": "7.22.16", "@babel/plugin-proposal-nullish-coalescing-operator": "7.18.6", "@babel/plugin-proposal-optional-chaining": "7.21.0", "@babel/plugin-transform-modules-commonjs": "7.22.15", @@ -762,9 +763,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.7.tgz", - "integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==", + "version": "7.22.16", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz", + "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==", "dev": true, "bin": { "parser": "bin/babel-parser.js" diff --git a/package.json b/package.json index 08c42ecc6da7..5bf6768c0122 100644 --- a/package.json +++ b/package.json @@ -130,6 +130,7 @@ "@babel/cli": "7.22.10", "@babel/core": "7.22.5", "@babel/eslint-parser": "7.21.3", + "@babel/parser": "7.22.16", "@babel/plugin-proposal-nullish-coalescing-operator": "7.18.6", "@babel/plugin-proposal-optional-chaining": "7.21.0", "@babel/plugin-transform-modules-commonjs": "7.22.15", diff --git a/src/__tests__/__snapshots__/exports.test.ts.snap b/src/__tests__/__snapshots__/exports.test.ts.snap index 28fbb4963c97..44dc3a0e7c63 100644 --- a/src/__tests__/__snapshots__/exports.test.ts.snap +++ b/src/__tests__/__snapshots__/exports.test.ts.snap @@ -3,83 +3,196 @@ exports[`@primer/react should not update exports without a semver change 1`] = ` [ "ActionList", + "type ActionListDescriptionProps", + "type ActionListDividerProps", + "type ActionListGroupProps", + "type ActionListItemProps", + "type ActionListLeadingVisualProps", + "type ActionListLinkItemProps", + "type ActionListProps", + "type ActionListTrailingVisualProps", "ActionMenu", + "type ActionMenuAnchorProps", + "type ActionMenuButtonProps", + "type ActionMenuProps", "AnchoredOverlay", + "type AnchoredOverlayProps", "Autocomplete", + "type AutocompleteInputProps", + "type AutocompleteMenuProps", + "type AutocompleteOverlayProps", "Avatar", "AvatarPair", + "type AvatarPairProps", + "type AvatarProps", "AvatarStack", + "type AvatarStackProps", "AvatarToken", "BaseStyles", + "type BaseStylesProps", "Box", + "type BoxProps", "BranchName", + "type BranchNameProps", "Breadcrumb", + "type BreadcrumbItemProps", + "type BreadcrumbProps", "Breadcrumbs", + "type BreadcrumbsItemProps", + "type BreadcrumbsProps", "Button", "ButtonGroup", + "type ButtonGroupProps", + "type ButtonProps", "Caret", + "type CaretProps", "Checkbox", "CheckboxGroup", + "type CheckboxProps", "CircleBadge", + "type CircleBadgeIconProps", + "type CircleBadgeProps", "CircleOcticon", + "type CircleOcticonProps", "ConfirmationDialog", + "type ConfirmationDialogProps", "CounterLabel", + "type CounterLabelProps", "Details", + "type DetailsProps", "Dialog", - "FilterList", + "type DialogHeaderProps", + "type DialogProps", "FilteredSearch", + "type FilteredSearchProps", + "FilterList", + "type FilterListItemProps", + "type FilterListProps", "Flash", + "type FlashProps", + "type FocusTrapHookSettings", + "type FocusZoneHookSettings", "FormControl", "Header", + "type HeaderItemProps", + "type HeaderLinkProps", + "type HeaderProps", "Heading", + "type HeadingProps", "IconButton", + "type IconButtonProps", "IssueLabelToken", "Label", "LabelGroup", + "type LabelGroupProps", + "type LabelProps", "Link", "LinkButton", + "type LinkProps", + "merge", "NavList", + "type NavListDividerProps", + "type NavListGroupProps", + "type NavListItemProps", + "type NavListLeadingVisualProps", + "type NavListProps", + "type NavListSubNavProps", + "type NavListTrailingVisualProps", "Octicon", + "type OcticonProps", "Overlay", - "PageLayout", + "type OverlayProps", "Pagehead", + "type PageheadProps", + "PageLayout", + "type PageLayoutContentProps", + "type PageLayoutFooterProps", + "type PageLayoutHeaderProps", + "type PageLayoutPaneProps", + "type PageLayoutProps", "Pagination", + "type PaginationProps", "PointerBox", + "type PointerBoxProps", "Popover", + "type PopoverContentProps", + "type PopoverProps", "Portal", + "type PortalProps", "ProgressBar", + "type ProgressBarProps", "Radio", "RadioGroup", + "type RadioProps", + "registerPortalRoot", "RelativeTime", - "SSRProvider", + "type RelativeTimeProps", "SegmentedControl", "Select", "SelectPanel", + "type SelectPanelProps", + "type SelectProps", "SideNav", + "type SideNavLinkProps", + "type SideNavProps", "Spinner", + "type SpinnerProps", "SplitPageLayout", + "type SplitPageLayoutContentProps", + "type SplitPageLayoutFooterProps", + "type SplitPageLayoutHeaderProps", + "type SplitPageLayoutPaneProps", + "type SplitPageLayoutProps", + "SSRProvider", "StateLabel", + "type StateLabelProps", "StyledOcticon", + "type StyledOcticonProps", "SubNav", + "type SubNavLinkProps", + "type SubNavLinksProps", + "type SubNavProps", + "sx", + "type SxProp", "TabNav", + "type TabNavLinkProps", + "type TabNavProps", "Text", + "Textarea", + "type TextareaProps", "TextInput", + "type TextInputProps", "TextInputWithTokens", - "Textarea", + "type TextInputWithTokensProps", + "type TextProps", + "theme", + "themeGet", "ThemeProvider", + "type ThemeProviderProps", "Timeline", + "type TimelineBadgeProps", + "type TimelineBodyProps", + "type TimelineBreakProps", + "type TimelineItemsProps", + "type TimelineProps", "ToggleSwitch", "Token", + "type TokenProps", "Tooltip", + "type TooltipProps", + "type TouchOrMouseEvent", "TreeView", + "type TreeViewErrorDialogProps", + "type TreeViewItemProps", + "type TreeViewProps", + "type TreeViewSubTreeProps", + "type TreeViewVisualProps", "Truncate", + "type TruncateProps", "UnderlineNav", "UnderlineNav2", - "merge", - "registerPortalRoot", - "sx", - "theme", - "themeGet", + "type UnderlineNavLinkProps", + "type UnderlineNavProps", "useColorSchemeVar", "useConfirm", "useDetails", @@ -93,72 +206,282 @@ exports[`@primer/react should not update exports without a semver change 1`] = ` "useRefObjectAsForwardedRef", "useResizeObserver", "useResponsiveValue", - "useSSRSafeId", "useSafeTimeout", + "useSSRSafeId", "useTheme", ] `; -exports[`@primer/react/decprecated should not update exports without a semver change 1`] = ` +exports[`@primer/react/deprecated should not update exports without a semver change 1`] = ` [ "Absolute", + "type AbsoluteProps", "ActionList", + "type ActionListProps", "ActionMenu", + "type ActionMenuProps", "BorderBox", + "type BorderBoxProps", "Button", "ButtonClose", + "type ButtonCloseProps", "ButtonDanger", + "type ButtonDangerProps", "ButtonInvisible", + "type ButtonInvisibleProps", "ButtonOutline", + "type ButtonOutlineProps", "ButtonPrimary", + "type ButtonPrimaryProps", + "type ButtonProps", "ButtonTableList", + "type ButtonTableListProps", "ChoiceFieldset", "ChoiceInputField", "Dropdown", "DropdownButton", + "type DropdownButtonProps", + "type DropdownCaretProps", + "type DropdownItemProps", "DropdownMenu", - "FilterList", + "type DropdownMenuProps", + "type DropdownProps", "FilteredSearch", + "type FilteredSearchProps", + "FilterList", + "type FilterListItemProps", + "type FilterListProps", "Fixed", + "type FixedProps", "Flex", + "type FlexProps", "FormGroup", + "type FormGroupLabelProps", + "type FormGroupProps", "Grid", + "type GridProps", "InputField", "Item", "Label", + "type LabelProps", "Position", + "type PositionProps", "Relative", + "type RelativeProps", "SelectMenu", + "type SelectMenuDividerProps", + "type SelectMenuFilterProps", + "type SelectMenuFooterProps", + "type SelectMenuHeaderProps", + "type SelectMenuItemProps", + "type SelectMenuListProps", + "type SelectMenuLoadingAnimationProps", + "type SelectMenuModalProps", + "type SelectMenuProps", + "type SelectMenuTabPanelProps", + "type SelectMenuTabProps", + "type SelectMenuTabsProps", "Sticky", + "type StickyProps", "UnderlineNav", + "type UnderlineNavLinkProps", + "type UnderlineNavProps", ] `; exports[`@primer/react/drafts should not update exports without a semver change 1`] = ` [ "Blankslate", + "type BlankslateProps", + "callbackCancelledResult", + "type CallbackCancelledResult", + "type ChildrenPropTypes", + "type Column", + "type ComboboxCommitEvent", "Content", + "createColumnHelper", "DataTable", + "type DataTableProps", + "default", + "default", "Dialog", + "type DialogButtonProps", + "type DialogHeaderProps", + "type DialogHeight", + "type DialogProps", + "type DialogWidth", + "type Emoji", + "type FileType", + "type FileUploadResult", "Footer", "Header", "Hidden", + "type HiddenProps", "InlineAutocomplete", + "type InlineAutocompleteProps", + "type InteractiveMarkdownViewerProps", "MarkdownEditor", + "type MarkdownEditorHandle", + "type MarkdownEditorProps", "MarkdownViewer", + "type MarkdownViewerProps", + "type Mentionable", + "type NavigationProps", "NavList", + "type NavListDividerProps", + "type NavListGroupProps", + "type NavListItemProps", + "type NavListLeadingVisualProps", + "type NavListProps", + "type NavListSubNavProps", + "type NavListTrailingVisualProps", "PageHeader", + "type PageHeaderProps", "Pane", + "type ParentLinkProps", + "type Reference", "Root", + "type SavedReply", "SegmentedControl", + "type ShowSuggestionsEvent", + "type SlotConfig", "SplitPageLayout", + "type SplitPageLayoutContentProps", + "type SplitPageLayoutFooterProps", + "type SplitPageLayoutHeaderProps", + "type SplitPageLayoutPaneProps", + "type SplitPageLayoutProps", + "type SubTreeState", + "type Suggestion", + "type Suggestions", + "type SyntheticChangeEmitter", "Table", + "type TableActionsProps", + "type TableBodyProps", + "type TableCellProps", + "type TableContainerProps", + "type TableHeaderProps", + "type TableHeadProps", + "type TableProps", + "type TableRowProps", + "type TableSubtitleProps", + "type TableTitleProps", + "type TitleProps", "Tooltip", "TooltipContext", + "type TooltipProps", "TreeView", + "type TreeViewErrorDialogProps", + "type TreeViewItemProps", + "type TreeViewProps", + "type TreeViewSubTreeProps", + "type TreeViewVisualProps", + "type Trigger", + "type TriggerPropsType", "UnderlineNav", + "type UnderlineNavItemProps", + "type UnderlineNavProps", + "useCombobox", + "useDynamicTextareaHeight", + "useIgnoreKeyboardActionsWhileComposing", + "useSafeAsyncCallback", + "useSlots", + "useSyntheticChange", +] +`; + +exports[`@primer/react/experimental should not update exports without a semver change 1`] = ` +[ + "Blankslate", + "type BlankslateProps", "callbackCancelledResult", + "type CallbackCancelledResult", + "type ChildrenPropTypes", + "type Column", + "type ComboboxCommitEvent", + "Content", "createColumnHelper", + "DataTable", + "type DataTableProps", + "default", + "default", + "Dialog", + "type DialogButtonProps", + "type DialogHeaderProps", + "type DialogHeight", + "type DialogProps", + "type DialogWidth", + "type Emoji", + "type FileType", + "type FileUploadResult", + "Footer", + "Header", + "Hidden", + "type HiddenProps", + "InlineAutocomplete", + "type InlineAutocompleteProps", + "type InteractiveMarkdownViewerProps", + "MarkdownEditor", + "type MarkdownEditorHandle", + "type MarkdownEditorProps", + "MarkdownViewer", + "type MarkdownViewerProps", + "type Mentionable", + "type NavigationProps", + "NavList", + "type NavListDividerProps", + "type NavListGroupProps", + "type NavListItemProps", + "type NavListLeadingVisualProps", + "type NavListProps", + "type NavListSubNavProps", + "type NavListTrailingVisualProps", + "PageHeader", + "type PageHeaderProps", + "Pane", + "type ParentLinkProps", + "type Reference", + "Root", + "type SavedReply", + "SegmentedControl", + "type ShowSuggestionsEvent", + "type SlotConfig", + "SplitPageLayout", + "type SplitPageLayoutContentProps", + "type SplitPageLayoutFooterProps", + "type SplitPageLayoutHeaderProps", + "type SplitPageLayoutPaneProps", + "type SplitPageLayoutProps", + "type SubTreeState", + "type Suggestion", + "type Suggestions", + "type SyntheticChangeEmitter", + "Table", + "type TableActionsProps", + "type TableBodyProps", + "type TableCellProps", + "type TableContainerProps", + "type TableHeaderProps", + "type TableHeadProps", + "type TableProps", + "type TableRowProps", + "type TableSubtitleProps", + "type TableTitleProps", + "type TitleProps", + "Tooltip", + "TooltipContext", + "type TooltipProps", + "TreeView", + "type TreeViewErrorDialogProps", + "type TreeViewItemProps", + "type TreeViewProps", + "type TreeViewSubTreeProps", + "type TreeViewVisualProps", + "type Trigger", + "type TriggerPropsType", + "UnderlineNav", + "type UnderlineNavItemProps", + "type UnderlineNavProps", "useCombobox", "useDynamicTextareaHeight", "useIgnoreKeyboardActionsWhileComposing", diff --git a/src/__tests__/exports.test.ts b/src/__tests__/exports.test.ts index 8f5ce20c67ad..638bf4d7379a 100644 --- a/src/__tests__/exports.test.ts +++ b/src/__tests__/exports.test.ts @@ -1,24 +1,607 @@ +import {existsSync} from 'node:fs' +import fs from 'node:fs/promises' +import path from 'node:path' // eslint-disable-next-line import/no-namespace -import * as Index from '..' -// eslint-disable-next-line import/no-namespace -import * as Drafts from '../drafts' -// eslint-disable-next-line import/no-namespace -import * as Deprecated from '../deprecated' +import * as parser from '@babel/parser' +import {traverse} from '@babel/core' +import {createHash} from 'node:crypto' + +const ROOT_DIR = path.resolve(__dirname, '..', '..') + +let project!: Project + +beforeAll(async () => { + project = await setup() +}) describe('@primer/react', () => { - it('should not update exports without a semver change', () => { - expect(Object.keys(Index).sort()).toMatchSnapshot() + it('should not update exports without a semver change', async () => { + const exports = project.getEntrypointExports(path.join(ROOT_DIR, 'src', 'index.ts')) + expect( + exports.map(exportInfo => { + if (exportInfo.type === 'type') { + return `type ${exportInfo.identifier}` + } + return exportInfo.identifier + }), + ).toMatchSnapshot() + }) +}) + +describe('@primer/react/experimental', () => { + it('should not update exports without a semver change', async () => { + const exports = project.getEntrypointExports(path.join(ROOT_DIR, 'src', 'experimental', 'index.ts')) + expect( + exports.map(exportInfo => { + if (exportInfo.type === 'type') { + return `type ${exportInfo.identifier}` + } + return exportInfo.identifier + }), + ).toMatchSnapshot() }) }) describe('@primer/react/drafts', () => { - it('should not update exports without a semver change', () => { - expect(Object.keys(Drafts).sort()).toMatchSnapshot() + it('should not update exports without a semver change', async () => { + const exports = project.getEntrypointExports(path.join(ROOT_DIR, 'src', 'drafts', 'index.ts')) + expect( + exports.map(exportInfo => { + if (exportInfo.type === 'type') { + return `type ${exportInfo.identifier}` + } + return exportInfo.identifier + }), + ).toMatchSnapshot() }) }) -describe('@primer/react/decprecated', () => { - it('should not update exports without a semver change', () => { - expect(Object.keys(Deprecated).sort()).toMatchSnapshot() +describe('@primer/react/deprecated', () => { + it('should not update exports without a semver change', async () => { + const exports = project.getEntrypointExports(path.join(ROOT_DIR, 'src', 'deprecated', 'index.ts')) + expect( + exports.map(exportInfo => { + if (exportInfo.type === 'type') { + return `type ${exportInfo.identifier}` + } + return exportInfo.identifier + }), + ).toMatchSnapshot() }) }) + +interface Project { + getEntrypointExports(filepath: string): Array +} + +type EntrypointExport = { + identifier: string + type: 'value' | 'type' +} + +type ExportAllDeclaration = { + type: 'ExportAllDeclaration' + source: string +} + +type ExportDefaultDeclaration = { + type: 'ExportDefaultDeclaration' + declaration: string + source?: string +} + +type ExportSpecifier = { + type: 'ExportSpecifier' + local: string + exported: string + exportKind?: 'value' | 'type' | null + source?: string + declaration?: string +} + +type ExportInfo = ExportAllDeclaration | ExportDefaultDeclaration | ExportSpecifier + +type Export = { + identifier: string + type: string | null + source: string | null + exportKind: 'value' | 'type' +} + +interface SourceModule { + type: 'source' + id: string + filepath: string + addSource(source: string): ReturnType | null + getSourceModuleId(source: string): string + addDependency(dependencyId: string): void + addExport(exportInfo: ExportInfo): void + getExports(): Array +} + +interface BareModule { + type: 'bare' + id: string + specifier: string +} + +async function setup(): Promise { + const graph = new Map() + const queue = [ + // main + path.join(ROOT_DIR, 'src', 'index.ts'), + + // deprecated + path.join(process.cwd(), 'src', 'deprecated', 'index.ts'), + + // experimental + path.join(process.cwd(), 'src', 'experimental', 'index.ts'), + ] + const BareModule = { + create(specifier: string): BareModule { + return { + type: 'bare', + id: BareModule.getModuleId(specifier), + specifier, + } + }, + getModuleId(specifier: string) { + return hash(specifier) + }, + } + const SourceModule = { + create(filepath: string) { + const dependencies = new Set() + const sources = new Map() + const exportsInfo: Array = [] + const mod: SourceModule = { + type: 'source', + id: SourceModule.getModuleId(filepath), + filepath, + addSource(source: string) { + if (sources.has(source)) { + return null + } + + const extension = path.extname(source) + if (extension !== '' && extensions.includes(extension)) { + return null + } + + const resolved = resolve(source, mod.filepath) + if (resolved.type === 'error') { + // eslint-disable-next-line no-console + console.log('Unable to resolve source') + // eslint-disable-next-line no-console + console.log(resolved.error) + return null + } + + if (resolved.type === 'relative') { + queue.push(resolved.value) + const id = SourceModule.getModuleId(resolved.value) + mod.addDependency(id) + sources.set(source, id) + } + + if (resolved.type === 'bare') { + const id = BareModule.getModuleId(resolved.path) + if (!graph.has(id)) { + graph.set(id, BareModule.create(resolved.path)) + } + mod.addDependency(id) + sources.set(source, id) + } + + if (resolved.type === 'absolute') { + throw new Error('Unimplemented') + } + + return resolved + }, + getSourceModuleId(source: string) { + if (sources.has(source)) { + return sources.get(source) + } + throw new Error(`Unable to find source: ${source}`) + }, + addDependency(dependencyId: string) { + dependencies.add(dependencyId) + }, + addExport(exportInfo: ExportInfo) { + const info = { + ...exportInfo, + } + + if (exportInfo.source) { + info.source = mod.getSourceModuleId(exportInfo.source) + } + + exportsInfo.push(info) + }, + getExports() { + return exportsInfo.flatMap(exportInfo => { + if (exportInfo.type === 'ExportSpecifier') { + return { + identifier: exportInfo.exported, + type: exportInfo.declaration ?? null, + source: exportInfo.source ?? null, + exportKind: exportInfo.exportKind ?? 'value', + } + } + + if (exportInfo.type === 'ExportDefaultDeclaration') { + return { + identifier: 'default', + type: exportInfo.declaration, + source: exportInfo.source ?? null, + exportKind: 'exportKind' in exportInfo ? (exportInfo.exportKind as 'type' | 'value') : 'value', + } + } + + // This branch matches exportInfo.type === 'ExportAllDeclaration' + const sourceModule = graph.get(exportInfo.source) + if (!sourceModule) { + return [] + } + + if (sourceModule.type === 'bare') { + return [] + } + + return sourceModule.getExports().map(exportInfo => { + return { + ...exportInfo, + source: exportInfo.source, + } + }) + }) + }, + } + + return mod + }, + getModuleId(filepath: string) { + return hash(filepath) + }, + } + + while (queue.length !== 0) { + const filepath = queue.shift() + if (!filepath) { + continue + } + + const id = SourceModule.getModuleId(filepath) + if (graph.has(id)) { + continue + } + + const mod = SourceModule.create(filepath) + const contents = await fs.readFile(filepath, 'utf8') + const ast = parser.parse(contents, { + sourceType: 'module', + plugins: [ + 'typescript', + // Language + 'jsx', + // Proposal + 'classProperties', + 'classPrivateProperties', + 'classPrivateMethods', + 'decorators-legacy', + 'dynamicImport', + 'exportDefaultFrom', + 'exportNamespaceFrom', + 'importMeta', + 'nullishCoalescingOperator', + 'numericSeparator', + 'objectRestSpread', + 'optionalCatchBinding', + 'optionalChaining', + 'topLevelAwait', + ], + }) + + const sources: Array = [] + + traverse(ast, { + ImportDeclaration(path) { + sources.push(path.node.source.value) + }, + + ExportDefaultDeclaration(path) { + // @ts-ignore this should exist on the type + if (path.node.source) { + // @ts-ignore this should exist on the type + sources.push(path.node.source.value) + } + }, + + ExportNamedDeclaration(path) { + if (path.node.source) { + sources.push(path.node.source.value) + } + }, + + ExportAllDeclaration(path) { + sources.push(path.node.source.value) + }, + }) + + for (const source of sources) { + const resolved = mod.addSource(source) + if (resolved === null) { + continue + } + + if (resolved.type === 'relative') { + queue.push(resolved.value) + } + } + + graph.set(mod.id, mod) + } + + for (const mod of graph.values()) { + if (mod.type !== 'source') { + continue + } + + const contents = await fs.readFile(mod.filepath, 'utf8') + const ast = parser.parse(contents, { + sourceType: 'module', + plugins: [ + 'typescript', + // Language + 'jsx', + // Proposal + 'classProperties', + 'classPrivateProperties', + 'classPrivateMethods', + 'decorators-legacy', + 'dynamicImport', + 'exportDefaultFrom', + 'exportNamespaceFrom', + 'importMeta', + 'nullishCoalescingOperator', + 'numericSeparator', + 'objectRestSpread', + 'optionalCatchBinding', + 'optionalChaining', + 'topLevelAwait', + ], + }) + + const exports: Array = [] + + traverse(ast, { + ExportAllDeclaration(path) { + exports.push({ + type: 'ExportAllDeclaration', + source: path.node.source.value, + }) + }, + + ExportDefaultDeclaration(path) { + exports.push({ + type: 'ExportDefaultDeclaration', + declaration: path.node.declaration.type, + // @ts-ignore this value may exist when using: + // export default from 'mod' + source: path.node.source?.value, + }) + }, + + ExportNamedDeclaration(path) { + for (const specifier of path.node.specifiers) { + const source = path.node.source?.value + + exports.push({ + type: 'ExportSpecifier', + // @ts-ignore this is available due to type narrowing + local: specifier.local.name, + // @ts-ignore this is available due to type narrowing + exported: specifier.exported.name, + exportKind: path.node.exportKind, + source, + }) + } + + if (path.node.declaration) { + if (path.node.declaration.type === 'VariableDeclaration') { + for (const declarator of path.node.declaration.declarations) { + exports.push({ + type: 'ExportSpecifier', + // @ts-ignore this value should exist due to type narrowing + local: declarator.id.name, + // @ts-ignore this value should exist due to type narrowing + exported: declarator.id.name, + exportKind: path.node.exportKind, + declaration: path.node.declaration.type, + }) + } + } + + // @ts-ignore this value should exist due to type narrowing + if (path.node.declaration.id) { + // @ts-ignore this value should exist due to type narrowing + const exported = path.node.declaration.id.name + + exports.push({ + type: 'ExportSpecifier', + exported, + local: exported, + exportKind: path.node.exportKind, + declaration: path.node.declaration.type, + }) + } + } + }, + }) + + for (const exportInfo of exports) { + mod.addExport(exportInfo) + } + } + + return { + getEntrypointExports(filepath: string): Array { + const id = SourceModule.getModuleId(filepath) + if (graph.has(id)) { + const mod = graph.get(id) + if (mod?.type === 'source') { + const moduleExports = mod.getExports() + return moduleExports + .map(exportInfo => { + return { + identifier: exportInfo.identifier, + type: exportInfo.exportKind, + } + }) + .sort((a, b) => { + if (a.identifier === b.identifier) { + if (a.type === 'value') { + return -1 + } + + if (b.type === 'value') { + return 1 + } + } + return a.identifier.localeCompare(b.identifier) + }) + } + } + + throw new Error(`Unable to find entrypoint with filepath: ${filepath}`) + }, + } +} + +const extensions = ['.tsx', '.ts', '.js', '.jsx', '.mjs', '.cjs'] + +// Terminology: https://nodejs.org/api/esm.html#terminology + +/** + * Represents an error when resolving the given import or export source + */ +type ResolveError = { + type: 'error' + error: Error +} + +/** + * import mod from './some/local/file'; + */ +type ResolveRelativeModule = { + type: 'relative' + value: string +} + +/** + * import mod from 'mod'; + */ +type ResolveBareModule = { + type: 'bare' + value: string + path: string +} + +/** + * import mod from '/mod'; + */ +type ResolveAbsoluteModule = { + type: 'absolute' + value: string +} + +/** + * Resolve the given import or export source. If the source is a filepath, it + * will attempt to resolve the module relative to the given filepath. + */ +function resolve( + source: string, + filepath: string, +): ResolveBareModule | ResolveRelativeModule | ResolveAbsoluteModule | ResolveError { + if (source.startsWith('.')) { + const directory = path.dirname(filepath) + const extension = path.extname(source) + if (extension === '' || !extensions.includes(extension)) { + const candidate = extensions + .flatMap(extension => { + return [ + path.resolve( + directory, + path.format({ + name: source, + ext: extension, + }), + ), + path.resolve( + directory, + path.format({ + dir: source, + name: 'index', + ext: extension, + }), + ), + ] + }) + .find(candidate => { + return existsSync(candidate) + }) + if (candidate) { + return { + type: 'relative', + value: candidate, + } + } + + return { + type: 'error', + error: new Error(`Unable to find file: ${source} from: ${filepath}`), + } + } + + const resolvedPath = path.resolve(directory, source) + if (!existsSync(resolvedPath)) { + return { + type: 'error', + error: new Error(`Unable to find file: ${source} from: ${filepath}`), + } + } + return { + type: 'relative', + value: resolvedPath, + } + } + + if (source.startsWith('/')) { + return { + type: 'absolute', + value: source, + } + } + + if (source.startsWith('@')) { + const [scope, name] = source.split('/') + return { + type: 'bare', + value: `${scope}/${name}`, + path: source, + } + } + + const [name] = source.split('/') + + return { + type: 'bare', + value: name, + path: source, + } +} + +function hash(data: string): string { + return createHash('sha1').update(data).digest('base64url') +} From b99b3ee7c8f5a416045530d260fbb1c854301f8e Mon Sep 17 00:00:00 2001 From: Josh Black Date: Thu, 12 Oct 2023 12:50:13 -0500 Subject: [PATCH 03/27] chore(deps): update eslint-plugin-github to v4.10 (#3805) * chore(deps): update eslint-plugin-github to v4.10 * test: update snapshots --------- Co-authored-by: Josh Black --- package-lock.json | 229 +++++++++++++++--- package.json | 2 +- src/FilterList/FilterList.tsx | 6 +- src/PageLayout/PageLayout.tsx | 1 + src/Select.tsx | 9 +- src/Select/Select.tsx | 9 +- src/ToggleSwitch/ToggleSwitch.tsx | 2 + .../__snapshots__/ToggleSwitch.test.tsx.snap | 2 + 8 files changed, 223 insertions(+), 37 deletions(-) diff --git a/package-lock.json b/package-lock.json index f279a87a2a8d..686174188bce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -114,7 +114,7 @@ "cross-env": "7.0.3", "eslint": "8.40.0", "eslint-import-resolver-typescript": "3.6.0", - "eslint-plugin-github": "4.8.0", + "eslint-plugin-github": "4.10.1", "eslint-plugin-jest": "27.2.1", "eslint-plugin-jsx-a11y": "6.7.1", "eslint-plugin-mdx": "2.2.0", @@ -18286,15 +18286,15 @@ } }, "node_modules/eslint-plugin-github": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-github/-/eslint-plugin-github-4.8.0.tgz", - "integrity": "sha512-1qu1qcyac4FfZmT9KNPr5250DwWzwp6uy6xAqHD2boE4OquUpeTni05yPn1b6y6vUYm/q8+npTdyYiRSqvg+BQ==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-github/-/eslint-plugin-github-4.10.1.tgz", + "integrity": "sha512-1AqQBockOM+m0ZUpwfjWtX0lWdX5cRi/hwJnSNvXoOmz/Hh+ULH6QFz6ENWueTWjoWpgPv0af3bj+snps6o4og==", "dev": true, "dependencies": { "@github/browserslist-config": "^1.0.0", - "@typescript-eslint/eslint-plugin": "^5.1.0", - "@typescript-eslint/parser": "^5.1.0", - "aria-query": "^5.1.3", + "@typescript-eslint/eslint-plugin": "^6.0.0", + "@typescript-eslint/parser": "^6.0.0", + "aria-query": "^5.3.0", "eslint-config-prettier": ">=8.0.0", "eslint-plugin-escompat": "^3.3.3", "eslint-plugin-eslint-comments": "^3.2.0", @@ -18303,10 +18303,10 @@ "eslint-plugin-import": "^2.25.2", "eslint-plugin-jsx-a11y": "^6.7.1", "eslint-plugin-no-only-tests": "^3.0.0", - "eslint-plugin-prettier": "^4.0.0", + "eslint-plugin-prettier": "^5.0.0", "eslint-rule-documentation": ">=1.0.0", "jsx-ast-utils": "^3.3.2", - "prettier": "^2.2.1", + "prettier": "^3.0.0", "svg-element-attributes": "^1.3.1" }, "bin": { @@ -18316,40 +18316,211 @@ "eslint": "^8.0.1" } }, - "node_modules/eslint-plugin-github/node_modules/eslint-plugin-prettier": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", - "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", + "node_modules/eslint-plugin-github/node_modules/@types/semver": { + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.3.tgz", + "integrity": "sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==", + "dev": true + }, + "node_modules/eslint-plugin-github/node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.5.tgz", + "integrity": "sha512-JhtAwTRhOUcP96D0Y6KYnwig/MRQbOoLGXTON2+LlyB/N35SP9j1boai2zzwXb7ypKELXMx3DVk9UTaEq1vHEw==", "dev": true, "dependencies": { - "prettier-linter-helpers": "^1.0.0" + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.7.5", + "@typescript-eslint/type-utils": "6.7.5", + "@typescript-eslint/utils": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" }, "engines": { - "node": ">=12.0.0" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": ">=7.28.0", - "prettier": ">=2.0.0" + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { - "eslint-config-prettier": { + "typescript": { "optional": true } } }, - "node_modules/eslint-plugin-github/node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "node_modules/eslint-plugin-github/node_modules/@typescript-eslint/parser": { + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.5.tgz", + "integrity": "sha512-bIZVSGx2UME/lmhLcjdVc7ePBwn7CLqKarUBL4me1C5feOd663liTGjMBGVcGr+BhnSLeP4SgwdvNnnkbIdkCw==", "dev": true, - "bin": { - "prettier": "bin-prettier.js" + "dependencies": { + "@typescript-eslint/scope-manager": "6.7.5", + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/typescript-estree": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5", + "debug": "^4.3.4" }, "engines": { - "node": ">=10.13.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-github/node_modules/@typescript-eslint/scope-manager": { + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.5.tgz", + "integrity": "sha512-GAlk3eQIwWOJeb9F7MKQ6Jbah/vx1zETSDw8likab/eFcqkjSD7BI75SDAeC5N2L0MmConMoPvTsmkrg71+B1A==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-plugin-github/node_modules/@typescript-eslint/type-utils": { + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.7.5.tgz", + "integrity": "sha512-Gs0qos5wqxnQrvpYv+pf3XfcRXW6jiAn9zE/K+DlmYf6FcpxeNYN0AIETaPR7rHO4K2UY+D0CIbDP9Ut0U4m1g==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "6.7.5", + "@typescript-eslint/utils": "6.7.5", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-github/node_modules/@typescript-eslint/types": { + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.5.tgz", + "integrity": "sha512-WboQBlOXtdj1tDFPyIthpKrUb+kZf2VroLZhxKa/VlwLlLyqv/PwUNgL30BlTVZV1Wu4Asu2mMYPqarSO4L5ZQ==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-plugin-github/node_modules/@typescript-eslint/typescript-estree": { + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.5.tgz", + "integrity": "sha512-NhJiJ4KdtwBIxrKl0BqG1Ur+uw7FiOnOThcYx9DpOGJ/Abc9z2xNzLeirCG02Ig3vkvrc2qFLmYSSsaITbKjlg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-github/node_modules/@typescript-eslint/utils": { + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.5.tgz", + "integrity": "sha512-pfRRrH20thJbzPPlPc4j0UNGvH1PjPlhlCMq4Yx7EGjV7lvEeGX0U6MJYe8+SyFutWgSHsdbJ3BXzZccYggezA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.7.5", + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/typescript-estree": "6.7.5", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/eslint-plugin-github/node_modules/@typescript-eslint/visitor-keys": { + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.5.tgz", + "integrity": "sha512-3MaWdDZtLlsexZzDSdQWsFQ9l9nL8B80Z4fImSpyllFC/KLqWQRdEcB+gGGO+N3Q2uL40EsG66wZLsohPxNXvg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.7.5", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-plugin-github/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-plugin-i18n-text": { @@ -38365,9 +38536,9 @@ } }, "node_modules/ts-api-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.1.tgz", - "integrity": "sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", + "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", "dev": true, "engines": { "node": ">=16.13.0" diff --git a/package.json b/package.json index 5bf6768c0122..930144f86e3e 100644 --- a/package.json +++ b/package.json @@ -199,7 +199,7 @@ "cross-env": "7.0.3", "eslint": "8.40.0", "eslint-import-resolver-typescript": "3.6.0", - "eslint-plugin-github": "4.8.0", + "eslint-plugin-github": "4.10.1", "eslint-plugin-jest": "27.2.1", "eslint-plugin-jsx-a11y": "6.7.1", "eslint-plugin-mdx": "2.2.0", diff --git a/src/FilterList/FilterList.tsx b/src/FilterList/FilterList.tsx index 8fee74ce2a1e..8809108574fd 100644 --- a/src/FilterList/FilterList.tsx +++ b/src/FilterList/FilterList.tsx @@ -60,11 +60,7 @@ export type FilterListItemProps = {count?: number} & ComponentProps) => { return ( - {count && ( - - {count} - - )} + {count && {count}} {children} ) diff --git a/src/PageLayout/PageLayout.tsx b/src/PageLayout/PageLayout.tsx index 1a556ee09ba2..8b5ce1a1f27d 100644 --- a/src/PageLayout/PageLayout.tsx +++ b/src/PageLayout/PageLayout.tsx @@ -798,6 +798,7 @@ const Pane = React.forwardRef {resizable && ( + // eslint-disable-next-line github/a11y-no-visually-hidden-interactive-element
diff --git a/src/Select.tsx b/src/Select.tsx index f08ef95c9b6d..ca67df0fad83 100644 --- a/src/Select.tsx +++ b/src/Select.tsx @@ -50,7 +50,14 @@ const StyledSelect = styled.select` ` const ArrowIndicatorSVG: React.FC> = ({className}) => ( - + ) diff --git a/src/Select/Select.tsx b/src/Select/Select.tsx index 6eb90b22d4ec..36bcdb33fbd5 100644 --- a/src/Select/Select.tsx +++ b/src/Select/Select.tsx @@ -50,7 +50,14 @@ const StyledSelect = styled.select` ` const ArrowIndicatorSVG: React.FC> = ({className}) => ( - + ) diff --git a/src/ToggleSwitch/ToggleSwitch.tsx b/src/ToggleSwitch/ToggleSwitch.tsx index b149cda48471..764865bcaadb 100644 --- a/src/ToggleSwitch/ToggleSwitch.tsx +++ b/src/ToggleSwitch/ToggleSwitch.tsx @@ -53,6 +53,7 @@ type InnerIconProps = {size?: ToggleSwitchProps['size']} const CircleIcon: React.FC> = ({size}) => (
{SWITCH_LABEL_TEXT}
+ + , + ) + const toggleSwitch = getByLabelText(SWITCH_LABEL_TEXT) + + expect(toggleSwitch).toHaveAttribute('aria-pressed', 'false') + }) + + it('renders a switch that is turned on', () => { + const {getByLabelText} = render( + <> +
{SWITCH_LABEL_TEXT}
+ + , + ) + const toggleSwitch = getByLabelText(SWITCH_LABEL_TEXT) + + expect(toggleSwitch).toHaveAttribute('aria-pressed', 'true') + }) + + it('renders a switch that is disabled', async () => { + const user = userEvent.setup() + const {getByLabelText} = render( + <> +
{SWITCH_LABEL_TEXT}
+ + , + ) + const toggleSwitch = getByLabelText(SWITCH_LABEL_TEXT) + + expect(toggleSwitch).toHaveAttribute('aria-pressed', 'false') + await user.click(toggleSwitch) + expect(toggleSwitch).toHaveAttribute('aria-pressed', 'false') + }) + + it("renders a switch who's state is loading", async () => { + const user = userEvent.setup() + const {getByLabelText, container} = render( + <> +
{SWITCH_LABEL_TEXT}
+ + , + ) + const toggleSwitch = getByLabelText(SWITCH_LABEL_TEXT) + const loadingSpinner = container.querySelector('svg') + + expect(loadingSpinner).toBeDefined() + expect(toggleSwitch).toHaveAttribute('aria-pressed', 'false') + await user.click(toggleSwitch) + expect(toggleSwitch).toHaveAttribute('aria-pressed', 'false') + }) + + it('switches from off to on uncontrolled', async () => { + const user = userEvent.setup() + const {getByLabelText} = render( + <> +
{SWITCH_LABEL_TEXT}
+ + , + ) + const toggleSwitch = getByLabelText(SWITCH_LABEL_TEXT) + + expect(toggleSwitch).toHaveAttribute('aria-pressed', 'false') + await user.click(toggleSwitch) + expect(toggleSwitch).toHaveAttribute('aria-pressed', 'true') + }) + + it('switches from off to on uncontrolled when clicking on status label', async () => { + const user = userEvent.setup() + const {getByLabelText, getByText} = render( + <> +
{SWITCH_LABEL_TEXT}
+ + , + ) + const toggleSwitch = getByLabelText(SWITCH_LABEL_TEXT) + const toggleSwitchStatusLabel = getByText('Off') + + expect(toggleSwitch).toHaveAttribute('aria-pressed', 'false') + await user.click(toggleSwitchStatusLabel) + expect(toggleSwitch).toHaveAttribute('aria-pressed', 'true') + }) + + it('switches from off to on with a controlled prop', async () => { + const user = userEvent.setup() + const ControlledSwitchComponent = () => { + const [isOn, setIsOn] = React.useState(false) + + const onClick = () => { + setIsOn(!isOn) + } + + return ( + <> +
{SWITCH_LABEL_TEXT}
+ + + ) + } + const {getByLabelText} = render() + const toggleSwitch = getByLabelText(SWITCH_LABEL_TEXT) + + expect(toggleSwitch).toHaveAttribute('aria-pressed', 'false') + await user.click(toggleSwitch) + expect(toggleSwitch).toHaveAttribute('aria-pressed', 'true') + }) + + it('calls onChange when the switch is toggled', async () => { + const user = userEvent.setup() + const handleChange = jest.fn() + const ControlledSwitchComponent = ({handleSwitchChange}: {handleSwitchChange: (on: boolean) => void}) => { + const [isOn, setIsOn] = React.useState(false) + + const onClick = () => { + setIsOn(!isOn) + } + + return ( + <> +
{SWITCH_LABEL_TEXT}
+ + + ) + } + const {getByLabelText} = render() + const toggleSwitch = getByLabelText(SWITCH_LABEL_TEXT) + + await user.click(toggleSwitch) + expect(handleChange).toHaveBeenCalledWith(true) + }) + + it('can pass data attributes to the rendered component', async () => { + const TEST_ID = 'a test id' + const ControlledSwitchComponent = () => { + return ( + <> +
{SWITCH_LABEL_TEXT}
+ + + ) + } + const {getByTestId} = render() + const toggleSwitch = getByTestId(TEST_ID) + expect(toggleSwitch).toBeInTheDocument() + }) + + it('supports a `ref` on the inner @@ -87,18 +101,18 @@ export const PullRequestPage = () => ( Open - + broccolinisoup {' '} - wants to merge 3 commits into main from{' '} - broccolinisoup/switch-to-new-underlineNav + wants to merge 3 commits into main from{' '} + bs/pageheader-title - main + main - page-header-initial + page-header-initial @@ -134,21 +148,120 @@ export const FilesPage = () => ( Files - - + + + + + + + alert('Main')}> + + + + main default + + alert('Branch 1')}>branch-1 + alert('Branch 2')}>branch-2 + + + + + + + + + + + + alert('Download')}>Download + + + alert('Jump to line')}> + Jump to line + L + + + alert('Copy path')}> + Copy path + ⌘⇧. + + alert('Copy permalink')}> + Copy permalink + ⌘⇧, + + + + alert('Show code folding buttons')}> + Show code folding buttons + + alert('Wrap lines')}>Wrap lines + alert('Center content')}>Center content + + + alert('Delete file clicked')}> + Delete file + ⌘D + + + + - ... - primer - react - src - PageHeader - PageHeader.tsx + react + src + + PageHeader + + + PageHeader.tsx + + PageHeader.tsx + @@ -167,14 +280,24 @@ export const WithPageLayout = () => { Pull requests - + PageHeader component initial layout explorations extra long pull request title   #1831 - {/* Pop up actions */} + + + + + + + alert('Edit button action')}>Edit + alert('Code button action')}>Code + + + @@ -189,18 +312,20 @@ export const WithPageLayout = () => { Open - + broccolinisoup {' '} - wants to merge 3 commits into main from{' '} - broccolinisoup/switch-to-new-underlineNav + wants to merge 3 commits into main from{' '} + + broccolinisoup/switch-to-new-underlineNav + - main + main - page-header-initial + page-header-initial @@ -224,32 +349,22 @@ export const WithPageLayout = () => { - - This box has really long content. If it is too long, it will cause x overflow and should show a scrollbar. - When this overflows, it should not break to overall page layout! - Assignees - - No one –{' '} - + + No one — + diff --git a/src/PageHeader/PageHeader.features.stories.tsx b/src/PageHeader/PageHeader.features.stories.tsx index d5801f2276db..cd78a9bf9790 100644 --- a/src/PageHeader/PageHeader.features.stories.tsx +++ b/src/PageHeader/PageHeader.features.stories.tsx @@ -71,14 +71,16 @@ export const WithComponentAsATitle = () => ( - ... - primer - react - src - PageHeader - PageHeader.tsx + react + src + + PageHeader + + + PageHeader.tsx + - Visually Hidden Title + PageHeader.tsx @@ -131,7 +133,7 @@ export const WithDescriptionSlot = () => ( - + broccolinisoup {' '} created this branch 5 days ago · 14 commits · updated today @@ -175,12 +177,12 @@ export const WithCustomNavigation = () => (
  • - + Item 1
  • - Item 2 + Item 2
  • @@ -211,8 +213,8 @@ export const WithParentLinkAndActionsOfContextArea = () => ( Parent Link - @@ -236,15 +238,16 @@ export const WithContextBarAndActionsOfContextArea = () => ( - ... - primer - react - src - PageHeader - PageHeader.tsx + react + src + + PageHeader + + + PageHeader.tsx + -