diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index e27af53..0d91176 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -1,19 +1,22 @@ -name: pr +name: PR + on: [pull_request] + +concurrency: + group: ${{ github.workflow }}-${{ github.event.number || github.ref }} + cancel-in-progress: true + jobs: test: - name: 'Test' + name: Test runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - with: - fetch-depth: '0' - - uses: pnpm/action-setup@v2 - name: Install pnpm - id: pnpm-install + - name: Checkout + uses: actions/checkout@v5.0.0 with: - version: 7 - run_install: false + fetch-depth: 0 + - name: Install pnpm + uses: pnpm/action-setup@v4 - name: Get pnpm store directory id: pnpm-cache diff --git a/.github/workflows/ci.yml b/.github/workflows/release.yml similarity index 77% rename from .github/workflows/ci.yml rename to .github/workflows/release.yml index 65a2b80..3055fcf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/release.yml @@ -1,24 +1,25 @@ -name: ci +name: Release + +on: + push: + branches: [main, alpha, beta, rc] + concurrency: group: publish-${{ github.github.base_ref }} cancel-in-progress: true -on: [push] + jobs: - test-and-publish: - name: 'Test & Publish' + release: + name: Release + if: github.repository_owner == 'TanStack' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - name: Checkout + uses: actions/checkout@v5.0.0 with: - fetch-depth: '0' - - uses: pnpm/action-setup@v2 - name: Install pnpm - id: pnpm-install - with: - version: 7 - run_install: false - env: - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + fetch-depth: 0 + - name: Install pnpm + uses: pnpm/action-setup@v4 - name: Get pnpm store directory id: pnpm-cache diff --git a/.nvmrc b/.nvmrc index 9e15be3..ae0e6a2 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v16.20.0 +v20.19.6 diff --git a/package.json b/package.json index 689ad30..2085e3e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { "private": true, "repository": "https://github.com/tanstack/ranger.git", + "packageManager": "pnpm@8.15.9", "scripts": { "clean-dist": "pnpm -rc --parallel exec 'rm -rf build dist'", "clean-all": "pnpm -rc --parallel exec 'rm -rf build dist node_modules'", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7134a6c..bcb4af6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,7 +1,7 @@ lockfileVersion: '6.0' settings: - autoInstallPeers: false + autoInstallPeers: true excludeLinksFromLockfile: false overrides: @@ -175,7 +175,7 @@ importers: version: 2.2.0(vite@3.2.5) vite: specifier: ^3.2.3 - version: 3.2.5 + version: 3.2.5(@types/node@17.0.45) examples/react/custom-steps: dependencies: @@ -200,7 +200,7 @@ importers: version: 2.2.0(vite@3.2.5) vite: specifier: ^3.2.3 - version: 3.2.5 + version: 3.2.5(@types/node@17.0.45) examples/react/custom-styles: dependencies: @@ -215,7 +215,7 @@ importers: version: 18.2.0(react@18.2.0) styled-components: specifier: ^5.3.6 - version: 5.3.11(react-dom@18.2.0)(react@18.2.0) + version: 5.3.11(@babel/core@7.20.12)(react-dom@18.2.0)(react-is@17.0.2)(react@18.2.0) devDependencies: '@types/react': specifier: ^18.0.26 @@ -228,7 +228,7 @@ importers: version: 2.2.0(vite@3.2.5) vite: specifier: ^3.2.3 - version: 3.2.5 + version: 3.2.5(@types/node@17.0.45) examples/react/logarithmic-interpolator: dependencies: @@ -253,7 +253,7 @@ importers: version: 2.2.0(vite@3.2.5) vite: specifier: ^3.2.3 - version: 3.2.5 + version: 3.2.5(@types/node@17.0.45) examples/react/update-on-drag: dependencies: @@ -278,7 +278,7 @@ importers: version: 2.2.0(vite@3.2.5) vite: specifier: ^3.2.3 - version: 3.2.5 + version: 3.2.5(@types/node@17.0.45) packages/ranger: {} @@ -315,7 +315,6 @@ packages: dependencies: '@jridgewell/gen-mapping': 0.1.1 '@jridgewell/trace-mapping': 0.3.17 - dev: true /@babel/code-frame@7.18.6: resolution: {integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==} @@ -332,7 +331,6 @@ packages: /@babel/compat-data@7.20.10: resolution: {integrity: sha512-sEnuDPpOJR/fcafHMjpcpGN5M2jbUGUHwmuWKM/YdPzeEDJg8bgmbcWQFUfE32MQjti1koACvoPVsDe8Uq+idg==} engines: {node: '>=6.9.0'} - dev: true /@babel/core@7.20.12: resolution: {integrity: sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==} @@ -346,16 +344,15 @@ packages: '@babel/helpers': 7.20.13 '@babel/parser': 7.20.13 '@babel/template': 7.20.7 - '@babel/traverse': 7.20.13 + '@babel/traverse': 7.20.13(supports-color@5.5.0) '@babel/types': 7.20.7 convert-source-map: 1.9.0 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.0 transitivePeerDependencies: - supports-color - dev: true /@babel/generator@7.20.7: resolution: {integrity: sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==} @@ -399,7 +396,6 @@ packages: browserslist: 4.21.4 lru-cache: 5.1.1 semver: 6.3.0 - dev: true /@babel/helper-create-class-features-plugin@7.20.12(@babel/core@7.20.12): resolution: {integrity: sha512-9OunRkbT0JQcednL0UFvbfXpAsUXiGjUk0a7sN8fUXX7Mue79cUSMjHGDRRi/Vz9vYlpIhLV5fMD5dKoMhhsNQ==} @@ -439,7 +435,7 @@ packages: '@babel/core': 7.20.12 '@babel/helper-compilation-targets': 7.20.7(@babel/core@7.20.12) '@babel/helper-plugin-utils': 7.20.2 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) lodash.debounce: 4.0.8 resolve: 1.22.1 semver: 6.3.0 @@ -501,11 +497,10 @@ packages: '@babel/helper-split-export-declaration': 7.18.6 '@babel/helper-validator-identifier': 7.19.1 '@babel/template': 7.20.7 - '@babel/traverse': 7.20.13 + '@babel/traverse': 7.20.13(supports-color@5.5.0) '@babel/types': 7.20.7 transitivePeerDependencies: - supports-color - dev: true /@babel/helper-optimise-call-expression@7.18.6: resolution: {integrity: sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==} @@ -547,7 +542,7 @@ packages: '@babel/helper-member-expression-to-functions': 7.20.7 '@babel/helper-optimise-call-expression': 7.18.6 '@babel/template': 7.20.7 - '@babel/traverse': 7.20.13 + '@babel/traverse': 7.20.13(supports-color@5.5.0) '@babel/types': 7.20.7 transitivePeerDependencies: - supports-color @@ -558,7 +553,6 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.20.7 - dev: true /@babel/helper-skip-transparent-expression-wrappers@7.20.0: resolution: {integrity: sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg==} @@ -594,7 +588,6 @@ packages: /@babel/helper-validator-option@7.18.6: resolution: {integrity: sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==} engines: {node: '>=6.9.0'} - dev: true /@babel/helper-wrap-function@7.20.5: resolution: {integrity: sha512-bYMxIWK5mh+TgXGVqAtnu5Yn1un+v8DDZtqyzKRLUzrh70Eal2O3aZ7aPYiMADO4uKlkzOiRiZ6GX5q3qxvW9Q==} @@ -602,7 +595,7 @@ packages: dependencies: '@babel/helper-function-name': 7.19.0 '@babel/template': 7.20.7 - '@babel/traverse': 7.20.13 + '@babel/traverse': 7.20.13(supports-color@5.5.0) '@babel/types': 7.20.7 transitivePeerDependencies: - supports-color @@ -613,11 +606,10 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/template': 7.20.7 - '@babel/traverse': 7.20.13 + '@babel/traverse': 7.20.13(supports-color@5.5.0) '@babel/types': 7.20.7 transitivePeerDependencies: - supports-color - dev: true /@babel/highlight@7.18.6: resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} @@ -915,12 +907,13 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-jsx@7.23.3: + /@babel/plugin-syntax-jsx@7.23.3(@babel/core@7.20.12): resolution: {integrity: sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: + '@babel/core': 7.20.12 '@babel/helper-plugin-utils': 7.22.5 dev: false @@ -1591,24 +1584,6 @@ packages: '@babel/parser': 7.20.13 '@babel/types': 7.20.7 - /@babel/traverse@7.20.13: - resolution: {integrity: sha512-kMJXfF0T6DIS9E8cgdLCSAL+cuCK+YEZHWiLK0SXpTo8YRj5lpJu3CDNKiIBCne4m9hhTIqUg6SYTAI39tAiVQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.21.4 - '@babel/generator': 7.20.7 - '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-function-name': 7.19.0 - '@babel/helper-hoist-variables': 7.18.6 - '@babel/helper-split-export-declaration': 7.18.6 - '@babel/parser': 7.20.13 - '@babel/types': 7.20.7 - debug: 4.3.4 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: true - /@babel/traverse@7.20.13(supports-color@5.5.0): resolution: {integrity: sha512-kMJXfF0T6DIS9E8cgdLCSAL+cuCK+YEZHWiLK0SXpTo8YRj5lpJu3CDNKiIBCne4m9hhTIqUg6SYTAI39tAiVQ==} engines: {node: '>=6.9.0'} @@ -1625,7 +1600,6 @@ packages: globals: 11.12.0 transitivePeerDependencies: - supports-color - dev: false /@babel/types@7.20.7: resolution: {integrity: sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==} @@ -1721,7 +1695,6 @@ packages: dependencies: '@jridgewell/set-array': 1.1.2 '@jridgewell/sourcemap-codec': 1.4.14 - dev: true /@jridgewell/gen-mapping@0.3.2: resolution: {integrity: sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==} @@ -2968,7 +2941,7 @@ packages: '@babel/plugin-transform-react-jsx-source': 7.19.6(@babel/core@7.20.12) magic-string: 0.26.7 react-refresh: 0.14.0 - vite: 3.2.5 + vite: 3.2.5(@types/node@17.0.45) transitivePeerDependencies: - supports-color dev: true @@ -3085,7 +3058,7 @@ packages: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} dependencies: - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) transitivePeerDependencies: - supports-color dev: true @@ -3094,7 +3067,7 @@ packages: resolution: {integrity: sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==} engines: {node: '>= 8.0.0'} dependencies: - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) depd: 1.1.2 humanize-ms: 1.2.1 transitivePeerDependencies: @@ -3319,17 +3292,17 @@ packages: - supports-color dev: true - /babel-plugin-styled-components@2.1.4(styled-components@5.3.11): + /babel-plugin-styled-components@2.1.4(@babel/core@7.20.12)(styled-components@5.3.11): resolution: {integrity: sha512-Xgp9g+A/cG47sUyRwwYxGM4bR/jDRg5N6it/8+HxCnbT5XNKSKDT9xm4oag/osgqjC2It/vH0yXsomOG6k558g==} peerDependencies: styled-components: '>= 2' dependencies: '@babel/helper-annotate-as-pure': 7.22.5 '@babel/helper-module-imports': 7.22.15 - '@babel/plugin-syntax-jsx': 7.23.3 + '@babel/plugin-syntax-jsx': 7.23.3(@babel/core@7.20.12) lodash: 4.17.21 picomatch: 2.3.1 - styled-components: 5.3.11(react-dom@18.2.0)(react@18.2.0) + styled-components: 5.3.11(@babel/core@7.20.12)(react-dom@18.2.0)(react-is@17.0.2)(react@18.2.0) transitivePeerDependencies: - '@babel/core' dev: false @@ -3387,7 +3360,6 @@ packages: electron-to-chromium: 1.4.284 node-releases: 2.0.8 update-browserslist-db: 1.0.10(browserslist@4.21.4) - dev: true /buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} @@ -3469,7 +3441,6 @@ packages: /caniuse-lite@1.0.30001448: resolution: {integrity: sha512-tq2YI+MJnooG96XpbTRYkBxLxklZPOdLmNIOdIhvf7SNJan6u5vCKum8iT7ZfCt70m1GPkuC7P3TtX6UuhupuA==} - dev: true /caseless@0.12.0: resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} @@ -3765,7 +3736,6 @@ packages: /convert-source-map@1.9.0: resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} - dev: true /core-js-compat@3.27.2: resolution: {integrity: sha512-welaYuF7ZtbYKGrIy7y3eb40d37rG1FvzEOfe7hSLd2iD6duMDqUhRfSvCGyC46HhR6Y8JXXdZ2lnRUMkPBpvg==} @@ -3873,17 +3843,6 @@ packages: ms: 2.0.0 dev: true - /debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - /debug@4.3.4(supports-color@5.5.0): resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} engines: {node: '>=6.0'} @@ -3895,7 +3854,6 @@ packages: dependencies: ms: 2.1.2 supports-color: 5.5.0 - dev: false /debuglog@1.0.1: resolution: {integrity: sha512-syBZ+rnAK3EgMsH2aYEOLUW7mZSY9Gb+0wUMCFsZvcmiz+HigA0LOcq/HoQqVuGG+EKykunc7QG2bzrponfaSw==} @@ -4064,7 +4022,6 @@ packages: /electron-to-chromium@1.4.284: resolution: {integrity: sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==} - dev: true /emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -4366,7 +4323,6 @@ packages: /escalade@3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} engines: {node: '>=6'} - dev: true /escape-string-regexp@1.0.5: resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} @@ -4619,7 +4575,6 @@ packages: /gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} - dev: true /get-caller-file@2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} @@ -4911,7 +4866,7 @@ packages: dependencies: '@tootallnate/once': 1.1.2 agent-base: 6.0.2 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) transitivePeerDependencies: - supports-color dev: true @@ -4930,7 +4885,7 @@ packages: engines: {node: '>= 6'} dependencies: agent-base: 6.0.2 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) transitivePeerDependencies: - supports-color dev: true @@ -4956,6 +4911,7 @@ packages: /iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} + requiresBuild: true dependencies: safer-buffer: 2.1.2 dev: true @@ -5397,7 +5353,6 @@ packages: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} hasBin: true - dev: true /jsonc-parser@3.2.0: resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} @@ -5587,7 +5542,6 @@ packages: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} dependencies: yallist: 3.1.1 - dev: true /lru-cache@6.0.0: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} @@ -6004,7 +5958,6 @@ packages: /node-releases@2.0.8: resolution: {integrity: sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==} - dev: true /nopt@4.0.3: resolution: {integrity: sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==} @@ -6667,7 +6620,6 @@ packages: /react-is@17.0.2: resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} - dev: true /react-refresh@0.14.0: resolution: {integrity: sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==} @@ -7113,7 +7065,6 @@ packages: /semver@6.3.0: resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} hasBin: true - dev: true /semver@7.3.8: resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==} @@ -7226,7 +7177,7 @@ packages: engines: {node: '>= 6'} dependencies: agent-base: 6.0.2 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) socks: 2.7.1 transitivePeerDependencies: - supports-color @@ -7237,7 +7188,7 @@ packages: engines: {node: '>= 10'} dependencies: agent-base: 6.0.2 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) socks: 2.7.1 transitivePeerDependencies: - supports-color @@ -7499,7 +7450,7 @@ packages: through: 2.3.8 dev: true - /styled-components@5.3.11(react-dom@18.2.0)(react@18.2.0): + /styled-components@5.3.11(@babel/core@7.20.12)(react-dom@18.2.0)(react-is@17.0.2)(react@18.2.0): resolution: {integrity: sha512-uuzIIfnVkagcVHv9nE0VPlHPSCmXIUGKfJ42LNjxCCTDTL5sgnJ8Z7GZBq0EnLYGln77tPpEpExt2+qa+cZqSw==} engines: {node: '>=10'} peerDependencies: @@ -7512,11 +7463,12 @@ packages: '@emotion/is-prop-valid': 1.2.1 '@emotion/stylis': 0.8.5 '@emotion/unitless': 0.7.5 - babel-plugin-styled-components: 2.1.4(styled-components@5.3.11) + babel-plugin-styled-components: 2.1.4(@babel/core@7.20.12)(styled-components@5.3.11) css-to-react-native: 3.2.0 hoist-non-react-statics: 3.3.2 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) + react-is: 17.0.2 shallowequal: 1.1.0 supports-color: 5.5.0 transitivePeerDependencies: @@ -7885,7 +7837,6 @@ packages: browserslist: 4.21.4 escalade: 3.1.1 picocolors: 1.0.0 - dev: true /uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -7950,7 +7901,7 @@ packages: engines: {node: '>=v14.16.0'} hasBin: true dependencies: - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) mlly: 1.1.0 pathe: 0.2.0 source-map: 0.6.1 @@ -7966,39 +7917,6 @@ packages: - terser dev: false - /vite@3.2.5: - resolution: {integrity: sha512-4mVEpXpSOgrssFZAOmGIr85wPHKvaDAcXqxVxVRZhljkJOMZi1ibLibzjLHzJvcok8BMguLc7g1W6W/GqZbLdQ==} - engines: {node: ^14.18.0 || >=16.0.0} - hasBin: true - peerDependencies: - '@types/node': '>= 14' - less: '*' - sass: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - sass: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - dependencies: - esbuild: 0.15.18 - postcss: 8.4.21 - resolve: 1.22.1 - rollup: 2.79.1 - optionalDependencies: - fsevents: 2.3.2 - dev: true - /vite@3.2.5(@types/node@17.0.45): resolution: {integrity: sha512-4mVEpXpSOgrssFZAOmGIr85wPHKvaDAcXqxVxVRZhljkJOMZi1ibLibzjLHzJvcok8BMguLc7g1W6W/GqZbLdQ==} engines: {node: ^14.18.0 || >=16.0.0} @@ -8031,7 +7949,6 @@ packages: rollup: 2.79.1 optionalDependencies: fsevents: 2.3.2 - dev: false /vitest@0.26.3: resolution: {integrity: sha512-FmHxU9aUCxTi23keF3vxb/Qp0lYXaaJ+jRLGOUmMS3qVTOJvgGE+f1VArupA6pEhaG2Ans4X+zV9dqM5WISMbg==} @@ -8061,7 +7978,7 @@ packages: acorn: 8.8.2 acorn-walk: 8.2.0 chai: 4.3.7 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) local-pkg: 0.4.3 source-map: 0.6.1 strip-literal: 1.0.0 @@ -8253,7 +8170,6 @@ packages: /yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - dev: true /yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} diff --git a/scripts/verify-links.ts b/scripts/verify-links.ts new file mode 100644 index 0000000..8a1c40d --- /dev/null +++ b/scripts/verify-links.ts @@ -0,0 +1,125 @@ +import { existsSync, readFileSync, statSync } from 'node:fs' +import { extname, resolve } from 'node:path' +import { glob } from 'tinyglobby' +// @ts-ignore Could not find a declaration file for module 'markdown-link-extractor'. +import markdownLinkExtractor from 'markdown-link-extractor' + +const errors: Array<{ + file: string + link: string + resolvedPath: string + reason: string +}> = [] + +function isRelativeLink(link: string) { + return ( + !link.startsWith('/') && + !link.startsWith('http://') && + !link.startsWith('https://') && + !link.startsWith('//') && + !link.startsWith('#') && + !link.startsWith('mailto:') + ) +} + +/** Remove any trailing .md */ +function stripExtension(p: string): string { + return p.replace(`${extname(p)}`, '') +} + +function relativeLinkExists(link: string, file: string): boolean { + // Remove hash if present + const linkWithoutHash = link.split('#')[0] + // If the link is empty after removing hash, it's not a file + if (!linkWithoutHash) return false + + // Strip the file/link extensions + const filePath = stripExtension(file) + const linkPath = stripExtension(linkWithoutHash) + + // Resolve the path relative to the markdown file's directory + // Nav up a level to simulate how links are resolved on the web + let absPath = resolve(filePath, '..', linkPath) + + // Ensure the resolved path is within /docs + const docsRoot = resolve('docs') + if (!absPath.startsWith(docsRoot)) { + errors.push({ + link, + file, + resolvedPath: absPath, + reason: 'Path outside /docs', + }) + return false + } + + // Check if this is an example path + const isExample = absPath.includes('/examples/') + + let exists = false + + if (isExample) { + // Transform /docs/framework/{framework}/examples/ to /examples/{framework}/ + absPath = absPath.replace( + /\/docs\/framework\/([^/]+)\/examples\//, + '/examples/$1/', + ) + // For examples, we want to check if the directory exists + exists = existsSync(absPath) && statSync(absPath).isDirectory() + } else { + // For non-examples, we want to check if the .md file exists + if (!absPath.endsWith('.md')) { + absPath = `${absPath}.md` + } + exists = existsSync(absPath) + } + + if (!exists) { + errors.push({ + link, + file, + resolvedPath: absPath, + reason: 'Not found', + }) + } + return exists +} + +async function verifyMarkdownLinks() { + // Find all markdown files in docs directory + const markdownFiles = await glob('docs/**/*.md', { + ignore: ['**/node_modules/**'], + }) + + console.log(`Found ${markdownFiles.length} markdown files\n`) + + // Process each file + for (const file of markdownFiles) { + const content = readFileSync(file, 'utf-8') + const links: Array = markdownLinkExtractor(content) + + const relativeLinks = links.filter((link: string) => { + return isRelativeLink(link) + }) + + if (relativeLinks.length > 0) { + relativeLinks.forEach((link) => { + relativeLinkExists(link, file) + }) + } + } + + if (errors.length > 0) { + console.log(`\n❌ Found ${errors.length} broken links:`) + errors.forEach((err) => { + console.log( + `${err.file}\n link: ${err.link}\n resolved: ${err.resolvedPath}\n why: ${err.reason}\n`, + ) + }) + process.exit(1) + } else { + console.log('\n✅ No broken links found!') + } +} + +verifyMarkdownLinks().catch(console.error)