diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index a73737f..1ff3e3d 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -13,12 +13,10 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4.0.0
- with:
- version: 9.1.1
- name: Use Node.js
uses: actions/setup-node@v4.0.2
with:
- node-version: 20
+ node-version: 22
cache: 'pnpm'
- run: pnpm install
- run: pnpm run build
@@ -29,14 +27,12 @@ jobs:
needs: [typecheck]
strategy:
matrix:
- node: ['20']
+ node: ['22']
steps:
- uses: actions/checkout@v4
with:
fetch-depth: '0'
- uses: pnpm/action-setup@v4.0.0
- with:
- version: 9.1.1
- name: Use Node.js
uses: actions/setup-node@v4.0.2
with:
@@ -48,7 +44,7 @@ jobs:
- run: pnpm run coverage
- name: Upload coverage report
if: success()
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v4
with:
name: coverage-report
path: coverage/lcov-report/index.html
@@ -56,14 +52,12 @@ jobs:
build:
strategy:
matrix:
- node: ['20']
+ node: ['22']
runs-on: ubuntu-22.04
needs: [typecheck]
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4.0.0
- with:
- version: 9.1.1
- name: Use Node.js
uses: actions/setup-node@v4.0.2
with:
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index e9c1033..c87bc20 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -23,14 +23,11 @@ jobs:
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
- uses: pnpm/action-setup@v4.0.0
- with:
- version: 9.1.1
- name: Use Node.js
uses: actions/setup-node@v4
with:
- node-version: 20
- cache: 'pnpm'
+ node-version: 22
- run: pnpm install
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..b58b603
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,5 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
diff --git a/.idea/biome.xml b/.idea/biome.xml
new file mode 100644
index 0000000..0b9612d
--- /dev/null
+++ b/.idea/biome.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..85ed8a7
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/unused-i18n.iml b/.idea/unused-i18n.iml
new file mode 100644
index 0000000..24643cc
--- /dev/null
+++ b/.idea/unused-i18n.iml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/biome.json b/biome.json
new file mode 100644
index 0000000..c9f4a37
--- /dev/null
+++ b/biome.json
@@ -0,0 +1,60 @@
+{
+ "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
+ "organizeImports": {
+ "enabled": false
+ },
+ "linter": {
+ "enabled": false
+ },
+ "vcs": {
+ "clientKind": "git",
+ "useIgnoreFile": false,
+ "defaultBranch": "main"
+ },
+ "formatter": {
+ "enabled": true,
+ "formatWithErrors": false,
+ "indentStyle": "space",
+ "indentWidth": 2,
+ "lineEnding": "lf",
+ "lineWidth": 80,
+ "attributePosition": "auto"
+ },
+ "javascript": {
+ "formatter": {
+ "jsxQuoteStyle": "double",
+ "quoteProperties": "asNeeded",
+ "trailingCommas": "all",
+ "semicolons": "asNeeded",
+ "arrowParentheses": "asNeeded",
+ "bracketSpacing": true,
+ "bracketSameLine": false,
+ "quoteStyle": "single",
+ "attributePosition": "auto"
+ }
+ },
+ "json": {
+ "formatter": {
+ "enabled": true
+ },
+ "parser": {
+ "allowComments": true
+ },
+ "linter": {
+ "enabled": true
+ }
+ },
+ "css": {
+ "formatter": {
+ "enabled": true,
+ "quoteStyle": "single"
+ },
+ "linter": {
+ "enabled": true
+ },
+ "parser": {
+ "allowWrongLineComments": false,
+ "cssModules": true
+ }
+ }
+}
diff --git a/package.json b/package.json
index ccb1df1..3a8944f 100644
--- a/package.json
+++ b/package.json
@@ -34,17 +34,19 @@
"coverage": "vitest run --coverage"
},
"dependencies": {
- "commander": "^12.1.0"
+ "commander": "^12.1.0",
+ "esbuild": "^0.24.0"
},
"devDependencies": {
+ "@biomejs/biome": "1.9.4",
"@changesets/changelog-github": "^0.5.0",
"@changesets/cli": "^2.27.3",
"@types/node": "^14.18.63",
"@vitest/coverage-c8": "^0.33.0",
"@vitest/coverage-istanbul": "^1.6.0",
"typescript": "^5.2.2",
- "vitest": "^1.6.0",
- "vite": "^5.2.0"
+ "vite": "^5.2.0",
+ "vitest": "^1.6.0"
},
"keywords": [
"i18n",
@@ -57,7 +59,8 @@
"next"
],
"engines": {
- "node": ">=18.x",
- "pnpm": ">=8.x"
- }
+ "node": ">=22.x",
+ "pnpm": ">=9.x"
+ },
+ "packageManager": "pnpm@9.13.2+sha512.88c9c3864450350e65a33587ab801acf946d7c814ed1134da4a924f6df5a2120fd36b46aab68f7cd1d413149112d53c7db3a4136624cfd00ff1846a0c6cef48a"
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 07779ff..b882c8c 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -11,7 +11,13 @@ importers:
commander:
specifier: ^12.1.0
version: 12.1.0
+ esbuild:
+ specifier: ^0.24.0
+ version: 0.24.0
devDependencies:
+ '@biomejs/biome':
+ specifier: 1.9.4
+ version: 1.9.4
'@changesets/changelog-github':
specifier: ^0.5.0
version: 0.5.0(encoding@0.1.13)
@@ -137,6 +143,59 @@ packages:
'@bcoe/v8-coverage@0.2.3':
resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
+ '@biomejs/biome@1.9.4':
+ resolution: {integrity: sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog==}
+ engines: {node: '>=14.21.3'}
+ hasBin: true
+
+ '@biomejs/cli-darwin-arm64@1.9.4':
+ resolution: {integrity: sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw==}
+ engines: {node: '>=14.21.3'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@biomejs/cli-darwin-x64@1.9.4':
+ resolution: {integrity: sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg==}
+ engines: {node: '>=14.21.3'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@biomejs/cli-linux-arm64-musl@1.9.4':
+ resolution: {integrity: sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA==}
+ engines: {node: '>=14.21.3'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@biomejs/cli-linux-arm64@1.9.4':
+ resolution: {integrity: sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g==}
+ engines: {node: '>=14.21.3'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@biomejs/cli-linux-x64-musl@1.9.4':
+ resolution: {integrity: sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg==}
+ engines: {node: '>=14.21.3'}
+ cpu: [x64]
+ os: [linux]
+
+ '@biomejs/cli-linux-x64@1.9.4':
+ resolution: {integrity: sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg==}
+ engines: {node: '>=14.21.3'}
+ cpu: [x64]
+ os: [linux]
+
+ '@biomejs/cli-win32-arm64@1.9.4':
+ resolution: {integrity: sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg==}
+ engines: {node: '>=14.21.3'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@biomejs/cli-win32-x64@1.9.4':
+ resolution: {integrity: sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA==}
+ engines: {node: '>=14.21.3'}
+ cpu: [x64]
+ os: [win32]
+
'@changesets/apply-release-plan@7.0.1':
resolution: {integrity: sha512-aPdSq/R++HOyfEeBGjEe6LNG8gs0KMSyRETD/J2092OkNq8mOioAxyKjMbvVUdzgr/HTawzMOz7lfw339KnsCA==}
@@ -201,138 +260,282 @@ packages:
cpu: [ppc64]
os: [aix]
+ '@esbuild/aix-ppc64@0.24.0':
+ resolution: {integrity: sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [aix]
+
'@esbuild/android-arm64@0.20.2':
resolution: {integrity: sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==}
engines: {node: '>=12'}
cpu: [arm64]
os: [android]
+ '@esbuild/android-arm64@0.24.0':
+ resolution: {integrity: sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [android]
+
'@esbuild/android-arm@0.20.2':
resolution: {integrity: sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==}
engines: {node: '>=12'}
cpu: [arm]
os: [android]
+ '@esbuild/android-arm@0.24.0':
+ resolution: {integrity: sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [android]
+
'@esbuild/android-x64@0.20.2':
resolution: {integrity: sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==}
engines: {node: '>=12'}
cpu: [x64]
os: [android]
+ '@esbuild/android-x64@0.24.0':
+ resolution: {integrity: sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [android]
+
'@esbuild/darwin-arm64@0.20.2':
resolution: {integrity: sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==}
engines: {node: '>=12'}
cpu: [arm64]
os: [darwin]
+ '@esbuild/darwin-arm64@0.24.0':
+ resolution: {integrity: sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [darwin]
+
'@esbuild/darwin-x64@0.20.2':
resolution: {integrity: sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==}
engines: {node: '>=12'}
cpu: [x64]
os: [darwin]
+ '@esbuild/darwin-x64@0.24.0':
+ resolution: {integrity: sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [darwin]
+
'@esbuild/freebsd-arm64@0.20.2':
resolution: {integrity: sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==}
engines: {node: '>=12'}
cpu: [arm64]
os: [freebsd]
+ '@esbuild/freebsd-arm64@0.24.0':
+ resolution: {integrity: sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [freebsd]
+
'@esbuild/freebsd-x64@0.20.2':
resolution: {integrity: sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==}
engines: {node: '>=12'}
cpu: [x64]
os: [freebsd]
+ '@esbuild/freebsd-x64@0.24.0':
+ resolution: {integrity: sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [freebsd]
+
'@esbuild/linux-arm64@0.20.2':
resolution: {integrity: sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==}
engines: {node: '>=12'}
cpu: [arm64]
os: [linux]
+ '@esbuild/linux-arm64@0.24.0':
+ resolution: {integrity: sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [linux]
+
'@esbuild/linux-arm@0.20.2':
resolution: {integrity: sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==}
engines: {node: '>=12'}
cpu: [arm]
os: [linux]
+ '@esbuild/linux-arm@0.24.0':
+ resolution: {integrity: sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [linux]
+
'@esbuild/linux-ia32@0.20.2':
resolution: {integrity: sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==}
engines: {node: '>=12'}
cpu: [ia32]
os: [linux]
+ '@esbuild/linux-ia32@0.24.0':
+ resolution: {integrity: sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [linux]
+
'@esbuild/linux-loong64@0.20.2':
resolution: {integrity: sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==}
engines: {node: '>=12'}
cpu: [loong64]
os: [linux]
+ '@esbuild/linux-loong64@0.24.0':
+ resolution: {integrity: sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==}
+ engines: {node: '>=18'}
+ cpu: [loong64]
+ os: [linux]
+
'@esbuild/linux-mips64el@0.20.2':
resolution: {integrity: sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==}
engines: {node: '>=12'}
cpu: [mips64el]
os: [linux]
+ '@esbuild/linux-mips64el@0.24.0':
+ resolution: {integrity: sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==}
+ engines: {node: '>=18'}
+ cpu: [mips64el]
+ os: [linux]
+
'@esbuild/linux-ppc64@0.20.2':
resolution: {integrity: sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==}
engines: {node: '>=12'}
cpu: [ppc64]
os: [linux]
+ '@esbuild/linux-ppc64@0.24.0':
+ resolution: {integrity: sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [linux]
+
'@esbuild/linux-riscv64@0.20.2':
resolution: {integrity: sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==}
engines: {node: '>=12'}
cpu: [riscv64]
os: [linux]
+ '@esbuild/linux-riscv64@0.24.0':
+ resolution: {integrity: sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==}
+ engines: {node: '>=18'}
+ cpu: [riscv64]
+ os: [linux]
+
'@esbuild/linux-s390x@0.20.2':
resolution: {integrity: sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==}
engines: {node: '>=12'}
cpu: [s390x]
os: [linux]
+ '@esbuild/linux-s390x@0.24.0':
+ resolution: {integrity: sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==}
+ engines: {node: '>=18'}
+ cpu: [s390x]
+ os: [linux]
+
'@esbuild/linux-x64@0.20.2':
resolution: {integrity: sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==}
engines: {node: '>=12'}
cpu: [x64]
os: [linux]
+ '@esbuild/linux-x64@0.24.0':
+ resolution: {integrity: sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [linux]
+
'@esbuild/netbsd-x64@0.20.2':
resolution: {integrity: sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==}
engines: {node: '>=12'}
cpu: [x64]
os: [netbsd]
+ '@esbuild/netbsd-x64@0.24.0':
+ resolution: {integrity: sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [netbsd]
+
+ '@esbuild/openbsd-arm64@0.24.0':
+ resolution: {integrity: sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openbsd]
+
'@esbuild/openbsd-x64@0.20.2':
resolution: {integrity: sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==}
engines: {node: '>=12'}
cpu: [x64]
os: [openbsd]
+ '@esbuild/openbsd-x64@0.24.0':
+ resolution: {integrity: sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [openbsd]
+
'@esbuild/sunos-x64@0.20.2':
resolution: {integrity: sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==}
engines: {node: '>=12'}
cpu: [x64]
os: [sunos]
+ '@esbuild/sunos-x64@0.24.0':
+ resolution: {integrity: sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [sunos]
+
'@esbuild/win32-arm64@0.20.2':
resolution: {integrity: sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==}
engines: {node: '>=12'}
cpu: [arm64]
os: [win32]
+ '@esbuild/win32-arm64@0.24.0':
+ resolution: {integrity: sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [win32]
+
'@esbuild/win32-ia32@0.20.2':
resolution: {integrity: sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==}
engines: {node: '>=12'}
cpu: [ia32]
os: [win32]
+ '@esbuild/win32-ia32@0.24.0':
+ resolution: {integrity: sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [win32]
+
'@esbuild/win32-x64@0.20.2':
resolution: {integrity: sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==}
engines: {node: '>=12'}
cpu: [x64]
os: [win32]
+ '@esbuild/win32-x64@0.24.0':
+ resolution: {integrity: sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [win32]
+
'@istanbuljs/schema@0.1.3':
resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==}
engines: {node: '>=8'}
@@ -814,6 +1017,11 @@ packages:
engines: {node: '>=12'}
hasBin: true
+ esbuild@0.24.0:
+ resolution: {integrity: sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==}
+ engines: {node: '>=18'}
+ hasBin: true
+
escalade@3.1.2:
resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==}
engines: {node: '>=6'}
@@ -2035,6 +2243,41 @@ snapshots:
'@bcoe/v8-coverage@0.2.3': {}
+ '@biomejs/biome@1.9.4':
+ optionalDependencies:
+ '@biomejs/cli-darwin-arm64': 1.9.4
+ '@biomejs/cli-darwin-x64': 1.9.4
+ '@biomejs/cli-linux-arm64': 1.9.4
+ '@biomejs/cli-linux-arm64-musl': 1.9.4
+ '@biomejs/cli-linux-x64': 1.9.4
+ '@biomejs/cli-linux-x64-musl': 1.9.4
+ '@biomejs/cli-win32-arm64': 1.9.4
+ '@biomejs/cli-win32-x64': 1.9.4
+
+ '@biomejs/cli-darwin-arm64@1.9.4':
+ optional: true
+
+ '@biomejs/cli-darwin-x64@1.9.4':
+ optional: true
+
+ '@biomejs/cli-linux-arm64-musl@1.9.4':
+ optional: true
+
+ '@biomejs/cli-linux-arm64@1.9.4':
+ optional: true
+
+ '@biomejs/cli-linux-x64-musl@1.9.4':
+ optional: true
+
+ '@biomejs/cli-linux-x64@1.9.4':
+ optional: true
+
+ '@biomejs/cli-win32-arm64@1.9.4':
+ optional: true
+
+ '@biomejs/cli-win32-x64@1.9.4':
+ optional: true
+
'@changesets/apply-release-plan@7.0.1':
dependencies:
'@babel/runtime': 7.24.6
@@ -2201,72 +2444,144 @@ snapshots:
'@esbuild/aix-ppc64@0.20.2':
optional: true
+ '@esbuild/aix-ppc64@0.24.0':
+ optional: true
+
'@esbuild/android-arm64@0.20.2':
optional: true
+ '@esbuild/android-arm64@0.24.0':
+ optional: true
+
'@esbuild/android-arm@0.20.2':
optional: true
+ '@esbuild/android-arm@0.24.0':
+ optional: true
+
'@esbuild/android-x64@0.20.2':
optional: true
+ '@esbuild/android-x64@0.24.0':
+ optional: true
+
'@esbuild/darwin-arm64@0.20.2':
optional: true
+ '@esbuild/darwin-arm64@0.24.0':
+ optional: true
+
'@esbuild/darwin-x64@0.20.2':
optional: true
+ '@esbuild/darwin-x64@0.24.0':
+ optional: true
+
'@esbuild/freebsd-arm64@0.20.2':
optional: true
+ '@esbuild/freebsd-arm64@0.24.0':
+ optional: true
+
'@esbuild/freebsd-x64@0.20.2':
optional: true
+ '@esbuild/freebsd-x64@0.24.0':
+ optional: true
+
'@esbuild/linux-arm64@0.20.2':
optional: true
+ '@esbuild/linux-arm64@0.24.0':
+ optional: true
+
'@esbuild/linux-arm@0.20.2':
optional: true
+ '@esbuild/linux-arm@0.24.0':
+ optional: true
+
'@esbuild/linux-ia32@0.20.2':
optional: true
+ '@esbuild/linux-ia32@0.24.0':
+ optional: true
+
'@esbuild/linux-loong64@0.20.2':
optional: true
+ '@esbuild/linux-loong64@0.24.0':
+ optional: true
+
'@esbuild/linux-mips64el@0.20.2':
optional: true
+ '@esbuild/linux-mips64el@0.24.0':
+ optional: true
+
'@esbuild/linux-ppc64@0.20.2':
optional: true
+ '@esbuild/linux-ppc64@0.24.0':
+ optional: true
+
'@esbuild/linux-riscv64@0.20.2':
optional: true
+ '@esbuild/linux-riscv64@0.24.0':
+ optional: true
+
'@esbuild/linux-s390x@0.20.2':
optional: true
+ '@esbuild/linux-s390x@0.24.0':
+ optional: true
+
'@esbuild/linux-x64@0.20.2':
optional: true
+ '@esbuild/linux-x64@0.24.0':
+ optional: true
+
'@esbuild/netbsd-x64@0.20.2':
optional: true
+ '@esbuild/netbsd-x64@0.24.0':
+ optional: true
+
+ '@esbuild/openbsd-arm64@0.24.0':
+ optional: true
+
'@esbuild/openbsd-x64@0.20.2':
optional: true
+ '@esbuild/openbsd-x64@0.24.0':
+ optional: true
+
'@esbuild/sunos-x64@0.20.2':
optional: true
+ '@esbuild/sunos-x64@0.24.0':
+ optional: true
+
'@esbuild/win32-arm64@0.20.2':
optional: true
+ '@esbuild/win32-arm64@0.24.0':
+ optional: true
+
'@esbuild/win32-ia32@0.20.2':
optional: true
+ '@esbuild/win32-ia32@0.24.0':
+ optional: true
+
'@esbuild/win32-x64@0.20.2':
optional: true
+ '@esbuild/win32-x64@0.24.0':
+ optional: true
+
'@istanbuljs/schema@0.1.3': {}
'@jest/schemas@29.6.3':
@@ -2837,6 +3152,33 @@ snapshots:
'@esbuild/win32-ia32': 0.20.2
'@esbuild/win32-x64': 0.20.2
+ esbuild@0.24.0:
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.24.0
+ '@esbuild/android-arm': 0.24.0
+ '@esbuild/android-arm64': 0.24.0
+ '@esbuild/android-x64': 0.24.0
+ '@esbuild/darwin-arm64': 0.24.0
+ '@esbuild/darwin-x64': 0.24.0
+ '@esbuild/freebsd-arm64': 0.24.0
+ '@esbuild/freebsd-x64': 0.24.0
+ '@esbuild/linux-arm': 0.24.0
+ '@esbuild/linux-arm64': 0.24.0
+ '@esbuild/linux-ia32': 0.24.0
+ '@esbuild/linux-loong64': 0.24.0
+ '@esbuild/linux-mips64el': 0.24.0
+ '@esbuild/linux-ppc64': 0.24.0
+ '@esbuild/linux-riscv64': 0.24.0
+ '@esbuild/linux-s390x': 0.24.0
+ '@esbuild/linux-x64': 0.24.0
+ '@esbuild/netbsd-x64': 0.24.0
+ '@esbuild/openbsd-arm64': 0.24.0
+ '@esbuild/openbsd-x64': 0.24.0
+ '@esbuild/sunos-x64': 0.24.0
+ '@esbuild/win32-arm64': 0.24.0
+ '@esbuild/win32-ia32': 0.24.0
+ '@esbuild/win32-x64': 0.24.0
+
escalade@3.1.2: {}
escape-string-regexp@1.0.5: {}
diff --git a/src/index.ts b/src/index.ts
index a3f3f51..528bedb 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,10 +1,10 @@
import * as fs from 'fs'
-import { loadConfig } from './utils/loadConfig'
-import { getMissingTranslations } from './utils/missingTranslations'
-import { summary } from './utils/summary'
-import { searchFilesRecursively } from './lib/search'
-import { analyze } from './lib/analyze'
-import { removeLocaleKeys } from './lib/remove'
+import { loadConfig } from '@utils/loadConfig'
+import { getMissingTranslations } from '@utils/missingTranslations'
+import { summary } from '@utils/summary'
+import { searchFilesRecursively } from '@lib/search'
+import { analyze } from '@lib/analyze'
+import { removeLocaleKeys } from '@lib/remove'
import { ProcessTranslationsArgs } from './types'
import { performance } from 'perf_hooks'
@@ -31,9 +31,9 @@ export const processTranslations = async ({
let allExtractedTranslations: string[] = []
let pathUnusedLocalesCount = 0
- srcPath.forEach((pathEntry) => {
- const ignorePathExists = config.ignorePaths?.some((ignorePath) =>
- pathEntry.includes(ignorePath)
+ srcPath.forEach(pathEntry => {
+ const ignorePathExists = config.ignorePaths?.some(ignorePath =>
+ pathEntry.includes(ignorePath),
)
if (ignorePathExists) return
const files = searchFilesRecursively({
@@ -43,11 +43,11 @@ export const processTranslations = async ({
})
const extractedTranslations = files
- .flatMap((file) =>
+ .flatMap(file =>
analyze({
filePath: file,
scopedNames: config.scopedNames,
- })
+ }),
)
.sort()
.filter((item, index, array) => array.indexOf(item) === index)
@@ -61,8 +61,8 @@ export const processTranslations = async ({
allExtractedTranslations = [...new Set(allExtractedTranslations)].sort()
const localeFilePath = `${localPath}/${localesNames}.${localesExtensions}`
- const ignorePathExists = config.ignorePaths?.some((ignorePath) =>
- localeFilePath.includes(ignorePath)
+ const ignorePathExists = config.ignorePaths?.some(ignorePath =>
+ localeFilePath.includes(ignorePath),
)
if (fs.existsSync(localeFilePath) && !ignorePathExists) {
console.log(`${localeFilePath}...`)
@@ -70,9 +70,9 @@ export const processTranslations = async ({
const localLines = fs
.readFileSync(localeFilePath, 'utf-8')
.split('\n')
- .map((line) => line.trim())
- .filter((line) => line.match(/'[^']*':/))
- .map((line) => line.match(/'([^']+)':/)?.[1] ?? '')
+ .map(line => line.trim())
+ .filter(line => line.match(/'[^']*':/))
+ .map(line => line.match(/'([^']+)':/)?.[1] ?? '')
.sort()
const missingTranslations = getMissingTranslations({
@@ -85,7 +85,7 @@ export const processTranslations = async ({
totalUnusedLocales += pathUnusedLocalesCount
const formattedMissingTranslations = missingTranslations
- .map((translation) => `\x1b[31m${translation}\x1b[0m`)
+ .map(translation => `\x1b[31m${translation}\x1b[0m`)
.join('\n')
const message = missingTranslations.length
@@ -113,8 +113,8 @@ export const processTranslations = async ({
summary({ unusedLocalesCountByPath, totalUnusedLocales })
console.log(
`\x1b[38;2;128;128;128mDuration : ${(endTime - startTime).toFixed(
- 0
- )}ms\x1b[0m`
+ 0,
+ )}ms\x1b[0m`,
)
// Check if totalUnusedLocales is greater than 0
diff --git a/src/lib/analyze.ts b/src/lib/analyze.ts
index 8fff4ef..2baf4b3 100644
--- a/src/lib/analyze.ts
+++ b/src/lib/analyze.ts
@@ -9,10 +9,10 @@ export const analyze = ({ filePath, scopedNames }: AnalyzeArgs): string[] => {
const namespaceTranslations = extractNamespaceTranslation({ fileContent })
const scopedTs = (
- scopedNames?.map((scopedName) =>
- namespaceTranslations.flatMap((namespaceTranslation) =>
- extractScopedTs({ fileContent, namespaceTranslation, scopedName })
- )
+ scopedNames?.map(scopedName =>
+ namespaceTranslations.flatMap(namespaceTranslation =>
+ extractScopedTs({ fileContent, namespaceTranslation, scopedName }),
+ ),
) ?? []
).flat(2)
diff --git a/src/lib/scopedNamespace/extractNamespaceTranslation.ts b/src/lib/scopedNamespace/extractNamespaceTranslation.ts
index 98fe3a6..507321f 100644
--- a/src/lib/scopedNamespace/extractNamespaceTranslation.ts
+++ b/src/lib/scopedNamespace/extractNamespaceTranslation.ts
@@ -1,28 +1,69 @@
import { ExtractTranslationArgs } from '../../types'
-
export const extractNamespaceTranslation = ({
fileContent,
}: ExtractTranslationArgs): string[] => {
+ // Match regular namespaceTranslation
const namespaceTranslationPattern =
/namespaceTranslation\(\s*['"`]([\s\S]*?)['"`]\s*,?\s*\)/g
+
+ // Match ternary inside namespaceTranslation
const namespaceTranslationPatternTernary =
- /namespaceTranslation\(\s*([^()]*\?)\s*['"`]([^'"`]*?)['"`]\s*:\s*['"`]([^'"`]*?)['"`]\s*\)/
+ /namespaceTranslation\(\s*([^\?]+?)\s*\?\s*['"\`]([^'"\\\`\n]+)['"`]\s*:\s*['"`]([^'"\\\`\n]+)['"`']\s*,?\s*\)/g
+
+ // Match template literal inside namespaceTranslation
+ const namespaceTranslationPatternTemplateLiteral =
+ /namespaceTranslation\(\s*`([\s\S]*?)`\s*\)/g
- const matches = []
+ const matches: string[] = []
let match
- // Extract matches for the regular namespaceTranslation pattern
+ // Extract regular namespaceTranslation matches
while ((match = namespaceTranslationPattern.exec(fileContent)) !== null) {
matches.push(match[1].trim())
}
- // Extract matches for the ternary pattern
- const ternaryMatch = fileContent.match(namespaceTranslationPatternTernary)
- if (ternaryMatch) {
- const trueValue = ternaryMatch[2].trim()
- const falseValue = ternaryMatch[3].trim()
+ // Extract ternary matches inside namespaceTranslation
+ while (
+ (match = namespaceTranslationPatternTernary.exec(fileContent)) !== null
+ ) {
+ const trueValue = match[2].trim()
+ const falseValue = match[3].trim()
matches.push(trueValue, falseValue)
}
- return matches
+ // Extract template literal matches inside namespaceTranslation
+ while (
+ (match = namespaceTranslationPatternTemplateLiteral.exec(fileContent)) !==
+ null
+ ) {
+ const templateLiteral = match[1].trim()
+
+ // Find the dynamic parts inside `${}` in the template literal
+ const dynamicPartsMatch = /\${([^}]+)}/g
+ let dynamicPart
+ while ((dynamicPart = dynamicPartsMatch.exec(templateLiteral)) !== null) {
+ const dynamicExpression = dynamicPart[1].trim()
+
+ // Now handle ternary expression inside this dynamic part
+ const ternaryMatch =
+ /([^\?]+?)\s*\?\s*['"`]([^'"\\\`\n]+)['"`]\s*:\s*['"`]([^'"\\\`\n]+)['"`]/g
+ let ternaryInnerMatch
+ while (
+ (ternaryInnerMatch = ternaryMatch.exec(dynamicExpression)) !== null
+ ) {
+ const trueValue = ternaryInnerMatch[2].trim()
+ const falseValue = ternaryInnerMatch[3].trim()
+ matches.push(trueValue, falseValue)
+ }
+
+ // Push the dynamic expression result into the matches
+ matches.push(dynamicExpression)
+ }
+
+ // Push the whole template literal into the matches
+ matches.push(templateLiteral)
+ }
+
+ // Remove duplicates and return the sorted result
+ return [...new Set(matches)].sort()
}
diff --git a/src/lib/scopedNamespace/extractScopedTs.ts b/src/lib/scopedNamespace/extractScopedTs.ts
index b26faf1..d649cf8 100644
--- a/src/lib/scopedNamespace/extractScopedTs.ts
+++ b/src/lib/scopedNamespace/extractScopedTs.ts
@@ -8,23 +8,23 @@ export const extractScopedTs = ({
// Patterns with the variable
const scopedTPattern = new RegExp(
`${scopedName}\\(\\s*['"\`']([\\s\\S]*?)['"\`']\\s*(?:,|\\))`,
- 'g'
+ 'g',
)
const scopedTPatternWithTernary = new RegExp(
`${scopedName}\\(\\s*([\\s\\S]+?)\\s*\\?\\s*['"\`']([^'"\\\`\n]+)['"\`']\\s*:\\s*['"\`']([^'"\\\`\n]+)['"\`'],?\\s*\\)`,
- 'gm'
+ 'gm',
)
const scopedTPatternWithTernaryAndParams = new RegExp(
`${scopedName}\\(\\s*([^?\n]+)\\s*\\?\\s*['"\`']([^'"\\\`]+)['"\`']\\s*:\\s*['"\`']([^'"\\\`]+)['"\`'],\\s*\\{[\\s\\S]*?\\},?\\s*\\)`,
- 'gm'
+ 'gm',
)
const scopedTVariablePattern = new RegExp(
`${scopedName}\\(\\s*([a-zA-Z_$][\\w.$]*)\\s*\\)`,
- 'g'
+ 'g',
)
const scopedTTemplatePattern = new RegExp(
`${scopedName}\\(\\s*\`([\\s\\S]*?)\`\\s*\\)`,
- 'g'
+ 'g',
)
const scopedTs: Set = new Set()
@@ -43,13 +43,13 @@ export const extractScopedTs = ({
`${namespaceTranslationTrimmed}.${trueValue
.replace(/'/g, '')
.replace(/,/g, '')
- .trim()}`
+ .trim()}`,
)
scopedTs.add(
`${namespaceTranslationTrimmed}.${falseValue
.replace(/'/g, '')
.replace(/,/g, '')
- .trim()}`
+ .trim()}`,
)
}
@@ -61,12 +61,12 @@ export const extractScopedTs = ({
scopedTs.add(
`${namespaceTranslationTrimmed}.${trueValue
.replace(/'/g, '')
- .replace(/,/g, '')}`
+ .replace(/,/g, '')}`,
)
scopedTs.add(
`${namespaceTranslationTrimmed}.${falseValue
.replace(/'/g, '')
- .replace(/,/g, '')}`
+ .replace(/,/g, '')}`,
)
}
@@ -85,12 +85,12 @@ export const extractScopedTs = ({
const [ifValue, elseValue] = ternary
.split(' ? ')[1]
.split(':')
- .map((val) => val.trim().replace(/'/g, ''))
+ .map(val => val.trim().replace(/'/g, ''))
const stringIf = `${scopedTWithNamespace.replace(fullMatch, ifValue)}`
const stringElse = `${scopedTWithNamespace.replace(
fullMatch,
- elseValue
+ elseValue,
)}`
scopedTs.add(stringIf)
@@ -113,14 +113,14 @@ export const extractScopedTs = ({
while ((match = scopedTTemplatePattern.exec(fileContent))) {
const templateLiteral = match[1]
- const dynamicParts = templateLiteral.split(/(\$\{[^}]+\})/).map((part) => {
+ const dynamicParts = templateLiteral.split(/(\$\{[^}]+\})/).map(part => {
if (part.startsWith('${') && part.endsWith('}')) {
return '**'
}
return part
})
const scopedTWithNamespace = `${namespaceTranslationTrimmed}.${dynamicParts.join(
- ''
+ '',
)}`
scopedTs.add(scopedTWithNamespace)
}
diff --git a/src/utils/loadConfig.ts b/src/utils/loadConfig.ts
index ffa0b3d..dc8d8ed 100644
--- a/src/utils/loadConfig.ts
+++ b/src/utils/loadConfig.ts
@@ -1,8 +1,9 @@
import * as fs from 'fs'
import * as path from 'path'
import { Config } from '../types'
+import { build } from 'esbuild'
-const supportedExtensions = ['.json', '.js', '.cjs']
+const supportedExtensions = ['.json', '.js', '.cjs', '.ts']
export const loadConfig = async (): Promise => {
const cwd = process.cwd()
@@ -18,7 +19,7 @@ export const loadConfig = async (): Promise => {
if (!configPath) {
throw new Error(
- 'Configuration file unused-i18n.config not found. Supported extensions: .json, .js, .cjs.'
+ 'Configuration file unused-i18n.config not found. Supported extensions: .json, .js, .cjs, .ts.',
)
}
@@ -27,6 +28,22 @@ export const loadConfig = async (): Promise => {
if (extension === '.json') {
const configContent = fs.readFileSync(configPath, 'utf-8')
return JSON.parse(configContent) as Config
+ } else if (extension === '.ts') {
+ const result = await build({
+ entryPoints: [configPath],
+ outfile: 'config.js',
+ platform: 'node',
+ format: 'esm',
+ bundle: true,
+ write: false,
+ })
+
+ const jsCode = result.outputFiles[0].text
+
+ const module = await import(
+ 'data:application/javascript,' + encodeURIComponent(jsCode)
+ )
+ return module.default as Config
} else {
const module = await import(configPath)
return module.default as Config
diff --git a/tests/lib/scopedNamespace/extractNamespaceTranslation.test.ts b/tests/lib/scopedNamespace/extractNamespaceTranslation.test.ts
index f79635c..30efdd0 100644
--- a/tests/lib/scopedNamespace/extractNamespaceTranslation.test.ts
+++ b/tests/lib/scopedNamespace/extractNamespaceTranslation.test.ts
@@ -22,6 +22,6 @@ describe('extractNamespaceTranslation', () => {
const expected = ['namespace.keyTrue', 'namespace.keyFalse']
const result = extractNamespaceTranslation({ fileContent })
- expect(result).toEqual(expected)
+ expect(result).toEqual(expect.arrayContaining(expected))
})
})
diff --git a/vite.config.ts b/vite.config.ts
index ff25a88..89afd1b 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -1,5 +1,6 @@
import { defineConfig } from 'vite'
import type { UserConfig } from 'vitest/config'
+import * as path from 'path';
const external = (id: string) => {
if (
@@ -7,7 +8,8 @@ const external = (id: string) => {
id.endsWith('path') ||
id.endsWith('perf_hooks') ||
id.endsWith('process') ||
- id.endsWith('commander')
+ id.endsWith('commander') ||
+ id.endsWith('esbuild')
) {
return true
}
@@ -44,6 +46,12 @@ export const defaultConfig: UserConfig = {
reporter: ['text', 'json', 'html'],
},
},
+ resolve: {
+ alias: {
+ '@utils': path.resolve(__dirname, 'src/utils'),
+ '@lib': path.resolve(__dirname, 'src/lib'),
+ },
+ },
}
export default defineConfig(defaultConfig)