From 952fad65ae936dde07966e0e3120a9ff06cccb76 Mon Sep 17 00:00:00 2001 From: Yassine Doghri Date: Sun, 26 Feb 2023 17:35:28 +0000 Subject: [PATCH] fix: handle localizePath trailing slash depending on astro's trailingSlash config fixes #119 --- .github/workflows/deploy.yml | 5 +- .github/workflows/publish.yml | 6 +- .github/workflows/test.yml | 2 +- .prettierignore | 29 +++++++ package.json | 6 +- pnpm-lock.yaml | 137 +++++++++++++++++--------------- src/__tests__/utils.test.ts | 21 +++++ src/config.ts | 1 + src/index.ts | 3 + src/types.ts | 9 +++ src/utils.ts | 55 +++++++++---- website/astro-i18next.config.ts | 3 + website/package.json | 5 +- website/pnpm-lock.yaml | 53 ++++++------ 14 files changed, 219 insertions(+), 116 deletions(-) create mode 100644 .prettierignore diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 1ca0df7..ced0852 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -23,11 +23,10 @@ jobs: - name: Install and Build 🔧 run: | - pnpm install + pnpm install --frozen-lockfile pnpm run build cd website - pnpm install - pnpm link .. + pnpm install --frozen-lockfile pnpm run build - name: Deploy 🚀 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index aec3733..c7a0bec 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -25,7 +25,7 @@ jobs: - name: Quality check 👌 run: | - pnpm install + pnpm install --frozen-lockfile pnpm run typecheck pnpm run lint pnpm run prettier @@ -49,7 +49,7 @@ jobs: - name: Bundle 📦 run: | - pnpm install + pnpm install --frozen-lockfile pnpm run build - name: Upload bundle as artifact 📤 @@ -88,7 +88,7 @@ jobs: - name: Release & Publish to NPM 🚀 run: | - pnpm install + pnpm install --frozen-lockfile pnpm run semantic-release env: NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5ac79d8..e31eb85 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,7 +20,7 @@ jobs: version: 7 - name: Install dependencies 📥 - run: pnpm install + run: pnpm install --frozen-lockfile - name: Run tests and collect coverage 🛠️ run: pnpm run test:coverage diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..553fd5c --- /dev/null +++ b/.prettierignore @@ -0,0 +1,29 @@ +# build output +dist + +# dependencies +node_modules/ + +# logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Output of 'npm pack' +*.tgz + +# macOS-specific files +.DS_Store + +# cache +.eslintcache + +# tests +coverage + +# Local Netlify folder +.netlify + +# pnpm +.pnpm-store +pnpm-lock.yaml diff --git a/package.json b/package.json index 42ca9b1..f454593 100644 --- a/package.json +++ b/package.json @@ -9,8 +9,8 @@ "build": "./build.cjs && pnpm run typecheck:emit", "pack": "pnpm run build && pnpm pack", "lint": "eslint --ext js,cjs,ts .", - "prettier": "prettier --check --ignore-path .gitignore .", - "prettier:fix": "prettier --write --ignore-path .gitignore .", + "prettier": "prettier --check --ignore-path .prettierignore .", + "prettier:fix": "prettier --write --ignore-path .prettierignore .", "typecheck": "tsc --noEmit", "typecheck:emit": "tsc --declaration --emitDeclarationOnly --outDir dist/types", "commit": "cz", @@ -96,7 +96,7 @@ "cz-conventional-changelog": "^3.3.0", "esbuild": "^0.17.10", "esbuild-plugin-fileloc": "^0.0.6", - "eslint": "^8.34.0", + "eslint": "^8.35.0", "eslint-config-prettier": "^8.6.0", "eslint-config-standard": "^17.0.0", "eslint-plugin-import": "^2.27.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 604f46d..7b0efd0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -18,7 +18,7 @@ specifiers: cz-conventional-changelog: ^3.3.0 esbuild: ^0.17.10 esbuild-plugin-fileloc: ^0.0.6 - eslint: ^8.34.0 + eslint: ^8.35.0 eslint-config-prettier: ^8.6.0 eslint-config-standard: ^17.0.0 eslint-plugin-import: ^2.27.5 @@ -62,8 +62,8 @@ devDependencies: "@semantic-release/git": 10.0.1_semantic-release@20.1.0 "@types/fs-extra": 11.0.1 "@types/yargs": 17.0.22 - "@typescript-eslint/eslint-plugin": 5.53.0_ny4s7qc6yg74faf3d6xty2ofzy - "@typescript-eslint/parser": 5.53.0_7kw3g6rralp5ps6mg3uyzz6azm + "@typescript-eslint/eslint-plugin": 5.53.0_cjo54hduev4bqhpjw5znwiokqu + "@typescript-eslint/parser": 5.53.0_ycpbpc6yetojsgtrx3mwntkhsu "@vitest/coverage-c8": 0.29.1_vitest@0.29.1 all-contributors-cli: 6.24.0 astro: 2.0.15 @@ -71,14 +71,14 @@ devDependencies: cz-conventional-changelog: 3.3.0 esbuild: 0.17.10 esbuild-plugin-fileloc: 0.0.6 - eslint: 8.34.0 - eslint-config-prettier: 8.6.0_eslint@8.34.0 - eslint-config-standard: 17.0.0_rwq7hzy2vtlwiajbw6pmw3rkzy - eslint-plugin-import: 2.27.5_dbs2zxbe2aiqaiiio3svelvkai - eslint-plugin-jest: 27.2.1_vslf5xus5vvvghisrumieu5qru - eslint-plugin-n: 15.6.1_eslint@8.34.0 - eslint-plugin-prettier: 4.2.1_u5wnrdwibbfomslmnramz52buy - eslint-plugin-promise: 6.1.1_eslint@8.34.0 + eslint: 8.35.0 + eslint-config-prettier: 8.6.0_eslint@8.35.0 + eslint-config-standard: 17.0.0_hwjsujmtoc7k47rjh5qfu7woty + eslint-plugin-import: 2.27.5_nhka4er4oejxhxq3ecgtwxvdji + eslint-plugin-jest: 27.2.1_koxjmbp6xr2mfedykzxazthkei + eslint-plugin-n: 15.6.1_eslint@8.35.0 + eslint-plugin-prettier: 4.2.1_u2zha4kiojzs42thzpgwygphmy + eslint-plugin-promise: 6.1.1_eslint@8.35.0 fdir: 6.0.1 fs-extra: 11.1.0 husky: 8.0.3 @@ -1340,10 +1340,10 @@ packages: dev: true optional: true - /@eslint/eslintrc/1.4.1: + /@eslint/eslintrc/2.0.0: resolution: { - integrity: sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==, + integrity: sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A==, } engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } dependencies: @@ -1360,6 +1360,14 @@ packages: - supports-color dev: true + /@eslint/js/8.35.0: + resolution: + { + integrity: sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw==, + } + engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + dev: true + /@humanwhocodes/config-array/0.11.8: resolution: { @@ -2119,7 +2127,7 @@ packages: "@types/yargs-parser": 21.0.0 dev: true - /@typescript-eslint/eslint-plugin/5.53.0_ny4s7qc6yg74faf3d6xty2ofzy: + /@typescript-eslint/eslint-plugin/5.53.0_cjo54hduev4bqhpjw5znwiokqu: resolution: { integrity: sha512-alFpFWNucPLdUOySmXCJpzr6HKC3bu7XooShWM+3w/EL6J2HIoB2PFxpLnq4JauWVk6DiVeNKzQlFEaE+X9sGw==, @@ -2133,12 +2141,12 @@ packages: typescript: optional: true dependencies: - "@typescript-eslint/parser": 5.53.0_7kw3g6rralp5ps6mg3uyzz6azm + "@typescript-eslint/parser": 5.53.0_ycpbpc6yetojsgtrx3mwntkhsu "@typescript-eslint/scope-manager": 5.53.0 - "@typescript-eslint/type-utils": 5.53.0_7kw3g6rralp5ps6mg3uyzz6azm - "@typescript-eslint/utils": 5.53.0_7kw3g6rralp5ps6mg3uyzz6azm + "@typescript-eslint/type-utils": 5.53.0_ycpbpc6yetojsgtrx3mwntkhsu + "@typescript-eslint/utils": 5.53.0_ycpbpc6yetojsgtrx3mwntkhsu debug: 4.3.4 - eslint: 8.34.0 + eslint: 8.35.0 grapheme-splitter: 1.0.4 ignore: 5.2.4 natural-compare-lite: 1.4.0 @@ -2150,7 +2158,7 @@ packages: - supports-color dev: true - /@typescript-eslint/parser/5.53.0_7kw3g6rralp5ps6mg3uyzz6azm: + /@typescript-eslint/parser/5.53.0_ycpbpc6yetojsgtrx3mwntkhsu: resolution: { integrity: sha512-MKBw9i0DLYlmdOb3Oq/526+al20AJZpANdT6Ct9ffxcV8nKCHz63t/S0IhlTFNsBIHJv+GY5SFJ0XfqVeydQrQ==, @@ -2167,7 +2175,7 @@ packages: "@typescript-eslint/types": 5.53.0 "@typescript-eslint/typescript-estree": 5.53.0_typescript@4.9.5 debug: 4.3.4 - eslint: 8.34.0 + eslint: 8.35.0 typescript: 4.9.5 transitivePeerDependencies: - supports-color @@ -2195,7 +2203,7 @@ packages: "@typescript-eslint/visitor-keys": 5.53.0 dev: true - /@typescript-eslint/type-utils/5.53.0_7kw3g6rralp5ps6mg3uyzz6azm: + /@typescript-eslint/type-utils/5.53.0_ycpbpc6yetojsgtrx3mwntkhsu: resolution: { integrity: sha512-HO2hh0fmtqNLzTAme/KnND5uFNwbsdYhCZghK2SoxGp3Ifn2emv+hi0PBUjzzSh0dstUIFqOj3bp0AwQlK4OWw==, @@ -2209,9 +2217,9 @@ packages: optional: true dependencies: "@typescript-eslint/typescript-estree": 5.53.0_typescript@4.9.5 - "@typescript-eslint/utils": 5.53.0_7kw3g6rralp5ps6mg3uyzz6azm + "@typescript-eslint/utils": 5.53.0_ycpbpc6yetojsgtrx3mwntkhsu debug: 4.3.4 - eslint: 8.34.0 + eslint: 8.35.0 tsutils: 3.21.0_typescript@4.9.5 typescript: 4.9.5 transitivePeerDependencies: @@ -2282,7 +2290,7 @@ packages: - supports-color dev: true - /@typescript-eslint/utils/5.52.0_7kw3g6rralp5ps6mg3uyzz6azm: + /@typescript-eslint/utils/5.52.0_ycpbpc6yetojsgtrx3mwntkhsu: resolution: { integrity: sha512-As3lChhrbwWQLNk2HC8Ree96hldKIqk98EYvypd3It8Q1f8d5zWyIoaZEp2va5667M4ZyE7X8UUR+azXrFl+NA==, @@ -2296,16 +2304,16 @@ packages: "@typescript-eslint/scope-manager": 5.52.0 "@typescript-eslint/types": 5.52.0 "@typescript-eslint/typescript-estree": 5.52.0_typescript@4.9.5 - eslint: 8.34.0 + eslint: 8.35.0 eslint-scope: 5.1.1 - eslint-utils: 3.0.0_eslint@8.34.0 + eslint-utils: 3.0.0_eslint@8.35.0 semver: 7.3.8 transitivePeerDependencies: - supports-color - typescript dev: true - /@typescript-eslint/utils/5.53.0_7kw3g6rralp5ps6mg3uyzz6azm: + /@typescript-eslint/utils/5.53.0_ycpbpc6yetojsgtrx3mwntkhsu: resolution: { integrity: sha512-VUOOtPv27UNWLxFwQK/8+7kvxVC+hPHNsJjzlJyotlaHjLSIgOCKj9I0DBUjwOOA64qjBwx5afAPjksqOxMO0g==, @@ -2319,9 +2327,9 @@ packages: "@typescript-eslint/scope-manager": 5.53.0 "@typescript-eslint/types": 5.53.0 "@typescript-eslint/typescript-estree": 5.53.0_typescript@4.9.5 - eslint: 8.34.0 + eslint: 8.35.0 eslint-scope: 5.1.1 - eslint-utils: 3.0.0_eslint@8.34.0 + eslint-utils: 3.0.0_eslint@8.35.0 semver: 7.3.8 transitivePeerDependencies: - supports-color @@ -4439,7 +4447,7 @@ packages: engines: { node: ">=12" } dev: true - /eslint-config-prettier/8.6.0_eslint@8.34.0: + /eslint-config-prettier/8.6.0_eslint@8.35.0: resolution: { integrity: sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA==, @@ -4448,10 +4456,10 @@ packages: peerDependencies: eslint: ">=7.0.0" dependencies: - eslint: 8.34.0 + eslint: 8.35.0 dev: true - /eslint-config-standard/17.0.0_rwq7hzy2vtlwiajbw6pmw3rkzy: + /eslint-config-standard/17.0.0_hwjsujmtoc7k47rjh5qfu7woty: resolution: { integrity: sha512-/2ks1GKyqSOkH7JFvXJicu0iMpoojkwB+f5Du/1SC0PtBL+s8v30k9njRZ21pm2drKYm2342jFnGWzttxPmZVg==, @@ -4462,10 +4470,10 @@ packages: eslint-plugin-n: ^15.0.0 eslint-plugin-promise: ^6.0.0 dependencies: - eslint: 8.34.0 - eslint-plugin-import: 2.27.5_dbs2zxbe2aiqaiiio3svelvkai - eslint-plugin-n: 15.6.1_eslint@8.34.0 - eslint-plugin-promise: 6.1.1_eslint@8.34.0 + eslint: 8.35.0 + eslint-plugin-import: 2.27.5_nhka4er4oejxhxq3ecgtwxvdji + eslint-plugin-n: 15.6.1_eslint@8.35.0 + eslint-plugin-promise: 6.1.1_eslint@8.35.0 dev: true /eslint-import-resolver-node/0.3.7: @@ -4481,7 +4489,7 @@ packages: - supports-color dev: true - /eslint-module-utils/2.7.4_3freb5c3ievl3t36g6rmbowrqe: + /eslint-module-utils/2.7.4_bchzgevzrq32s4jgdbchl2wqu4: resolution: { integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==, @@ -4505,15 +4513,15 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - "@typescript-eslint/parser": 5.53.0_7kw3g6rralp5ps6mg3uyzz6azm + "@typescript-eslint/parser": 5.53.0_ycpbpc6yetojsgtrx3mwntkhsu debug: 3.2.7 - eslint: 8.34.0 + eslint: 8.35.0 eslint-import-resolver-node: 0.3.7 transitivePeerDependencies: - supports-color dev: true - /eslint-plugin-es/4.1.0_eslint@8.34.0: + /eslint-plugin-es/4.1.0_eslint@8.35.0: resolution: { integrity: sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==, @@ -4522,12 +4530,12 @@ packages: peerDependencies: eslint: ">=4.19.1" dependencies: - eslint: 8.34.0 + eslint: 8.35.0 eslint-utils: 2.1.0 regexpp: 3.2.0 dev: true - /eslint-plugin-import/2.27.5_dbs2zxbe2aiqaiiio3svelvkai: + /eslint-plugin-import/2.27.5_nhka4er4oejxhxq3ecgtwxvdji: resolution: { integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==, @@ -4540,15 +4548,15 @@ packages: "@typescript-eslint/parser": optional: true dependencies: - "@typescript-eslint/parser": 5.53.0_7kw3g6rralp5ps6mg3uyzz6azm + "@typescript-eslint/parser": 5.53.0_ycpbpc6yetojsgtrx3mwntkhsu array-includes: 3.1.6 array.prototype.flat: 1.3.1 array.prototype.flatmap: 1.3.1 debug: 3.2.7 doctrine: 2.1.0 - eslint: 8.34.0 + eslint: 8.35.0 eslint-import-resolver-node: 0.3.7 - eslint-module-utils: 2.7.4_3freb5c3ievl3t36g6rmbowrqe + eslint-module-utils: 2.7.4_bchzgevzrq32s4jgdbchl2wqu4 has: 1.0.3 is-core-module: 2.11.0 is-glob: 4.0.3 @@ -4563,7 +4571,7 @@ packages: - supports-color dev: true - /eslint-plugin-jest/27.2.1_vslf5xus5vvvghisrumieu5qru: + /eslint-plugin-jest/27.2.1_koxjmbp6xr2mfedykzxazthkei: resolution: { integrity: sha512-l067Uxx7ZT8cO9NJuf+eJHvt6bqJyz2Z29wykyEdz/OtmcELQl2MQGQLX8J94O1cSJWAwUSEvCjwjA7KEK3Hmg==, @@ -4579,15 +4587,15 @@ packages: jest: optional: true dependencies: - "@typescript-eslint/eslint-plugin": 5.53.0_ny4s7qc6yg74faf3d6xty2ofzy - "@typescript-eslint/utils": 5.52.0_7kw3g6rralp5ps6mg3uyzz6azm - eslint: 8.34.0 + "@typescript-eslint/eslint-plugin": 5.53.0_cjo54hduev4bqhpjw5znwiokqu + "@typescript-eslint/utils": 5.52.0_ycpbpc6yetojsgtrx3mwntkhsu + eslint: 8.35.0 transitivePeerDependencies: - supports-color - typescript dev: true - /eslint-plugin-n/15.6.1_eslint@8.34.0: + /eslint-plugin-n/15.6.1_eslint@8.35.0: resolution: { integrity: sha512-R9xw9OtCRxxaxaszTQmQAlPgM+RdGjaL1akWuY/Fv9fRAi8Wj4CUKc6iYVG8QNRjRuo8/BqVYIpfqberJUEacA==, @@ -4597,9 +4605,9 @@ packages: eslint: ">=7.0.0" dependencies: builtins: 5.0.1 - eslint: 8.34.0 - eslint-plugin-es: 4.1.0_eslint@8.34.0 - eslint-utils: 3.0.0_eslint@8.34.0 + eslint: 8.35.0 + eslint-plugin-es: 4.1.0_eslint@8.35.0 + eslint-utils: 3.0.0_eslint@8.35.0 ignore: 5.2.4 is-core-module: 2.11.0 minimatch: 3.1.2 @@ -4607,7 +4615,7 @@ packages: semver: 7.3.8 dev: true - /eslint-plugin-prettier/4.2.1_u5wnrdwibbfomslmnramz52buy: + /eslint-plugin-prettier/4.2.1_u2zha4kiojzs42thzpgwygphmy: resolution: { integrity: sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==, @@ -4621,13 +4629,13 @@ packages: eslint-config-prettier: optional: true dependencies: - eslint: 8.34.0 - eslint-config-prettier: 8.6.0_eslint@8.34.0 + eslint: 8.35.0 + eslint-config-prettier: 8.6.0_eslint@8.35.0 prettier: 2.8.4 prettier-linter-helpers: 1.0.0 dev: true - /eslint-plugin-promise/6.1.1_eslint@8.34.0: + /eslint-plugin-promise/6.1.1_eslint@8.35.0: resolution: { integrity: sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==, @@ -4636,7 +4644,7 @@ packages: peerDependencies: eslint: ^7.0.0 || ^8.0.0 dependencies: - eslint: 8.34.0 + eslint: 8.35.0 dev: true /eslint-scope/5.1.1: @@ -4671,7 +4679,7 @@ packages: eslint-visitor-keys: 1.3.0 dev: true - /eslint-utils/3.0.0_eslint@8.34.0: + /eslint-utils/3.0.0_eslint@8.35.0: resolution: { integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==, @@ -4680,7 +4688,7 @@ packages: peerDependencies: eslint: ">=5" dependencies: - eslint: 8.34.0 + eslint: 8.35.0 eslint-visitor-keys: 2.1.0 dev: true @@ -4708,15 +4716,16 @@ packages: engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } dev: true - /eslint/8.34.0: + /eslint/8.35.0: resolution: { - integrity: sha512-1Z8iFsucw+7kSqXNZVslXS8Ioa4u2KM7GPwuKtkTFAqZ/cHMcEaR+1+Br0wLlot49cNxIiZk5wp8EAbPcYZxTg==, + integrity: sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw==, } engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } hasBin: true dependencies: - "@eslint/eslintrc": 1.4.1 + "@eslint/eslintrc": 2.0.0 + "@eslint/js": 8.35.0 "@humanwhocodes/config-array": 0.11.8 "@humanwhocodes/module-importer": 1.0.1 "@nodelib/fs.walk": 1.2.8 @@ -4727,7 +4736,7 @@ packages: doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.1.1 - eslint-utils: 3.0.0_eslint@8.34.0 + eslint-utils: 3.0.0_eslint@8.35.0 eslint-visitor-keys: 3.3.0 espree: 9.4.1 esquery: 1.4.2 diff --git a/src/__tests__/utils.test.ts b/src/__tests__/utils.test.ts index 514af91..564182a 100644 --- a/src/__tests__/utils.test.ts +++ b/src/__tests__/utils.test.ts @@ -6,6 +6,7 @@ import { localizeUrl, deeplyStringifyObject, detectLocaleFromPath, + handleTrailingSlash, } from "../utils"; import i18next from "i18next"; import { afterEach, describe, expect, it, vi } from "vitest"; @@ -355,6 +356,26 @@ describe("localizePath(...)", () => { }); }); +describe("handleTrailingSlash(...)", () => { + it("renders the path taking the correct trailingSlash into account", () => { + expect(handleTrailingSlash("/fr/a-propos", "always")).toBe("/fr/a-propos/"); + expect(handleTrailingSlash("/fr/a-propos/", "always")).toBe( + "/fr/a-propos/" + ); + expect(handleTrailingSlash("/fr/a-propos", "never")).toBe("/fr/a-propos"); + expect(handleTrailingSlash("/fr/a-propos/", "never")).toBe("/fr/a-propos"); + + expect(handleTrailingSlash("/fr/a-propos/", "ignore")).toBe( + "/fr/a-propos/" + ); + expect(handleTrailingSlash("/fr/a-propos", "ignore")).toBe("/fr/a-propos"); + + expect(handleTrailingSlash("/", "always")).toBe("/"); + expect(handleTrailingSlash("/", "never")).toBe("/"); + expect(handleTrailingSlash("/", "ignore")).toBe("/"); + }); +}); + describe("localizeUrl(...)", () => { it("generates the correct url given a url with supported locale", () => { setAstroI18nextConfig({ diff --git a/src/config.ts b/src/config.ts index 207ddda..77bf993 100644 --- a/src/config.ts +++ b/src/config.ts @@ -10,6 +10,7 @@ export const AstroI18next: AstroI18nextGlobal = { routes: {}, flatRoutes: {}, showDefaultLocale: false, + trailingSlash: "ignore", }, }; diff --git a/src/index.ts b/src/index.ts index 77a4aa7..879c96a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -64,6 +64,9 @@ export default (options?: AstroI18nextOptions): AstroIntegration => { ); } + // add trailingSlash config from astro if not set + astroI18nextConfig.trailingSlash = config.trailingSlash; + if (astroI18nextConfig.load.includes("server")) { // Build server side i18next config // set i18next supported and fallback languages (same as locales) diff --git a/src/types.ts b/src/types.ts index 38a86d8..217e634 100644 --- a/src/types.ts +++ b/src/types.ts @@ -115,4 +115,13 @@ export interface AstroI18nextConfig { * ``` */ i18nextClientPlugins?: Plugins; + + /** + * Set the route matching behavior of the dev server. Choose from the following options: + * + * 'always' - Only match URLs that include a trailing slash (ex: "/foo/") + * 'never' - Never match URLs that include a trailing slash (ex: "/foo") + * 'ignore' - Match URLs regardless of whether a trailing "/" exists + */ + trailingSlash?: "always" | "never" | "ignore"; } diff --git a/src/utils.ts b/src/utils.ts index 04f482c..5dee603 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -116,14 +116,10 @@ export const createReferenceStringFromHTML = (html: string) => { "contextSeparator", ] .map((key) => { - const str = i18next.options[key]; - if (str) { - return { - key, - str: i18next.options[key], - }; - } - return undefined; + return { + key, + str: i18next.options[key], + }; }) .filter(function (val: T | undefined): val is T { return typeof val !== "undefined"; @@ -184,6 +180,24 @@ export const createReferenceStringFromHTML = (html: string) => { return sanitizedString; }; +export const handleTrailingSlash = ( + path: string, + trailingSlash: AstroI18nextConfig["trailingSlash"] +) => { + if (path === "/") { + return path; + } + + switch (trailingSlash) { + case "always": + return path.endsWith("/") ? path : path + "/"; + case "never": + return path.replace(/\/$/, ""); + default: + return path; + } +}; + /** * Injects the given locale to a path */ @@ -211,22 +225,30 @@ export const localizePath = ( path = pathSegments.length === 0 ? "" : pathSegments.join("/"); base = baseSegments.length === 0 ? "/" : "/" + baseSegments.join("/") + "/"; - const { flatRoutes, showDefaultLocale, defaultLocale, locales } = - AstroI18next.config; + const { + flatRoutes, + showDefaultLocale, + defaultLocale, + locales, + trailingSlash, + } = AstroI18next.config; if (!locales.includes(locale)) { console.warn( `WARNING(astro-i18next): "${locale}" locale is not supported, add it to the locales in your astro config.` ); - return `${base}${path}`; + return handleTrailingSlash(`${base}${path}`, trailingSlash); } if (pathSegments.length === 0) { if (showDefaultLocale) { - return `${base}${locale}`; + return handleTrailingSlash(`${base}${locale}`, trailingSlash); } - return locale === defaultLocale ? base : `${base}${locale}`; + return handleTrailingSlash( + locale === defaultLocale ? base : `${base}${locale}`, + trailingSlash + ); } // check if the path is not already present in flatRoutes @@ -263,10 +285,13 @@ export const localizePath = ( localizedPath.replace(/\/$/, "") ) ) { - return flatRoutes[localizedPath.replace(/\/$/, "")]; + return handleTrailingSlash( + flatRoutes[localizedPath.replace(/\/$/, "")], + trailingSlash + ); } - return localizedPath; + return handleTrailingSlash(localizedPath, trailingSlash); }; /** diff --git a/website/astro-i18next.config.ts b/website/astro-i18next.config.ts index 0179941..da32bac 100644 --- a/website/astro-i18next.config.ts +++ b/website/astro-i18next.config.ts @@ -8,6 +8,9 @@ const config: AstroI18nextConfig = { about: "a-propos", }, }, + i18nextServer: { + debug: true, + }, }; export default config; diff --git a/website/package.json b/website/package.json index d3674e5..ecc8ee9 100644 --- a/website/package.json +++ b/website/package.json @@ -7,7 +7,7 @@ "dev": "astro dev", "start": "astro dev", "build": "astro build", - "autolink": "cd .. && pnpm link && cd website && pnpm link astro-i18next", + "autolink": "pnpm link .. && pnpm link astro-i18next", "package:build": "cd .. && pnpm run build && cd website", "package:pack": "cd .. && pnpm run build && pnpm run pack && cd website", "preview": "astro preview", @@ -17,8 +17,9 @@ "@astrojs/sitemap": "^1.1.0", "@astrojs/tailwind": "^3.0.1", "astro": "^2.0.15", - "astro-i18next": "1.0.0-beta.17", + "astro-i18next": "file:..", "astro-seo": "^0.7.1", + "i18next": "^22.4.10", "tailwindcss": "^3.2.7" } } diff --git a/website/pnpm-lock.yaml b/website/pnpm-lock.yaml index ae15c73..6d6ac51 100644 --- a/website/pnpm-lock.yaml +++ b/website/pnpm-lock.yaml @@ -4,16 +4,18 @@ specifiers: "@astrojs/sitemap": ^1.1.0 "@astrojs/tailwind": ^3.0.1 astro: ^2.0.15 - astro-i18next: 1.0.0-beta.17 + astro-i18next: file:.. astro-seo: ^0.7.1 + i18next: ^22.4.10 tailwindcss: ^3.2.7 dependencies: "@astrojs/sitemap": 1.1.0 "@astrojs/tailwind": 3.0.1_enl5tymeuxlslzmmdrwlr7zkvy astro: 2.0.15 - astro-i18next: 1.0.0-beta.17_astro@2.0.15 + astro-i18next: file:.._32ggdqizw6cm6nidtk5kjvtpuy astro-seo: 0.7.1 + i18next: 22.4.10 tailwindcss: 3.2.7 packages: @@ -1201,29 +1203,6 @@ packages: } dev: false - /astro-i18next/1.0.0-beta.17_astro@2.0.15: - resolution: - { - integrity: sha512-EyVhwLuNcQoQnte4Gn/2Mj9SuTS7lmWPZFDRF+rrONcBSm/Il3wQv78PaOUWfdE3QjHznYfg8o6RvLuvu6RM4Q==, - } - hasBin: true - peerDependencies: - astro: ">=1.0.0" - dependencies: - "@proload/core": 0.3.3 - "@proload/plugin-tsm": 0.2.1_@proload+core@0.3.3 - astro: 2.0.15 - i18next: 22.4.10 - i18next-browser-languagedetector: 7.0.1 - i18next-fs-backend: 2.1.1 - i18next-http-backend: 2.1.1 - iso-639-1: 2.1.15 - locale-emoji: 0.3.0 - pathe: 1.1.0 - transitivePeerDependencies: - - encoding - dev: false - /astro-seo/0.7.1: resolution: { @@ -5142,3 +5121,27 @@ packages: integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==, } dev: false + + file:.._32ggdqizw6cm6nidtk5kjvtpuy: + resolution: { directory: .., type: directory } + id: file:.. + name: astro-i18next + version: 1.0.0-beta.17 + hasBin: true + peerDependencies: + astro: ">=1.0.0" + i18next: ^22.4.0 + dependencies: + "@proload/core": 0.3.3 + "@proload/plugin-tsm": 0.2.1_@proload+core@0.3.3 + astro: 2.0.15 + i18next: 22.4.10 + i18next-browser-languagedetector: 7.0.1 + i18next-fs-backend: 2.1.1 + i18next-http-backend: 2.1.1 + iso-639-1: 2.1.15 + locale-emoji: 0.3.0 + pathe: 1.1.0 + transitivePeerDependencies: + - encoding + dev: false