diff --git a/.github/workflows/backend.yml b/.github/workflows/backend.yml new file mode 100644 index 0000000..40cc7d6 --- /dev/null +++ b/.github/workflows/backend.yml @@ -0,0 +1,12 @@ +name: FoF Linguist PHP + +on: [workflow_dispatch, push, pull_request] + +jobs: + run: + uses: flarum/framework/.github/workflows/REUSABLE_backend.yml@main + with: + enable_backend_testing: false + enable_phpstan: true + + backend_directory: . diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index a5d4493..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: JavaScript - -on: - push: - branches: - - master - -jobs: - build: - name: JS / Build - runs-on: ubuntu-latest - - steps: - - name: Check out code - uses: actions/checkout@v3 - - - name: Restore npm cache - uses: actions/cache@v3 - with: - path: ~/.npm - key: ${{ runner.os }}-node-${{ hashFiles('js/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-node- - - # Our action will install npm, cd into `./js`, run `npm run build` and - # `npm run build-typings`, then commit and upload any changes - - name: Build production JS - uses: flarum/action-build@v3 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - build_script: build - package_manager: npm diff --git a/.github/workflows/frontend.yml b/.github/workflows/frontend.yml new file mode 100644 index 0000000..d28d91a --- /dev/null +++ b/.github/workflows/frontend.yml @@ -0,0 +1,19 @@ +name: FoF Linguist JS + +on: [workflow_dispatch, push, pull_request] + +jobs: + run: + uses: flarum/framework/.github/workflows/REUSABLE_frontend.yml@main + with: + enable_bundlewatch: false + enable_prettier: false + enable_typescript: false + + frontend_directory: ./js + backend_directory: . + js_package_manager: npm + main_git_branch: master + + secrets: + bundlewatch_github_token: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }} diff --git a/composer.json b/composer.json index 8db9f36..ede67c2 100644 --- a/composer.json +++ b/composer.json @@ -50,11 +50,26 @@ }, "flagrow": { "discuss": "https://discuss.flarum.org/d/7026" + }, + "flarum-cli": { + "modules": { + "githubActions": true + } } }, "autoload": { "psr-4": { "FoF\\Linguist\\": "src/" } + }, + "require-dev": { + "flarum/phpstan": "*" + }, + "scripts": { + "analyse:phpstan": "phpstan analyse", + "clear-cache:phpstan": "phpstan clear-result-cache" + }, + "scripts-descriptions": { + "analyse:phpstan": "Run static analysis" } } diff --git a/js/package-lock.json b/js/package-lock.json index 0430b13..1131f97 100644 --- a/js/package-lock.json +++ b/js/package-lock.json @@ -7,11 +7,13 @@ "name": "@fof/linguist", "dependencies": { "flarum-webpack-config": "^2.0", - "webpack": "^5.76", - "webpack-cli": "^4.0" + "webpack": "^5.89.0", + "webpack-cli": "^5.1.4" }, "devDependencies": { - "flarum": "^0.1.0-beta.16" + "@flarum/prettier-config": "^1.0.0", + "flarum-tsconfig": "^1.0.2", + "prettier": "^3.0.3" } }, "node_modules/@ampproject/remapping": { @@ -27,11 +29,12 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", "dependencies": { - "@babel/highlight": "^7.18.6" + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" }, "engines": { "node": ">=6.9.0" @@ -75,12 +78,13 @@ } }, "node_modules/@babel/generator": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.5.tgz", - "integrity": "sha512-jl7JY2Ykn9S0yj4DQP82sYvPU+T3g0HFcWTqDLqiuA9tGRNIj9VfbtXGAYTTkyNEnQk1jkMGOdYka8aG/lulCA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.3.tgz", + "integrity": "sha512-keeZWAV4LU3tW0qRi19HRpabC/ilM0HRBBzf9/k8FFiG4KVpiv0FIy4hHfLfFQZNhziCTPTmd59zoyv6DNISzg==", "dependencies": { - "@babel/types": "^7.20.5", + "@babel/types": "^7.23.3", "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" }, "engines": { @@ -192,9 +196,9 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "engines": { "node": ">=6.9.0" } @@ -211,23 +215,23 @@ } }, "node_modules/@babel/helper-function-name": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", - "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dependencies": { - "@babel/template": "^7.18.10", - "@babel/types": "^7.19.0" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -347,28 +351,28 @@ } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "engines": { "node": ">=6.9.0" } @@ -409,12 +413,12 @@ } }, "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, "engines": { @@ -422,9 +426,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.5.tgz", - "integrity": "sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.3.tgz", + "integrity": "sha512-uVsWNvlVsIninV2prNz/3lHCb+5CJ+e+IUBfbjToAHODtfGYLfCFuY4AU7TskI+dAKk+njsPiBjq1gKTvZOBaw==", "bin": { "parser": "bin/babel-parser.js" }, @@ -1635,31 +1639,31 @@ } }, "node_modules/@babel/template": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", - "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.18.10", - "@babel/types": "^7.18.10" + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.5.tgz", - "integrity": "sha512-WM5ZNN3JITQIq9tFZaw1ojLU3WgWdtkxnhM1AegMS+PvHjkM5IXjmYEGY7yukz5XS4sJyEf2VzWjI8uAavhxBQ==", - "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.5", - "@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.5", - "@babel/types": "^7.20.5", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.3.tgz", + "integrity": "sha512-+K0yF1/9yR0oHdE0StHuEj3uTPzwwbrLGfNOndVJVV2TqA5+j3oljJUb4nmB954FLGjNem976+B+eDuLIjesiQ==", + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.3", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.3", + "@babel/types": "^7.23.3", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -1668,12 +1672,12 @@ } }, "node_modules/@babel/types": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.5.tgz", - "integrity": "sha512-c9fst/h2/dcF7H+MJKZ2T0KjEQ8hY/BNnDk/H3XY8C4Aw/eWQXWn/lWntHF9ooUBnGmEvbfGrTgLWc+um0YDUg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.3.tgz", + "integrity": "sha512-OZnvoH2l8PK5eUvEcUyCt/sXgr/h+UWpVuBbOljwcrAgUl6lpchoQ++PHGyQy1AtYnVA6CEq3y5xeEI10brpXw==", "dependencies": { - "@babel/helper-string-parser": "^7.19.4", - "@babel/helper-validator-identifier": "^7.19.1", + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, "engines": { @@ -1688,6 +1692,12 @@ "node": ">=10.0.0" } }, + "node_modules/@flarum/prettier-config": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@flarum/prettier-config/-/prettier-config-1.0.0.tgz", + "integrity": "sha512-3/AcliIi5jPt4i7COb5hsLv6hm4EeXT9yI9I2EuEvhPi2QR+O9Y/8wrqRuO5mDkRzCIhUY+mjIL/f9770Zwfqg==", + "dev": true + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", @@ -1717,18 +1727,18 @@ } }, "node_modules/@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", "dependencies": { "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" } }, "node_modules/@jridgewell/source-map/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", "dependencies": { "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -1776,177 +1786,215 @@ } }, "node_modules/@types/estree": { - "version": "0.0.51", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", - "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==" + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" + }, + "node_modules/@types/jquery": { + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.27.tgz", + "integrity": "sha512-TR28Y8ezIGgfyA02UOh9x+Fy16/1qWYAnvtRd2gTBJuccX/vmddyti0MezLkTv7f+OLofVc2T961VPyKv1tXJQ==", + "dev": true, + "dependencies": { + "@types/sizzle": "*" + } }, "node_modules/@types/json-schema": { "version": "7.0.11", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" }, + "node_modules/@types/mithril": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@types/mithril/-/mithril-2.2.4.tgz", + "integrity": "sha512-IVljKi2AyaKCOV0SjH1QvGyLH9Twxp4Ty9vk8ZdIlOmegNYNuIHh6mMpJ5RREQVf2L2bk9bpjSQ9YBmaaL1bBg==", + "dev": true + }, "node_modules/@types/node": { - "version": "18.11.15", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.15.tgz", - "integrity": "sha512-VkhBbVo2+2oozlkdHXLrb3zjsRkpdnaU2bXmX8Wgle3PUi569eLRaHGlgETQHR7lLL1w7GiG3h9SnePhxNDecw==" + "version": "20.9.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.0.tgz", + "integrity": "sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/sizzle": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.6.tgz", + "integrity": "sha512-m04Om5Gz6kbjUwAQ7XJJQ30OdEFsSmAVsvn4NYwcTRyMVpKKa1aPuESw1n2CxS5fYkOQv3nHgDKeNa8e76fUkw==", + "dev": true + }, + "node_modules/@types/throttle-debounce": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/throttle-debounce/-/throttle-debounce-2.1.0.tgz", + "integrity": "sha512-5eQEtSCoESnh2FsiLTxE121IiE60hnMqcb435fShf4bpLRjEu1Eoekht23y6zXS9Ts3l+Szu3TARnTsA0GkOkQ==", + "dev": true }, "node_modules/@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", + "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" } }, "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==" + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" }, "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==" + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" }, "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==" + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", + "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==" }, "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", - "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==" + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" }, "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", + "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6" } }, "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, "node_modules/@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", "dependencies": { "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==" + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" }, "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", + "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-opt": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6", + "@webassemblyjs/wast-printer": "1.11.6" } }, "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", + "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", + "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6" } }, "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", + "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", + "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", "dependencies": { - "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/ast": "1.11.6", "@xtuc/long": "4.2.2" } }, "node_modules/@webpack-cli/configtest": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.2.0.tgz", - "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", + "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", + "engines": { + "node": ">=14.15.0" + }, "peerDependencies": { - "webpack": "4.x.x || 5.x.x", - "webpack-cli": "4.x.x" + "webpack": "5.x.x", + "webpack-cli": "5.x.x" } }, "node_modules/@webpack-cli/info": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.5.0.tgz", - "integrity": "sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==", - "dependencies": { - "envinfo": "^7.7.3" + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", + "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", + "engines": { + "node": ">=14.15.0" }, "peerDependencies": { - "webpack-cli": "4.x.x" + "webpack": "5.x.x", + "webpack-cli": "5.x.x" } }, "node_modules/@webpack-cli/serve": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.7.0.tgz", - "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", + "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", + "engines": { + "node": ">=14.15.0" + }, "peerDependencies": { - "webpack-cli": "4.x.x" + "webpack": "5.x.x", + "webpack-cli": "5.x.x" }, "peerDependenciesMeta": { "webpack-dev-server": { @@ -1965,9 +2013,9 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" }, "node_modules/acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", "bin": { "acorn": "bin/acorn" }, @@ -1976,9 +2024,9 @@ } }, "node_modules/acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", "peerDependencies": { "acorn": "^8" } @@ -2226,6 +2274,12 @@ "node": ">= 8" } }, + "node_modules/dayjs": { + "version": "1.11.10", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", + "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==", + "dev": true + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -2261,9 +2315,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", - "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -2273,9 +2327,9 @@ } }, "node_modules/envinfo": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", - "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.11.0.tgz", + "integrity": "sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg==", "bin": { "envinfo": "dist/cli.js" }, @@ -2284,9 +2338,9 @@ } }, "node_modules/es-module-lexer": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==" + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", + "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==" }, "node_modules/escalade": { "version": "3.1.1", @@ -2405,11 +2459,17 @@ "node": ">=8" } }, - "node_modules/flarum": { - "version": "0.1.0-beta.16", - "resolved": "https://registry.npmjs.org/flarum/-/flarum-0.1.0-beta.16.tgz", - "integrity": "sha512-uovm+6J8TO35dfbTSRtHRH6tz71W4dnEDfB63NOKHIhOz8oRh65qyWpXtlBOjv9f1cFMkMcjGHbWetb5lAIEnQ==", - "dev": true + "node_modules/flarum-tsconfig": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/flarum-tsconfig/-/flarum-tsconfig-1.0.2.tgz", + "integrity": "sha512-RUaN7D6noLK9vY1F86NIc+IlIP1YAA3bJ4jGR5pIm8UxvLBLW8qrAHzIosuQJgvnge7VgTA5c2LoNefUK/9EiQ==", + "dev": true, + "dependencies": { + "@types/jquery": "^3.5.5", + "@types/mithril": "^2.0.7", + "@types/throttle-debounce": "^2.1.0", + "dayjs": "^1.10.4" + } }, "node_modules/flarum-webpack-config": { "version": "2.0.0", @@ -2517,11 +2577,11 @@ } }, "node_modules/interpret": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", - "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", "engines": { - "node": ">= 0.10" + "node": ">=10.13.0" } }, "node_modules/is-core-module": { @@ -2820,6 +2880,21 @@ "node": ">=8" } }, + "node_modules/prettier": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", + "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -2837,14 +2912,14 @@ } }, "node_modules/rechoir": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", - "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", "dependencies": { - "resolve": "^1.9.0" + "resolve": "^1.20.0" }, "engines": { - "node": ">= 0.10" + "node": ">= 10.13.0" } }, "node_modules/regenerate": { @@ -2988,17 +3063,17 @@ } }, "node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" } }, "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", + "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", "dependencies": { "randombytes": "^2.1.0" } @@ -3094,12 +3169,12 @@ } }, "node_modules/terser": { - "version": "5.16.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.1.tgz", - "integrity": "sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw==", + "version": "5.24.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.24.0.tgz", + "integrity": "sha512-ZpGR4Hy3+wBEzVEnHvstMvqpD/nABNelQn/z2r0fjVWGQsN3bpOLzQlqDxmb4CDZnXq5lpjnQ+mHQLAOpfM5iw==", "dependencies": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -3111,15 +3186,15 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.6", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz", - "integrity": "sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ==", + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", + "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.14", + "@jridgewell/trace-mapping": "^0.3.17", "jest-worker": "^27.4.5", "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.0", - "terser": "^5.14.1" + "serialize-javascript": "^6.0.1", + "terser": "^5.16.8" }, "engines": { "node": ">= 10.13.0" @@ -3144,9 +3219,9 @@ } }, "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -3188,6 +3263,11 @@ "node": ">=4.2.0" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", @@ -3270,21 +3350,21 @@ } }, "node_modules/webpack": { - "version": "5.76.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.0.tgz", - "integrity": "sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA==", + "version": "5.89.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", + "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==", "dependencies": { "@types/eslint-scope": "^3.7.3", - "@types/estree": "^0.0.51", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", + "@types/estree": "^1.0.0", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", + "acorn-import-assertions": "^1.9.0", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.10.0", - "es-module-lexer": "^0.9.0", + "enhanced-resolve": "^5.15.0", + "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", @@ -3293,9 +3373,9 @@ "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", + "schema-utils": "^3.2.0", "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.3", + "terser-webpack-plugin": "^5.3.7", "watchpack": "^2.4.0", "webpack-sources": "^3.2.3" }, @@ -3410,43 +3490,41 @@ } }, "node_modules/webpack-cli": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.10.0.tgz", - "integrity": "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==", + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", + "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", "dependencies": { "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^1.2.0", - "@webpack-cli/info": "^1.5.0", - "@webpack-cli/serve": "^1.7.0", + "@webpack-cli/configtest": "^2.1.1", + "@webpack-cli/info": "^2.0.2", + "@webpack-cli/serve": "^2.0.5", "colorette": "^2.0.14", - "commander": "^7.0.0", + "commander": "^10.0.1", "cross-spawn": "^7.0.3", + "envinfo": "^7.7.3", "fastest-levenshtein": "^1.0.12", "import-local": "^3.0.2", - "interpret": "^2.2.0", - "rechoir": "^0.7.0", + "interpret": "^3.1.1", + "rechoir": "^0.8.0", "webpack-merge": "^5.7.3" }, "bin": { "webpack-cli": "bin/cli.js" }, "engines": { - "node": ">=10.13.0" + "node": ">=14.15.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "webpack": "4.x.x || 5.x.x" + "webpack": "5.x.x" }, "peerDependenciesMeta": { "@webpack-cli/generators": { "optional": true }, - "@webpack-cli/migrate": { - "optional": true - }, "webpack-bundle-analyzer": { "optional": true }, @@ -3456,11 +3534,11 @@ } }, "node_modules/webpack-cli/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", "engines": { - "node": ">= 10" + "node": ">=14" } }, "node_modules/webpack-merge": { @@ -3484,9 +3562,9 @@ } }, "node_modules/webpack/node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -3551,11 +3629,12 @@ } }, "@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", "requires": { - "@babel/highlight": "^7.18.6" + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" } }, "@babel/compat-data": { @@ -3586,12 +3665,13 @@ } }, "@babel/generator": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.5.tgz", - "integrity": "sha512-jl7JY2Ykn9S0yj4DQP82sYvPU+T3g0HFcWTqDLqiuA9tGRNIj9VfbtXGAYTTkyNEnQk1jkMGOdYka8aG/lulCA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.3.tgz", + "integrity": "sha512-keeZWAV4LU3tW0qRi19HRpabC/ilM0HRBBzf9/k8FFiG4KVpiv0FIy4hHfLfFQZNhziCTPTmd59zoyv6DNISzg==", "requires": { - "@babel/types": "^7.20.5", + "@babel/types": "^7.23.3", "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" }, "dependencies": { @@ -3672,9 +3752,9 @@ } }, "@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==" + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==" }, "@babel/helper-explode-assignable-expression": { "version": "7.18.6", @@ -3685,20 +3765,20 @@ } }, "@babel/helper-function-name": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", - "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "requires": { - "@babel/template": "^7.18.10", - "@babel/types": "^7.19.0" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" } }, "@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", "requires": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" } }, "@babel/helper-member-expression-to-functions": { @@ -3785,22 +3865,22 @@ } }, "@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "requires": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" } }, "@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==" + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==" }, "@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==" + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==" }, "@babel/helper-validator-option": { "version": "7.18.6", @@ -3829,19 +3909,19 @@ } }, "@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", "requires": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", "js-tokens": "^4.0.0" } }, "@babel/parser": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.5.tgz", - "integrity": "sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA==" + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.3.tgz", + "integrity": "sha512-uVsWNvlVsIninV2prNz/3lHCb+5CJ+e+IUBfbjToAHODtfGYLfCFuY4AU7TskI+dAKk+njsPiBjq1gKTvZOBaw==" }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.18.6", @@ -4617,39 +4697,39 @@ } }, "@babel/template": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", - "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.18.10", - "@babel/types": "^7.18.10" + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" } }, "@babel/traverse": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.5.tgz", - "integrity": "sha512-WM5ZNN3JITQIq9tFZaw1ojLU3WgWdtkxnhM1AegMS+PvHjkM5IXjmYEGY7yukz5XS4sJyEf2VzWjI8uAavhxBQ==", - "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.5", - "@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.5", - "@babel/types": "^7.20.5", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.3.tgz", + "integrity": "sha512-+K0yF1/9yR0oHdE0StHuEj3uTPzwwbrLGfNOndVJVV2TqA5+j3oljJUb4nmB954FLGjNem976+B+eDuLIjesiQ==", + "requires": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.3", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.3", + "@babel/types": "^7.23.3", "debug": "^4.1.0", "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.5.tgz", - "integrity": "sha512-c9fst/h2/dcF7H+MJKZ2T0KjEQ8hY/BNnDk/H3XY8C4Aw/eWQXWn/lWntHF9ooUBnGmEvbfGrTgLWc+um0YDUg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.3.tgz", + "integrity": "sha512-OZnvoH2l8PK5eUvEcUyCt/sXgr/h+UWpVuBbOljwcrAgUl6lpchoQ++PHGyQy1AtYnVA6CEq3y5xeEI10brpXw==", "requires": { - "@babel/helper-string-parser": "^7.19.4", - "@babel/helper-validator-identifier": "^7.19.1", + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" } }, @@ -4658,6 +4738,12 @@ "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==" }, + "@flarum/prettier-config": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@flarum/prettier-config/-/prettier-config-1.0.0.tgz", + "integrity": "sha512-3/AcliIi5jPt4i7COb5hsLv6hm4EeXT9yI9I2EuEvhPi2QR+O9Y/8wrqRuO5mDkRzCIhUY+mjIL/f9770Zwfqg==", + "dev": true + }, "@jridgewell/gen-mapping": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", @@ -4678,18 +4764,18 @@ "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" }, "@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", "requires": { "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" }, "dependencies": { "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", "requires": { "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -4736,169 +4822,197 @@ } }, "@types/estree": { - "version": "0.0.51", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", - "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==" + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" + }, + "@types/jquery": { + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.27.tgz", + "integrity": "sha512-TR28Y8ezIGgfyA02UOh9x+Fy16/1qWYAnvtRd2gTBJuccX/vmddyti0MezLkTv7f+OLofVc2T961VPyKv1tXJQ==", + "dev": true, + "requires": { + "@types/sizzle": "*" + } }, "@types/json-schema": { "version": "7.0.11", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" }, + "@types/mithril": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@types/mithril/-/mithril-2.2.4.tgz", + "integrity": "sha512-IVljKi2AyaKCOV0SjH1QvGyLH9Twxp4Ty9vk8ZdIlOmegNYNuIHh6mMpJ5RREQVf2L2bk9bpjSQ9YBmaaL1bBg==", + "dev": true + }, "@types/node": { - "version": "18.11.15", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.15.tgz", - "integrity": "sha512-VkhBbVo2+2oozlkdHXLrb3zjsRkpdnaU2bXmX8Wgle3PUi569eLRaHGlgETQHR7lLL1w7GiG3h9SnePhxNDecw==" + "version": "20.9.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.0.tgz", + "integrity": "sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==", + "requires": { + "undici-types": "~5.26.4" + } + }, + "@types/sizzle": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.6.tgz", + "integrity": "sha512-m04Om5Gz6kbjUwAQ7XJJQ30OdEFsSmAVsvn4NYwcTRyMVpKKa1aPuESw1n2CxS5fYkOQv3nHgDKeNa8e76fUkw==", + "dev": true + }, + "@types/throttle-debounce": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/throttle-debounce/-/throttle-debounce-2.1.0.tgz", + "integrity": "sha512-5eQEtSCoESnh2FsiLTxE121IiE60hnMqcb435fShf4bpLRjEu1Eoekht23y6zXS9Ts3l+Szu3TARnTsA0GkOkQ==", + "dev": true }, "@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", + "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", "requires": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" } }, "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==" + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" }, "@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==" + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" }, "@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==" + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", + "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==" }, "@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", - "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", "@xtuc/long": "4.2.2" } }, "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==" + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" }, "@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", + "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6" } }, "@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", "requires": { "@xtuc/ieee754": "^1.2.0" } }, "@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", "requires": { "@xtuc/long": "4.2.2" } }, "@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==" + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" }, "@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", + "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-opt": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6", + "@webassemblyjs/wast-printer": "1.11.6" } }, "@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", + "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, "@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", + "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6" } }, "@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", + "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, "@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", + "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", "requires": { - "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/ast": "1.11.6", "@xtuc/long": "4.2.2" } }, "@webpack-cli/configtest": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.2.0.tgz", - "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", + "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", "requires": {} }, "@webpack-cli/info": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.5.0.tgz", - "integrity": "sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==", - "requires": { - "envinfo": "^7.7.3" - } + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", + "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", + "requires": {} }, "@webpack-cli/serve": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.7.0.tgz", - "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", + "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", "requires": {} }, "@xtuc/ieee754": { @@ -4912,14 +5026,14 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" }, "acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==" + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==" }, "acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", "requires": {} }, "acorn-walk": { @@ -5092,6 +5206,12 @@ "which": "^2.0.1" } }, + "dayjs": { + "version": "1.11.10", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", + "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==", + "dev": true + }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -5116,23 +5236,23 @@ "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==" }, "enhanced-resolve": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", - "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", "requires": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "envinfo": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", - "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==" + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.11.0.tgz", + "integrity": "sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg==" }, "es-module-lexer": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==" + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", + "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==" }, "escalade": { "version": "3.1.1", @@ -5217,11 +5337,17 @@ "path-exists": "^4.0.0" } }, - "flarum": { - "version": "0.1.0-beta.16", - "resolved": "https://registry.npmjs.org/flarum/-/flarum-0.1.0-beta.16.tgz", - "integrity": "sha512-uovm+6J8TO35dfbTSRtHRH6tz71W4dnEDfB63NOKHIhOz8oRh65qyWpXtlBOjv9f1cFMkMcjGHbWetb5lAIEnQ==", - "dev": true + "flarum-tsconfig": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/flarum-tsconfig/-/flarum-tsconfig-1.0.2.tgz", + "integrity": "sha512-RUaN7D6noLK9vY1F86NIc+IlIP1YAA3bJ4jGR5pIm8UxvLBLW8qrAHzIosuQJgvnge7VgTA5c2LoNefUK/9EiQ==", + "dev": true, + "requires": { + "@types/jquery": "^3.5.5", + "@types/mithril": "^2.0.7", + "@types/throttle-debounce": "^2.1.0", + "dayjs": "^1.10.4" + } }, "flarum-webpack-config": { "version": "2.0.0", @@ -5299,9 +5425,9 @@ } }, "interpret": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", - "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==" + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==" }, "is-core-module": { "version": "2.11.0", @@ -5517,6 +5643,12 @@ "find-up": "^4.0.0" } }, + "prettier": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", + "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", + "dev": true + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -5531,11 +5663,11 @@ } }, "rechoir": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", - "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", "requires": { - "resolve": "^1.9.0" + "resolve": "^1.20.0" } }, "regenerate": { @@ -5636,14 +5768,14 @@ } }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" }, "serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", + "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", "requires": { "randombytes": "^2.1.0" } @@ -5712,32 +5844,32 @@ "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==" }, "terser": { - "version": "5.16.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.1.tgz", - "integrity": "sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw==", + "version": "5.24.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.24.0.tgz", + "integrity": "sha512-ZpGR4Hy3+wBEzVEnHvstMvqpD/nABNelQn/z2r0fjVWGQsN3bpOLzQlqDxmb4CDZnXq5lpjnQ+mHQLAOpfM5iw==", "requires": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", "commander": "^2.20.0", "source-map-support": "~0.5.20" } }, "terser-webpack-plugin": { - "version": "5.3.6", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz", - "integrity": "sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ==", + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", + "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", "requires": { - "@jridgewell/trace-mapping": "^0.3.14", + "@jridgewell/trace-mapping": "^0.3.17", "jest-worker": "^27.4.5", "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.0", - "terser": "^5.14.1" + "serialize-javascript": "^6.0.1", + "terser": "^5.16.8" }, "dependencies": { "schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "requires": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -5761,6 +5893,11 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==" }, + "undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, "unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", @@ -5812,21 +5949,21 @@ } }, "webpack": { - "version": "5.76.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.0.tgz", - "integrity": "sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA==", + "version": "5.89.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", + "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==", "requires": { "@types/eslint-scope": "^3.7.3", - "@types/estree": "^0.0.51", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", + "@types/estree": "^1.0.0", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", + "acorn-import-assertions": "^1.9.0", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.10.0", - "es-module-lexer": "^0.9.0", + "enhanced-resolve": "^5.15.0", + "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", @@ -5835,17 +5972,17 @@ "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", + "schema-utils": "^3.2.0", "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.3", + "terser-webpack-plugin": "^5.3.7", "watchpack": "^2.4.0", "webpack-sources": "^3.2.3" }, "dependencies": { "schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "requires": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -5921,28 +6058,29 @@ } }, "webpack-cli": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.10.0.tgz", - "integrity": "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==", + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", + "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", "requires": { "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^1.2.0", - "@webpack-cli/info": "^1.5.0", - "@webpack-cli/serve": "^1.7.0", + "@webpack-cli/configtest": "^2.1.1", + "@webpack-cli/info": "^2.0.2", + "@webpack-cli/serve": "^2.0.5", "colorette": "^2.0.14", - "commander": "^7.0.0", + "commander": "^10.0.1", "cross-spawn": "^7.0.3", + "envinfo": "^7.7.3", "fastest-levenshtein": "^1.0.12", "import-local": "^3.0.2", - "interpret": "^2.2.0", - "rechoir": "^0.7.0", + "interpret": "^3.1.1", + "rechoir": "^0.8.0", "webpack-merge": "^5.7.3" }, "dependencies": { "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==" } } }, diff --git a/js/package.json b/js/package.json index 8a24722..fe1f8ea 100644 --- a/js/package.json +++ b/js/package.json @@ -3,14 +3,18 @@ "name": "@fof/linguist", "dependencies": { "flarum-webpack-config": "^2.0", - "webpack": "^5.76", - "webpack-cli": "^4.0" + "webpack": "^5.89.0", + "webpack-cli": "^5.1.4" }, "scripts": { "dev": "webpack --mode development --watch", - "build": "webpack --mode production" + "build": "webpack --mode production", + "format": "prettier --write src", + "format-check": "prettier --check src" }, "devDependencies": { - "flarum": "^0.1.0-beta.16" + "prettier": "^3.0.3", + "@flarum/prettier-config": "^1.0.0", + "flarum-tsconfig": "^1.0.2" } } diff --git a/js/src/admin/components/StringKey.js b/js/src/admin/components/StringKey.js index f9a8c41..309e565 100644 --- a/js/src/admin/components/StringKey.js +++ b/js/src/admin/components/StringKey.js @@ -1,29 +1,30 @@ -import StringLocale from '../components/StringLocale'; -import localesAsArray from '../utils/localesAsArray'; -import highlightMithril from '../utils/highlightMithril'; +import StringLocale from "../components/StringLocale"; +import localesAsArray from "../utils/localesAsArray"; +import highlightMithril from "../utils/highlightMithril"; /* global m */ export default class StringKey { view(vnode) { - const { - stringKey, - highlight, - onchange, - } = vnode.attrs; + const { stringKey, highlight, onchange } = vnode.attrs; - return m('.FoF-Linguist-Key', [ - m('.FoF-Linguist-Key-Code', m('code', highlightMithril(stringKey.key(), highlight))), - m('.FoF-Linguist-Locales', [ - ...localesAsArray().map(locale => m(StringLocale, { - key: locale.key, - locale, - stringKey, - highlight, - onchange, - })), + return m(".FoF-Linguist-Key", [ + m( + ".FoF-Linguist-Key-Code", + m("code", highlightMithril(stringKey.key(), highlight)), + ), + m(".FoF-Linguist-Locales", [ + ...localesAsArray().map((locale) => + m(StringLocale, { + key: locale.key, + locale, + stringKey, + highlight, + onchange, + }), + ), m(StringLocale, { - key: 'all', + key: "all", locale: null, stringKey, highlight, diff --git a/js/src/admin/components/StringLocale.js b/js/src/admin/components/StringLocale.js index c3f6f89..2b31c91 100644 --- a/js/src/admin/components/StringLocale.js +++ b/js/src/admin/components/StringLocale.js @@ -1,7 +1,7 @@ -import app from 'flarum/admin/app'; -import ItemList from 'flarum/common/utils/ItemList'; -import Button from 'flarum/common/components/Button'; -import highlightMithril from '../utils/highlightMithril'; +import app from "flarum/admin/app"; +import ItemList from "flarum/common/utils/ItemList"; +import Button from "flarum/common/components/Button"; +import highlightMithril from "../utils/highlightMithril"; /* global m */ @@ -10,105 +10,166 @@ export default class StringLocale { this.stringKey = vnode.attrs.stringKey; this.locale = vnode.attrs.locale; this.localeKey = this.locale ? this.locale.key : null; - this.originalString = this.localeKey && this.stringKey.locales().hasOwnProperty(this.localeKey) ? this.stringKey.locales()[this.localeKey] : null; - - this.string = app.store.all('fof-linguist-string').find( - string => string.key() === this.stringKey.key() && string.locale() === this.localeKey - ); - - this.value = this.string ? this.string.value() : ''; + this.originalString = + this.localeKey && + this.stringKey.locales().hasOwnProperty(this.localeKey) + ? this.stringKey.locales()[this.localeKey] + : null; + + this.string = app.store + .all("fof-linguist-string") + .find( + (string) => + string.key() === this.stringKey.key() && + string.locale() === this.localeKey, + ); + + this.value = this.string ? this.string.value() : ""; this.dirty = false; this.processing = false; // We check whether any original translation in any language has a newline // By not hard-coding to English, this should work pretty well even if the fallback locale is modified, // or if a text happens to not be available in the fallback language - const originalHasNewLine = Object.keys(this.stringKey.locales()).some(key => this.stringKey.locales()[key].indexOf('\n') !== -1); + const originalHasNewLine = Object.keys(this.stringKey.locales()).some( + (key) => this.stringKey.locales()[key].indexOf("\n") !== -1, + ); - this.inputType = 'input'; + this.inputType = "input"; // We will enable multi-line editing if the original has a newline, or if the current custom value already has one - if (originalHasNewLine || this.value.indexOf('\n') !== -1) { - this.inputType = 'textarea'; + if (originalHasNewLine || this.value.indexOf("\n") !== -1) { + this.inputType = "textarea"; } } view(vnode) { - const placeholderText = this.originalString ? this.originalString : '(' + app.translator.trans('fof-linguist.admin.placeholder.' + (this.localeKey ? 'not-translated' : 'all-locales')) + ')'; - - return m('.FoF-Linguist-Locale', [ - m('label.FoF-Linguist-Label', this.localeName()), - m('.FoF-Linguist-Field', { - className: (this.value ? 'FoF-Linguist-Field--with-value' : '') + (this.originalString ? ' FoF-Linguist-Field--with-original-string' : ''), - title: placeholderText, - }, [ - m('.FoF-Linguist-Field-Wrap', [ - m(this.inputType, { - className: 'FormControl FoF-Linguist-Input', - value: this.value, - oninput: event => { - this.value = event.target.value; - this.dirty = true; - - // Remove dirty state if the user erased his text without saving - if (!this.value && !this.string) { - this.dirty = false; - } - }, - disabled: this.processing, - }), - m('.FoF-Linguist-Placeholder', [ - m('span.FoF-Linguist-Placeholder-Hint', app.translator.trans('fof-linguist.admin.placeholder.hint')), - ' ', - m('span', this.originalString ? highlightMithril(placeholderText, vnode.attrs.highlight) : placeholderText), + const placeholderText = this.originalString + ? this.originalString + : "(" + + app.translator.trans( + "fof-linguist.admin.placeholder." + + (this.localeKey ? "not-translated" : "all-locales"), + ) + + ")"; + + return m(".FoF-Linguist-Locale", [ + m("label.FoF-Linguist-Label", this.localeName()), + m( + ".FoF-Linguist-Field", + { + className: + (this.value ? "FoF-Linguist-Field--with-value" : "") + + (this.originalString + ? " FoF-Linguist-Field--with-original-string" + : ""), + title: placeholderText, + }, + [ + m(".FoF-Linguist-Field-Wrap", [ + m(this.inputType, { + className: "FormControl FoF-Linguist-Input", + value: this.value, + oninput: (event) => { + this.value = event.target.value; + this.dirty = true; + + // Remove dirty state if the user erased his text without saving + if (!this.value && !this.string) { + this.dirty = false; + } + }, + disabled: this.processing, + }), + m(".FoF-Linguist-Placeholder", [ + m( + "span.FoF-Linguist-Placeholder-Hint", + app.translator.trans( + "fof-linguist.admin.placeholder.hint", + ), + ), + " ", + m( + "span", + this.originalString + ? highlightMithril( + placeholderText, + vnode.attrs.highlight, + ) + : placeholderText, + ), + ]), ]), - ]), - ]), - m('.FoF-Linguist-Controls', this.actions(vnode.attrs.onchange).toArray()), + ], + ), + m( + ".FoF-Linguist-Controls", + this.actions(vnode.attrs.onchange).toArray(), + ), ]); } localeName() { if (this.locale) { - return [this.locale.name + ' (', m('code', this.locale.key), ')']; + return [this.locale.name + " (", m("code", this.locale.key), ")"]; } else { - return app.translator.trans('fof-linguist.admin.locales.all'); + return app.translator.trans("fof-linguist.admin.locales.all"); } } actions(onchange) { const items = new ItemList(); - items.add('apply', Button.component({ - type: 'button', - className: 'Button Button--primary', - loading: this.processing, - disabled: !this.dirty, - onclick: () => { - this.saveString(onchange); - }, - }, app.translator.trans('fof-linguist.admin.buttons.apply'))); - - items.add('reset', Button.component({ - type: 'button', - className: 'Button', - loading: this.processing, - disabled: !this.dirty && !this.string, - onclick: () => { - this.deleteString(onchange); - }, - }, app.translator.trans('fof-linguist.admin.buttons.reset'))); + items.add( + "apply", + Button.component( + { + type: "button", + className: "Button Button--primary", + loading: this.processing, + disabled: !this.dirty, + onclick: () => { + this.saveString(onchange); + }, + }, + app.translator.trans("fof-linguist.admin.buttons.apply"), + ), + ); - if (this.originalString) { - items.add('copy-original', Button.component({ - type: 'button', - className: 'Button', - loading: this.processing, - onclick: () => { - this.value = this.originalString; - this.dirty = true; + items.add( + "reset", + Button.component( + { + type: "button", + className: "Button", + loading: this.processing, + disabled: !this.dirty && !this.string, + onclick: () => { + this.deleteString(onchange); + }, }, - }, app.translator.trans('fof-linguist.admin.buttons.copy-original'))); + app.translator.trans("fof-linguist.admin.buttons.reset"), + ), + ); + + if (this.originalString) { + items.add( + "copy-original", + Button.component( + { + type: "button", + className: "Button", + loading: this.processing, + onclick: () => { + this.value = this.originalString; + this.dirty = true; + }, + }, + app.translator.trans( + "fof-linguist.admin.buttons.copy-original", + ), + ), + ); } return items; @@ -122,11 +183,11 @@ export default class StringLocale { } if (!this.string) { - this.string = app.store.createRecord('fof-linguist-string', { + this.string = app.store.createRecord("fof-linguist-string", { attributes: { key: this.stringKey.key(), locale: this.localeKey, - value: '', + value: "", }, }); } @@ -137,41 +198,47 @@ export default class StringLocale { this.processing = true; - this.string.save(this.string.data.attributes).then(() => { - this.processing = false; - this.dirty = false; + this.string + .save(this.string.data.attributes) + .then(() => { + this.processing = false; + this.dirty = false; - onchange(); + onchange(); - m.redraw(); - }).catch(err => { - this.processing = false; + m.redraw(); + }) + .catch((err) => { + this.processing = false; - throw err; - }); + throw err; + }); } deleteString(onchange) { if (this.string) { this.processing = true; - this.string.delete().then(() => { - this.processing = false; - this.dirty = false; + this.string + .delete() + .then(() => { + this.processing = false; + this.dirty = false; - this.string = null; - this.value = ''; + this.string = null; + this.value = ""; - onchange(); + onchange(); - m.redraw(); - }).catch(err => { - this.processing = false; + m.redraw(); + }) + .catch((err) => { + this.processing = false; - throw err; - }); + throw err; + }); } else { - this.value = ''; + this.value = ""; this.dirty = false; } } diff --git a/js/src/admin/components/index.js b/js/src/admin/components/index.js index 8d237cf..19c3e88 100644 --- a/js/src/admin/components/index.js +++ b/js/src/admin/components/index.js @@ -1,5 +1,5 @@ -import StringKey from './StringKey'; -import StringLocale from './StringLocale'; +import StringKey from "./StringKey"; +import StringLocale from "./StringLocale"; export const components = { StringKey, diff --git a/js/src/admin/index.js b/js/src/admin/index.js index 3fe3c19..f231755 100644 --- a/js/src/admin/index.js +++ b/js/src/admin/index.js @@ -1,29 +1,29 @@ -import app from 'flarum/admin/app'; -import StringKey from './models/StringKey'; -import TextString from './models/TextString'; -import LinguistPage from './pages/LinguistPage'; +import app from "flarum/admin/app"; +import StringKey from "./models/StringKey"; +import TextString from "./models/TextString"; +import LinguistPage from "./pages/LinguistPage"; -export * from './components'; -export * from './models'; -export * from './pages'; -export * from './utils'; +export * from "./components"; +export * from "./models"; +export * from "./pages"; +export * from "./utils"; -app.initializers.add('fof-linguist', app => { - app.store.models['fof-linguist-string-key'] = StringKey; - app.store.models['fof-linguist-string'] = TextString; +app.initializers.add("fof-linguist", (app) => { + app.store.models["fof-linguist-string-key"] = StringKey; + app.store.models["fof-linguist-string"] = TextString; app.extensionData - .for('fof-linguist') + .for("fof-linguist") .registerPage(LinguistPage) .registerPermission( { - icon: 'fas fa-italic', + icon: "fas fa-italic", label: app.translator.trans( - 'fof-linguist.admin.permissions.view_string_keys' + "fof-linguist.admin.permissions.view_string_keys", ), - permission: 'viewStringKeys', + permission: "viewStringKeys", allowGuest: true, }, - 'view' + "view", ); }); diff --git a/js/src/admin/models/StringKey.js b/js/src/admin/models/StringKey.js index 3584259..93bd984 100644 --- a/js/src/admin/models/StringKey.js +++ b/js/src/admin/models/StringKey.js @@ -1,6 +1,6 @@ -import Model from 'flarum/common/Model'; +import Model from "flarum/common/Model"; export default class StringKey extends Model { - key = Model.attribute('key'); - locales = Model.attribute('locales'); + key = Model.attribute("key"); + locales = Model.attribute("locales"); } diff --git a/js/src/admin/models/TextString.js b/js/src/admin/models/TextString.js index 696cc75..15ddd06 100644 --- a/js/src/admin/models/TextString.js +++ b/js/src/admin/models/TextString.js @@ -1,11 +1,13 @@ -import Model from 'flarum/common/Model'; +import Model from "flarum/common/Model"; export default class TextString extends Model { - key = Model.attribute('key'); - locale = Model.attribute('locale'); - value = Model.attribute('value'); + key = Model.attribute("key"); + locale = Model.attribute("locale"); + value = Model.attribute("value"); apiEndpoint() { - return '/fof/linguist/strings' + (this.exists ? '/' + this.data.id : ''); + return ( + "/fof/linguist/strings" + (this.exists ? "/" + this.data.id : "") + ); } } diff --git a/js/src/admin/models/index.js b/js/src/admin/models/index.js index b834832..ac3f847 100644 --- a/js/src/admin/models/index.js +++ b/js/src/admin/models/index.js @@ -1,5 +1,5 @@ -import StringKey from './StringKey'; -import TextString from './TextString'; +import StringKey from "./StringKey"; +import TextString from "./TextString"; export const models = { StringKey, diff --git a/js/src/admin/pages/CoveragePage.js b/js/src/admin/pages/CoveragePage.js index 264c7b6..d65a2d0 100644 --- a/js/src/admin/pages/CoveragePage.js +++ b/js/src/admin/pages/CoveragePage.js @@ -1,20 +1,22 @@ -import app from 'flarum/admin/app'; -import Button from 'flarum/common/components/Button'; -import icon from 'flarum/common/helpers/icon'; -import localesAsArray from '../utils/localesAsArray'; -import namespaceLabel from '../utils/namespaceLabel'; -import frontendLabel from '../utils/frontendLabel'; +import app from "flarum/admin/app"; +import Button from "flarum/common/components/Button"; +import icon from "flarum/common/helpers/icon"; +import localesAsArray from "../utils/localesAsArray"; +import namespaceLabel from "../utils/namespaceLabel"; +import frontendLabel from "../utils/frontendLabel"; /* global m */ export default class CoveragePage { oninit() { - this.columns = 'locale'; + this.columns = "locale"; this.showAllFrontends = false; this.totalPercent = true; this.locale = []; - const firstNonEnglishLocale = localesAsArray().find(locale => locale.key !== 'en'); + const firstNonEnglishLocale = localesAsArray().find( + (locale) => locale.key !== "en", + ); if (firstNonEnglishLocale) { this.locale = firstNonEnglishLocale.key; @@ -28,92 +30,242 @@ export default class CoveragePage { visibleFrontends = vnode.attrs.frontends; } - const {browseWithFilters} = vnode.attrs; + const { browseWithFilters } = vnode.attrs; return [ - m('.FoF-Linguist-Filters', [ - m('.ButtonGroup', [ - Button.component({ - className: 'Button' + (this.totalPercent ? ' active' : ''), - onclick: () => { - this.totalPercent = true; + m(".FoF-Linguist-Filters", [ + m(".ButtonGroup", [ + Button.component( + { + className: + "Button" + (this.totalPercent ? " active" : ""), + onclick: () => { + this.totalPercent = true; + }, }, - }, app.translator.trans('fof-linguist.admin.coverage.total-options.percent')), - Button.component({ - className: 'Button' + (this.totalPercent ? ' ' : ' active'), - onclick: () => { - this.totalPercent = false; + app.translator.trans( + "fof-linguist.admin.coverage.total-options.percent", + ), + ), + Button.component( + { + className: + "Button" + + (this.totalPercent ? " " : " active"), + onclick: () => { + this.totalPercent = false; + }, }, - }, app.translator.trans('fof-linguist.admin.coverage.total-options.count')), + app.translator.trans( + "fof-linguist.admin.coverage.total-options.count", + ), + ), ]), - m('.ButtonGroup', [ - Button.component({ - className: 'Button' + (this.columns === 'locale' ? ' active' : ''), - onclick: () => { - this.columns = 'locale'; + m(".ButtonGroup", [ + Button.component( + { + className: + "Button" + + (this.columns === "locale" ? " active" : ""), + onclick: () => { + this.columns = "locale"; + }, }, - }, app.translator.trans('fof-linguist.admin.coverage.column-options.locale')), - Button.component({ - className: 'Button' + (this.columns === 'namespace' ? ' active' : ''), - onclick: () => { - this.columns = 'namespace'; - this.showAllFrontends = false; + app.translator.trans( + "fof-linguist.admin.coverage.column-options.locale", + ), + ), + Button.component( + { + className: + "Button" + + (this.columns === "namespace" ? " active" : ""), + onclick: () => { + this.columns = "namespace"; + this.showAllFrontends = false; + }, }, - }, app.translator.trans('fof-linguist.admin.coverage.column-options.namespace')), + app.translator.trans( + "fof-linguist.admin.coverage.column-options.namespace", + ), + ), ]), - this.columns === 'namespace' ? m('.ButtonGroup', localesAsArray().map( - locale => Button.component({ - className: 'Button' + (this.locale === locale.key ? ' active' : ''), - onclick: () => { - if (this.locale !== locale.key) { - this.locale = locale.key; - } - }, - }, locale.name + ' (' + locale.key + ')') - )) : null, + this.columns === "namespace" + ? m( + ".ButtonGroup", + localesAsArray().map((locale) => + Button.component( + { + className: + "Button" + + (this.locale === locale.key + ? " active" + : ""), + onclick: () => { + if (this.locale !== locale.key) { + this.locale = locale.key; + } + }, + }, + locale.name + " (" + locale.key + ")", + ), + ), + ) + : null, ]), - m('table.FoF-Linguist-Coverage', [ - m('thead', m('tr', [ - m('th', app.translator.trans('fof-linguist.admin.coverage.columns.namespace')), - this.columns === 'locale' ? localesAsArray().map(locale => m('th', locale.name + ' (' + locale.key + ')')) : [ - this.showAllFrontends ? visibleFrontends.map(frontend => m('th', frontendLabel(frontend))) : [ - m('th', app.translator.trans('fof-linguist.admin.coverage.columns.all-except-admin')), - m('th', frontendLabel('admin')), - m('th', Button.component({ - className: 'Button', - onclick: () => { - this.showAllFrontends = true; - }, - }, app.translator.trans('fof-linguist.admin.coverage.columns.all-frontends'))), - ], - ], - ])), - m('tbody', [ - this.columns === 'locale' ? m('tr', [ - m('td', [ - m('span.FoF-Linguist-Coverage-Extension-Icon.FoF-Linguist-Coverage-Namespace-Icon'), - m('span.FoF-Linguist-Coverage-Extension-Title', app.translator.trans('fof-linguist.admin.coverage.all-namespaces')), - ]), - localesAsArray().map(locale => m('td', this.localeCoverage(browseWithFilters, locale.key))), - ]) : null, - vnode.attrs.namespaces.map(namespace => { - return m('tr', [ - m('td', namespace.extension ? [ - m('span.FoF-Linguist-Coverage-Extension-Icon', { - style: namespace.extension.icon, - }, namespace.extension.icon ? icon(namespace.extension.icon.name) : ''), - m('span.FoF-Linguist-Coverage-Extension-Title', namespace.extension.extra['flarum-extension'].title), - ] : [ - m('span.FoF-Linguist-Coverage-Extension-Icon.FoF-Linguist-Coverage-Namespace-Icon'), - m('span.FoF-Linguist-Coverage-Extension-Title', namespaceLabel(namespace.namespace)), - ]), - this.columns === 'locale' ? localesAsArray().map(locale => m('td', this.localeCoverage(browseWithFilters, locale.key, namespace.namespace))) : [ - this.showAllFrontends ? - visibleFrontends.map(frontend => m('td', this.prefixCoverage(browseWithFilters, namespace.namespace, frontend))) : [ - m('td', this.prefixCoverage(browseWithFilters, namespace.namespace, '_all_except_admin')), - m('td', this.prefixCoverage(browseWithFilters, namespace.namespace, 'admin')), - ], - ], + m("table.FoF-Linguist-Coverage", [ + m( + "thead", + m("tr", [ + m( + "th", + app.translator.trans( + "fof-linguist.admin.coverage.columns.namespace", + ), + ), + this.columns === "locale" + ? localesAsArray().map((locale) => + m( + "th", + locale.name + " (" + locale.key + ")", + ), + ) + : [ + this.showAllFrontends + ? visibleFrontends.map((frontend) => + m("th", frontendLabel(frontend)), + ) + : [ + m( + "th", + app.translator.trans( + "fof-linguist.admin.coverage.columns.all-except-admin", + ), + ), + m("th", frontendLabel("admin")), + m( + "th", + Button.component( + { + className: "Button", + onclick: () => { + this.showAllFrontends = true; + }, + }, + app.translator.trans( + "fof-linguist.admin.coverage.columns.all-frontends", + ), + ), + ), + ], + ], + ]), + ), + m("tbody", [ + this.columns === "locale" + ? m("tr", [ + m("td", [ + m( + "span.FoF-Linguist-Coverage-Extension-Icon.FoF-Linguist-Coverage-Namespace-Icon", + ), + m( + "span.FoF-Linguist-Coverage-Extension-Title", + app.translator.trans( + "fof-linguist.admin.coverage.all-namespaces", + ), + ), + ]), + localesAsArray().map((locale) => + m( + "td", + this.localeCoverage( + browseWithFilters, + locale.key, + ), + ), + ), + ]) + : null, + vnode.attrs.namespaces.map((namespace) => { + return m("tr", [ + m( + "td", + namespace.extension + ? [ + m( + "span.FoF-Linguist-Coverage-Extension-Icon", + { + style: namespace.extension + .icon, + }, + namespace.extension.icon + ? icon( + namespace.extension.icon + .name, + ) + : "", + ), + m( + "span.FoF-Linguist-Coverage-Extension-Title", + namespace.extension.extra[ + "flarum-extension" + ].title, + ), + ] + : [ + m( + "span.FoF-Linguist-Coverage-Extension-Icon.FoF-Linguist-Coverage-Namespace-Icon", + ), + m( + "span.FoF-Linguist-Coverage-Extension-Title", + namespaceLabel( + namespace.namespace, + ), + ), + ], + ), + this.columns === "locale" + ? localesAsArray().map((locale) => + m( + "td", + this.localeCoverage( + browseWithFilters, + locale.key, + namespace.namespace, + ), + ), + ) + : [ + this.showAllFrontends + ? visibleFrontends.map((frontend) => + m( + "td", + this.prefixCoverage( + browseWithFilters, + namespace.namespace, + frontend, + ), + ), + ) + : [ + m( + "td", + this.prefixCoverage( + browseWithFilters, + namespace.namespace, + "_all_except_admin", + ), + ), + m( + "td", + this.prefixCoverage( + browseWithFilters, + namespace.namespace, + "admin", + ), + ), + ], + ], ]); }), ]), @@ -126,43 +278,57 @@ export default class CoveragePage { return null; } - return this.localeCoverage(browseWithFilters, this.locale, namespace, frontend); + return this.localeCoverage( + browseWithFilters, + this.locale, + namespace, + frontend, + ); } localeCoverage(browseWithFilters, locale, namespace, frontend) { - const stringKeys = app.store.all('fof-linguist-string-key').filter(key => { - if (!namespace) { - return true; - } + const stringKeys = app.store + .all("fof-linguist-string-key") + .filter((key) => { + if (!namespace) { + return true; + } - const parts = key.key().split('.'); + const parts = key.key().split("."); - if (parts[0] !== namespace) { - return false; - } + if (parts[0] !== namespace) { + return false; + } - if (frontend === '_all_except_admin') { - if (parts.length >= 2 && parts[1] === 'admin') { + if (frontend === "_all_except_admin") { + if (parts.length >= 2 && parts[1] === "admin") { + return false; + } + } else if ( + frontend && + (parts.length < 2 || parts[1] !== frontend) + ) { return false; } - } else if (frontend && (parts.length < 2 || parts[1] !== frontend)) { - return false; - } - return true; - }); + return true; + }); if (stringKeys.length === 0) { - return '-'; + return "-"; } let customCount = 0; let originalCount = 0; - stringKeys.forEach(stringKey => { - const customString = app.store.all('fof-linguist-string').find( - string => string.key() === stringKey.key() && string.locale() === locale - ); + stringKeys.forEach((stringKey) => { + const customString = app.store + .all("fof-linguist-string") + .find( + (string) => + string.key() === stringKey.key() && + string.locale() === locale, + ); if (customString) { customCount++; @@ -171,48 +337,68 @@ export default class CoveragePage { } }); - const percent = Math.round(((customCount + originalCount) / stringKeys.length) * 100); + const percent = Math.round( + ((customCount + originalCount) / stringKeys.length) * 100, + ); let specialStyle; if (percent === 100) { - specialStyle = 'full'; + specialStyle = "full"; } else if (percent < 5) { - specialStyle = 'low'; + specialStyle = "low"; } let label; if (this.totalPercent) { - label = app.translator.trans('fof-linguist.admin.coverage.count.percent', { - percent: percent + '', // Keeps zero as string - }); + label = app.translator.trans( + "fof-linguist.admin.coverage.count.percent", + { + percent: percent + "", // Keeps zero as string + }, + ); } else { - label = app.translator.trans('fof-linguist.admin.coverage.count.total', { - translated: (customCount + originalCount) + '', // Keeps zero as string - total: stringKeys.length, - }); + label = app.translator.trans( + "fof-linguist.admin.coverage.count.total", + { + translated: customCount + originalCount + "", // Keeps zero as string + total: stringKeys.length, + }, + ); } - return m('.FoF-Linguist-Coverage-Progress-Wrap', [ - m('.FoF-Linguist-Progress', { - className: specialStyle ? 'FoF-Linguist-Progress--' + specialStyle : '', - }, [ - m('.FoF-Linguist-Progress-Bar', { - style: { - width: Math.max(percent, 5) + '%', // Always show the progress bar even if very close to 0 - }, - }), - m('.FoF-Linguist-Progress-Label', label), - m('.FoF-Linguist-Progress-More', app.translator.trans('fof-linguist.admin.coverage.count.details', { - total: stringKeys.length, - original: originalCount + '', // Cast to string to preserve zero - custom: customCount + '', - })), - ]), + return m(".FoF-Linguist-Coverage-Progress-Wrap", [ + m( + ".FoF-Linguist-Progress", + { + className: specialStyle + ? "FoF-Linguist-Progress--" + specialStyle + : "", + }, + [ + m(".FoF-Linguist-Progress-Bar", { + style: { + width: Math.max(percent, 5) + "%", // Always show the progress bar even if very close to 0 + }, + }), + m(".FoF-Linguist-Progress-Label", label), + m( + ".FoF-Linguist-Progress-More", + app.translator.trans( + "fof-linguist.admin.coverage.count.details", + { + total: stringKeys.length, + original: originalCount + "", // Cast to string to preserve zero + custom: customCount + "", + }, + ), + ), + ], + ), Button.component({ - icon: 'fas fa-filter', - className: 'Button Button--icon', + icon: "fas fa-filter", + className: "Button Button--icon", onclick: () => { const options = { missingTranslationsInLocales: [locale], @@ -228,7 +414,9 @@ export default class CoveragePage { browseWithFilters(options); }, - title: app.translator.trans('fof-linguist.admin.coverage.apply-missing-filter'), + title: app.translator.trans( + "fof-linguist.admin.coverage.apply-missing-filter", + ), }), ]); } diff --git a/js/src/admin/pages/ExportPage.js b/js/src/admin/pages/ExportPage.js index de0ae1a..21df458 100644 --- a/js/src/admin/pages/ExportPage.js +++ b/js/src/admin/pages/ExportPage.js @@ -1,20 +1,20 @@ -import app from 'flarum/admin/app'; -import Select from 'flarum/common/components/Select'; -import Switch from 'flarum/common/components/Switch'; -import LinkButton from 'flarum/common/components/LinkButton'; -import localesAsArray from '../utils/localesAsArray'; -import namespaceLabel from '../utils/namespaceLabel'; +import app from "flarum/admin/app"; +import Select from "flarum/common/components/Select"; +import Switch from "flarum/common/components/Switch"; +import LinkButton from "flarum/common/components/LinkButton"; +import localesAsArray from "../utils/localesAsArray"; +import namespaceLabel from "../utils/namespaceLabel"; /* global m */ export default class ExportPage { oninit() { - this.locale = 'en'; + this.locale = "en"; this.namespace = null; this.includeOriginals = false; this.includeAll = false; this.loading = false; - this.output = ''; + this.output = ""; this.fetchOutput(); } @@ -22,122 +22,167 @@ export default class ExportPage { view(vnode) { const localeOptions = {}; - localesAsArray().forEach(locale => { - localeOptions[locale.key] = locale.name + ' (' + locale.key + ')'; + localesAsArray().forEach((locale) => { + localeOptions[locale.key] = locale.name + " (" + locale.key + ")"; }); - localeOptions.all = app.translator.trans('fof-linguist.admin.export.locale-all') + localeOptions.all = app.translator.trans( + "fof-linguist.admin.export.locale-all", + ); const namespaceOptions = { - _all: app.translator.trans('fof-linguist.admin.export.namespace-all'), + _all: app.translator.trans( + "fof-linguist.admin.export.namespace-all", + ), }; - vnode.attrs.namespaces.forEach(namespace => { + vnode.attrs.namespaces.forEach((namespace) => { if (namespace.extension) { - namespaceOptions[namespace.namespace] = namespace.extension.extra['flarum-extension'].title; + namespaceOptions[namespace.namespace] = + namespace.extension.extra["flarum-extension"].title; } else { - namespaceOptions[namespace.namespace] = namespaceLabel(namespace.namespace); - + namespaceOptions[namespace.namespace] = namespaceLabel( + namespace.namespace, + ); } }); return [ - m('h2', app.translator.trans('fof-linguist.admin.export.title')), - m('.Form-group', m('.Alert', app.translator.trans('fof-linguist.admin.export.warning'))), - m('.Form-group', [ - m('label', app.translator.trans('fof-linguist.admin.export.locale')), + m("h2", app.translator.trans("fof-linguist.admin.export.title")), + m( + ".Form-group", + m( + ".Alert", + app.translator.trans("fof-linguist.admin.export.warning"), + ), + ), + m(".Form-group", [ + m( + "label", + app.translator.trans("fof-linguist.admin.export.locale"), + ), Select.component({ options: localeOptions, value: this.locale, - onchange: value => { + onchange: (value) => { this.locale = value; this.fetchOutput(); }, }), ]), - m('.Form-group', [ - m('label', app.translator.trans('fof-linguist.admin.export.namespace')), + m(".Form-group", [ + m( + "label", + app.translator.trans("fof-linguist.admin.export.namespace"), + ), Select.component({ options: namespaceOptions, - value: this.namespace === null ? '_all' : this.namespace, - onchange: value => { - this.namespace = value === '_all' ? null : value; + value: this.namespace === null ? "_all" : this.namespace, + onchange: (value) => { + this.namespace = value === "_all" ? null : value; this.fetchOutput(); }, }), ]), - m('.Form-group', [ - Switch.component({ - state: this.includeOriginals, - onchange: value => { - this.includeOriginals = value; - - this.fetchOutput(); - } - }, app.translator.trans('fof-linguist.admin.export.include-originals')), + m(".Form-group", [ + Switch.component( + { + state: this.includeOriginals, + onchange: (value) => { + this.includeOriginals = value; + + this.fetchOutput(); + }, + }, + app.translator.trans( + "fof-linguist.admin.export.include-originals", + ), + ), ]), - m('.Form-group', [ - Switch.component({ - state: this.includeAll, - onchange: value => { - this.includeAll = value; - - this.fetchOutput(); - } - }, app.translator.trans('fof-linguist.admin.export.include-all')), + m(".Form-group", [ + Switch.component( + { + state: this.includeAll, + onchange: (value) => { + this.includeAll = value; + + this.fetchOutput(); + }, + }, + app.translator.trans( + "fof-linguist.admin.export.include-all", + ), + ), ]), - m('.Form-group', [ - m('label', [ - app.translator.trans('fof-linguist.admin.export.output'), - ' ', - LinkButton.component({ - className: 'Button Button--primary', - href: this.exportUrl(), - external: true, - // If a namespace is selected, we use it as filename (language pack convention) - // otherwise we use the locale as filename (extension convention) - download: (this.namespace || this.locale) + '.yml', - }, app.translator.trans('fof-linguist.admin.export.download')), + m(".Form-group", [ + m("label", [ + app.translator.trans("fof-linguist.admin.export.output"), + " ", + LinkButton.component( + { + className: "Button Button--primary", + href: this.exportUrl(), + external: true, + // If a namespace is selected, we use it as filename (language pack convention) + // otherwise we use the locale as filename (extension convention) + download: (this.namespace || this.locale) + ".yml", + }, + app.translator.trans( + "fof-linguist.admin.export.download", + ), + ), ]), - m('textarea.FormControl.FoF-Export-Textarea', { + m("textarea.FormControl.FoF-Export-Textarea", { readonly: true, value: this.output, rows: 10, - placeholder: this.loading ? app.translator.trans('fof-linguist.admin.export.output-loading') : app.translator.trans('fof-linguist.admin.export.output-empty'), + placeholder: this.loading + ? app.translator.trans( + "fof-linguist.admin.export.output-loading", + ) + : app.translator.trans( + "fof-linguist.admin.export.output-empty", + ), }), ]), ]; } exportUrl() { - return app.forum.attribute('apiUrl') + '/fof/linguist/export?' + m.buildQueryString({ - locale: this.locale, - namespace: this.namespace, - includeOriginals: this.includeOriginals ? '1' : '0', - includeAll: this.includeAll ? '1' : '0', - }); + return ( + app.forum.attribute("apiUrl") + + "/fof/linguist/export?" + + m.buildQueryString({ + locale: this.locale, + namespace: this.namespace, + includeOriginals: this.includeOriginals ? "1" : "0", + includeAll: this.includeAll ? "1" : "0", + }) + ); } fetchOutput() { this.loading = true; - this.output = ''; + this.output = ""; app.request({ - method: 'GET', + method: "GET", url: this.exportUrl(), // Flarum doesn't support a raw to have the raw text response // So we'll encode the response with JSON so Flarum can parse if afterwards - extract: raw => JSON.stringify(raw), - }).then(output => { - this.loading = false; - this.output = output; - m.redraw(); - }).catch(error => { - this.loading = false; - m.redraw(); - throw error; - }); + extract: (raw) => JSON.stringify(raw), + }) + .then((output) => { + this.loading = false; + this.output = output; + m.redraw(); + }) + .catch((error) => { + this.loading = false; + m.redraw(); + throw error; + }); } } diff --git a/js/src/admin/pages/ImportPage.js b/js/src/admin/pages/ImportPage.js index 382dda7..c4ec3b3 100644 --- a/js/src/admin/pages/ImportPage.js +++ b/js/src/admin/pages/ImportPage.js @@ -1,95 +1,134 @@ -import app from 'flarum/admin/app'; -import Button from 'flarum/common/components/Button'; -import Select from 'flarum/common/components/Select'; -import Switch from 'flarum/common/components/Switch'; -import extractText from 'flarum/common/utils/extractText'; -import localesAsArray from '../utils/localesAsArray'; +import app from "flarum/admin/app"; +import Button from "flarum/common/components/Button"; +import Select from "flarum/common/components/Select"; +import Switch from "flarum/common/components/Switch"; +import extractText from "flarum/common/utils/extractText"; +import localesAsArray from "../utils/localesAsArray"; /* global m */ export default class ImportPage { oninit() { - this.locale = 'en'; + this.locale = "en"; this.overrideExisting = true; - this.input = ''; + this.input = ""; this.loading = false; } view() { const localeOptions = {}; - localesAsArray().forEach(locale => { - localeOptions[locale.key] = locale.name + ' (' + locale.key + ')'; + localesAsArray().forEach((locale) => { + localeOptions[locale.key] = locale.name + " (" + locale.key + ")"; }); - localeOptions.all = app.translator.trans('fof-linguist.admin.import.locale-all') + localeOptions.all = app.translator.trans( + "fof-linguist.admin.import.locale-all", + ); return [ - m('h2', app.translator.trans('fof-linguist.admin.import.title')), - m('.Form-group', [ - m('label', app.translator.trans('fof-linguist.admin.import.input')), - m('textarea.FormControl', { + m("h2", app.translator.trans("fof-linguist.admin.import.title")), + m(".Form-group", [ + m( + "label", + app.translator.trans("fof-linguist.admin.import.input"), + ), + m("textarea.FormControl", { value: this.input, - oninput: event => { + oninput: (event) => { this.input = event.target.value; }, rows: 10, - placeholder: app.translator.trans('fof-linguist.admin.import.input-placeholder'), + placeholder: app.translator.trans( + "fof-linguist.admin.import.input-placeholder", + ), }), ]), - m('.Form-group', [ - m('label', app.translator.trans('fof-linguist.admin.import.locale')), + m(".Form-group", [ + m( + "label", + app.translator.trans("fof-linguist.admin.import.locale"), + ), Select.component({ options: localeOptions, value: this.locale, - onchange: value => { + onchange: (value) => { this.locale = value; this.fetchOutput(); }, }), ]), - m('.Form-group', [ - Switch.component({ - state: this.overrideExisting, - onchange: value => { - this.overrideExisting = value; - } - }, app.translator.trans('fof-linguist.admin.import.override-existing')), + m(".Form-group", [ + Switch.component( + { + state: this.overrideExisting, + onchange: (value) => { + this.overrideExisting = value; + }, + }, + app.translator.trans( + "fof-linguist.admin.import.override-existing", + ), + ), ]), - m('.Form-group', Button.component({ - className: 'Button Button--primary', - onclick: () => { - this.loading = true; + m( + ".Form-group", + Button.component( + { + className: "Button Button--primary", + onclick: () => { + this.loading = true; - app.request({ - method: 'POST', - url: app.forum.attribute('apiUrl') + '/fof/linguist/import', - body: { - input: this.input, - locale: this.locale, - ignoreExisting: !this.overrideExisting, - }, - }).then(data => { - this.loading = false; - m.redraw(); + app.request({ + method: "POST", + url: + app.forum.attribute("apiUrl") + + "/fof/linguist/import", + body: { + input: this.input, + locale: this.locale, + ignoreExisting: !this.overrideExisting, + }, + }) + .then((data) => { + this.loading = false; + m.redraw(); - if (confirm(extractText(app.translator.trans(this.overrideExisting ? 'fof-linguist.admin.import.results' : 'fof-linguist.admin.import.results-with-ignore', { - imported: data.imported + '', // Cast to string to preserve zeros - ignored: data.ignored + '', - identical: data.identical + '', - })))) { - window.location.reload(); - } - }).catch(error => { - this.loading = false; - m.redraw(); - throw error; - }); - }, - disabled: this.loading || !this.input, - loading: this.loading, - }, app.translator.trans('fof-linguist.admin.import.submit'))), + if ( + confirm( + extractText( + app.translator.trans( + this.overrideExisting + ? "fof-linguist.admin.import.results" + : "fof-linguist.admin.import.results-with-ignore", + { + imported: + data.imported + "", // Cast to string to preserve zeros + ignored: + data.ignored + "", + identical: + data.identical + "", + }, + ), + ), + ) + ) { + window.location.reload(); + } + }) + .catch((error) => { + this.loading = false; + m.redraw(); + throw error; + }); + }, + disabled: this.loading || !this.input, + loading: this.loading, + }, + app.translator.trans("fof-linguist.admin.import.submit"), + ), + ), ]; } } diff --git a/js/src/admin/pages/LinguistPage.js b/js/src/admin/pages/LinguistPage.js index c5c20de..60cefae 100644 --- a/js/src/admin/pages/LinguistPage.js +++ b/js/src/admin/pages/LinguistPage.js @@ -1,10 +1,10 @@ -import app from 'flarum/admin/app'; -import ExtensionPage from 'flarum/admin/components/ExtensionPage'; -import LoadingIndicator from 'flarum/common/components/LoadingIndicator'; -import StringsPage from './StringsPage'; -import CoveragePage from './CoveragePage'; -import ExportPage from './ExportPage'; -import ImportPage from './ImportPage'; +import app from "flarum/admin/app"; +import ExtensionPage from "flarum/admin/components/ExtensionPage"; +import LoadingIndicator from "flarum/common/components/LoadingIndicator"; +import StringsPage from "./StringsPage"; +import CoveragePage from "./CoveragePage"; +import ExportPage from "./ExportPage"; +import ImportPage from "./ImportPage"; /* global m */ @@ -12,80 +12,87 @@ export default class LinguistPage extends ExtensionPage { oninit(vnode) { super.oninit(vnode); - this.tab = 'strings'; + this.tab = "strings"; this.ready = false; this.namespaces = []; // First level of translation keys. Usually an extension ID, but also core and validation - this.frontends = [ - 'forum', - 'admin', - 'lib', - 'ref', - 'api', - ]; // Second level of translation keys: forum, admin, ... + this.frontends = ["forum", "admin", "lib", "ref", "api"]; // Second level of translation keys: forum, admin, ... this.initialBrowseFilters = {}; Promise.all([ - app.request({ - method: 'GET', - url: app.forum.attribute('apiUrl') + '/fof/linguist/strings', - }).then(result => { - app.store.pushPayload(result); - }), - app.request({ - method: 'GET', - url: app.forum.attribute('apiUrl') + '/fof/linguist/string-keys', - }).then(result => { - const keys = app.store.pushPayload(result); - - const namespaces = []; - - keys.forEach(key => { - const parts = key.key().split('.'); - - const namespace = parts[0]; - - if (['core', 'validation'].indexOf(namespace) === -1 && namespaces.indexOf(namespace) === -1) { - namespaces.push(namespace); - } - - if (parts.length > 1 && namespace !== 'validation') { - const frontend = parts[1]; - - if (this.frontends.indexOf(frontend) === -1) { - this.frontends.push(frontend); + app + .request({ + method: "GET", + url: + app.forum.attribute("apiUrl") + "/fof/linguist/strings", + }) + .then((result) => { + app.store.pushPayload(result); + }), + app + .request({ + method: "GET", + url: + app.forum.attribute("apiUrl") + + "/fof/linguist/string-keys", + }) + .then((result) => { + const keys = app.store.pushPayload(result); + + const namespaces = []; + + keys.forEach((key) => { + const parts = key.key().split("."); + + const namespace = parts[0]; + + if ( + ["core", "validation"].indexOf(namespace) === -1 && + namespaces.indexOf(namespace) === -1 + ) { + namespaces.push(namespace); } - } - }); - - namespaces.sort(); - - this.namespaces = [ - { - namespace: 'core', - }, - { - namespace: 'validation', - }, - ...namespaces.map(namespace => { - // First we look if the namespace matches an extension ID, that's the most common naming - let extension = app.data.extensions[namespace]; - // If that's unsuccessful, we'll look if the full package name was used as namespace - if (!extension) { - extension = Object.values(app.data.extensions).find(extension => { - const packageNameWithDash = extension.name.replace('/', '-'); + if (parts.length > 1 && namespace !== "validation") { + const frontend = parts[1]; - return namespace === packageNameWithDash; - }); + if (this.frontends.indexOf(frontend) === -1) { + this.frontends.push(frontend); + } } - - return { - namespace, - extension, - }; - }), - ]; - }), + }); + + namespaces.sort(); + + this.namespaces = [ + { + namespace: "core", + }, + { + namespace: "validation", + }, + ...namespaces.map((namespace) => { + // First we look if the namespace matches an extension ID, that's the most common naming + let extension = app.data.extensions[namespace]; + + // If that's unsuccessful, we'll look if the full package name was used as namespace + if (!extension) { + extension = Object.values( + app.data.extensions, + ).find((extension) => { + const packageNameWithDash = + extension.name.replace("/", "-"); + + return namespace === packageNameWithDash; + }); + } + + return { + namespace, + extension, + }; + }), + ]; + }), ]).then(() => { this.ready = true; m.redraw(); @@ -93,40 +100,75 @@ export default class LinguistPage extends ExtensionPage { } content() { - return m('.ExtensionPage-settings', m('.container', [ - this.contentTab(), - ])); + return m( + ".ExtensionPage-settings", + m(".container", [this.contentTab()]), + ); } infoItems() { const items = super.infoItems(); - items.add('linguist-tabs', m('ul.FoF-Linguist-Tabs', [ - m('li', m('a', { - className: this.tab === 'strings' ? 'active' : '', - onclick: () => { - this.tab = 'strings'; - }, - }, app.translator.trans('fof-linguist.admin.tabs.strings'))), - m('li', m('a', { - className: this.tab === 'coverage' ? 'active' : '', - onclick: () => { - this.tab = 'coverage'; - }, - }, app.translator.trans('fof-linguist.admin.tabs.coverage'))), - m('li', m('a', { - className: this.tab === 'export' ? 'active' : '', - onclick: () => { - this.tab = 'export'; - }, - }, app.translator.trans('fof-linguist.admin.tabs.export'))), - m('li', m('a', { - className: this.tab === 'import' ? 'active' : '', - onclick: () => { - this.tab = 'import'; - }, - }, app.translator.trans('fof-linguist.admin.tabs.import'))), - ]), 100); + items.add( + "linguist-tabs", + m("ul.FoF-Linguist-Tabs", [ + m( + "li", + m( + "a", + { + className: this.tab === "strings" ? "active" : "", + onclick: () => { + this.tab = "strings"; + }, + }, + app.translator.trans("fof-linguist.admin.tabs.strings"), + ), + ), + m( + "li", + m( + "a", + { + className: this.tab === "coverage" ? "active" : "", + onclick: () => { + this.tab = "coverage"; + }, + }, + app.translator.trans( + "fof-linguist.admin.tabs.coverage", + ), + ), + ), + m( + "li", + m( + "a", + { + className: this.tab === "export" ? "active" : "", + onclick: () => { + this.tab = "export"; + }, + }, + app.translator.trans("fof-linguist.admin.tabs.export"), + ), + ), + m( + "li", + m( + "a", + { + className: this.tab === "import" ? "active" : "", + onclick: () => { + this.tab = "import"; + }, + }, + app.translator.trans("fof-linguist.admin.tabs.import"), + ), + ), + ]), + 100, + ); return items; } @@ -137,26 +179,26 @@ export default class LinguistPage extends ExtensionPage { } switch (this.tab) { - case 'strings': + case "strings": return m(StringsPage, { namespaces: this.namespaces, frontends: this.frontends, initialBrowseFilters: this.initialBrowseFilters, }); - case 'coverage': + case "coverage": return m(CoveragePage, { namespaces: this.namespaces, frontends: this.frontends, - browseWithFilters: filters => { + browseWithFilters: (filters) => { this.initialBrowseFilters = filters; - this.tab = 'strings'; + this.tab = "strings"; }, }); - case 'export': + case "export": return m(ExportPage, { namespaces: this.namespaces, }); - case 'import': + case "import": return m(ImportPage); } diff --git a/js/src/admin/pages/StringsPage.js b/js/src/admin/pages/StringsPage.js index 4709dc2..5923444 100644 --- a/js/src/admin/pages/StringsPage.js +++ b/js/src/admin/pages/StringsPage.js @@ -1,15 +1,15 @@ -import app from 'flarum/admin/app'; -import Button from 'flarum/common/components/Button'; -import Dropdown from 'flarum/common/components/Dropdown'; -import Select from 'flarum/common/components/Select'; -import Alert from 'flarum/common/components/Alert'; -import LoadingModal from 'flarum/admin/components/LoadingModal'; -import extractText from 'flarum/common/utils/extractText'; -import localesAsArray from '../utils/localesAsArray'; -import StringKey from '../components/StringKey'; -import namespaceLabel from '../utils/namespaceLabel'; -import frontendLabel from '../utils/frontendLabel'; -import booleanCheck from '../utils/booleanCheck'; +import app from "flarum/admin/app"; +import Button from "flarum/common/components/Button"; +import Dropdown from "flarum/common/components/Dropdown"; +import Select from "flarum/common/components/Select"; +import Alert from "flarum/common/components/Alert"; +import LoadingModal from "flarum/admin/components/LoadingModal"; +import extractText from "flarum/common/utils/extractText"; +import localesAsArray from "../utils/localesAsArray"; +import StringKey from "../components/StringKey"; +import namespaceLabel from "../utils/namespaceLabel"; +import frontendLabel from "../utils/frontendLabel"; +import booleanCheck from "../utils/booleanCheck"; /* global m */ @@ -19,16 +19,19 @@ export default class StringsPage { oninit(vnode) { this.numberOfResultsToShow = RESULTS_PER_PAGE; - this.filters = Object.assign({ - search: '', - withOwnTranslations: false, - missingTranslationsNegation: 'without', - missingTranslationsType: 'any', - missingTranslationsOperation: 'or', - missingTranslationsInLocales: [], - forExtension: null, - frontend: null, - }, vnode.attrs.initialBrowseFilters || {}); + this.filters = Object.assign( + { + search: "", + withOwnTranslations: false, + missingTranslationsNegation: "without", + missingTranslationsType: "any", + missingTranslationsOperation: "or", + missingTranslationsInLocales: [], + forExtension: null, + frontend: null, + }, + vnode.attrs.initialBrowseFilters || {}, + ); this.results = []; @@ -40,208 +43,405 @@ export default class StringsPage { return [ // Additional divs are used to reduce Mithril redraws as much as possible when the conditional components appear - m('div', this.cacheClearInstructions()), - m('.FoF-Linguist-Filters', [ - m('input.FormControl', { + m("div", this.cacheClearInstructions()), + m(".FoF-Linguist-Filters", [ + m("input.FormControl", { value: this.filters.search, - oninput: event => { + oninput: (event) => { this.filters.search = event.target.value; this.applyFilters(); }, - placeholder: app.translator.trans('fof-linguist.admin.filters.search'), + placeholder: app.translator.trans( + "fof-linguist.admin.filters.search", + ), }), - Button.component({ - className: 'Button' + (this.filters.withOwnTranslations ? ' FoF-Linguist-Filter--Selected' : ''), - icon: `far fa-${this.filters.withOwnTranslations ? 'check-square' : 'square'}`, - onclick: () => { - this.filters.withOwnTranslations = !this.filters.withOwnTranslations; - this.applyFilters(); - }, - }, app.translator.trans('fof-linguist.admin.filters.with-own-translations')), - Dropdown.component({ - buttonClassName: 'Button' + (this.filters.forExtension ? ' FoF-Linguist-Filter--Selected' : ''), - label: app.translator.trans('fof-linguist.admin.filters.for-extension'), - }, vnode.attrs.namespaces.map( - namespace => Button.component({ - className: 'Button', - icon: `far fa-${this.filters.forExtension === namespace.namespace ? 'dot-circle' : 'circle'}`, + Button.component( + { + className: + "Button" + + (this.filters.withOwnTranslations + ? " FoF-Linguist-Filter--Selected" + : ""), + icon: `far fa-${ + this.filters.withOwnTranslations + ? "check-square" + : "square" + }`, onclick: () => { - if (this.filters.forExtension === namespace.namespace) { - this.filters.forExtension = null; - } else { - this.filters.forExtension = namespace.namespace; - } - + this.filters.withOwnTranslations = + !this.filters.withOwnTranslations; this.applyFilters(); }, - }, namespace.extension ? namespace.extension.extra['flarum-extension'].title : namespaceLabel(namespace.namespace)) - )), - Dropdown.component({ - buttonClassName: 'Button' + (this.filters.frontend ? ' FoF-Linguist-Filter--Selected' : ''), - label: app.translator.trans('fof-linguist.admin.filters.frontend'), - }, [ - '_all_except_admin', - ...vnode.attrs.frontends, - ].map( - frontend => Button.component({ - className: 'Button', - icon: `far fa-${this.filters.frontend === frontend ? 'dot-circle' : 'circle'}`, - onclick: () => { - if (this.filters.frontend === frontend) { - this.filters.frontend = null; - } else { - this.filters.frontend = frontend; - } - - this.applyFilters(); - }, - }, frontend === '_all_except_admin' ? app.translator.trans('fof-linguist.admin.filters.frontend-all-except-admin') : frontendLabel(frontend)) - )), - Dropdown.component({ - buttonClassName: 'Button' + (this.filters.missingTranslationsInLocales.length ? ' FoF-Linguist-Filter--Selected' : ''), - label: app.translator.trans('fof-linguist.admin.filters.missing'), - }, [ - m('.FoF-Linguist-Missing-Filter', { - onclick(event) { - // Prevent closing the dropdown - event.stopPropagation(); - }, - }, [ - Select.component({ - value: this.filters.missingTranslationsNegation, - onchange: value => { - this.filters.missingTranslationsNegation = value; - - if (this.filters.missingTranslationsInLocales.length) { - this.applyFilters(); - } - }, - options: { - without: app.translator.trans('fof-linguist.admin.filters.negation-options.without'), - with: app.translator.trans('fof-linguist.admin.filters.negation-options.with'), - }, - }), - Select.component({ - value: this.filters.missingTranslationsType, - onchange: value => { - this.filters.missingTranslationsType = value; + }, + app.translator.trans( + "fof-linguist.admin.filters.with-own-translations", + ), + ), + Dropdown.component( + { + buttonClassName: + "Button" + + (this.filters.forExtension + ? " FoF-Linguist-Filter--Selected" + : ""), + label: app.translator.trans( + "fof-linguist.admin.filters.for-extension", + ), + }, + vnode.attrs.namespaces.map((namespace) => + Button.component( + { + className: "Button", + icon: `far fa-${ + this.filters.forExtension === + namespace.namespace + ? "dot-circle" + : "circle" + }`, + onclick: () => { + if ( + this.filters.forExtension === + namespace.namespace + ) { + this.filters.forExtension = null; + } else { + this.filters.forExtension = + namespace.namespace; + } - if (this.filters.missingTranslationsInLocales.length) { this.applyFilters(); - } + }, }, - options: { - any: app.translator.trans('fof-linguist.admin.filters.type-options.any'), - original: app.translator.trans('fof-linguist.admin.filters.type-options.original'), - own: app.translator.trans('fof-linguist.admin.filters.type-options.own'), - }, - }), - m('p', app.translator.trans('fof-linguist.admin.filters.missing-middle-label')), - Select.component({ - value: this.filters.missingTranslationsOperation, - onchange: value => { - this.filters.missingTranslationsOperation = value; - - if (this.filters.missingTranslationsInLocales.length) { - this.applyFilters(); - } + namespace.extension + ? namespace.extension.extra["flarum-extension"] + .title + : namespaceLabel(namespace.namespace), + ), + ), + ), + Dropdown.component( + { + buttonClassName: + "Button" + + (this.filters.frontend + ? " FoF-Linguist-Filter--Selected" + : ""), + label: app.translator.trans( + "fof-linguist.admin.filters.frontend", + ), + }, + ["_all_except_admin", ...vnode.attrs.frontends].map( + (frontend) => + Button.component( + { + className: "Button", + icon: `far fa-${ + this.filters.frontend === frontend + ? "dot-circle" + : "circle" + }`, + onclick: () => { + if ( + this.filters.frontend === frontend + ) { + this.filters.frontend = null; + } else { + this.filters.frontend = frontend; + } + + this.applyFilters(); + }, + }, + frontend === "_all_except_admin" + ? app.translator.trans( + "fof-linguist.admin.filters.frontend-all-except-admin", + ) + : frontendLabel(frontend), + ), + ), + ), + Dropdown.component( + { + buttonClassName: + "Button" + + (this.filters.missingTranslationsInLocales.length + ? " FoF-Linguist-Filter--Selected" + : ""), + label: app.translator.trans( + "fof-linguist.admin.filters.missing", + ), + }, + [ + m( + ".FoF-Linguist-Missing-Filter", + { + onclick(event) { + // Prevent closing the dropdown + event.stopPropagation(); + }, }, - options: { - or: app.translator.trans('fof-linguist.admin.filters.operation-options.or'), - and: app.translator.trans('fof-linguist.admin.filters.operation-options.and'), + [ + Select.component({ + value: this.filters + .missingTranslationsNegation, + onchange: (value) => { + this.filters.missingTranslationsNegation = + value; + + if ( + this.filters + .missingTranslationsInLocales + .length + ) { + this.applyFilters(); + } + }, + options: { + without: app.translator.trans( + "fof-linguist.admin.filters.negation-options.without", + ), + with: app.translator.trans( + "fof-linguist.admin.filters.negation-options.with", + ), + }, + }), + Select.component({ + value: this.filters.missingTranslationsType, + onchange: (value) => { + this.filters.missingTranslationsType = + value; + + if ( + this.filters + .missingTranslationsInLocales + .length + ) { + this.applyFilters(); + } + }, + options: { + any: app.translator.trans( + "fof-linguist.admin.filters.type-options.any", + ), + original: app.translator.trans( + "fof-linguist.admin.filters.type-options.original", + ), + own: app.translator.trans( + "fof-linguist.admin.filters.type-options.own", + ), + }, + }), + m( + "p", + app.translator.trans( + "fof-linguist.admin.filters.missing-middle-label", + ), + ), + Select.component({ + value: this.filters + .missingTranslationsOperation, + onchange: (value) => { + this.filters.missingTranslationsOperation = + value; + + if ( + this.filters + .missingTranslationsInLocales + .length + ) { + this.applyFilters(); + } + }, + options: { + or: app.translator.trans( + "fof-linguist.admin.filters.operation-options.or", + ), + and: app.translator.trans( + "fof-linguist.admin.filters.operation-options.and", + ), + }, + }), + ], + ), + ...localesAsArray().map((locale) => + Button.component( + { + className: "Button", + icon: `far fa-${ + this.filters.missingTranslationsInLocales.indexOf( + locale.key, + ) !== -1 + ? "check-square" + : "square" + }`, + onclick: () => { + if ( + this.filters.missingTranslationsInLocales.indexOf( + locale.key, + ) !== -1 + ) { + this.filters.missingTranslationsInLocales = + this.filters.missingTranslationsInLocales.filter( + (key) => key !== locale.key, + ); + } else { + this.filters.missingTranslationsInLocales.push( + locale.key, + ); + } + + this.applyFilters(); + }, + }, + locale.name + " (" + locale.key + ")", + ), + ), + ], + ), + Dropdown.component( + { + buttonClassName: "Button", + label: app.translator.trans( + "fof-linguist.admin.filters.mass-edit", + ), + }, + [ + Button.component( + { + icon: "far fa-clone", + className: "Button", + onclick: () => { + const strings = app.store + .all("fof-linguist-string") + .filter((string) => { + const key = app.store.getById( + "fof-linguist-string-key", + string.key(), + ); + + return ( + key && + key.locales()[ + string.locale() + ] === string.value() + ); + }); + + if ( + confirm( + extractText( + app.translator.trans( + "fof-linguist.admin.buttons.delete-redundant-confirm", + { + count: + strings.length + "", + }, + ), + ), + ) + ) { + if (strings.length === 0) { + return; + } + + app.modal.show(LoadingModal); + + Promise.all( + strings.map((string) => + string.delete(), + ), + ).then(() => { + window.location.reload(); + }); + } + }, }, - }), - ]), - ...localesAsArray().map( - locale => Button.component({ - className: 'Button', - icon: `far fa-${this.filters.missingTranslationsInLocales.indexOf(locale.key) !== -1 ? 'check-square' : 'square'}`, - onclick: () => { - if (this.filters.missingTranslationsInLocales.indexOf(locale.key) !== -1) { - this.filters.missingTranslationsInLocales = this.filters.missingTranslationsInLocales.filter(key => key !== locale.key); - } else { - this.filters.missingTranslationsInLocales.push(locale.key); - } - - this.applyFilters(); + app.translator.trans( + "fof-linguist.admin.buttons.delete-redundant", + ), + ), + Button.component( + { + icon: "fas fa-trash", + className: "Button", + onclick: () => { + const strings = app.store.all( + "fof-linguist-string", + ); + + if ( + confirm( + extractText( + app.translator.trans( + "fof-linguist.admin.buttons.delete-all-confirm", + { + count: + strings.length + "", + }, + ), + ), + ) + ) { + if (strings.length === 0) { + return; + } + + app.modal.show(LoadingModal); + + Promise.all( + strings.map((string) => + string.delete(), + ), + ).then(() => { + window.location.reload(); + }); + } + }, }, - }, locale.name + ' (' + locale.key + ')') - ), - ]), - Dropdown.component({ - buttonClassName: 'Button', - label: app.translator.trans('fof-linguist.admin.filters.mass-edit'), - }, [ - Button.component({ - icon: 'far fa-clone', - className: 'Button', - onclick: () => { - const strings = app.store.all('fof-linguist-string').filter(string => { - const key = app.store.getById('fof-linguist-string-key', string.key()); - - return key && key.locales()[string.locale()] === string.value(); - }); - - if (confirm(extractText(app.translator.trans('fof-linguist.admin.buttons.delete-redundant-confirm', { - count: strings.length + '', - })))) { - if (strings.length === 0) { - return; - } - - app.modal.show(LoadingModal); - - Promise.all(strings.map(string => string.delete())).then(() => { - window.location.reload(); - }); - } - }, - }, app.translator.trans('fof-linguist.admin.buttons.delete-redundant')), - Button.component({ - icon: 'fas fa-trash', - className: 'Button', - onclick: () => { - const strings = app.store.all('fof-linguist-string'); - - if (confirm(extractText(app.translator.trans('fof-linguist.admin.buttons.delete-all-confirm', { - count: strings.length + '', - })))) { - if (strings.length === 0) { - return; - } - - app.modal.show(LoadingModal); - - Promise.all(strings.map(string => string.delete())).then(() => { - window.location.reload(); - }); - } - }, - }, app.translator.trans('fof-linguist.admin.buttons.delete-all')), - ]), + app.translator.trans( + "fof-linguist.admin.buttons.delete-all", + ), + ), + ], + ), ]), - m('div', keys.map(stringKey => m(StringKey, { - key: stringKey.id(), - stringKey, - highlight: this.filters.search, - onchange: () => { - // We use the setting and not a local variable because we need to preserve state - // if we navigate away and back to the Linguist page without refreshing the admin panel - app.data.settings['fof.linguist.should-clear-cache'] = '1'; - }, - }))), - m('.FoF-Linguist-Results', [ - app.translator.trans('fof-linguist.admin.filters.results', { - shown: keys.length + '', // cast to string otherwise number isn't displayed - total: this.results.length + '', + m( + "div", + keys.map((stringKey) => + m(StringKey, { + key: stringKey.id(), + stringKey, + highlight: this.filters.search, + onchange: () => { + // We use the setting and not a local variable because we need to preserve state + // if we navigate away and back to the Linguist page without refreshing the admin panel + app.data.settings[ + "fof.linguist.should-clear-cache" + ] = "1"; + }, + }), + ), + ), + m(".FoF-Linguist-Results", [ + app.translator.trans("fof-linguist.admin.filters.results", { + shown: keys.length + "", // cast to string otherwise number isn't displayed + total: this.results.length + "", }), - ' ', - (this.results.length > keys.length ? Button.component({ - className: 'Button', - onclick: () => { - this.numberOfResultsToShow += RESULTS_PER_PAGE; - }, - }, app.translator.trans('fof-linguist.admin.buttons.load-more')) : null), + " ", + this.results.length > keys.length + ? Button.component( + { + className: "Button", + onclick: () => { + this.numberOfResultsToShow += + RESULTS_PER_PAGE; + }, + }, + app.translator.trans( + "fof-linguist.admin.buttons.load-more", + ), + ) + : null, ]), ]; } @@ -249,105 +449,144 @@ export default class StringsPage { applyFilters() { this.numberOfResultsToShow = RESULTS_PER_PAGE; - const keysWithCustomTranslations = app.store.all('fof-linguist-string').map(string => string.key()); + const keysWithCustomTranslations = app.store + .all("fof-linguist-string") + .map((string) => string.key()); const keysWithCustomTranslationsIn = {}; - localesAsArray().forEach(locale => { - keysWithCustomTranslationsIn[locale.key] = app.store.all('fof-linguist-string') - .filter(string => string.locale() === locale.key) - .map(string => string.key()); + localesAsArray().forEach((locale) => { + keysWithCustomTranslationsIn[locale.key] = app.store + .all("fof-linguist-string") + .filter((string) => string.locale() === locale.key) + .map((string) => string.key()); }); - let lowercaseSearch = ''; + let lowercaseSearch = ""; if (this.filters.search) { lowercaseSearch = this.filters.search.toLowerCase(); } - this.results = app.store.all('fof-linguist-string-key').filter(key => { - if (this.filters.withOwnTranslations && keysWithCustomTranslations.indexOf(key.key()) === -1) { - return false; - } - - if (this.filters.missingTranslationsInLocales.length) { - let operation = this.filters.missingTranslationsOperation; - - // Because the whole operation is reversed at the end based on with or without, - // we actually need to make the opposite boolean computation on the "has" variables - if (this.filters.missingTranslationsNegation === 'without') { - operation = operation === 'or' ? 'and' : 'or'; + this.results = app.store + .all("fof-linguist-string-key") + .filter((key) => { + if ( + this.filters.withOwnTranslations && + keysWithCustomTranslations.indexOf(key.key()) === -1 + ) { + return false; } - const hasOriginalTranslation = booleanCheck(operation, this.filters.missingTranslationsInLocales.map(locale => { - return key.locales().hasOwnProperty(locale); - })); - const hasOwnTranslation = booleanCheck(operation, this.filters.missingTranslationsInLocales.map(locale => { - return keysWithCustomTranslationsIn[locale].indexOf(key.key()) !== -1; - })); - - let matchesType = false; - - switch (this.filters.missingTranslationsType) { - case 'any': - matchesType = hasOriginalTranslation || hasOwnTranslation; - break; - case 'original': - matchesType = hasOriginalTranslation; - break; - case 'own': - matchesType = hasOwnTranslation; - break; - } + if (this.filters.missingTranslationsInLocales.length) { + let operation = this.filters.missingTranslationsOperation; - if (this.filters.missingTranslationsNegation === 'without') { - matchesType = !matchesType; - } - - if (!matchesType) { - return false; - } - } + // Because the whole operation is reversed at the end based on with or without, + // we actually need to make the opposite boolean computation on the "has" variables + if ( + this.filters.missingTranslationsNegation === "without" + ) { + operation = operation === "or" ? "and" : "or"; + } - if (this.filters.forExtension) { - if (key.key().indexOf(this.filters.forExtension + '.') !== 0) { - return false; - } - } + const hasOriginalTranslation = booleanCheck( + operation, + this.filters.missingTranslationsInLocales.map( + (locale) => { + return key.locales().hasOwnProperty(locale); + }, + ), + ); + const hasOwnTranslation = booleanCheck( + operation, + this.filters.missingTranslationsInLocales.map( + (locale) => { + return ( + keysWithCustomTranslationsIn[ + locale + ].indexOf(key.key()) !== -1 + ); + }, + ), + ); + + let matchesType = false; + + switch (this.filters.missingTranslationsType) { + case "any": + matchesType = + hasOriginalTranslation || hasOwnTranslation; + break; + case "original": + matchesType = hasOriginalTranslation; + break; + case "own": + matchesType = hasOwnTranslation; + break; + } - if (this.filters.frontend) { - const parts = key.key().split('.'); + if ( + this.filters.missingTranslationsNegation === "without" + ) { + matchesType = !matchesType; + } - if (this.filters.frontend === '_all_except_admin') { - // We will keep everything that isn't admin, including if it's a single level deep - if (parts.length >= 2 && parts[1] === 'admin') { + if (!matchesType) { return false; } - } else { - // Keep only parts with 2 levels or more where second level matches frontend - if (parts.length < 2 || parts[1] !== this.filters.frontend) { + } + + if (this.filters.forExtension) { + if ( + key.key().indexOf(this.filters.forExtension + ".") !== 0 + ) { return false; } } - } - if (lowercaseSearch) { - if (key.key().toLowerCase().indexOf(lowercaseSearch) !== -1) { - return true; + if (this.filters.frontend) { + const parts = key.key().split("."); + + if (this.filters.frontend === "_all_except_admin") { + // We will keep everything that isn't admin, including if it's a single level deep + if (parts.length >= 2 && parts[1] === "admin") { + return false; + } + } else { + // Keep only parts with 2 levels or more where second level matches frontend + if ( + parts.length < 2 || + parts[1] !== this.filters.frontend + ) { + return false; + } + } } - const locales = key.locales(); - - for (let locale in locales) { - if (locales.hasOwnProperty(locale) && locales[locale].toLowerCase().indexOf(lowercaseSearch) !== -1) { + if (lowercaseSearch) { + if ( + key.key().toLowerCase().indexOf(lowercaseSearch) !== -1 + ) { return true; } - } - return false; - } + const locales = key.locales(); + + for (let locale in locales) { + if ( + locales.hasOwnProperty(locale) && + locales[locale] + .toLowerCase() + .indexOf(lowercaseSearch) !== -1 + ) { + return true; + } + } - return true; - }); + return false; + } + + return true; + }); m.redraw(); } @@ -361,24 +600,36 @@ export default class StringsPage { // Check for flag that says cache should be cleared // This value is set both server-side and client-side in the onchange code above for immediate effect - if (app.data.settings['fof.linguist.should-clear-cache'] !== '1') { + if (app.data.settings["fof.linguist.should-clear-cache"] !== "1") { return null; } - return Alert.component({ - dismissible: false, - controls: [Button.component({ - className: 'Button Button--link', - onclick() { - // Same logic as in core StatusWidget - app.modal.show(LoadingModal); - - app.request({ - method: 'DELETE', - url: app.forum.attribute('apiUrl') + '/cache', - }).then(() => window.location.reload()); - }, - }, app.translator.trans('fof-linguist.admin.clear-cache.button'))], - }, app.translator.trans('fof-linguist.admin.clear-cache.text')); + return Alert.component( + { + dismissible: false, + controls: [ + Button.component( + { + className: "Button Button--link", + onclick() { + // Same logic as in core StatusWidget + app.modal.show(LoadingModal); + + app.request({ + method: "DELETE", + url: + app.forum.attribute("apiUrl") + + "/cache", + }).then(() => window.location.reload()); + }, + }, + app.translator.trans( + "fof-linguist.admin.clear-cache.button", + ), + ), + ], + }, + app.translator.trans("fof-linguist.admin.clear-cache.text"), + ); } } diff --git a/js/src/admin/pages/index.js b/js/src/admin/pages/index.js index f959aa6..a821417 100644 --- a/js/src/admin/pages/index.js +++ b/js/src/admin/pages/index.js @@ -1,8 +1,8 @@ -import CoveragePage from './CoveragePage'; -import ExportPage from './ExportPage'; -import ImportPage from './ImportPage'; -import LinguistPage from './LinguistPage'; -import StringsPage from './StringsPage'; +import CoveragePage from "./CoveragePage"; +import ExportPage from "./ExportPage"; +import ImportPage from "./ImportPage"; +import LinguistPage from "./LinguistPage"; +import StringsPage from "./StringsPage"; export const pages = { CoveragePage, diff --git a/js/src/admin/utils/booleanCheck.js b/js/src/admin/utils/booleanCheck.js index 8ae8be4..9894c43 100644 --- a/js/src/admin/utils/booleanCheck.js +++ b/js/src/admin/utils/booleanCheck.js @@ -1,13 +1,13 @@ export default function (operation, booleans) { return booleans.reduce((a, b) => { - if (a === 'start') { + if (a === "start") { return b; } - if (operation === 'or') { + if (operation === "or") { return a || b; } return a && b; - }, 'start'); + }, "start"); } diff --git a/js/src/admin/utils/frontendLabel.js b/js/src/admin/utils/frontendLabel.js index 8ba5152..fee9222 100644 --- a/js/src/admin/utils/frontendLabel.js +++ b/js/src/admin/utils/frontendLabel.js @@ -1,7 +1,10 @@ -import app from 'flarum/admin/app'; +import app from "flarum/admin/app"; export default function (frontend) { - const translation = app.translator.translations['fof-linguist.admin.known-frontend.' + frontend]; + const translation = + app.translator.translations[ + "fof-linguist.admin.known-frontend." + frontend + ]; if (translation) { return translation; diff --git a/js/src/admin/utils/highlightMithril.js b/js/src/admin/utils/highlightMithril.js index 6ebfd39..c4728c1 100644 --- a/js/src/admin/utils/highlightMithril.js +++ b/js/src/admin/utils/highlightMithril.js @@ -1,6 +1,6 @@ /* global m */ -const HIGHLIGHT_DELIMITER = ''; +const HIGHLIGHT_DELIMITER = ""; // Takes a string and highlight a keyword with a span with mithril template // The output will be an array if a keyword is given @@ -12,14 +12,17 @@ export default function (string, highlight) { const lowercaseHighliht = highlight.toLowerCase(); // Regex to match the highlighted work in a case-insensitive manner - const regex = new RegExp(lowercaseHighliht.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'i'); + const regex = new RegExp( + lowercaseHighliht.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), + "i", + ); return string - .replace(regex, HIGHLIGHT_DELIMITER + '$&' + HIGHLIGHT_DELIMITER) + .replace(regex, HIGHLIGHT_DELIMITER + "$&" + HIGHLIGHT_DELIMITER) .split(HIGHLIGHT_DELIMITER) - .map(text => { + .map((text) => { if (text.toLowerCase() === lowercaseHighliht) { - return m('span.FoF-Linguist-Highlight', text); + return m("span.FoF-Linguist-Highlight", text); } return text; diff --git a/js/src/admin/utils/index.js b/js/src/admin/utils/index.js index de97317..53d857d 100644 --- a/js/src/admin/utils/index.js +++ b/js/src/admin/utils/index.js @@ -1,8 +1,8 @@ -import booleanCheck from './booleanCheck'; -import frontendLabel from './frontendLabel'; -import highlightMithril from './highlightMithril'; -import localesAsArray from './localesAsArray'; -import namespaceLabel from './namespaceLabel'; +import booleanCheck from "./booleanCheck"; +import frontendLabel from "./frontendLabel"; +import highlightMithril from "./highlightMithril"; +import localesAsArray from "./localesAsArray"; +import namespaceLabel from "./namespaceLabel"; export const utils = { booleanCheck, diff --git a/js/src/admin/utils/localesAsArray.js b/js/src/admin/utils/localesAsArray.js index 976f5fb..3bd7faf 100644 --- a/js/src/admin/utils/localesAsArray.js +++ b/js/src/admin/utils/localesAsArray.js @@ -1,4 +1,4 @@ -import app from 'flarum/admin/app'; +import app from "flarum/admin/app"; export default function () { let locales = []; @@ -10,7 +10,7 @@ export default function () { continue; } - if (key === 'en') { + if (key === "en") { englishFound = true; } @@ -25,10 +25,10 @@ export default function () { // It's the bundled locale for most extensions, so it makes sense to have access to it as reference if (!englishFound) { locales.unshift({ - key: 'en', + key: "en", // Hard-coded to the same value as in flarum/lang-english composer.json // Since other locale names won't be translated to the current language either it doesn't make sense to use a translation - name: 'English', + name: "English", }); } diff --git a/js/src/admin/utils/namespaceLabel.js b/js/src/admin/utils/namespaceLabel.js index 3ea8b30..21d8ec2 100644 --- a/js/src/admin/utils/namespaceLabel.js +++ b/js/src/admin/utils/namespaceLabel.js @@ -1,7 +1,10 @@ -import app from 'flarum/admin/app'; +import app from "flarum/admin/app"; export default function (namespace) { - const translation = app.translator.translations['fof-linguist.admin.known-namespace.' + namespace]; + const translation = + app.translator.translations[ + "fof-linguist.admin.known-namespace." + namespace + ]; if (translation) { return translation; diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..03cf261 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,13 @@ +includes: + - vendor/flarum/phpstan/extension.neon + +parameters: + # The level will be increased in Flarum 2.0 + level: 5 + paths: + - extend.php + - src + excludePaths: + - *.blade.php + checkMissingIterableValueType: false + databaseMigrationsPath: ['migrations'] diff --git a/src/Api/Controllers/ExportController.php b/src/Api/Controllers/ExportController.php index 15a595c..d47729f 100644 --- a/src/Api/Controllers/ExportController.php +++ b/src/Api/Controllers/ExportController.php @@ -80,6 +80,7 @@ public function handle(ServerRequestInterface $request): ResponseInterface $node = &$nestedTranslations; foreach (explode('.', $key) as $path) { + /** @phpstan-ignore-next-line */ if (!array_key_exists($path, $node)) { $node[$path] = []; } diff --git a/src/Api/Controllers/ImportController.php b/src/Api/Controllers/ImportController.php index 23c9ac9..2fe112d 100644 --- a/src/Api/Controllers/ImportController.php +++ b/src/Api/Controllers/ImportController.php @@ -64,9 +64,6 @@ public function handle(ServerRequestInterface $request): ResponseInterface ]); } - /** - * @var TextString $string - */ $string = TextString::query() ->where('locale', $locale) ->where('key', $key) diff --git a/src/Api/Serializers/StringSerializer.php b/src/Api/Serializers/StringSerializer.php index 7fb17ba..7514490 100644 --- a/src/Api/Serializers/StringSerializer.php +++ b/src/Api/Serializers/StringSerializer.php @@ -11,6 +11,10 @@ public function getType($model): string return 'fof-linguist-string'; } + /** + * @param \FoF\Linguist\TextString $model + * @return array + */ protected function getDefaultAttributes($model): array { return $model->toArray(); diff --git a/src/Repositories/StringRepository.php b/src/Repositories/StringRepository.php index 1f7941b..230f364 100644 --- a/src/Repositories/StringRepository.php +++ b/src/Repositories/StringRepository.php @@ -36,7 +36,7 @@ public function all() /** * @param $id - * @return TextString|Model + * @return TextString */ public function findOrFail($id) { diff --git a/src/Translator/NoOpConfigCache.php b/src/Translator/NoOpConfigCache.php index 32043f1..34c1cf5 100644 --- a/src/Translator/NoOpConfigCache.php +++ b/src/Translator/NoOpConfigCache.php @@ -10,7 +10,7 @@ class NoOpConfigCache implements ConfigCacheInterface /** * Gets the cache file path. * - * @return string The cache file path + * @return string|null The cache file path */ public function getPath() {