diff --git a/.eslintrc.cjs b/.eslintrc.cjs index d8872c9..1172589 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -13,7 +13,7 @@ module.exports = { parserOptions: { ecmaVersion: 'latest', sourceType: 'module', - project: "tsconfig.lint.json", + project: "tsconfig.node.json", tsconfigRootDir: __dirname, }, plugins: ['react-refresh', 'prettier'], diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6cf74e0..3a88c20 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -25,9 +25,29 @@ jobs: env: CI: true + cypress: + runs-on: ubuntu-latest + strategy: + matrix: + browsers: + - chrome + - firefox + - edge + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Cypress run + uses: cypress-io/github-action@v6 + with: + config-file: 'test/component/cypress.config.ts' + start: npm run vue:component:serve + browser: ${{ matrix.browsers }} + status-checks: name: status-checks - needs: [build] + needs: + - build + - cypress permissions: contents: none if: always() @@ -38,7 +58,7 @@ jobs: run: | echo 'Configuration for Status checks that are required' echo '${{ toJSON(needs) }}' - if [[ ('skipped' == '${{ needs.build.result }}') || ('success' == '${{ needs.build.result }}') ]]; then + if [[ (('skipped' == '${{ needs.build.result }}') || ('success' == '${{ needs.build.result }}')) && (('skipped' == '${{ needs.cypress.result }}') || ('success' == '${{ needs.cypress.result }}')) ]]; then exit 0 fi exit 1 diff --git a/config/react/.env b/config/react/.env new file mode 100644 index 0000000..08634f5 --- /dev/null +++ b/config/react/.env @@ -0,0 +1 @@ +VITE_FWK=react diff --git a/config/vue/.env b/config/vue/.env new file mode 100644 index 0000000..ac61d6b --- /dev/null +++ b/config/vue/.env @@ -0,0 +1 @@ +VITE_FWK=vue diff --git a/index.html b/index.html index b7a8e45..76e5ae4 100644 --- a/index.html +++ b/index.html @@ -1,13 +1,13 @@ - + - Library using React + Library -
- +
+ diff --git a/package-lock.json b/package-lock.json index 03ae99b..45d4318 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,11 +10,14 @@ "dependencies": { "i18next": "^23.2.11", "i18next-browser-languagedetector": "^8.0.0", + "i18next-vue": "^4.0.0", "piqure": "^2.0.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-i18next": "^15.0.1", - "react-router-dom": "^6.14.2" + "react-router-dom": "^6.14.2", + "vue": "^3.4.36", + "vue-router": "^4.4.3" }, "devDependencies": { "@types/react": "^18.2.17", @@ -23,6 +26,7 @@ "@typescript-eslint/eslint-plugin": "^6.2.0", "@typescript-eslint/parser": "^6.2.0", "@vitejs/plugin-react": "^4.0.1", + "@vitejs/plugin-vue": "^5.1.2", "@vitest/coverage-v8": "^2.0.5", "axios": "^1.4.0", "cypress": "^13.13.2", @@ -35,7 +39,8 @@ "start-server-and-test": "^2.0.0", "typescript": "^5.0.2", "vite": "^5.4.0", - "vitest": "^2.0.5" + "vitest": "^2.0.5", + "vue-tsc": "^2.0.29" } }, "node_modules/@ampproject/remapping": { @@ -209,7 +214,6 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -218,7 +222,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -264,7 +267,6 @@ "version": "7.25.3", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.3.tgz", "integrity": "sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw==", - "dev": true, "dependencies": { "@babel/types": "^7.25.2" }, @@ -352,7 +354,6 @@ "version": "7.25.2", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.2.tgz", "integrity": "sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==", - "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.24.8", "@babel/helper-validator-identifier": "^7.24.7", @@ -1125,8 +1126,7 @@ "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", @@ -1816,6 +1816,19 @@ "vite": "^4.2.0 || ^5.0.0" } }, + "node_modules/@vitejs/plugin-vue": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.1.2.tgz", + "integrity": "sha512-nY9IwH12qeiJqumTCLJLE7IiNx7HZ39cbHaysEUd+Myvbz9KAqd2yq+U01Kab1R/H1BmiyM2ShTYlNH32Fzo3A==", + "dev": true, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0", + "vue": "^3.2.25" + } + }, "node_modules/@vitest/coverage-v8": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.0.5.tgz", @@ -1923,6 +1936,183 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/@volar/language-core": { + "version": "2.4.0-alpha.18", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.0-alpha.18.tgz", + "integrity": "sha512-JAYeJvYQQROmVRtSBIczaPjP3DX4QW1fOqW1Ebs0d3Y3EwSNRglz03dSv0Dm61dzd0Yx3WgTW3hndDnTQqgmyg==", + "dev": true, + "dependencies": { + "@volar/source-map": "2.4.0-alpha.18" + } + }, + "node_modules/@volar/source-map": { + "version": "2.4.0-alpha.18", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.0-alpha.18.tgz", + "integrity": "sha512-MTeCV9MUwwsH0sNFiZwKtFrrVZUK6p8ioZs3xFzHc2cvDXHWlYN3bChdQtwKX+FY2HG6H3CfAu1pKijolzIQ8g==", + "dev": true + }, + "node_modules/@volar/typescript": { + "version": "2.4.0-alpha.18", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.0-alpha.18.tgz", + "integrity": "sha512-sXh5Y8sqGUkgxpMWUGvRXggxYHAVxg0Pa1C42lQZuPDrW6vHJPR0VCK8Sr7WJsAW530HuNQT/ZIskmXtxjybMQ==", + "dev": true, + "dependencies": { + "@volar/language-core": "2.4.0-alpha.18", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.4.36", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.36.tgz", + "integrity": "sha512-qBkndgpwFKdupmOPoiS10i7oFdN7a+4UNDlezD0GlQ1kuA1pNrscg9g12HnB5E8hrWSuEftRsbJhL1HI2zpJhg==", + "dependencies": { + "@babel/parser": "^7.24.7", + "@vue/shared": "3.4.36", + "entities": "^5.0.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/compiler-core/node_modules/entities": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-5.0.0.tgz", + "integrity": "sha512-BeJFvFRJddxobhvEdm5GqHzRV/X+ACeuw0/BuuxsCh1EUZcAIz8+kYmBp/LrQuloy6K1f3a0M7+IhmZ7QnkISA==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/@vue/compiler-core/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, + "node_modules/@vue/compiler-dom": { + "version": "3.4.36", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.36.tgz", + "integrity": "sha512-eEIjy4GwwZTFon/Y+WO8tRRNGqylaRlA79T1RLhUpkOzJ7EtZkkb8MurNfkqY6x6Qiu0R7ESspEF7GkPR/4yYg==", + "dependencies": { + "@vue/compiler-core": "3.4.36", + "@vue/shared": "3.4.36" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.4.36", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.36.tgz", + "integrity": "sha512-rhuHu7qztt/rNH90dXPTzhB7hLQT2OC4s4GrPVqmzVgPY4XBlfWmcWzn4bIPEWNImt0CjO7kfHAf/1UXOtx3vw==", + "dependencies": { + "@babel/parser": "^7.24.7", + "@vue/compiler-core": "3.4.36", + "@vue/compiler-dom": "3.4.36", + "@vue/compiler-ssr": "3.4.36", + "@vue/shared": "3.4.36", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.10", + "postcss": "^8.4.40", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/compiler-sfc/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.4.36", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.36.tgz", + "integrity": "sha512-Wt1zyheF0zVvRJyhY74uxQbnkXV2Le/JPOrAxooR4rFYKC7cFr+cRqW6RU3cM/bsTy7sdZ83IDuy/gLPSfPGng==", + "dependencies": { + "@vue/compiler-dom": "3.4.36", + "@vue/shared": "3.4.36" + } + }, + "node_modules/@vue/compiler-vue2": { + "version": "2.7.16", + "resolved": "https://registry.npmjs.org/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz", + "integrity": "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==", + "dev": true, + "dependencies": { + "de-indent": "^1.0.2", + "he": "^1.2.0" + } + }, + "node_modules/@vue/devtools-api": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.3.tgz", + "integrity": "sha512-0MiMsFma/HqA6g3KLKn+AGpL1kgKhFWszC9U29NfpWK5LE7bjeXxySWJrOJ77hBz+TBrBQ7o4QJqbPbqbs8rJw==" + }, + "node_modules/@vue/language-core": { + "version": "2.0.29", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-2.0.29.tgz", + "integrity": "sha512-o2qz9JPjhdoVj8D2+9bDXbaI4q2uZTHQA/dbyZT4Bj1FR9viZxDJnLcKVHfxdn6wsOzRgpqIzJEEmSSvgMvDTQ==", + "dev": true, + "dependencies": { + "@volar/language-core": "~2.4.0-alpha.18", + "@vue/compiler-dom": "^3.4.0", + "@vue/compiler-vue2": "^2.7.16", + "@vue/shared": "^3.4.0", + "computeds": "^0.0.1", + "minimatch": "^9.0.3", + "muggle-string": "^0.4.1", + "path-browserify": "^1.0.1" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@vue/reactivity": { + "version": "3.4.36", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.36.tgz", + "integrity": "sha512-wN1aoCwSoqrt1yt8wO0gc13QaC+Vk1o6AoSt584YHNnz6TGDhh1NCMUYgAnvp4HEIkLdGsaC1bvu/P+wpoDEXw==", + "dependencies": { + "@vue/shared": "3.4.36" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.4.36", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.36.tgz", + "integrity": "sha512-9+TR14LAVEerZWLOm/N/sG2DVYhrH2bKgFrbH/FVt/Q8Jdw4OtdcGMRC6Tx8VAo0DA1eqAqrZaX0fbOaOxxZ4A==", + "dependencies": { + "@vue/reactivity": "3.4.36", + "@vue/shared": "3.4.36" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.4.36", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.36.tgz", + "integrity": "sha512-2Qe2fKkLxgZBVvHrG0QMNLL4bsx7Ae88pyXebY2WnQYABpOnGYvA+axMbcF9QwM4yxnsv+aELbC0eiNVns7mGw==", + "dependencies": { + "@vue/reactivity": "3.4.36", + "@vue/runtime-core": "3.4.36", + "@vue/shared": "3.4.36", + "csstype": "^3.1.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.4.36", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.36.tgz", + "integrity": "sha512-2XW90Rq8+Y7S1EIsAuubZVLm0gCU8HYb5mRAruFdwfC3XSOU5/YKePz29csFzsch8hXaY5UHh7ZMddmi1XTJEA==", + "dependencies": { + "@vue/compiler-ssr": "3.4.36", + "@vue/shared": "3.4.36" + }, + "peerDependencies": { + "vue": "3.4.36" + } + }, + "node_modules/@vue/shared": { + "version": "3.4.36", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.36.tgz", + "integrity": "sha512-fdPLStwl1sDfYuUftBaUVn2pIrVFDASYerZSrlBvVBfylObPA1gtcWJHy5Ox8jLEJ524zBibss488Q3SZtU1uA==" + }, "node_modules/acorn": { "version": "8.12.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", @@ -2525,6 +2715,12 @@ "node": ">=4.0.0" } }, + "node_modules/computeds": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/computeds/-/computeds-0.0.1.tgz", + "integrity": "sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==", + "dev": true + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2578,8 +2774,7 @@ "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "node_modules/cypress": { "version": "13.13.2", @@ -2766,6 +2961,12 @@ "integrity": "sha512-Rt2g+nTbLlDWZTwwrIXjy9MeiZmSDI375FvZs72ngxx8PDC6YXOeR3q5LAuPzjZQxhiWdRKac7RKV+YyQYfYIg==", "dev": true }, + "node_modules/de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", + "dev": true + }, "node_modules/debug": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", @@ -3948,6 +4149,15 @@ "node": ">= 0.4" } }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, "node_modules/html-encoding-sniffer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", @@ -4053,6 +4263,15 @@ "@babel/runtime": "^7.23.2" } }, + "node_modules/i18next-vue": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/i18next-vue/-/i18next-vue-4.0.0.tgz", + "integrity": "sha512-yaKWMyFGweyA4EF7JXSGRAvZQ1CJTKjim0iPBsSjFQuuI6lK7cJf6dWK7uO9leB2EnB5JPd8UVtYLTjHXlCVPw==", + "peerDependencies": { + "i18next": ">=23", + "vue": "^3.3.4" + } + }, "node_modules/iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", @@ -4825,7 +5044,6 @@ "version": "0.30.11", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", - "dev": true, "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } @@ -4959,11 +5177,16 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "node_modules/muggle-string": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", + "dev": true + }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "dev": true, "funding": [ { "type": "github", @@ -5154,6 +5377,12 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -5257,8 +5486,7 @@ "node_modules/picocolors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", - "dev": true + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -5290,7 +5518,6 @@ "version": "8.4.41", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==", - "dev": true, "funding": [ { "type": "opencollective", @@ -5914,7 +6141,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -6270,7 +6496,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, "engines": { "node": ">=4" } @@ -6396,7 +6621,7 @@ "version": "5.5.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", - "dev": true, + "devOptional": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -6789,6 +7014,63 @@ "node": ">=0.10.0" } }, + "node_modules/vscode-uri": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", + "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", + "dev": true + }, + "node_modules/vue": { + "version": "3.4.36", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.36.tgz", + "integrity": "sha512-mIFvbLgjODfx3Iy1SrxOsiPpDb8Bo3EU+87ioimOZzZTOp15IEdAels70IjBOLO3ZFlLW5AhdwY4dWbXVQKYow==", + "dependencies": { + "@vue/compiler-dom": "3.4.36", + "@vue/compiler-sfc": "3.4.36", + "@vue/runtime-dom": "3.4.36", + "@vue/server-renderer": "3.4.36", + "@vue/shared": "3.4.36" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-router": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.4.3.tgz", + "integrity": "sha512-sv6wmNKx2j3aqJQDMxLFzs/u/mjA9Z5LCgy6BE0f7yFWMjrPLnS/sPNn8ARY/FXw6byV18EFutn5lTO6+UsV5A==", + "dependencies": { + "@vue/devtools-api": "^6.6.3" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/vue-tsc": { + "version": "2.0.29", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-2.0.29.tgz", + "integrity": "sha512-MHhsfyxO3mYShZCGYNziSbc63x7cQ5g9kvijV7dRe1TTXBRLxXyL0FnXWpUF1xII2mJ86mwYpYsUmMwkmerq7Q==", + "dev": true, + "dependencies": { + "@volar/typescript": "~2.4.0-alpha.18", + "@vue/language-core": "2.0.29", + "semver": "^7.5.4" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": ">=5.0.0" + } + }, "node_modules/w3c-xmlserializer": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", diff --git a/package.json b/package.json index d3dccc5..9247727 100644 --- a/package.json +++ b/package.json @@ -4,27 +4,35 @@ "version": "0.0.0", "type": "module", "scripts": { - "dev": "vite", - "component:serve": "NODE_ENV=production vite", - "build": "tsc && vite build", + "react:dev": "vite --config vite-react.config.ts", + "react:build": "tsc && vite --config vite-react.config.ts build", + "react:component:serve": "NODE_ENV=production vite --config vite-react.config.ts", + "vue:dev": "vite --config vite-vue.config.ts", + "vue:build": "vue-tsc && vite --config vite-vue.config.ts build", + "vue:component:serve": "vite --config vite-vue.config.ts", + "preview": "vite preview", "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0 --ignore-path .gitignore", "lint:fix": "npm run lint -- --fix", - "preview": "vite preview", "test": "vitest", "test:ci": "vitest run --coverage", - "test:component": "start-server-and-test component:serve http://localhost:3030 test:component:open", - "test:component:ci": "start-server-and-test dev http://localhost:3030 test:component:run", + "react:test:component": "start-server-and-test react:component:serve http://localhost:3030 test:component:open", + "react:test:component:ci": "start-server-and-test vue:component:serve http://localhost:3030 test:component:run", + "vue:test:component": "start-server-and-test vue:component:serve http://localhost:3030 test:component:open", + "vue:test:component:ci": "start-server-and-test vue:component:serve http://localhost:3030 test:component:run", "test:component:open": "cypress open --config-file test/component/cypress.config.ts", "test:component:run": "cypress run --config-file test/component/cypress.config.ts" }, "dependencies": { "i18next": "^23.2.11", "i18next-browser-languagedetector": "^8.0.0", + "i18next-vue": "^4.0.0", "piqure": "^2.0.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-i18next": "^15.0.1", - "react-router-dom": "^6.14.2" + "react-router-dom": "^6.14.2", + "vue": "^3.4.36", + "vue-router": "^4.4.3" }, "devDependencies": { "@types/react": "^18.2.17", @@ -33,6 +41,7 @@ "@typescript-eslint/eslint-plugin": "^6.2.0", "@typescript-eslint/parser": "^6.2.0", "@vitejs/plugin-react": "^4.0.1", + "@vitejs/plugin-vue": "^5.1.2", "@vitest/coverage-v8": "^2.0.5", "axios": "^1.4.0", "cypress": "^13.13.2", @@ -45,6 +54,7 @@ "start-server-and-test": "^2.0.0", "typescript": "^5.0.2", "vite": "^5.4.0", - "vitest": "^2.0.5" + "vitest": "^2.0.5", + "vue-tsc": "^2.0.29" } } diff --git a/src/VueMain.vue b/src/VueMain.vue new file mode 100644 index 0000000..fb80c6b --- /dev/null +++ b/src/VueMain.vue @@ -0,0 +1,7 @@ + + diff --git a/src/library/application/LibraryApp.vue b/src/library/application/LibraryApp.vue new file mode 100644 index 0000000..a44ab87 --- /dev/null +++ b/src/library/application/LibraryApp.vue @@ -0,0 +1,3 @@ + diff --git a/src/library/application/LibraryProvider.ts b/src/library/application/libraryProvider.ts similarity index 100% rename from src/library/application/LibraryProvider.ts rename to src/library/application/libraryProvider.ts diff --git a/src/library/application/LibraryRoutes.tsx b/src/library/application/libraryReactRoutes.tsx similarity index 91% rename from src/library/application/LibraryRoutes.tsx rename to src/library/application/libraryReactRoutes.tsx index 1dbb45d..058cb05 100644 --- a/src/library/application/LibraryRoutes.tsx +++ b/src/library/application/libraryReactRoutes.tsx @@ -8,7 +8,7 @@ const BooksPage = () => { return ; }; -export const libraryRoutes: RouteObject = { +export const libraryReactRoutes: RouteObject = { path: '/', element: , children: [ diff --git a/src/library/application/libraryVueRoutes.ts b/src/library/application/libraryVueRoutes.ts new file mode 100644 index 0000000..062e517 --- /dev/null +++ b/src/library/application/libraryVueRoutes.ts @@ -0,0 +1,17 @@ +import { RouteRecordRaw } from 'vue-router'; +import BookComponent from '@/library/infrastructure/primary/BookComponent.vue'; +import { ISBN } from '@/library/domain/ISBN.ts'; +import LibraryApp from "@/library/application/LibraryApp.vue"; + +export const libraryVueRoutes = + { + path: '/', + component: LibraryApp, + children: [ + { + path: 'book/:isbn', + component: BookComponent, + props: route => ({ isbn: ISBN.of(route.params['isbn'] as string) }), + } + ] + } satisfies RouteRecordRaw; diff --git a/src/library/index.tsx b/src/library/index.tsx deleted file mode 100644 index 3129646..0000000 --- a/src/library/index.tsx +++ /dev/null @@ -1,4 +0,0 @@ -export { libraryProvider } from './application/LibraryProvider.ts'; -export { libraryRoutes } from './application/LibraryRoutes.tsx'; - -export { libraryTranslations } from '@/library/application/language/LibraryTranslations.ts'; diff --git a/src/library/infrastructure/primary/BookComponent.vue b/src/library/infrastructure/primary/BookComponent.vue new file mode 100644 index 0000000..501a576 --- /dev/null +++ b/src/library/infrastructure/primary/BookComponent.vue @@ -0,0 +1,52 @@ + + + diff --git a/src/library/infrastructure/primary/BookInfoComponent.vue b/src/library/infrastructure/primary/BookInfoComponent.vue new file mode 100644 index 0000000..d2e78cc --- /dev/null +++ b/src/library/infrastructure/primary/BookInfoComponent.vue @@ -0,0 +1,29 @@ + + diff --git a/src/library/infrastructure/primary/Loader.ts b/src/library/infrastructure/primary/Loader.ts index 3f57c55..165ac0b 100644 --- a/src/library/infrastructure/primary/Loader.ts +++ b/src/library/infrastructure/primary/Loader.ts @@ -1,8 +1,8 @@ import { ReactElement } from 'react'; -const LoadingInProgress = Symbol(); -const LoadingError = Symbol(); -const LoadingSuccess = Symbol(); +export const LoadingInProgress = Symbol(); +export const LoadingError = Symbol(); +export const LoadingSuccess = Symbol(); type LoadingStatus = typeof LoadingError | typeof LoadingInProgress | typeof LoadingSuccess; @@ -10,17 +10,17 @@ interface LoadWithStatus { status: LoadingStatus; } -interface LoadSuccess extends LoadWithStatus { +export interface LoadSuccess extends LoadWithStatus { content: T; status: typeof LoadingSuccess; } -interface LoadError extends LoadWithStatus { +export interface LoadError extends LoadWithStatus { errorMessage: string; status: typeof LoadingError; } -interface LoadInProgress extends LoadWithStatus { +export interface LoadInProgress extends LoadWithStatus { status: typeof LoadingInProgress; } diff --git a/src/library/react.tsx b/src/library/react.tsx new file mode 100644 index 0000000..3d177b2 --- /dev/null +++ b/src/library/react.tsx @@ -0,0 +1,4 @@ +export { libraryProvider } from '@/library/application/libraryProvider.ts'; +export { libraryReactRoutes } from '@/library/application/libraryReactRoutes.tsx'; + +export { libraryTranslations } from '@/library/application/language/LibraryTranslations.ts'; diff --git a/src/library/vue.ts b/src/library/vue.ts new file mode 100644 index 0000000..adb04b4 --- /dev/null +++ b/src/library/vue.ts @@ -0,0 +1,4 @@ +export { libraryProvider } from './application/libraryProvider.ts'; +export { libraryVueRoutes } from './application/libraryVueRoutes.ts'; + +export { libraryTranslations } from '@/library/application/language/LibraryTranslations.ts'; diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..8818587 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,18 @@ +async function createFor(fwk: string): Promise<() => void> { + if (fwk === 'vue') { + const { createVue } = await import('@/vue.ts'); + return createVue; + } + if (fwk === 'react') { + const { createReact } = await import('@/react.tsx'); + return createReact; + } + throw new Error(`There is no way to create the framework ${fwk}`); +} + +const main = async () => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + await createFor(import.meta.env.VITE_FWK).then(create => create()); +}; + +void main(); diff --git a/src/main.tsx b/src/main.tsx deleted file mode 100644 index afa2674..0000000 --- a/src/main.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import React from 'react'; -import ReactDOM from 'react-dom/client'; -import { createBrowserRouter, RouterProvider } from 'react-router-dom'; -import i18n from 'i18next'; -import { initReactI18next } from 'react-i18next'; -import LanguageDetector from 'i18next-browser-languagedetector'; -import { toTranslationResources } from '@/Translations.ts'; -import { staticRoutes, staticTranslations } from '@/static'; -import { libraryProvider, libraryRoutes, libraryTranslations } from '@/library'; -import { modalProvider, ModalArea } from '@/modal'; - -const router = createBrowserRouter([libraryRoutes, ...staticRoutes]); - -void i18n - .use(initReactI18next) - .use(LanguageDetector) - .init({ - resources: toTranslationResources(staticTranslations, libraryTranslations), - fallbackLng: 'en', - interpolation: { - escapeValue: false, - }, - }); - -modalProvider(); -libraryProvider(); - -ReactDOM.createRoot(document.getElementById('root')!).render( - - - - -); diff --git a/src/modal/ModalAction.ts b/src/modal/ModalAction.ts index c6a4418..3f433da 100644 --- a/src/modal/ModalAction.ts +++ b/src/modal/ModalAction.ts @@ -1,9 +1,7 @@ -import { ReactNode } from 'react'; - -export class ModalAction { +export class ModalAction { constructor(private readonly doc: Document) {} - open(component: ReactNode) { + open(component: C) { const modalOpen = new CustomEvent('modal.open', { detail: component }); this.doc.dispatchEvent(modalOpen); } diff --git a/src/modal/ModalKey.ts b/src/modal/ModalKey.ts deleted file mode 100644 index 343256d..0000000 --- a/src/modal/ModalKey.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { key } from 'piqure'; -import { ModalAction } from '@/modal/ModalAction.ts'; -import { ModalListen } from '@/modal/ModalListen.ts'; - -export const MODAL_ACTION = key('Modal action'); -export const MODAL_LISTEN = key('Modal listen'); diff --git a/src/modal/ModalListen.ts b/src/modal/ModalListen.ts index 50f6425..3de4a53 100644 --- a/src/modal/ModalListen.ts +++ b/src/modal/ModalListen.ts @@ -1,11 +1,10 @@ -import { ReactNode } from 'react'; -export class ModalListen { +export class ModalListen { constructor(private readonly doc: Document) {} - onOpen(opened: (component: ReactNode) => void): void { + onOpen(opened: (component: T) => void): void { this.doc.addEventListener('modal.open', event => { - const custom = event as CustomEvent; + const custom = event as CustomEvent; opened(custom.detail); }); } diff --git a/src/modal/ModalProvider.ts b/src/modal/ModalProvider.ts deleted file mode 100644 index 1d481f8..0000000 --- a/src/modal/ModalProvider.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { provide } from '@/injections.ts'; -import { MODAL_ACTION, MODAL_LISTEN } from '@/modal/ModalKey.ts'; -import { ModalAction } from '@/modal/ModalAction.ts'; -import { ModalListen } from '@/modal/ModalListen.ts'; - -export const modalProvider = (): void => { - provide(MODAL_ACTION, new ModalAction(document)); - provide(MODAL_LISTEN, new ModalListen(document)); -}; diff --git a/src/modal/ModalArea.tsx b/src/modal/ReactModalArea.tsx similarity index 75% rename from src/modal/ModalArea.tsx rename to src/modal/ReactModalArea.tsx index 794f7c8..cfe43a3 100644 --- a/src/modal/ModalArea.tsx +++ b/src/modal/ReactModalArea.tsx @@ -1,10 +1,10 @@ import { inject } from '@/injections.ts'; -import { MODAL_ACTION, MODAL_LISTEN } from '@/modal/ModalKey.ts'; +import { REACT_MODAL_ACTION, REACT_MODAL_LISTEN } from '@/modal/ReactModalKey.ts'; import { ReactNode, useEffect, useState } from 'react'; -export const ModalArea = () => { - const modal = inject(MODAL_LISTEN); - const modalAction = inject(MODAL_ACTION); +export const ReactModalArea = () => { + const modal = inject(REACT_MODAL_LISTEN); + const modalAction = inject(REACT_MODAL_ACTION); const [body, setBody] = useState(); const [opened, setOpened] = useState(false); diff --git a/src/modal/ReactModalKey.ts b/src/modal/ReactModalKey.ts new file mode 100644 index 0000000..cb78a22 --- /dev/null +++ b/src/modal/ReactModalKey.ts @@ -0,0 +1,7 @@ +import { key } from 'piqure'; +import { ModalAction } from '@/modal/ModalAction.ts'; +import { ModalListen } from '@/modal/ModalListen.ts'; +import {ReactNode} from "react"; + +export const REACT_MODAL_ACTION = key>('Modal action'); +export const REACT_MODAL_LISTEN = key>('Modal listen'); diff --git a/src/modal/VueModalArea.vue b/src/modal/VueModalArea.vue new file mode 100644 index 0000000..70991ac --- /dev/null +++ b/src/modal/VueModalArea.vue @@ -0,0 +1,40 @@ + + + diff --git a/src/modal/VueModalKey.ts b/src/modal/VueModalKey.ts new file mode 100644 index 0000000..ddfd854 --- /dev/null +++ b/src/modal/VueModalKey.ts @@ -0,0 +1,7 @@ +import { key } from 'piqure'; +import { ModalAction } from '@/modal/ModalAction.ts'; +import { ModalListen } from '@/modal/ModalListen.ts'; +import {Component} from "vue"; + +export const VUE_MODAL_ACTION = key>('Modal action'); +export const VUE_MODAL_LISTEN = key>('Modal listen'); diff --git a/src/modal/index.ts b/src/modal/index.ts deleted file mode 100644 index 3e3eb4d..0000000 --- a/src/modal/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { modalProvider } from './ModalProvider.ts'; -export { ModalArea } from './ModalArea.tsx'; -export { MODAL_ACTION } from '@/modal/ModalKey.ts'; diff --git a/src/modal/react.ts b/src/modal/react.ts new file mode 100644 index 0000000..7ba28de --- /dev/null +++ b/src/modal/react.ts @@ -0,0 +1,3 @@ +export { reactModalProvider } from './reactModalProvider.ts'; +export { ReactModalArea } from './ReactModalArea.tsx'; +export { REACT_MODAL_ACTION } from '@/modal/ReactModalKey.ts'; diff --git a/src/modal/reactModalProvider.ts b/src/modal/reactModalProvider.ts new file mode 100644 index 0000000..ddc177a --- /dev/null +++ b/src/modal/reactModalProvider.ts @@ -0,0 +1,9 @@ +import { provide } from '@/injections.ts'; +import { REACT_MODAL_ACTION, REACT_MODAL_LISTEN } from '@/modal/ReactModalKey.ts'; +import { ModalAction } from '@/modal/ModalAction.ts'; +import { ModalListen } from '@/modal/ModalListen.ts'; + +export const reactModalProvider = (): void => { + provide(REACT_MODAL_ACTION, new ModalAction(document)); + provide(REACT_MODAL_LISTEN, new ModalListen(document)); +}; diff --git a/src/modal/vue.ts b/src/modal/vue.ts new file mode 100644 index 0000000..cfa05fc --- /dev/null +++ b/src/modal/vue.ts @@ -0,0 +1,6 @@ +export { vueModalProvider } from './vueModalProvider.ts'; + +import VueModalArea from "@/modal/VueModalArea.vue"; +export { VueModalArea }; + +export { VUE_MODAL_ACTION } from '@/modal/VueModalKey.ts'; diff --git a/src/modal/vueModalProvider.ts b/src/modal/vueModalProvider.ts new file mode 100644 index 0000000..4a6eb4d --- /dev/null +++ b/src/modal/vueModalProvider.ts @@ -0,0 +1,10 @@ +import { provide } from '@/injections.ts'; +import { ModalAction } from '@/modal/ModalAction.ts'; +import { ModalListen } from '@/modal/ModalListen.ts'; +import {VUE_MODAL_ACTION} from "@/modal/vue.ts"; +import {VUE_MODAL_LISTEN} from "@/modal/VueModalKey.ts"; + +export const vueModalProvider = (): void => { + provide(VUE_MODAL_ACTION, new ModalAction(document)); + provide(VUE_MODAL_LISTEN, new ModalListen(document)); +}; diff --git a/src/react.tsx b/src/react.tsx new file mode 100644 index 0000000..23cd4bf --- /dev/null +++ b/src/react.tsx @@ -0,0 +1,35 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import { createBrowserRouter, RouterProvider } from 'react-router-dom'; +import i18n from 'i18next'; +import { initReactI18next } from 'react-i18next'; +import LanguageDetector from 'i18next-browser-languagedetector'; +import { toTranslationResources } from '@/Translations.ts'; +import { staticReactRoutes, staticTranslations } from '@/static/react'; +import { libraryProvider, libraryReactRoutes, libraryTranslations } from '@/library/react.tsx'; +import { reactModalProvider, ReactModalArea } from '@/modal/react'; + +export const createReact = () => { + const router = createBrowserRouter([libraryReactRoutes, ...staticReactRoutes]); + + void i18n + .use(initReactI18next) + .use(LanguageDetector) + .init({ + resources: toTranslationResources(staticTranslations, libraryTranslations), + fallbackLng: 'en', + interpolation: { + escapeValue: false, + }, + }); + + reactModalProvider(); + libraryProvider(); + + ReactDOM.createRoot(document.getElementById('app')!).render( + + + + + ); +}; diff --git a/src/static/ContactComponent.vue b/src/static/ContactComponent.vue new file mode 100644 index 0000000..543448a --- /dev/null +++ b/src/static/ContactComponent.vue @@ -0,0 +1,10 @@ + + + diff --git a/src/static/about/About.tsx b/src/static/about/About.tsx index 85566a8..34d340a 100644 --- a/src/static/about/About.tsx +++ b/src/static/about/About.tsx @@ -1,13 +1,13 @@ import { useTranslation } from 'react-i18next'; import { inject } from '@/injections.ts'; -import { MODAL_ACTION } from '@/modal'; +import { REACT_MODAL_ACTION } from '@/modal/react'; import { MoreInfo } from '@/static/about/MoreInfo.tsx'; import { CGU } from '@/static/about/CGU.tsx'; export const About = () => { const { t } = useTranslation(); - const modal = inject(MODAL_ACTION); + const modal = inject(REACT_MODAL_ACTION); const moreInfo = () => { modal.open(); diff --git a/src/static/about/AboutComponent.vue b/src/static/about/AboutComponent.vue new file mode 100644 index 0000000..49b7ff5 --- /dev/null +++ b/src/static/about/AboutComponent.vue @@ -0,0 +1,40 @@ + + + diff --git a/src/static/about/CGUComponent.vue b/src/static/about/CGUComponent.vue new file mode 100644 index 0000000..a84d6b3 --- /dev/null +++ b/src/static/about/CGUComponent.vue @@ -0,0 +1,9 @@ + + + diff --git a/src/static/about/MoreInfoComponent.vue b/src/static/about/MoreInfoComponent.vue new file mode 100644 index 0000000..7b8c89c --- /dev/null +++ b/src/static/about/MoreInfoComponent.vue @@ -0,0 +1,9 @@ + + + diff --git a/src/static/index.ts b/src/static/index.ts deleted file mode 100644 index a4ac588..0000000 --- a/src/static/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { staticRoutes } from './StaticRoutes.tsx'; -export { staticTranslations } from './language/StaticTranslations.ts'; diff --git a/src/static/language/StaticTranslations.ts b/src/static/language/staticTranslations.ts similarity index 100% rename from src/static/language/StaticTranslations.ts rename to src/static/language/staticTranslations.ts diff --git a/src/static/react.ts b/src/static/react.ts new file mode 100644 index 0000000..445e0b6 --- /dev/null +++ b/src/static/react.ts @@ -0,0 +1,2 @@ +export { staticReactRoutes } from './staticReactRoutes.tsx'; +export { staticTranslations } from './language/staticTranslations.ts'; diff --git a/src/static/StaticRoutes.tsx b/src/static/staticReactRoutes.tsx similarity index 83% rename from src/static/StaticRoutes.tsx rename to src/static/staticReactRoutes.tsx index 83e1745..9d7ff19 100644 --- a/src/static/StaticRoutes.tsx +++ b/src/static/staticReactRoutes.tsx @@ -2,7 +2,7 @@ import { RouteObject } from 'react-router-dom'; import { About } from '@/static/about/About.tsx'; import { Contact } from '@/static/Contact.tsx'; -export const staticRoutes: RouteObject[] = [ +export const staticReactRoutes: RouteObject[] = [ { path: '/about', element: , diff --git a/src/static/staticVueRoutes.ts b/src/static/staticVueRoutes.ts new file mode 100644 index 0000000..d7c8080 --- /dev/null +++ b/src/static/staticVueRoutes.ts @@ -0,0 +1,14 @@ +import {RouteRecordRaw} from "vue-router"; +import ContactComponent from "@/static/ContactComponent.vue"; +import AboutComponent from "@/static/about/AboutComponent.vue"; + +export const staticVueRoutes = [ + { + path: '/about', + component: AboutComponent, + }, + { + path: '/contact', + component: ContactComponent, + } +] satisfies RouteRecordRaw[]; diff --git a/src/static/vue.ts b/src/static/vue.ts new file mode 100644 index 0000000..c4e1094 --- /dev/null +++ b/src/static/vue.ts @@ -0,0 +1,2 @@ +export { staticVueRoutes } from './staticVueRoutes.ts'; +export { staticTranslations } from './language/staticTranslations.ts'; diff --git a/src/vue.ts b/src/vue.ts new file mode 100644 index 0000000..4de48e9 --- /dev/null +++ b/src/vue.ts @@ -0,0 +1,30 @@ +import { createApp } from 'vue'; +import VueMain from './VueMain.vue'; +import {libraryProvider, libraryTranslations, libraryVueRoutes} from '@/library/vue'; +import { createRouter, createWebHistory } from 'vue-router'; +import i18next from 'i18next'; +import I18NextVue from 'i18next-vue'; +import { toTranslationResources } from '@/Translations.ts'; +import LanguageDetector from 'i18next-browser-languagedetector'; +import {staticTranslations, staticVueRoutes} from "@/static/vue.ts"; +import {vueModalProvider} from "@/modal/vue.ts"; + +export const createVue = () => { + const router = createRouter({ + history: createWebHistory(), + routes: [libraryVueRoutes, ...staticVueRoutes], + }); + + void i18next.use(LanguageDetector).init({ + resources: toTranslationResources(staticTranslations, libraryTranslations), + fallbackLng: 'en', + interpolation: { + escapeValue: false, + }, + }); + + vueModalProvider(); + libraryProvider(); + + createApp(VueMain).use(router).use(I18NextVue, { i18next }).mount('#app'); +}; diff --git a/test/component/spec/library/library.spec.ts b/test/component/spec/library/library.spec.ts index ea69a7a..e451f27 100644 --- a/test/component/spec/library/library.spec.ts +++ b/test/component/spec/library/library.spec.ts @@ -80,7 +80,7 @@ describe('Library', () => { cy.contains(dataSelector('book.label.title'), 'Title: '); }); - it.only('Should have french labels', () => { + it('Should have french labels', () => { stubOpenLibraryIsbn(); cy.visit('/book/9780321125217', loadLanguage('fr')); diff --git a/tsconfig.app.json b/tsconfig.app.json new file mode 100644 index 0000000..938a7db --- /dev/null +++ b/tsconfig.app.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "preserve", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"] +} diff --git a/tsconfig.json b/tsconfig.json index 2a27e96..1ffef60 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,24 +1,7 @@ { - "compilerOptions": { - "target": "ES2020", - "useDefineForClassFields": true, - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "module": "ESNext", - "skipLibCheck": true, - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "react-jsx", - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true, - "paths": { - "@/*": ["./src/*"] - } - }, - "include": ["src"], - "references": [{ "path": "./tsconfig.node.json" }] + "files": [], + "references": [ + { "path": "./tsconfig.app.json" }, + { "path": "./tsconfig.node.json" } + ] } diff --git a/tsconfig.lint.json b/tsconfig.lint.json deleted file mode 100644 index d5c782d..0000000 --- a/tsconfig.lint.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "extends": "./tsconfig.json", - "include": ["*.ts", "src", "test"] -} diff --git a/tsconfig.node.json b/tsconfig.node.json index 42872c5..3e00f47 100644 --- a/tsconfig.node.json +++ b/tsconfig.node.json @@ -1,10 +1,22 @@ { "compilerOptions": { - "composite": true, - "skipLibCheck": true, + "target": "ES2022", + "lib": ["ES2023"], "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ "moduleResolution": "bundler", - "allowSyntheticDefaultImports": true + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true }, - "include": ["vite.config.ts"] + "include": ["vite-vue.config.ts"] } diff --git a/vite.config.ts b/vite-react.config.ts similarity index 70% rename from vite.config.ts rename to vite-react.config.ts index b5c6959..55d2b78 100644 --- a/vite.config.ts +++ b/vite-react.config.ts @@ -11,4 +11,10 @@ export default defineConfig({ server: { port: 3030, }, + envDir: path.resolve(__dirname, 'config', 'react'), + build: { + rollupOptions: { + external: [new RegExp(/\.vue/)], + }, + }, }); diff --git a/vite-vue.config.ts b/vite-vue.config.ts new file mode 100644 index 0000000..706d5ac --- /dev/null +++ b/vite-vue.config.ts @@ -0,0 +1,15 @@ +import { defineConfig } from 'vite'; +import vue from '@vitejs/plugin-vue'; +import * as path from 'path'; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [vue()], + resolve: { + alias: [{ find: '@', replacement: path.resolve(__dirname, 'src') }], + }, + server: { + port: 3030, + }, + envDir: path.resolve(__dirname, 'config', 'vue'), +});