From e397fae928b6ec411de9ab614473879a6bc1bc0e Mon Sep 17 00:00:00 2001 From: chunyu <12914@example.com> Date: Tue, 15 Sep 2026 15:26:56 +0800 Subject: [PATCH] =?UTF-8?q?feat(C-05)=EF=BC=9ASEO=E9=A2=84=E6=B8=B2?= =?UTF-8?q?=E6=9F=93+=E4=BE=9D=E8=B5=96=E7=98=A6=E8=BA=AB+i18n=E8=A1=A5?= =?UTF-8?q?=E9=BD=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit build链追加seo预渲染(19工具页静态HTML+sitemap+robots)与seo:check验收;剔除chakra/emotion/@types/qrcode死依赖(pnpm-lock同步,手写qrcode.d.ts顶上);6语言locales补齐新功能文案。附带vite/nginx代理段与C-01同口径微调。e01-visual.spec.ts仅归档不跑(需8756/5173真机)。 --- package.json | 4 +- pnpm-lock.yaml | 1359 +------------------------------------ scripts/check_seo.mjs | 79 +++ scripts/seo_prerender.mjs | 132 ++++ src/locales/en.json | 346 +++++++++- src/locales/ja.json | 346 +++++++++- src/locales/ko.json | 38 +- src/locales/ru.json | 346 +++++++++- src/locales/zh-TW.json | 38 +- src/locales/zh.json | 442 +++++++++--- src/qrcode.d.ts | 17 + tests/e01-visual.spec.ts | 32 + 12 files changed, 1635 insertions(+), 1544 deletions(-) create mode 100644 scripts/check_seo.mjs create mode 100644 scripts/seo_prerender.mjs create mode 100644 src/qrcode.d.ts create mode 100644 tests/e01-visual.spec.ts diff --git a/package.json b/package.json index 9b09e22..7febf1f 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,9 @@ "type": "module", "scripts": { "dev": "vite --host :: --port 5173", - "build": "tsc -b && vite build", + "build": "tsc -b && vite build && node scripts/seo_prerender.mjs", + "seo": "node scripts/seo_prerender.mjs", + "seo:check": "node scripts/check_seo.mjs", "lint": "eslint .", "preview": "vite preview" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 04ba6a1..5743108 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,18 +11,9 @@ importers: '@ant-design/icons': specifier: 6.x version: 6.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@chakra-ui/react': - specifier: ^3.34.0 - version: 3.34.0(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4)(supports-color@7.2.0))(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@emotion/react': - specifier: ^11.14.0 - version: 11.14.0(@types/react@19.2.14)(react@19.2.4)(supports-color@7.2.0) '@reduxjs/toolkit': specifier: ^2.11.2 version: 2.11.2(react-redux@9.2.0(@types/react@19.2.14)(react@19.2.4)(redux@5.0.1))(react@19.2.4) - '@types/qrcode': - specifier: ^1.5.6 - version: 1.5.6 antd: specifier: ^6.3.5 version: 6.3.5(date-fns@2.30.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -50,15 +41,9 @@ importers: katex: specifier: ^0.16.44 version: 0.16.44 - next-themes: - specifier: ^0.4.6 - version: 0.4.6(react-dom@19.2.4(react@19.2.4))(react@19.2.4) qrcode: specifier: ^1.5.4 version: 1.5.4 - qrcode.react: - specifier: ^4.2.0 - version: 4.2.0(react@19.2.4) react: specifier: ^19.2.4 version: 19.2.4 @@ -74,9 +59,6 @@ importers: react-json-tree: specifier: ^0.20.0 version: 0.20.0(@types/react@19.2.14)(react@19.2.4) - react-lorem-ipsum: - specifier: ^1.4.10 - version: 1.4.10 react-markdown: specifier: ^10.1.0 version: 10.1.0(@types/react@19.2.14)(react@19.2.4)(supports-color@7.2.0) @@ -86,9 +68,6 @@ importers: react-router-dom: specifier: ^7.14.0 version: 7.14.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react-syntax-highlighter: - specifier: ^16.1.1 - version: 16.1.1(react@19.2.4) rehype-highlight: specifier: ^7.0.2 version: 7.0.2 @@ -101,9 +80,6 @@ importers: remark-math: specifier: ^6.0.0 version: 6.0.0(supports-color@7.2.0) - zustand: - specifier: ^5.0.12 - version: 5.0.12(@types/react@19.2.14)(immer@11.1.4)(react@19.2.4)(use-sync-external-store@1.6.0(react@19.2.4)) devDependencies: '@eslint/js': specifier: ^9.39.4 @@ -123,9 +99,6 @@ importers: '@types/react-dom': specifier: ^19.2.3 version: 19.2.3(@types/react@19.2.14) - '@types/react-syntax-highlighter': - specifier: ^15.5.13 - version: 15.5.13 '@vitejs/plugin-react': specifier: ^6.0.1 version: 6.0.1(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@24.12.0)) @@ -188,12 +161,6 @@ packages: react: ^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - '@ark-ui/react@5.35.0': - resolution: {integrity: sha512-W1HcL5obYT2QftSiOP8rChJezoDsZNU+nH6pdib1+zScMm/oYAkxanHQfCCfnOhAGNpbhfUAmTm118+ggtgboQ==} - peerDependencies: - react: '>=18.0.0' - react-dom: '>=18.0.0' - '@babel/code-frame@7.29.0': resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} engines: {node: '>=6.9.0'} @@ -265,13 +232,6 @@ packages: resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} - '@chakra-ui/react@3.34.0': - resolution: {integrity: sha512-VLhpVwv5IVxhwajO10KnS1VQT4hDqQMQP/A796Ya+uVu8AdoSX+5HHyTLTkYIeXIDMe0xLqJfov04OBKbBchJA==} - peerDependencies: - '@emotion/react': '>=11' - react: '>=18' - react-dom: '>=18' - '@emnapi/core@1.9.1': resolution: {integrity: sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA==} @@ -281,56 +241,12 @@ packages: '@emnapi/wasi-threads@1.2.0': resolution: {integrity: sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg==} - '@emotion/babel-plugin@11.13.5': - resolution: {integrity: sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==} - - '@emotion/cache@11.14.0': - resolution: {integrity: sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==} - '@emotion/hash@0.8.0': resolution: {integrity: sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==} - '@emotion/hash@0.9.2': - resolution: {integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==} - - '@emotion/is-prop-valid@1.4.0': - resolution: {integrity: sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw==} - - '@emotion/memoize@0.9.0': - resolution: {integrity: sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==} - - '@emotion/react@11.14.0': - resolution: {integrity: sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==} - peerDependencies: - '@types/react': '*' - react: '>=16.8.0' - peerDependenciesMeta: - '@types/react': - optional: true - - '@emotion/serialize@1.3.3': - resolution: {integrity: sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==} - - '@emotion/sheet@1.4.0': - resolution: {integrity: sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==} - - '@emotion/unitless@0.10.0': - resolution: {integrity: sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==} - '@emotion/unitless@0.7.5': resolution: {integrity: sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==} - '@emotion/use-insertion-effect-with-fallbacks@1.2.0': - resolution: {integrity: sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==} - peerDependencies: - react: '>=16.8.0' - - '@emotion/utils@1.4.2': - resolution: {integrity: sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==} - - '@emotion/weak-memoize@0.4.0': - resolution: {integrity: sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==} - '@eslint-community/eslint-utils@4.9.1': resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -369,15 +285,6 @@ packages: resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@floating-ui/core@1.7.5': - resolution: {integrity: sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==} - - '@floating-ui/dom@1.7.6': - resolution: {integrity: sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==} - - '@floating-ui/utils@0.2.11': - resolution: {integrity: sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==} - '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} @@ -394,12 +301,6 @@ packages: resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} - '@internationalized/date@3.12.0': - resolution: {integrity: sha512-/PyIMzK29jtXaGU23qTvNZxvBXRtKbNnGDFD+PY6CZw/Y8Ex8pFUzkuCJCG9aOqmShjqhS9mPqP6Dk5onQY8rQ==} - - '@internationalized/number@3.6.5': - resolution: {integrity: sha512-6hY4Kl4HPBvtfS62asS/R22JzNNy8vi/Ssev7x6EobfCp+9QIB2hKvI2EtbdJ0VSQacxVNtqhE/NmF/NZ0gm6g==} - '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} @@ -425,9 +326,6 @@ packages: '@oxc-project/types@0.122.0': resolution: {integrity: sha512-oLAl5kBpV4w69UtFZ9xqcmTi+GENWOcPF7FCrczTiBbmC0ibXxCwyvZGbO39rCVEuLGAZM84DH0pUIyyv/YJzA==} - '@pandacss/is-valid-prop@1.9.1': - resolution: {integrity: sha512-G4UHGPbyDR8UnxITHLiv8h88KWEAAs8NBX8yXLeb98ny2GEEhS3RBMK1Lq/tpNwwWimgLXxHfATyUkzqfgLjtg==} - '@playwright/test@1.60.0': resolution: {integrity: sha512-O71yZIbAh/PxDMNGns37GHBIfrVkEVyn+AXyIa5dOTfb4/xNvRWV+Vv/NMbNCtODB/pO7vLlF2OTmMVLhmr7Ag==} engines: {node: '>=18'} @@ -834,9 +732,6 @@ packages: '@standard-schema/utils@0.3.0': resolution: {integrity: sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==} - '@swc/helpers@0.5.20': - resolution: {integrity: sha512-2egEBHUMasdypIzrprsu8g+OEVd7Vp2MM3a2eVlM/cyFYto0nGz5BX5BTgh/ShZZI9ed+ozEq+Ngt+rgmUs8tw==} - '@tybys/wasm-util@0.10.1': resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} @@ -874,23 +769,11 @@ packages: '@types/node@24.12.0': resolution: {integrity: sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==} - '@types/parse-json@4.0.2': - resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} - - '@types/prismjs@1.26.6': - resolution: {integrity: sha512-vqlvI7qlMvcCBbVe0AKAb4f97//Hy0EBTaiW8AalRnG/xAN5zOiWWyrNqNXeq8+KAuvRewjCVY1+IPxk4RdNYw==} - - '@types/qrcode@1.5.6': - resolution: {integrity: sha512-te7NQcV2BOvdj2b1hCAHzAoMNuj65kNBMz0KBaxM6c3VGBOhU0dURQKOtH8CFNI/dsKkwlv32p26qYQTWoB5bw==} - '@types/react-dom@19.2.3': resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} peerDependencies: '@types/react': ^19.2.0 - '@types/react-syntax-highlighter@15.5.13': - resolution: {integrity: sha512-uLGJ87j6Sz8UaBAooU0T6lWJ0dBmjZgN1PZTrj05TNql2/XpC6+4HhMT5syIdFUUt+FASfCeLLv4kBygNU+8qA==} - '@types/react@19.2.14': resolution: {integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==} @@ -982,235 +865,6 @@ packages: babel-plugin-react-compiler: optional: true - '@zag-js/accordion@1.38.2': - resolution: {integrity: sha512-lr3K8R4c8cY1ghcU4lpav4dAXCFqFcNOrieqy4lsS5n5CSrpLbL1EFrOdTBux/CCeijmipFp14ddUZGHWHIDJQ==} - - '@zag-js/anatomy@1.38.2': - resolution: {integrity: sha512-3wEwuHkHiErD1r36MrC1Jd4lqvQK+wQ5EgqdEk8r3L2koD7fTdq8CB5KbMcP0JM08eFCOo2CBl3gP3VBmiTNJA==} - - '@zag-js/angle-slider@1.38.2': - resolution: {integrity: sha512-VugKx/iClEiHA5AXY/d2zZzfpgAHD2hyV7f0k3FzuLIsgeJmZDTc3YNMX2BCrcbD8qNrambO3e2b31mMt1HxFg==} - - '@zag-js/aria-hidden@1.38.2': - resolution: {integrity: sha512-TvMdHUouslt6RZmKZ6k41B1KTqjOFaD4T6c4sTb6qSUkuTYgyYsA7ZqimiR0vcvmmG852nSaOepvr6Jj0sRPNA==} - - '@zag-js/async-list@1.38.2': - resolution: {integrity: sha512-URi5Wl0uJ4TJ/MFh5IKAsLKSb21e9tTPegZ7Vvr1XO5tWd9neY3nwVYImHq93Tv1nwhkttdOvUTKdnwlpr9NiQ==} - - '@zag-js/auto-resize@1.38.2': - resolution: {integrity: sha512-0nVYusVmxDfa1j8fyycQCxcULT07BUM+23BlEslPy0Hfzt5c7CwMQFan4JiMia82RzgnWv3s+5svVMvI++ZZqw==} - - '@zag-js/avatar@1.38.2': - resolution: {integrity: sha512-DmhoaJG+IcKFSWSrtfcI91WJNSJQx2PYDmChnOtNvyGIXibNHkoYXzvZTCrKsVGgKeUXFtOxSqSYMbzxgL2k2Q==} - - '@zag-js/carousel@1.38.2': - resolution: {integrity: sha512-/edO3DYuJ23znbR1LhxWKQeIAkd/VkSPFY5vNWKA879FWLjAf5ZWAGe+jKXayAOaWqcTFKp9uCUSbesO5eFiDg==} - - '@zag-js/cascade-select@1.38.2': - resolution: {integrity: sha512-5NONGij0U5utqgv1lFeWz+WZYcoa9nhI+EU0XGojJ5VUTZbQVgxWeS8WDxcpneT29n1xqQkmv+6SZ3fYcBDkxA==} - - '@zag-js/checkbox@1.38.2': - resolution: {integrity: sha512-AAljBvGog/jLWhdEFc2ADzsGODoGua8fWZs0RUYq/wQ9UBiG4w5VRyPAq5ZEzaIoSruoHm5AHN9D9VdWN9py3g==} - - '@zag-js/clipboard@1.38.2': - resolution: {integrity: sha512-LIDcuZDU70cvMAbIz7LgeXM+CvhRW8Ez84UPkorwT+EyDCOaCNEADabSY2AM4WKn81EV56UKkwSNblkhP3gmZA==} - - '@zag-js/collapsible@1.38.2': - resolution: {integrity: sha512-7yBlX/9d/A7Da/9PZoBye0nA+FjVZv7rjrUfmO2NhoERt2IV6r0S143DrwcW3ELjz+76HzV+wlP8ytruqaK1gQ==} - - '@zag-js/collection@1.38.2': - resolution: {integrity: sha512-1Edek5yrjHfpmciK4M5PoUbDFRgEEkFh3HMIwWjMRdcRzea9ibVhSGXvXsenafC/b3so/ApEXBhs1ch7dFn+NQ==} - - '@zag-js/color-picker@1.38.2': - resolution: {integrity: sha512-d2/FBAQ3waAY7T0zhMN5gbz7z2Z5vr3wtyT+qcMfwweeBBQEST8iQMc4JUZgTfZ/V+Uqv/A1L644/IRXq6Jpyg==} - - '@zag-js/color-utils@1.38.2': - resolution: {integrity: sha512-neo0qU1fvIbptrgDMzXI7gz3DSYvxFEf61YskVXJkPGY4u4+unx89j/R1G9wC4lF/pl8kPiTsb7TK7+UnFf5/Q==} - - '@zag-js/combobox@1.38.2': - resolution: {integrity: sha512-J2M1vB3Keepv2Wr/sC5kue18ver+nf/7gj9LgHxSU5sgwl9Fr4wZLPH1s9ZQ7FDhBXjWsitILbf9dqR1UpyLJQ==} - - '@zag-js/core@1.38.2': - resolution: {integrity: sha512-UaRU6TVOJV07phQkToR6fNceJbfPiNLx2itSh78ofHn8w9w860mNrS5tyn8HExuNwY5JVQdfMkyFlMF0LfgVLQ==} - - '@zag-js/date-picker@1.38.2': - resolution: {integrity: sha512-Jhss1wt33YjnMYWUAPMnze3ObkkLJnmqWN2H2fgHEBRQyJScVj+MHWhWPpAXsU2hf70Re19kdPld5vADIfACMA==} - peerDependencies: - '@internationalized/date': '>=3.0.0' - - '@zag-js/date-utils@1.38.2': - resolution: {integrity: sha512-TwyIlBNS4ctx4zMjFTq9IVqSFFiHwv4WeB4hauqrBVARFzj1twE7r9mLFPbpq7FYuqwLuA4b9CaaVv3STukszg==} - peerDependencies: - '@internationalized/date': '>=3.0.0' - - '@zag-js/dialog@1.38.2': - resolution: {integrity: sha512-cVYBXiEnQ30UjudJxODoV8Au/18VyePEvJ9SollGFJYnr+/2mCue5CoraOQJqoZVED3tdUCBodz9kyjS1CcvAw==} - - '@zag-js/dismissable@1.38.2': - resolution: {integrity: sha512-4B83ZGD8YKnwiXwL4J49txeXSPdS29bPt6p00v99u6nJPlQRRubzPUQo4OJr6NxUuT9cIn2kDqt5oj8ZCwhmng==} - - '@zag-js/dom-query@1.38.2': - resolution: {integrity: sha512-E2plmm/bDjMQhi4fmyhw2uhoQv2cgNYaG+fzLrJgepLqovCOTU85lwzaLFiB7ldG2a9DVmjbAnFX4nVVWvaxGA==} - - '@zag-js/drawer@1.38.2': - resolution: {integrity: sha512-QoXYUHKcppju84sOHuOUJVhJpnYcFAOUtV6RSSIwVcUpkAReUE+NmwGviMxqRAmaXZc8yz7QPCm/H55Ywm+d6Q==} - - '@zag-js/editable@1.38.2': - resolution: {integrity: sha512-S4QigLJneTTwR8EE3Nq44e/z/Byo3+4heuWWkBW6UF78EIeFdJrWK7EWzSDvSJTM5/ViEZpCkQElDonoxgzJUA==} - - '@zag-js/file-upload@1.38.2': - resolution: {integrity: sha512-sA5gKafIRDcKc6zsEYrByQQpl2am+ioRzGcuxhwBdOIacJP3G2vs4bJx0wCbdM8O9Ue11s9KBcqfJhenDlBWMg==} - - '@zag-js/file-utils@1.38.2': - resolution: {integrity: sha512-498kXYSlUrNXdjmn0mKfovd7zQv1PnLXhNW94L0DYX7GcAqd6SQ4QohtxbT4IHrzlV9FfskKhe9ahXxV2IlNVQ==} - - '@zag-js/floating-panel@1.38.2': - resolution: {integrity: sha512-awpjnVRML6Q3+q5akA/S/XAu2bWEjIPpdpG+vVE5Ki0HnRsVDOKyFJVJ2+LC0gApx8BzsSWZLXPxZZqbWmr5cA==} - - '@zag-js/focus-trap@1.38.2': - resolution: {integrity: sha512-m1CBTmUy7kHsMVBFlzOmxddxESv7ce6XOX+3YhXKWNJLvnt4a3bWMnh+C3CmV7B14pntTkQwfXJALR6e3gfS6Q==} - - '@zag-js/focus-visible@1.38.2': - resolution: {integrity: sha512-ME0zulSEZLxR9jJqtwDpcWuBnZKO/8xQ+UtuYrJPvqPyUyUVkxFon+jCqNUOGjK4rHB+OjEV19LrHAzq6CQjNg==} - - '@zag-js/highlight-word@1.38.2': - resolution: {integrity: sha512-wIhPX6FBUFyt9gVwH+GnjUtxOP2im8qK6ejW/igvn9L4viLZ3Fmwas2fuaWaLqW6yxo54zDtf9BPG+1rPDbnZQ==} - - '@zag-js/hover-card@1.38.2': - resolution: {integrity: sha512-Un/65bC+ppCktMBd798z7x90t6/kvvqkASxezV6ds0Ex56TB26KQnaRPUASV+fW6uH4nLdBOeGlCH3cC8KEPYg==} - - '@zag-js/i18n-utils@1.38.2': - resolution: {integrity: sha512-/thV2gwDtfubrL8gcBXGiNmQVcHACmYIXneLVW94wVADdsuRKV/s0QrMQXe/QH3f3M9QAU5VWQnoz9Z2ySilGQ==} - - '@zag-js/image-cropper@1.38.2': - resolution: {integrity: sha512-O4u7ub98qkyw7uass5Xr3clJCLWS7yJwTmM+aX+zwCMTVLK1dlZhwVZwrmsRA7FKVKKWJBmpVUd+DzLEwFvZKg==} - - '@zag-js/interact-outside@1.38.2': - resolution: {integrity: sha512-jszzVoozqcO3vn1iiZ726xYXpy/mR+fLnx1tBs4Dvkg/n52Mm3Uv+pFDBfHgswqS/kRJ/U8P0fItFJjOH0yvlA==} - - '@zag-js/json-tree-utils@1.38.2': - resolution: {integrity: sha512-qyUSoFgwDsg9ulMEQ+a3vIos6T2AJBCjBj34U72KjjWcked6nNFs/4Y8bNh9xEdqH82txV0Wkqme8qj2iU3AcA==} - - '@zag-js/listbox@1.38.2': - resolution: {integrity: sha512-gXJJ8ziTyRowkKaQa4sfUJ9TvU7IJdF/0YIACXRUDaZIaEIe7igZfYiasBASQDk4OvRGZzAhxNGceeOa8W8rbQ==} - - '@zag-js/live-region@1.38.2': - resolution: {integrity: sha512-6qVPHEZRPbO/BKUTGXC3otZXODpsRg/lliBHUHzK7Pg83eSW4yGQI+XKRjmJnoWvB7U5vFXDC3SXG3aO0dyLYQ==} - - '@zag-js/marquee@1.38.2': - resolution: {integrity: sha512-z1e6ZPynA1izDpAqgHENrC9PDt+N7Xg5dut4Vzw1w46CForFib5pv+xIRa4DxvUhXpuHCpZ1bDS0+8Hub/5Wlg==} - - '@zag-js/menu@1.38.2': - resolution: {integrity: sha512-n0AO5uz31csUcnk1daHf/O5T2Yqtdo8KV9PInrIxwKXwfeLM2uFTHubhP2bv/j7+R+LpnZkK5laXe9WxKueBVQ==} - - '@zag-js/navigation-menu@1.38.2': - resolution: {integrity: sha512-FDfeixgwrcpC/FxJGzGp+kKgurndCohUuh/lLiNJ5pNId5ThUMr1CNFKGZMcdjhJcNMO+R1hhgyLyuFwtS+kGg==} - - '@zag-js/number-input@1.38.2': - resolution: {integrity: sha512-WJJA6EusT1HGDJlzW9YpbgOJ6Qv3TM1jcBNftrGCLGNhePXBzLzsTZKp+IZdjkI+11bab5siXwU9wcQWUhmUNw==} - - '@zag-js/pagination@1.38.2': - resolution: {integrity: sha512-pqdR7Eek6FFK4EyVRZbxwRymvunguGVAZAHrg0Aij/CnPbZZATDk4gQbGKpIgEywSYSk6m4hurjLg8L+shkfVQ==} - - '@zag-js/password-input@1.38.2': - resolution: {integrity: sha512-kDtuYq77QCzUF9oOGgHzmdlOHAvLj/syMnx+Sb4KEwBAJCIBrpJKymgEUxK4VumySApvI6OMmuCZN9uRvB0HrA==} - - '@zag-js/pin-input@1.38.2': - resolution: {integrity: sha512-kMmlRTOLBqxVaBM4Ly7NZi4VbB5SJUfcmyj6pxHV+YSqzFpuS8/o24CTtbLWUg9Zh4wSuM7vnx8A0viWg92V2Q==} - - '@zag-js/popover@1.38.2': - resolution: {integrity: sha512-LPA4Ld/eD34/C+/jsojXU/GiG9Y4rYN1xFAJIeOdUGF9fAvMVr+TEhvNUnVV7FnIbK5hdFOy7EgAAEL34uqBow==} - - '@zag-js/popper@1.38.2': - resolution: {integrity: sha512-iqAFCeximjd2SGbsciXxbrHdrB/T5jeV4bf5KAPPGNM8Ce/dMcz5RteAArqBYJt1RDpB5px4RdeO8y+8vZOK/w==} - - '@zag-js/presence@1.38.2': - resolution: {integrity: sha512-jDBN6Jw6+oDZT7yms1/ZyfwTZjKI8wHpAOPdOOD+uwoJSW/zCrwyymLRf28QVqCfr60gD/oaHt3azKA8sO6ySQ==} - - '@zag-js/progress@1.38.2': - resolution: {integrity: sha512-PY8fD2whXqLWafcIAOt8puFcLtnzutk9z074bWrWAV0dhUAzCTuMXF4hPrB/Qf+11CHxZZS467zp8WbgdPhIEw==} - - '@zag-js/qr-code@1.38.2': - resolution: {integrity: sha512-CdPhZ+RfT3DXAKCJr/QY1Sud/b1PDbIpJ2zJxCQI5FyOBK1+rS/FOZ106R5E57+o8pFxBq7BXjp3lMPHYBsyag==} - - '@zag-js/radio-group@1.38.2': - resolution: {integrity: sha512-hyQq2AVCov/lgtfXraA/y2cKd9NKKdzXJT7sO2/59eKHyRYMylV3oatcQ2WqjrrnPxEfqLcQ7CWxl7NlcdnTow==} - - '@zag-js/rating-group@1.38.2': - resolution: {integrity: sha512-MggGwIcMWVvuRgDZJPnEvGnk5xYarbXOJnnP7BQK/31OgjRZmxwAAUKxHFDGY8vxRQ2XVTwmrPNTUVDDpQUJxQ==} - - '@zag-js/react@1.38.2': - resolution: {integrity: sha512-9MViJDg8zQZLITtTRkVIj00KnLc8NU9m9D4Qis2VbMnXg/Wp3mxpW0je8+Dd650ptPKQGFXYONnBB6iIxYJOtA==} - peerDependencies: - react: '>=18.0.0' - react-dom: '>=18.0.0' - - '@zag-js/rect-utils@1.38.2': - resolution: {integrity: sha512-VX/EHbtq++h+rFGrj/ql3EFPuJwFQLAYjOxyMvEKF34L8N5imDodIyVqrQfumZl5MMGmKstz/x1kL4nHYAxyWQ==} - - '@zag-js/remove-scroll@1.38.2': - resolution: {integrity: sha512-2NInlGgJmMQKMOyd5J2pc+L9/wj4NBhz028VwE31yxCK4dm3swcm5NYHdBAdpNG96ymximJsJndTkry7pnNNIA==} - - '@zag-js/scroll-area@1.38.2': - resolution: {integrity: sha512-Z9XuPizDWb3G4RVY6KMj8TpGuurT7C6DQhqMCWfqZkVXwjvC/DOZVDeIxwFOMl/i59UawIL7ttpZCxieeaQhNQ==} - - '@zag-js/scroll-snap@1.38.2': - resolution: {integrity: sha512-Z3+B++TIv39ZpVES9eaL2qK8UCONctkIKLXzBMDsK1gq0RfTt2xS765D1TH4bitvSc2c0x0ojHCf+Ui99CkXcQ==} - - '@zag-js/select@1.38.2': - resolution: {integrity: sha512-F0qOw0ntyVO1G80iwktVFF3XYUodP9Tfet5XrCmDN+kM2trumn94wV+1plE/7/SRjDED7uwaCSpaBXaFiv8KUw==} - - '@zag-js/signature-pad@1.38.2': - resolution: {integrity: sha512-8ZY0cvESLNEKV3dTRLY2lwIaRpgABOSbUsCEi5Aa1w0s/kdUnlwLoJdK96ryE5yb+65lU1q4VvUT40rqIFxX8w==} - - '@zag-js/slider@1.38.2': - resolution: {integrity: sha512-EBiCCLpwOA5eMcFgIMcAxNKQDePUqcVE+tTePteUVzzRONK1F/HLsLevIkpdJ4UouhPcDSsu5o2AH+w3bxW4sA==} - - '@zag-js/splitter@1.38.2': - resolution: {integrity: sha512-Z7lQPTGJWv9GGrFHeg0OvpK6KpnCnoqnVS665rkLaAfmVhak84sh9lJsRiuzm68dobXmbgP/OaD5u0xHo2hgDQ==} - - '@zag-js/steps@1.38.2': - resolution: {integrity: sha512-5fxZVSrgJk5YElhdgoM2p4YhZd9HNVjzKg5uLj4966MOE7jGITUCfvEybMXI+/eOlrh+7CX9Y+iG0PGj+p5wVg==} - - '@zag-js/store@1.38.2': - resolution: {integrity: sha512-TlJM6M2dW5W9jr6US4/R/VobLmlFrSv48ls18XffmXp+uuwZ7Aisciq0Djtwx7Y7e5KhlUWtk4ncE5PtjP4AzQ==} - - '@zag-js/switch@1.38.2': - resolution: {integrity: sha512-EIK0DO8cFcDqE6cobEh66O07nufwQnRnpVvgOWpoB13Ts/LyQ/HUxF377JRPa4EYIY2/hIt6L8zvwfgFHUGAMg==} - - '@zag-js/tabs@1.38.2': - resolution: {integrity: sha512-yqCKQ+ugYtwAuF8ya6fkI577Yz96apRwHDawPem4xRq381YC5TYDrLpWvRj4UjakPOjs+1mHf2+53RYQhhEpEg==} - - '@zag-js/tags-input@1.38.2': - resolution: {integrity: sha512-WV7uz5UGXThL8PqTor8tFKtLsTO79B7mRjoVNwgSKJ473C+Z9tFhJx+S6cPXvSx0PcDxYBX1DXI0NFWVgWVD4Q==} - - '@zag-js/timer@1.38.2': - resolution: {integrity: sha512-CwF6F4CuT4pKcOsL2t3gKLi3l4Sbr13eGGuZyJTn1fwjPsepEdq4ppxKto+/pYC30pzyrQRRqsL59H4k757z/A==} - - '@zag-js/toast@1.38.2': - resolution: {integrity: sha512-VRTfTjRrnn9U8RVKr2dTUWBzMBALNy5PMxr+z7Q1hUufv0JYfzPsSkVXsbSjI5OZPklbJ5P1ugmUrtVrATyGHw==} - - '@zag-js/toggle-group@1.38.2': - resolution: {integrity: sha512-vl9hDypfxiwR3gcsai+lBwRcPR1NwwNVP8ZhS3mdMwi3v5Lr4R4UCZc0l2/qFPj+IQ0q01VIGJJbkkFCB7a3iQ==} - - '@zag-js/toggle@1.38.2': - resolution: {integrity: sha512-8Hk5E4IK7wkG6hk/PI1c9f1vcgVGxbVIDI7WqTk5EeCSIWSKvIGAsBSCuWK2N7nlDlXuUQ4Ns2tvNZF9SfBG7A==} - - '@zag-js/tooltip@1.38.2': - resolution: {integrity: sha512-pFVWc6KjLujIvyOz2CzFQu4e9NVC61yE0oQpjRIQwzZAICxxiPE3QeOtb0Aw3Jhd0n2Y7qxuLyFI6gcAxI9Sxg==} - - '@zag-js/tour@1.38.2': - resolution: {integrity: sha512-HwHN7gC30Epfz0VEQsgcnzUK71cpB/Wl/HXv9daeDgtXHdqhJcnpaRVthfQr8ebSEBBWWui4r8dAxGJxrtUing==} - - '@zag-js/tree-view@1.38.2': - resolution: {integrity: sha512-w2R+EI6/ovTjGI6Vu/z6pMS9ZUMjSsj7jAsm7ZKbfwNngSIJBAu+kdAAZbeovl9MW/gnNVgpuJuS6N4yqANdIw==} - - '@zag-js/types@1.38.2': - resolution: {integrity: sha512-fvUf3J4QOFAliuo5wHTO/awO0GKFAn5AHNOXbGH5IuoxIwa0oK5tSXVwdF8JE7ISOkQh4oB2fq3g4QjxmAXDyA==} - - '@zag-js/utils@1.38.2': - resolution: {integrity: sha512-8UuWDomJ5JLX/KSDjEA4poX9rzqkGL47RiSCuVod+qZpWD0jpyXP7Lf600GUFtirRAiuN3x1+7KE6Elt/0rxtw==} - acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -1247,10 +901,6 @@ packages: axios@1.14.0: resolution: {integrity: sha512-3Y8yrqLSwjuzpXuZ0oIYZ/XGgLwUIBU3uLvbcpb0pidD9ctpShJd43KSlEEkVQg6DS0G9NKyzOvBfUtDKEyHvQ==} - babel-plugin-macros@3.1.0: - resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} - engines: {node: '>=10', npm: '>=6'} - bail@2.0.2: resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} @@ -1350,9 +1000,6 @@ packages: concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - convert-source-map@1.9.0: - resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} - convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} @@ -1363,10 +1010,6 @@ packages: core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - cosmiconfig@7.1.0: - resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} - engines: {node: '>=10'} - cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -1435,9 +1078,6 @@ packages: resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} engines: {node: '>=0.12'} - error-ex@1.3.4: - resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} - es-define-property@1.0.1: resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} engines: {node: '>= 0.4'} @@ -1539,9 +1179,6 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - fault@1.0.4: - resolution: {integrity: sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==} - fdir@6.5.0: resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} engines: {node: '>=12.0.0'} @@ -1555,9 +1192,6 @@ packages: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} - find-root@1.1.0: - resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} - find-up@4.1.0: resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} engines: {node: '>=8'} @@ -1586,10 +1220,6 @@ packages: resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} engines: {node: '>= 6'} - format@0.2.2: - resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==} - engines: {node: '>=0.4.x'} - fsevents@2.3.2: resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -1687,19 +1317,10 @@ packages: hermes-parser@0.25.1: resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} - highlight.js@10.7.3: - resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==} - highlight.js@11.11.1: resolution: {integrity: sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==} engines: {node: '>=12.0.0'} - highlightjs-vue@1.0.0: - resolution: {integrity: sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA==} - - hoist-non-react-statics@3.3.2: - resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} - html-parse-stringify@3.0.1: resolution: {integrity: sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==} @@ -1751,16 +1372,9 @@ packages: is-alphanumerical@2.0.1: resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} - is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - is-arrayish@0.3.4: resolution: {integrity: sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==} - is-core-module@2.16.1: - resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} - engines: {node: '>= 0.4'} - is-decimal@2.0.1: resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} @@ -1807,9 +1421,6 @@ packages: json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} @@ -1915,9 +1526,6 @@ packages: resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} engines: {node: '>= 12.0.0'} - lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - locate-path@5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} @@ -1935,9 +1543,6 @@ packages: longest-streak@3.1.0: resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} - lowlight@1.20.0: - resolution: {integrity: sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==} - lowlight@3.3.0: resolution: {integrity: sha512-0JNhgFoPvP6U6lE/UdVsSq99tn6DhjjpAj5MxG49ewd2mOBVtwWYIT8ClyABhq198aXXODMU6Ox8DrGy/CpTZQ==} @@ -2112,12 +1717,6 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - next-themes@0.4.6: - resolution: {integrity: sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==} - peerDependencies: - react: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc - react-dom: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc - node-releases@2.0.36: resolution: {integrity: sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==} @@ -2155,10 +1754,6 @@ packages: parse-entities@4.0.2: resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==} - parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} - parse5@7.3.0: resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} @@ -2170,16 +1765,6 @@ packages: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} - path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - - path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} - - perfect-freehand@1.2.3: - resolution: {integrity: sha512-bHZSfqDHGNlPpgH2yxXgPHlQSPpEbo+qg7li0M78J9vNAi2yjwLeA4x79BEQhX44lEWpCLSFCeRZwpw0niiXPA==} - picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -2209,35 +1794,20 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - prismjs@1.30.0: - resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==} - engines: {node: '>=6'} - process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} property-information@7.1.0: resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==} - proxy-compare@3.0.1: - resolution: {integrity: sha512-V9plBAt3qjMlS1+nC8771KNf6oJ12gExvaxnNzN/9yVRLdTv/lc+oJlnSzrdYDAvBfTStPCoiaCOTmTs0adv7Q==} - proxy-from-env@2.1.0: resolution: {integrity: sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==} engines: {node: '>=10'} - proxy-memoize@3.0.1: - resolution: {integrity: sha512-VDdG/VYtOgdGkWJx7y0o7p+zArSf2383Isci8C+BP3YXgMYDoPd3cCBjw0JdWb6YBb9sFiOPbAADDVTPJnh+9g==} - punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} - qrcode.react@4.2.0: - resolution: {integrity: sha512-QpgqWi8rD9DsS9EP3z7BT+5lY5SFhsqGjpgW5DY/i3mK4M9DTBNz3ErMi8BWYEfI3L0d8GIbGmcdFAS1uIRGjA==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - qrcode@1.5.4: resolution: {integrity: sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==} engines: {node: '>=10.13.0'} @@ -2272,9 +1842,6 @@ packages: peerDependencies: react: '*' - react-is@16.13.1: - resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} - react-is@18.3.1: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} @@ -2284,9 +1851,6 @@ packages: '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - react-lorem-ipsum@1.4.10: - resolution: {integrity: sha512-PCEuauLZTGJkm++oxJeUycEgQOBg3qmmD7pn5sUyq9e0OvvNbW32RKQsSgalAYGUIbS91UkDgxvt6iHVAsqYJw==} - react-markdown@10.1.0: resolution: {integrity: sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==} peerDependencies: @@ -2322,12 +1886,6 @@ packages: react-dom: optional: true - react-syntax-highlighter@16.1.1: - resolution: {integrity: sha512-PjVawBGy80C6YbC5DDZJeUjBmC7skaoEUdvfFQediQHgCL7aKyVHe57SaJGfQsloGDac+gCpTfRdtxzWWKmCXA==} - engines: {node: '>= 16.20.2'} - peerDependencies: - react: '>= 0.14.0' - react@19.2.4: resolution: {integrity: sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==} engines: {node: '>=0.10.0'} @@ -2343,9 +1901,6 @@ packages: redux@5.0.1: resolution: {integrity: sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==} - refractor@5.0.0: - resolution: {integrity: sha512-QXOrHQF5jOpjjLfiNk5GFnWhRXvxjUVnlFxkeDmewR5sXkr3iM46Zo+CnRR8B+MDVqkULW4EcLVcRBNOPXHosw==} - rehype-highlight@7.0.2: resolution: {integrity: sha512-k158pK7wdC2qL3M5NcZROZ2tR/l7zOzjxXd5VGdcfIyoijjQqpHd3JKtYSBDpDZ38UI2WJWuFAtkMDxmx5kstA==} @@ -2381,11 +1936,6 @@ packages: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} - resolve@1.22.11: - resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} - engines: {node: '>= 0.4'} - hasBin: true - rolldown@1.0.0-rc.12: resolution: {integrity: sha512-yP4USLIMYrwpPHEFB5JGH1uxhcslv6/hL0OyvTuY+3qlOSJvZ7ntYnoWpehBxufkgN0cvXxppuTu5hHa/zPh+A==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2433,10 +1983,6 @@ packages: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} - source-map@0.5.7: - resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} - engines: {node: '>=0.10.0'} - space-separated-tokens@2.0.2: resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} @@ -2467,9 +2013,6 @@ packages: style-to-object@1.0.14: resolution: {integrity: sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==} - stylis@4.2.0: - resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==} - stylis@4.3.6: resolution: {integrity: sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==} @@ -2477,10 +2020,6 @@ packages: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} - supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - throttle-debounce@5.0.2: resolution: {integrity: sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==} engines: {node: '>=12.22'} @@ -2553,9 +2092,6 @@ packages: peerDependencies: browserslist: '>= 4.21.0' - uqr@0.1.2: - resolution: {integrity: sha512-MJu7ypHq6QasgF5YRTjqscSzQp/W11zoUk6kvmlH+fmWEs63Y0Eib13hYFwAzagRJcVY8WVnlV+eBDUGMJ5IbA==} - uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -2648,10 +2184,6 @@ packages: yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - yaml@1.10.3: - resolution: {integrity: sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==} - engines: {node: '>= 6'} - yargs-parser@18.1.3: resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} engines: {node: '>=6'} @@ -2673,24 +2205,6 @@ packages: zod@4.3.6: resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==} - zustand@5.0.12: - resolution: {integrity: sha512-i77ae3aZq4dhMlRhJVCYgMLKuSiZAaUPAct2AksxQ+gOtimhGMdXljRT21P5BNpeT4kXlLIckvkPM029OljD7g==} - engines: {node: '>=12.20.0'} - peerDependencies: - '@types/react': '>=18.0.0' - immer: '>=9.0.6' - react: '>=18.0.0' - use-sync-external-store: '>=1.2.0' - peerDependenciesMeta: - '@types/react': - optional: true - immer: - optional: true - react: - optional: true - use-sync-external-store: - optional: true - zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} @@ -2742,77 +2256,6 @@ snapshots: react-dom: 19.2.4(react@19.2.4) throttle-debounce: 5.0.2 - '@ark-ui/react@5.35.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@internationalized/date': 3.12.0 - '@zag-js/accordion': 1.38.2 - '@zag-js/anatomy': 1.38.2 - '@zag-js/angle-slider': 1.38.2 - '@zag-js/async-list': 1.38.2 - '@zag-js/auto-resize': 1.38.2 - '@zag-js/avatar': 1.38.2 - '@zag-js/carousel': 1.38.2 - '@zag-js/cascade-select': 1.38.2 - '@zag-js/checkbox': 1.38.2 - '@zag-js/clipboard': 1.38.2 - '@zag-js/collapsible': 1.38.2 - '@zag-js/collection': 1.38.2 - '@zag-js/color-picker': 1.38.2 - '@zag-js/color-utils': 1.38.2 - '@zag-js/combobox': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/date-picker': 1.38.2(@internationalized/date@3.12.0) - '@zag-js/date-utils': 1.38.2(@internationalized/date@3.12.0) - '@zag-js/dialog': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/drawer': 1.38.2 - '@zag-js/editable': 1.38.2 - '@zag-js/file-upload': 1.38.2 - '@zag-js/file-utils': 1.38.2 - '@zag-js/floating-panel': 1.38.2 - '@zag-js/focus-trap': 1.38.2 - '@zag-js/focus-visible': 1.38.2 - '@zag-js/highlight-word': 1.38.2 - '@zag-js/hover-card': 1.38.2 - '@zag-js/i18n-utils': 1.38.2 - '@zag-js/image-cropper': 1.38.2 - '@zag-js/json-tree-utils': 1.38.2 - '@zag-js/listbox': 1.38.2 - '@zag-js/marquee': 1.38.2 - '@zag-js/menu': 1.38.2 - '@zag-js/navigation-menu': 1.38.2 - '@zag-js/number-input': 1.38.2 - '@zag-js/pagination': 1.38.2 - '@zag-js/password-input': 1.38.2 - '@zag-js/pin-input': 1.38.2 - '@zag-js/popover': 1.38.2 - '@zag-js/presence': 1.38.2 - '@zag-js/progress': 1.38.2 - '@zag-js/qr-code': 1.38.2 - '@zag-js/radio-group': 1.38.2 - '@zag-js/rating-group': 1.38.2 - '@zag-js/react': 1.38.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@zag-js/scroll-area': 1.38.2 - '@zag-js/select': 1.38.2 - '@zag-js/signature-pad': 1.38.2 - '@zag-js/slider': 1.38.2 - '@zag-js/splitter': 1.38.2 - '@zag-js/steps': 1.38.2 - '@zag-js/switch': 1.38.2 - '@zag-js/tabs': 1.38.2 - '@zag-js/tags-input': 1.38.2 - '@zag-js/timer': 1.38.2 - '@zag-js/toast': 1.38.2 - '@zag-js/toggle': 1.38.2 - '@zag-js/toggle-group': 1.38.2 - '@zag-js/tooltip': 1.38.2 - '@zag-js/tour': 1.38.2 - '@zag-js/tree-view': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - '@babel/code-frame@7.29.0': dependencies: '@babel/helper-validator-identifier': 7.28.5 @@ -2915,19 +2358,6 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 - '@chakra-ui/react@3.34.0(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4)(supports-color@7.2.0))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@ark-ui/react': 5.35.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@emotion/is-prop-valid': 1.4.0 - '@emotion/react': 11.14.0(@types/react@19.2.14)(react@19.2.4)(supports-color@7.2.0) - '@emotion/serialize': 1.3.3 - '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.2.4) - '@emotion/utils': 1.4.2 - '@pandacss/is-valid-prop': 1.9.1 - csstype: 3.2.3 - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - '@emnapi/core@1.9.1': dependencies: '@emnapi/wasi-threads': 1.2.0 @@ -2944,78 +2374,10 @@ snapshots: tslib: 2.8.1 optional: true - '@emotion/babel-plugin@11.13.5(supports-color@7.2.0)': - dependencies: - '@babel/helper-module-imports': 7.28.6(supports-color@7.2.0) - '@babel/runtime': 7.29.2 - '@emotion/hash': 0.9.2 - '@emotion/memoize': 0.9.0 - '@emotion/serialize': 1.3.3 - babel-plugin-macros: 3.1.0 - convert-source-map: 1.9.0 - escape-string-regexp: 4.0.0 - find-root: 1.1.0 - source-map: 0.5.7 - stylis: 4.2.0 - transitivePeerDependencies: - - supports-color - - '@emotion/cache@11.14.0': - dependencies: - '@emotion/memoize': 0.9.0 - '@emotion/sheet': 1.4.0 - '@emotion/utils': 1.4.2 - '@emotion/weak-memoize': 0.4.0 - stylis: 4.2.0 - '@emotion/hash@0.8.0': {} - '@emotion/hash@0.9.2': {} - - '@emotion/is-prop-valid@1.4.0': - dependencies: - '@emotion/memoize': 0.9.0 - - '@emotion/memoize@0.9.0': {} - - '@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4)(supports-color@7.2.0)': - dependencies: - '@babel/runtime': 7.29.2 - '@emotion/babel-plugin': 11.13.5(supports-color@7.2.0) - '@emotion/cache': 11.14.0 - '@emotion/serialize': 1.3.3 - '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.2.4) - '@emotion/utils': 1.4.2 - '@emotion/weak-memoize': 0.4.0 - hoist-non-react-statics: 3.3.2 - react: 19.2.4 - optionalDependencies: - '@types/react': 19.2.14 - transitivePeerDependencies: - - supports-color - - '@emotion/serialize@1.3.3': - dependencies: - '@emotion/hash': 0.9.2 - '@emotion/memoize': 0.9.0 - '@emotion/unitless': 0.10.0 - '@emotion/utils': 1.4.2 - csstype: 3.2.3 - - '@emotion/sheet@1.4.0': {} - - '@emotion/unitless@0.10.0': {} - '@emotion/unitless@0.7.5': {} - '@emotion/use-insertion-effect-with-fallbacks@1.2.0(react@19.2.4)': - dependencies: - react: 19.2.4 - - '@emotion/utils@1.4.2': {} - - '@emotion/weak-memoize@0.4.0': {} - '@eslint-community/eslint-utils@4.9.1(eslint@9.39.4(supports-color@7.2.0))': dependencies: eslint: 9.39.4(supports-color@7.2.0) @@ -3062,17 +2424,6 @@ snapshots: '@eslint/core': 0.17.0 levn: 0.4.1 - '@floating-ui/core@1.7.5': - dependencies: - '@floating-ui/utils': 0.2.11 - - '@floating-ui/dom@1.7.6': - dependencies: - '@floating-ui/core': 1.7.5 - '@floating-ui/utils': 0.2.11 - - '@floating-ui/utils@0.2.11': {} - '@humanfs/core@0.19.1': {} '@humanfs/node@0.16.7': @@ -3084,14 +2435,6 @@ snapshots: '@humanwhocodes/retry@0.4.3': {} - '@internationalized/date@3.12.0': - dependencies: - '@swc/helpers': 0.5.20 - - '@internationalized/number@3.6.5': - dependencies: - '@swc/helpers': 0.5.20 - '@jridgewell/gen-mapping@0.3.13': dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -3120,8 +2463,6 @@ snapshots: '@oxc-project/types@0.122.0': {} - '@pandacss/is-valid-prop@1.9.1': {} - '@playwright/test@1.60.0': dependencies: playwright: 1.60.0 @@ -3543,10 +2884,6 @@ snapshots: '@standard-schema/utils@0.3.0': {} - '@swc/helpers@0.5.20': - dependencies: - tslib: 2.8.1 - '@tybys/wasm-util@0.10.1': dependencies: tslib: 2.8.1 @@ -3586,22 +2923,10 @@ snapshots: dependencies: undici-types: 7.16.0 - '@types/parse-json@4.0.2': {} - - '@types/prismjs@1.26.6': {} - - '@types/qrcode@1.5.6': - dependencies: - '@types/node': 24.12.0 - '@types/react-dom@19.2.3(@types/react@19.2.14)': dependencies: '@types/react': 19.2.14 - '@types/react-syntax-highlighter@15.5.13': - dependencies: - '@types/react': 19.2.14 - '@types/react@19.2.14': dependencies: csstype: 3.2.3 @@ -3713,562 +3038,6 @@ snapshots: '@rolldown/pluginutils': 1.0.0-rc.7 vite: 8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@24.12.0) - '@zag-js/accordion@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/anatomy@1.38.2': {} - - '@zag-js/angle-slider@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/rect-utils': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/aria-hidden@1.38.2': - dependencies: - '@zag-js/dom-query': 1.38.2 - - '@zag-js/async-list@1.38.2': - dependencies: - '@zag-js/core': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/auto-resize@1.38.2': - dependencies: - '@zag-js/dom-query': 1.38.2 - - '@zag-js/avatar@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/carousel@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/scroll-snap': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/cascade-select@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/collection': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dismissable': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/focus-visible': 1.38.2 - '@zag-js/popper': 1.38.2 - '@zag-js/rect-utils': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/checkbox@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/focus-visible': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/clipboard@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/collapsible@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/collection@1.38.2': - dependencies: - '@zag-js/utils': 1.38.2 - - '@zag-js/color-picker@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/color-utils': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dismissable': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/popper': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/color-utils@1.38.2': - dependencies: - '@zag-js/utils': 1.38.2 - - '@zag-js/combobox@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/aria-hidden': 1.38.2 - '@zag-js/collection': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dismissable': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/focus-visible': 1.38.2 - '@zag-js/popper': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/core@1.38.2': - dependencies: - '@zag-js/dom-query': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/date-picker@1.38.2(@internationalized/date@3.12.0)': - dependencies: - '@internationalized/date': 3.12.0 - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/date-utils': 1.38.2(@internationalized/date@3.12.0) - '@zag-js/dismissable': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/live-region': 1.38.2 - '@zag-js/popper': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/date-utils@1.38.2(@internationalized/date@3.12.0)': - dependencies: - '@internationalized/date': 3.12.0 - - '@zag-js/dialog@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/aria-hidden': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dismissable': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/focus-trap': 1.38.2 - '@zag-js/remove-scroll': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/dismissable@1.38.2': - dependencies: - '@zag-js/dom-query': 1.38.2 - '@zag-js/interact-outside': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/dom-query@1.38.2': - dependencies: - '@zag-js/types': 1.38.2 - - '@zag-js/drawer@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/aria-hidden': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dismissable': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/focus-trap': 1.38.2 - '@zag-js/remove-scroll': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/editable@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/interact-outside': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/file-upload@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/file-utils': 1.38.2 - '@zag-js/i18n-utils': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/file-utils@1.38.2': - dependencies: - '@zag-js/i18n-utils': 1.38.2 - - '@zag-js/floating-panel@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/popper': 1.38.2 - '@zag-js/rect-utils': 1.38.2 - '@zag-js/store': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/focus-trap@1.38.2': - dependencies: - '@zag-js/dom-query': 1.38.2 - - '@zag-js/focus-visible@1.38.2': - dependencies: - '@zag-js/dom-query': 1.38.2 - - '@zag-js/highlight-word@1.38.2': {} - - '@zag-js/hover-card@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dismissable': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/popper': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/i18n-utils@1.38.2': - dependencies: - '@zag-js/dom-query': 1.38.2 - - '@zag-js/image-cropper@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/interact-outside@1.38.2': - dependencies: - '@zag-js/dom-query': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/json-tree-utils@1.38.2': {} - - '@zag-js/listbox@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/collection': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/focus-visible': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/live-region@1.38.2': {} - - '@zag-js/marquee@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/menu@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dismissable': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/focus-visible': 1.38.2 - '@zag-js/popper': 1.38.2 - '@zag-js/rect-utils': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/navigation-menu@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dismissable': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/number-input@1.38.2': - dependencies: - '@internationalized/number': 3.6.5 - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/pagination@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/password-input@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/pin-input@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/popover@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/aria-hidden': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dismissable': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/focus-trap': 1.38.2 - '@zag-js/popper': 1.38.2 - '@zag-js/remove-scroll': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/popper@1.38.2': - dependencies: - '@floating-ui/dom': 1.7.6 - '@zag-js/dom-query': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/presence@1.38.2': - dependencies: - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/types': 1.38.2 - - '@zag-js/progress@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/qr-code@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - proxy-memoize: 3.0.1 - uqr: 0.1.2 - - '@zag-js/radio-group@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/focus-visible': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/rating-group@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/react@1.38.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@zag-js/core': 1.38.2 - '@zag-js/store': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - - '@zag-js/rect-utils@1.38.2': {} - - '@zag-js/remove-scroll@1.38.2': - dependencies: - '@zag-js/dom-query': 1.38.2 - - '@zag-js/scroll-area@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/scroll-snap@1.38.2': - dependencies: - '@zag-js/dom-query': 1.38.2 - - '@zag-js/select@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/collection': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dismissable': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/focus-visible': 1.38.2 - '@zag-js/popper': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/signature-pad@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - perfect-freehand: 1.2.3 - - '@zag-js/slider@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/splitter@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/steps@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/store@1.38.2': - dependencies: - proxy-compare: 3.0.1 - - '@zag-js/switch@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/focus-visible': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/tabs@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/tags-input@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/auto-resize': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/interact-outside': 1.38.2 - '@zag-js/live-region': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/timer@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/toast@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dismissable': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/toggle-group@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/toggle@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/tooltip@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/focus-visible': 1.38.2 - '@zag-js/popper': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/tour@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dismissable': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/focus-trap': 1.38.2 - '@zag-js/interact-outside': 1.38.2 - '@zag-js/popper': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/tree-view@1.38.2': - dependencies: - '@zag-js/anatomy': 1.38.2 - '@zag-js/collection': 1.38.2 - '@zag-js/core': 1.38.2 - '@zag-js/dom-query': 1.38.2 - '@zag-js/types': 1.38.2 - '@zag-js/utils': 1.38.2 - - '@zag-js/types@1.38.2': - dependencies: - csstype: 3.2.3 - - '@zag-js/utils@1.38.2': {} - acorn-jsx@5.3.2(acorn@8.16.0): dependencies: acorn: 8.16.0 @@ -4357,12 +3126,6 @@ snapshots: transitivePeerDependencies: - debug - babel-plugin-macros@3.1.0: - dependencies: - '@babel/runtime': 7.29.2 - cosmiconfig: 7.1.0 - resolve: 1.22.11 - bail@2.0.2: {} balanced-match@1.0.2: {} @@ -4450,22 +3213,12 @@ snapshots: concat-map@0.0.1: {} - convert-source-map@1.9.0: {} - convert-source-map@2.0.0: {} cookie@1.1.1: {} core-util-is@1.0.3: {} - cosmiconfig@7.1.0: - dependencies: - '@types/parse-json': 4.0.2 - import-fresh: 3.3.1 - parse-json: 5.2.0 - path-type: 4.0.0 - yaml: 1.10.3 - cross-spawn@7.0.6: dependencies: path-key: 3.1.1 @@ -4523,10 +3276,6 @@ snapshots: entities@6.0.1: {} - error-ex@1.3.4: - dependencies: - is-arrayish: 0.2.1 - es-define-property@1.0.1: {} es-errors@1.3.0: {} @@ -4641,10 +3390,6 @@ snapshots: fast-levenshtein@2.0.6: {} - fault@1.0.4: - dependencies: - format: 0.2.2 - fdir@6.5.0(picomatch@4.0.4): optionalDependencies: picomatch: 4.0.4 @@ -4653,8 +3398,6 @@ snapshots: dependencies: flat-cache: 4.0.1 - find-root@1.1.0: {} - find-up@4.1.0: dependencies: locate-path: 5.0.0 @@ -4684,8 +3427,6 @@ snapshots: hasown: 2.0.2 mime-types: 2.1.35 - format@0.2.2: {} - fsevents@2.3.2: optional: true @@ -4824,16 +3565,8 @@ snapshots: dependencies: hermes-estree: 0.25.1 - highlight.js@10.7.3: {} - highlight.js@11.11.1: {} - highlightjs-vue@1.0.0: {} - - hoist-non-react-statics@3.3.2: - dependencies: - react-is: 16.13.1 - html-parse-stringify@3.0.1: dependencies: void-elements: 3.1.0 @@ -4876,14 +3609,8 @@ snapshots: is-alphabetical: 2.0.1 is-decimal: 2.0.1 - is-arrayish@0.2.1: {} - is-arrayish@0.3.4: {} - is-core-module@2.16.1: - dependencies: - hasown: 2.0.2 - is-decimal@2.0.1: {} is-extglob@2.1.1: {} @@ -4914,8 +3641,6 @@ snapshots: json-buffer@3.0.1: {} - json-parse-even-better-errors@2.3.1: {} - json-schema-traverse@0.4.1: {} json-stable-stringify-without-jsonify@1.0.1: {} @@ -4999,8 +3724,6 @@ snapshots: lightningcss-win32-arm64-msvc: 1.32.0 lightningcss-win32-x64-msvc: 1.32.0 - lines-and-columns@1.2.4: {} - locate-path@5.0.0: dependencies: p-locate: 4.1.0 @@ -5015,11 +3738,6 @@ snapshots: longest-streak@3.1.0: {} - lowlight@1.20.0: - dependencies: - fault: 1.0.4 - highlight.js: 10.7.3 - lowlight@3.3.0: dependencies: '@types/hast': 3.0.4 @@ -5420,11 +4138,6 @@ snapshots: natural-compare@1.4.0: {} - next-themes@0.4.6(react-dom@19.2.4(react@19.2.4))(react@19.2.4): - dependencies: - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - node-releases@2.0.36: {} optionator@0.9.4: @@ -5470,13 +4183,6 @@ snapshots: is-decimal: 2.0.1 is-hexadecimal: 2.0.1 - parse-json@5.2.0: - dependencies: - '@babel/code-frame': 7.29.0 - error-ex: 1.3.4 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - parse5@7.3.0: dependencies: entities: 6.0.1 @@ -5485,12 +4191,6 @@ snapshots: path-key@3.1.1: {} - path-parse@1.0.7: {} - - path-type@4.0.0: {} - - perfect-freehand@1.2.3: {} - picocolors@1.1.1: {} picomatch@4.0.4: {} @@ -5513,26 +4213,14 @@ snapshots: prelude-ls@1.2.1: {} - prismjs@1.30.0: {} - process-nextick-args@2.0.1: {} property-information@7.1.0: {} - proxy-compare@3.0.1: {} - proxy-from-env@2.1.0: {} - proxy-memoize@3.0.1: - dependencies: - proxy-compare: 3.0.1 - punycode@2.3.1: {} - qrcode.react@4.2.0(react@19.2.4): - dependencies: - react: 19.2.4 - qrcode@1.5.4: dependencies: dijkstrajs: 1.0.3 @@ -5566,8 +4254,6 @@ snapshots: dependencies: react: 19.2.4 - react-is@16.13.1: {} - react-is@18.3.1: {} react-json-tree@0.20.0(@types/react@19.2.14)(react@19.2.4): @@ -5577,8 +4263,6 @@ snapshots: react: 19.2.4 react-base16-styling: 0.10.0 - react-lorem-ipsum@1.4.10: {} - react-markdown@10.1.0(@types/react@19.2.14)(react@19.2.4)(supports-color@7.2.0): dependencies: '@types/hast': 3.0.4 @@ -5620,16 +4304,6 @@ snapshots: optionalDependencies: react-dom: 19.2.4(react@19.2.4) - react-syntax-highlighter@16.1.1(react@19.2.4): - dependencies: - '@babel/runtime': 7.29.2 - highlight.js: 10.7.3 - highlightjs-vue: 1.0.0 - lowlight: 1.20.0 - prismjs: 1.30.0 - react: 19.2.4 - refractor: 5.0.0 - react@19.2.4: {} readable-stream@2.3.8: @@ -5648,13 +4322,6 @@ snapshots: redux@5.0.1: {} - refractor@5.0.0: - dependencies: - '@types/hast': 3.0.4 - '@types/prismjs': 1.26.6 - hastscript: 9.0.1 - parse-entities: 4.0.2 - rehype-highlight@7.0.2: dependencies: '@types/hast': 3.0.4 @@ -5724,12 +4391,6 @@ snapshots: resolve-from@4.0.0: {} - resolve@1.22.11: - dependencies: - is-core-module: 2.16.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - rolldown@1.0.0-rc.12(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1): dependencies: '@oxc-project/types': 0.122.0 @@ -5784,8 +4445,6 @@ snapshots: source-map-js@1.2.1: {} - source-map@0.5.7: {} - space-separated-tokens@2.0.2: {} string-convert@0.2.1: {} @@ -5819,16 +4478,12 @@ snapshots: dependencies: inline-style-parser: 0.2.7 - stylis@4.2.0: {} - stylis@4.3.6: {} supports-color@7.2.0: dependencies: has-flag: 4.0.0 - supports-preserve-symlinks-flag@1.0.0: {} - throttle-debounce@5.0.2: {} tinyglobby@0.2.15: @@ -5844,7 +4499,8 @@ snapshots: dependencies: typescript: 5.9.3 - tslib@2.8.1: {} + tslib@2.8.1: + optional: true type-check@0.4.0: dependencies: @@ -5914,8 +4570,6 @@ snapshots: escalade: 3.2.0 picocolors: 1.1.1 - uqr@0.1.2: {} - uri-js@4.4.1: dependencies: punycode: 2.3.1 @@ -5977,8 +4631,6 @@ snapshots: yallist@3.1.1: {} - yaml@1.10.3: {} - yargs-parser@18.1.3: dependencies: camelcase: 5.3.1 @@ -6006,11 +4658,4 @@ snapshots: zod@4.3.6: {} - zustand@5.0.12(@types/react@19.2.14)(immer@11.1.4)(react@19.2.4)(use-sync-external-store@1.6.0(react@19.2.4)): - optionalDependencies: - '@types/react': 19.2.14 - immer: 11.1.4 - react: 19.2.4 - use-sync-external-store: 1.6.0(react@19.2.4) - zwitch@2.0.4: {} diff --git a/scripts/check_seo.mjs b/scripts/check_seo.mjs new file mode 100644 index 0000000..443269e --- /dev/null +++ b/scripts/check_seo.mjs @@ -0,0 +1,79 @@ +#!/usr/bin/env node +/* C-05 SEO 验收:扫描 dist 校验 title/description/sitemap 覆盖。 + * 用法:node scripts/check_seo.mjs [--dist dist] + * 退出码:0 全绿;1 有失败(打印明细)。 + */ +import { readFileSync, existsSync, readdirSync } from 'node:fs' +import { join, resolve } from 'node:path' + +const args = process.argv.slice(2) +const distIdx = args.indexOf('--dist') +const DIST = resolve(distIdx >= 0 && args[distIdx + 1] ? args[distIdx + 1] : 'dist') + +const EXPECT_TOOLS = [ + '/baidu-translate', '/utility/json-formatter', '/utility/timestamp', '/utility/base64', + '/utility/encoding-converter', '/utility/regex', '/utility/code-formatter', '/utility/color-converter', + '/qrcode-generator', '/utility/text-diff', '/utility/calculator', '/utility/date-calculator', + '/utility/image-compressor', '/color-picker', '/utility/charset-converter', '/utility/image-editor', +] +const EXPECT_PAGES = ['/', '/utility', '/top'] + +let fail = 0 +const ok = (cond, msg) => { + console.log(`${cond ? 'PASS' : 'FAIL'} ${msg}`) + if (!cond) fail++ +} + +const titleOf = (html) => (html.match(/([\s\S]*?)<\/title>/) || [])[1] || '' +const descOf = (html) => (html.match(/<meta name="description" content="([\s\S]*?)"\s*\/?>/) || [])[1] || '' + +// 1. 工具页 HTML 含正文 + 唯一 title/description +const titles = new Set() +for (const u of EXPECT_TOOLS) { + const f = join(DIST, u.replace(/^\//, ''), 'index.html') + ok(existsSync(f), `${u} -> dist 产物存在`) + if (!existsSync(f)) continue + const html = readFileSync(f, 'utf-8') + const t = titleOf(html), d = descOf(html) + ok(t.length > 0, `${u} title 非空(${t.slice(0, 24)}…)`) + ok(!titles.has(t), `${u} title 唯一`) + titles.add(t) + ok(d.length > 0, `${u} description 非空`) + ok(html.includes('<h1>') && html.includes('免费在线工具'), `${u} 含静态正文(h1+说明,非空#root)`) + ok(html.includes('og:title') && html.includes('og:description'), `${u} OG 标签齐全`) +} + +// 2. 聚合页 +for (const u of EXPECT_PAGES) { + const f = u === '/' ? join(DIST, 'index.seo.html') : join(DIST, u.replace(/^\//, ''), 'index.html') + ok(existsSync(f), `${u} -> 聚合产物存在`) + if (!existsSync(f)) continue + const html = readFileSync(f, 'utf-8') + ok(titleOf(html).length > 0 && descOf(html).length > 0, `${u} title/description 非空`) +} + +// 3. sitemap/robots +const sm = join(DIST, 'sitemap.xml') +ok(existsSync(sm), 'sitemap.xml 存在') +if (existsSync(sm)) { + const body = readFileSync(sm, 'utf-8') + const missing = [...EXPECT_TOOLS, ...EXPECT_PAGES].filter((u) => !body.includes(`<loc>`) || !body.includes(u)) + ok(missing.length === 0, `sitemap 覆盖 ${EXPECT_TOOLS.length + EXPECT_PAGES.length} URL${missing.length ? '(缺:' + missing.join(',') + ')' : ''}`) +} +const robots = join(DIST, 'robots.txt') +ok(existsSync(robots), 'robots.txt 存在') +if (existsSync(robots)) { + const body = readFileSync(robots, 'utf-8') + ok(body.includes('Sitemap:'), 'robots 指向 sitemap') + ok(body.includes('Disallow: /profile') && body.includes('Disallow: /wallet/'), 'robots 屏蔽登录态页') +} + +// 4. SPA 外壳未被破坏 +const shell = join(DIST, 'index.html') +ok(existsSync(shell) && readFileSync(shell, 'utf-8').includes('id="root"'), 'SPA 外壳 index.html 完好(含 #root)') + +// 5. 种子对齐:TOOLS 数量 == 后端启用工具数(硬编码 16,漂移即报) +ok(EXPECT_TOOLS.length === 16, `工具清单 16 条(与 seed_tools 启用数对齐)`) + +console.log(fail === 0 ? `\nSEO CHECK ALL GREEN (${EXPECT_TOOLS.length} tools + ${EXPECT_PAGES.length} pages)` : `\nSEO CHECK FAILED: ${fail} 项`) +process.exit(fail === 0 ? 0 : 1) diff --git a/scripts/seo_prerender.mjs b/scripts/seo_prerender.mjs new file mode 100644 index 0000000..b5c0df0 --- /dev/null +++ b/scripts/seo_prerender.mjs @@ -0,0 +1,132 @@ +#!/usr/bin/env node +/* C-05 SEO 预渲染:构建后脚本(无重依赖,纯 Node)。 + * 数据源:与后端 seed_tools.py 同源的工具清单(url_path/name/description 必须对齐种子)。 + * 产出(dist/ 内): + * - 每个工具页 <url_path>/index.html:独立 title/description/OG + 含正文的静态 HTML + * - / /utility /top 三个聚合页的静态 HTML + * - sitemap.xml(全部工具 URL + 聚合页)+ robots.txt + * 用法:npm run build 后自动执行(package.json build 链);也可单独 node scripts/seo_prerender.mjs --dist dist [--base https://www.example.com] + * 注意:base 默认为占位,部署时用 --base 传入真实域名重跑本脚本即可刷新 sitemap/OG。 + */ +import { mkdirSync, readFileSync, writeFileSync, existsSync } from 'node:fs' +import { dirname, join, resolve } from 'node:path' + +const args = process.argv.slice(2) +const distIdx = args.indexOf('--dist') +const baseIdx = args.indexOf('--base') +const DIST = resolve(distIdx >= 0 && args[distIdx + 1] ? args[distIdx + 1] : 'dist') +const BASE = (baseIdx >= 0 && args[baseIdx + 1] ? args[baseIdx + 1] : 'https://tools.example.com').replace(/\/$/, '') +const SHELL = join(DIST, 'index.html') + +// 与 chunyu_project/tool/management/commands/seed_tools.py 同源(url_path/name/description 对齐)。 +// is_new 仅用于正文徽标,不影响收录。 +const TOOLS = [ + { name: '万能翻译', en: 'Online Translator - 200+ Languages', url: '/baidu-translate', desc: '支持200+语种互译,文本翻译、语种识别、图片翻译、语音翻译', kw: '在线翻译,语种识别,文本翻译,免费翻译工具' }, + { name: 'JSON格式化', en: 'JSON Formatter & Validator', url: '/utility/json-formatter', desc: 'JSON数据格式化、压缩、校验', kw: 'JSON格式化,JSON压缩,JSON校验,JSON在线工具' }, + { name: '时间戳转换', en: 'Unix Timestamp Converter', url: '/utility/timestamp', desc: 'Unix时间戳与日期时间互转', kw: '时间戳转换,Unix时间戳,日期互转,在线时间工具' }, + { name: 'Base64编解码', en: 'Base64 Encoder & Decoder', url: '/utility/base64', desc: 'Base64编码与解码工具', kw: 'Base64编码,Base64解码,在线Base64工具' }, + { name: '编码转换器', en: 'URL/Base64/Unicode/Hex Encoder', url: '/utility/encoding-converter', desc: '多种编码格式互转,支持URL/Base64/Unicode/Hex/Binary等', kw: 'URL编码,Unicode转换,Hex转换,在线编码工具' }, + { name: '正则表达式测试', en: 'Online Regex Tester', url: '/utility/regex', desc: '在线正则表达式测试与验证', kw: '正则测试,在线正则,Regex tester,正则验证' }, + { name: '代码格式化', en: 'Code Formatter - JS/TS/Python/HTML/CSS', url: '/utility/code-formatter', desc: '多语言代码格式化工具,支持JS/TS/Python/HTML/CSS等', kw: '代码格式化,JS格式化,Python格式化,在线代码美化' }, + { name: '颜色转换器', en: 'HEX/RGB/HSL Color Converter', url: '/utility/color-converter', desc: 'HEX、RGB、HSL颜色格式转换', kw: '颜色转换,HEX转RGB,HSL,在线取色换算' }, + { name: '二维码生成', en: 'Free QR Code Generator', url: '/qrcode-generator', desc: '生成自定义样式二维码', kw: '二维码生成,免费二维码,在线QR Code' }, + { name: '文本对比', en: 'Online Text Diff Tool', url: '/utility/text-diff', desc: '文本差异对比工具', kw: '文本对比,文本差异,在线diff工具' }, + { name: '计算器', en: 'Online Scientific Calculator', url: '/utility/calculator', desc: '科学计算器', kw: '在线计算器,科学计算器,免费计算工具' }, + { name: '日期计算器', en: 'Date Calculator - Days Between Dates', url: '/utility/date-calculator', desc: '日期间隔计算与推算', kw: '日期计算,日期间隔,天数计算,在线日期工具' }, + { name: '图片压缩', en: 'Online Image Compressor', url: '/utility/image-compressor', desc: '在线图片压缩工具', kw: '图片压缩,在线压缩图片,免费图片压缩' }, + { name: '取色器', en: 'Color Picker - HEX/RGB/HSL', url: '/color-picker', desc: '颜色拾取、HEX/RGB/HSL转换、历史记录', kw: '取色器,在线取色,HEX RGB转换' }, + { name: '字符编码转换', en: 'GBK/UTF-8 Charset Converter', url: '/utility/charset-converter', desc: 'GBK/UTF-8/Big5/Shift_JIS 等字符集互转,支持文件上传下载', kw: '字符集转换,GBK UTF8互转,编码转换工具' }, + { name: '图片编辑', en: 'Online Photo Editor - Crop & Filters', url: '/utility/image-editor', desc: '在线图片编辑,支持裁剪、滤镜、调节、文字、画笔', kw: '在线图片编辑,图片裁剪,图片滤镜' }, +] + +// 聚合页(首页 / 工具列表 / 热榜) +const PAGES = [ + { url: '/', title: '可乐开发工具箱 - 免费在线开发者工具', desc: '一站式免费开发者工具:JSON格式化、时间戳转换、Base64、正则测试、二维码生成、图片压缩等16款在线工具,开箱即用。', kw: '开发者工具,在线工具,免费工具箱,JSON格式化,时间戳' , h1: '可乐开发工具箱', body: '16 款免费在线开发者工具:JSON格式化、时间戳转换、Base64编解码、正则测试、二维码生成、图片压缩、取色器等,打开即用,无需安装。'}, + { url: '/utility', title: '全部在线工具 - 可乐开发工具箱', desc: '浏览全部16款免费在线工具:开发、设计、实用分类齐全,JSON/时间戳/编码/图片/颜色工具一站配齐。', kw: '在线工具列表,全部工具,免费开发工具', h1: '全部在线工具', body: '按开发、设计、实用分类浏览 16 款免费在线工具,每款工具均可直接打开使用。' }, + { url: '/top', title: '工具热榜 - 大家都在用的在线工具', desc: '可乐工具热榜:按真实使用量排序,发现最受欢迎的JSON格式化、二维码生成、时间戳转换等工具。', kw: '工具热榜,热门工具,常用在线工具', h1: '工具热榜', body: '按近7天真实使用量排序的工具热榜,快速找到大家都在用的在线工具。' }, +] + +function esc(s) { + return String(s ?? '').replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"') +} + +function pageHtml({ title, desc, kw, url, h1, body, extra = '' }) { + const canon = `${BASE}${url}` + return `<!doctype html> +<html lang="zh-CN"> +<head> +<meta charset="UTF-8" /> +<meta name="viewport" content="width=device-width, initial-scale=1.0" /> +<title>${esc(title)} + + + + + + + + + + +
+

${esc(h1)}

+

${esc(body)}

+${extra} +

在可乐工具箱中打开使用

+
+
+ + + +` +} + +function main() { + if (!existsSync(SHELL)) { + console.error(`[seo] shell 不存在:${SHELL},请先跑 vite build`) + process.exit(1) + } + const t0 = Date.now() + const toolLinks = TOOLS.map((t) => `
  • ${esc(t.name)} - ${esc(t.desc)}
  • `).join('\n') + + let count = 0 + for (const p of PAGES) { + const out = join(DIST, p.url === '/' ? 'index.seo.html' : p.url.replace(/^\//, '') + '/index.html') + void out + // 首页 SEO 正文直接写 heritage 文件: dist/index.seo.html 供 nginx 优先返回(不覆盖 SPA 外壳 index.html) + const target = p.url === '/' + ? join(DIST, 'index.seo.html') + : join(DIST, p.url.replace(/^\//, ''), 'index.html') + mkdirSync(dirname(target), { recursive: true }) + writeFileSync(target, pageHtml({ ...p, extra: `` }), 'utf-8') + count++ + } + for (const t of TOOLS) { + const target = join(DIST, t.url.replace(/^\//, ''), 'index.html') + mkdirSync(dirname(target), { recursive: true }) + const others = TOOLS.filter((x) => x.url !== t.url).slice(0, 8) + .map((x) => `
  • ${esc(x.name)}
  • `).join('\n') + writeFileSync(target, pageHtml({ + title: `${t.name} - 免费在线工具 | 可乐开发工具箱`, + desc: `${t.desc}。免费在线${t.name}工具,打开即用,无需下载安装。`, + kw: t.kw, + url: t.url, + h1: `${t.name} - 免费在线工具`, + body: `${t.desc}。${t.en}。`, + extra: `

    相关工具

    \n`, + }), 'utf-8') + count++ + } + + // sitemap.xml:聚合页 + 全部工具页 + const urls = [...PAGES.map((p) => p.url), ...TOOLS.map((t) => t.url)] + const today = new Date().toISOString().slice(0, 10) + const sm = `\n\n` + + urls.map((u) => ` ${esc(BASE + u)}${today}weekly${u === '/' ? '1.0' : u.startsWith('/utility/') || u.startsWith('/qrcode') || u === '/baidu-translate' || u === '/color-picker' ? '0.8' : '0.6'}`).join('\n') + + `\n\n` + writeFileSync(join(DIST, 'sitemap.xml'), sm, 'utf-8') + writeFileSync(join(DIST, 'robots.txt'), `User-agent: *\nAllow: /\nDisallow: /profile\nDisallow: /wallet/\nDisallow: /console\nDisallow: /messages\nDisallow: /chat\nSitemap: ${BASE}/sitemap.xml\n`, 'utf-8') + console.log(`[seo] prerender done: ${count} html + sitemap(${urls.length} urls) + robots.txt in ${Date.now() - t0}ms -> ${DIST}`) +} + +main() diff --git a/src/locales/en.json b/src/locales/en.json index 9ba0219..1871ba8 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -266,7 +266,11 @@ "desc": "Learn about the latest features and improvements" }, "viewAll": "View all", - "more": "More" + "more": "More", + "hotTools": { + "title": "Trending Tools", + "desc": "The most-used tools by our users" + } }, "update": { "newFeature": "New Feature", @@ -365,6 +369,18 @@ }, "common": { "viewDetails": "View details" + }, + "checkin": { + "title": "Daily Check-in", + "notSignedToday": "Not checked in today", + "signedToday": "Checked in today", + "weekProgress": "{count} days this week", + "loginHint": "Check in daily to earn points, coins and XP", + "loginBtn": "Sign in to check in", + "btn": "Check in", + "signed": "Checked in", + "success": "Check-in successful!", + "pointsUnit": "pts" } }, "tools": { @@ -616,7 +632,8 @@ "newest": "Latest", "mostViews": "Most Viewed", "mostLikes": "Most Liked", - "mostComments": "Most Commented" + "mostComments": "Most Commented", + "following": "Following" }, "pagination": { "total": "{{count}} articles", @@ -650,6 +667,12 @@ "following": "Following", "follow": "+ Follow", "updated": "Updated" + }, + "empty": { + "title": "No articles yet", + "hint": "Try a different filter", + "followingTitle": "No followed authors yet", + "followingHint": "Follow authors to see their posts here" } }, "invite": { @@ -2317,36 +2340,284 @@ "other": "Other" }, "templates": { - "phone": { "label": "Phone", "regex": "^1[3-9]\\d{9}$", "category": "basic", "desc": "11-digit Chinese phone number", "flags": { "g": true } }, - "email": { "label": "Email", "regex": "^[\\w-]+@[\\w-]+\\.[a-z]{2,}$", "category": "basic", "desc": "Email address", "flags": { "g": true, "i": true } }, - "idCard": { "label": "ID Card", "regex": "^[1-9]\\d{5}(19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[\\dXx]$", "category": "basic", "desc": "18-digit ID number", "flags": { "g": true } }, - "bankCard": { "label": "Bank Card", "regex": "^\\d{16,19}$", "category": "basic", "desc": "16-19 digit bank card number", "flags": { "g": true } }, - "telephone": { "label": "Telephone", "regex": "^\\d{3,4}-?\\d{7,8}$", "category": "basic", "desc": "Landline with area code", "flags": { "g": true } }, - "zipCode": { "label": "Zip Code", "regex": "^[1-9]\\d{5}$", "category": "basic", "desc": "6-digit zip code", "flags": { "g": true } }, - "url": { "label": "URL", "regex": "^https?:\\/\\/[\\w\\.-]+\\.[a-z]{2,}(\\/\\S*)?$", "category": "network", "desc": "HTTP/HTTPS URL", "flags": { "g": true, "i": true } }, - "ip": { "label": "IP Address", "regex": "^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)$", "category": "network", "desc": "IPv4 address", "flags": { "g": true } }, - "domain": { "label": "Domain", "regex": "^[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+$", "category": "network", "desc": "Domain name", "flags": { "g": true, "i": true } }, - "mac": { "label": "MAC Address", "regex": "^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$", "category": "network", "desc": "MAC address", "flags": { "g": true, "i": true } }, - "number": { "label": "Number", "regex": "^-?\\d+(\\.\\d+)?$", "category": "number", "desc": "Positive/negative integer or decimal", "flags": { "g": true } }, - "integer": { "label": "Integer", "regex": "^-?\\d+$", "category": "number", "desc": "Positive/negative integer", "flags": { "g": true } }, - "positiveInteger": { "label": "Positive Integer", "regex": "^[1-9]\\d*$", "category": "number", "desc": "Greater than 0", "flags": { "g": true } }, - "negativeInteger": { "label": "Negative Integer", "regex": "^-[1-9]\\d*$", "category": "number", "desc": "Less than 0", "flags": { "g": true } }, - "float": { "label": "Float", "regex": "^-?\\d+\\.\\d+$", "category": "number", "desc": "Positive/negative decimal", "flags": { "g": true } }, - "date": { "label": "Date", "regex": "^\\d{4}-\\d{2}-\\d{2}$", "category": "datetime", "desc": "YYYY-MM-DD format", "flags": { "g": true } }, - "time": { "label": "Time", "regex": "^([01]\\d|2[0-3]):[0-5]\\d(:[0-5]\\d)?$", "category": "datetime", "desc": "HH:MM:SS format", "flags": { "g": true } }, - "datetime": { "label": "DateTime", "regex": "^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$", "category": "datetime", "desc": "YYYY-MM-DD HH:MM:SS", "flags": { "g": true } }, - "username": { "label": "Username", "regex": "^[a-zA-Z][a-zA-Z0-9_]{3,15}$", "category": "account", "desc": "4-16 chars starting with letter", "flags": { "g": true } }, - "password": { "label": "Strong Password", "regex": "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[\\s\\S]{8,}$", "category": "account", "desc": "8+ chars with upper, lower, digit", "flags": { "g": true } }, - "imageFile": { "label": "Image File", "regex": "\\.(jpg|jpeg|png|gif|bmp|svg)$", "category": "file", "desc": "Common image formats", "flags": { "g": true, "i": true } }, - "docFile": { "label": "Document File", "regex": "\\.(doc|docx|pdf|txt|xls|xlsx)$", "category": "file", "desc": "Common document formats", "flags": { "g": true, "i": true } }, - "videoFile": { "label": "Video File", "regex": "\\.(mp4|avi|mov|wmv|flv|mkv)$", "category": "file", "desc": "Common video formats", "flags": { "g": true, "i": true } }, - "chinese": { "label": "Chinese", "regex": "^[\\u4e00-\\u9fa5]+$", "category": "other", "desc": "Chinese characters only", "flags": { "g": true } }, - "english": { "label": "English", "regex": "^[a-zA-Z]+$", "category": "other", "desc": "English letters only", "flags": { "g": true } }, - "htmlTag": { "label": "HTML Tag", "regex": "<[^>]+>", "category": "other", "desc": "HTML tag", "flags": { "g": true } }, - "hexColor": { "label": "Hex Color", "regex": "^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$", "category": "other", "desc": "#RGB or #RRGGBB format", "flags": { "g": true, "i": true } }, - "plateNumber": { "label": "Plate Number", "regex": "^[\\u4e00-\\u9fa5][A-Z][A-Z0-9]{5}$", "category": "other", "desc": "Chinese plate number", "flags": { "g": true } }, - "wechat": { "label": "WeChat ID", "regex": "^[a-zA-Z][-_a-zA-Z0-9]{5,19}$", "category": "other", "desc": "6-20 chars starting with letter", "flags": { "g": true } }, - "qq": { "label": "QQ Number", "regex": "^[1-9][0-9]{4,10}$", "category": "other", "desc": "5-11 digit QQ number", "flags": { "g": true } } + "phone": { + "label": "Phone", + "regex": "^1[3-9]\\d{9}$", + "category": "basic", + "desc": "11-digit Chinese phone number", + "flags": { + "g": true + } + }, + "email": { + "label": "Email", + "regex": "^[\\w-]+@[\\w-]+\\.[a-z]{2,}$", + "category": "basic", + "desc": "Email address", + "flags": { + "g": true, + "i": true + } + }, + "idCard": { + "label": "ID Card", + "regex": "^[1-9]\\d{5}(19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[\\dXx]$", + "category": "basic", + "desc": "18-digit ID number", + "flags": { + "g": true + } + }, + "bankCard": { + "label": "Bank Card", + "regex": "^\\d{16,19}$", + "category": "basic", + "desc": "16-19 digit bank card number", + "flags": { + "g": true + } + }, + "telephone": { + "label": "Telephone", + "regex": "^\\d{3,4}-?\\d{7,8}$", + "category": "basic", + "desc": "Landline with area code", + "flags": { + "g": true + } + }, + "zipCode": { + "label": "Zip Code", + "regex": "^[1-9]\\d{5}$", + "category": "basic", + "desc": "6-digit zip code", + "flags": { + "g": true + } + }, + "url": { + "label": "URL", + "regex": "^https?:\\/\\/[\\w\\.-]+\\.[a-z]{2,}(\\/\\S*)?$", + "category": "network", + "desc": "HTTP/HTTPS URL", + "flags": { + "g": true, + "i": true + } + }, + "ip": { + "label": "IP Address", + "regex": "^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)$", + "category": "network", + "desc": "IPv4 address", + "flags": { + "g": true + } + }, + "domain": { + "label": "Domain", + "regex": "^[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+$", + "category": "network", + "desc": "Domain name", + "flags": { + "g": true, + "i": true + } + }, + "mac": { + "label": "MAC Address", + "regex": "^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$", + "category": "network", + "desc": "MAC address", + "flags": { + "g": true, + "i": true + } + }, + "number": { + "label": "Number", + "regex": "^-?\\d+(\\.\\d+)?$", + "category": "number", + "desc": "Positive/negative integer or decimal", + "flags": { + "g": true + } + }, + "integer": { + "label": "Integer", + "regex": "^-?\\d+$", + "category": "number", + "desc": "Positive/negative integer", + "flags": { + "g": true + } + }, + "positiveInteger": { + "label": "Positive Integer", + "regex": "^[1-9]\\d*$", + "category": "number", + "desc": "Greater than 0", + "flags": { + "g": true + } + }, + "negativeInteger": { + "label": "Negative Integer", + "regex": "^-[1-9]\\d*$", + "category": "number", + "desc": "Less than 0", + "flags": { + "g": true + } + }, + "float": { + "label": "Float", + "regex": "^-?\\d+\\.\\d+$", + "category": "number", + "desc": "Positive/negative decimal", + "flags": { + "g": true + } + }, + "date": { + "label": "Date", + "regex": "^\\d{4}-\\d{2}-\\d{2}$", + "category": "datetime", + "desc": "YYYY-MM-DD format", + "flags": { + "g": true + } + }, + "time": { + "label": "Time", + "regex": "^([01]\\d|2[0-3]):[0-5]\\d(:[0-5]\\d)?$", + "category": "datetime", + "desc": "HH:MM:SS format", + "flags": { + "g": true + } + }, + "datetime": { + "label": "DateTime", + "regex": "^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$", + "category": "datetime", + "desc": "YYYY-MM-DD HH:MM:SS", + "flags": { + "g": true + } + }, + "username": { + "label": "Username", + "regex": "^[a-zA-Z][a-zA-Z0-9_]{3,15}$", + "category": "account", + "desc": "4-16 chars starting with letter", + "flags": { + "g": true + } + }, + "password": { + "label": "Strong Password", + "regex": "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[\\s\\S]{8,}$", + "category": "account", + "desc": "8+ chars with upper, lower, digit", + "flags": { + "g": true + } + }, + "imageFile": { + "label": "Image File", + "regex": "\\.(jpg|jpeg|png|gif|bmp|svg)$", + "category": "file", + "desc": "Common image formats", + "flags": { + "g": true, + "i": true + } + }, + "docFile": { + "label": "Document File", + "regex": "\\.(doc|docx|pdf|txt|xls|xlsx)$", + "category": "file", + "desc": "Common document formats", + "flags": { + "g": true, + "i": true + } + }, + "videoFile": { + "label": "Video File", + "regex": "\\.(mp4|avi|mov|wmv|flv|mkv)$", + "category": "file", + "desc": "Common video formats", + "flags": { + "g": true, + "i": true + } + }, + "chinese": { + "label": "Chinese", + "regex": "^[\\u4e00-\\u9fa5]+$", + "category": "other", + "desc": "Chinese characters only", + "flags": { + "g": true + } + }, + "english": { + "label": "English", + "regex": "^[a-zA-Z]+$", + "category": "other", + "desc": "English letters only", + "flags": { + "g": true + } + }, + "htmlTag": { + "label": "HTML Tag", + "regex": "<[^>]+>", + "category": "other", + "desc": "HTML tag", + "flags": { + "g": true + } + }, + "hexColor": { + "label": "Hex Color", + "regex": "^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$", + "category": "other", + "desc": "#RGB or #RRGGBB format", + "flags": { + "g": true, + "i": true + } + }, + "plateNumber": { + "label": "Plate Number", + "regex": "^[\\u4e00-\\u9fa5][A-Z][A-Z0-9]{5}$", + "category": "other", + "desc": "Chinese plate number", + "flags": { + "g": true + } + }, + "wechat": { + "label": "WeChat ID", + "regex": "^[a-zA-Z][-_a-zA-Z0-9]{5,19}$", + "category": "other", + "desc": "6-20 chars starting with letter", + "flags": { + "g": true + } + }, + "qq": { + "label": "QQ Number", + "regex": "^[1-9][0-9]{4,10}$", + "category": "other", + "desc": "5-11 digit QQ number", + "flags": { + "g": true + } + } }, "matchCount": "{{count}} match(es)", "resultPos": "Position", @@ -2650,7 +2921,8 @@ "downloads": "Downloads", "noMaterials": "No course materials", "noVideo": "No video tutorial", - "videoNotSupported": "Your browser does not support video playback" + "videoNotSupported": "Your browser does not support video playback", + "minutes": "min" }, "codeFormatter": { "history": { @@ -2913,5 +3185,13 @@ "codeExists": "This code is already taken, please try another", "codeInvalid": "Custom code only allows alphanumeric, hyphens, underscores, 3-20 chars" } + }, + "codeRunner": { + "run": "Run", + "clear": "Clear", + "outputEmpty": "Click Run to see output", + "practice": "Practice", + "pageTitle": "Run Code Online", + "pageDesc": "Run JavaScript and Python in a browser sandbox — write and practice as you learn" } } diff --git a/src/locales/ja.json b/src/locales/ja.json index 0108941..ea36a79 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -266,7 +266,11 @@ "desc": "プラットフォームの最新機能と改善を知る" }, "viewAll": "すべて表示", - "more": "もっと見る" + "more": "もっと見る", + "hotTools": { + "title": "人気ツールランキング", + "desc": "みんなが使っている効率ツール" + } }, "update": { "newFeature": "新機能", @@ -365,6 +369,18 @@ }, "common": { "viewDetails": "詳細を見る" + }, + "checkin": { + "title": "毎日チェックイン", + "notSignedToday": "今日まだチェックインしていません", + "signedToday": "今日チェックイン済み", + "weekProgress": "今週 {count} 日達成", + "loginHint": "毎日チェックインでポイント・コイン・経験値を獲得", + "loginBtn": "ログインしてチェックイン", + "btn": "チェックイン", + "signed": "済み", + "success": "チェックイン成功!", + "pointsUnit": "pt" } }, "tools": { @@ -596,7 +612,8 @@ "newest": "最新", "mostViews": "最多閲覧", "mostLikes": "最多いいね", - "mostComments": "最多コメント" + "mostComments": "最多コメント", + "following": "フォロー" }, "pagination": { "total": "{{count}} 件の記事", @@ -630,6 +647,12 @@ "following": "フォロー中", "follow": "+ フォロー", "updated": "更新日時" + }, + "empty": { + "title": "記事がありません", + "hint": "条件を変えて試してください", + "followingTitle": "フォロー中の作者がいません", + "followingHint": "作者をフォローするとここに表示されます" } }, "invite": { @@ -2235,36 +2258,284 @@ "other": "その他" }, "templates": { - "phone": { "label": "電話番号", "regex": "^1[3-9]\\d{9}$", "category": "basic", "desc": "中国の11桁携帯電話番号", "flags": { "g": true } }, - "email": { "label": "メールアドレス", "regex": "^[\\w-]+@[\\w-]+\\.[a-z]{2,}$", "category": "basic", "desc": "メールアドレス", "flags": { "g": true, "i": true } }, - "idCard": { "label": "身分証番号", "regex": "^[1-9]\\d{5}(19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[\\dXx]$", "category": "basic", "desc": "18桁身分証番号", "flags": { "g": true } }, - "bankCard": { "label": "銀行カード", "regex": "^\\d{16,19}$", "category": "basic", "desc": "16-19桁銀行カード番号", "flags": { "g": true } }, - "telephone": { "label": "固定電話", "regex": "^\\d{3,4}-?\\d{7,8}$", "category": "basic", "desc": "市外局番付き固定電話", "flags": { "g": true } }, - "zipCode": { "label": "郵便番号", "regex": "^[1-9]\\d{5}$", "category": "basic", "desc": "6桁郵便番号", "flags": { "g": true } }, - "url": { "label": "URL", "regex": "^https?:\\/\\/[\\w\\.-]+\\.[a-z]{2,}(\\/\\S*)?$", "category": "network", "desc": "HTTP/HTTPS URL", "flags": { "g": true, "i": true } }, - "ip": { "label": "IPアドレス", "regex": "^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)$", "category": "network", "desc": "IPv4アドレス", "flags": { "g": true } }, - "domain": { "label": "ドメイン", "regex": "^[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+$", "category": "network", "desc": "ドメイン名", "flags": { "g": true, "i": true } }, - "mac": { "label": "MACアドレス", "regex": "^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$", "category": "network", "desc": "MACアドレス", "flags": { "g": true, "i": true } }, - "number": { "label": "数値", "regex": "^-?\\d+(\\.\\d+)?$", "category": "number", "desc": "正負の整数または小数", "flags": { "g": true } }, - "integer": { "label": "整数", "regex": "^-?\\d+$", "category": "number", "desc": "正負の整数", "flags": { "g": true } }, - "positiveInteger": { "label": "正の整数", "regex": "^[1-9]\\d*$", "category": "number", "desc": "0より大きい整数", "flags": { "g": true } }, - "negativeInteger": { "label": "負の整数", "regex": "^-[1-9]\\d*$", "category": "number", "desc": "0より小さい整数", "flags": { "g": true } }, - "float": { "label": "浮動小数点", "regex": "^-?\\d+\\.\\d+$", "category": "number", "desc": "正負の小数", "flags": { "g": true } }, - "date": { "label": "日付", "regex": "^\\d{4}-\\d{2}-\\d{2}$", "category": "datetime", "desc": "YYYY-MM-DD形式", "flags": { "g": true } }, - "time": { "label": "時刻", "regex": "^([01]\\d|2[0-3]):[0-5]\\d(:[0-5]\\d)?$", "category": "datetime", "desc": "HH:MM:SS形式", "flags": { "g": true } }, - "datetime": { "label": "日時", "regex": "^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$", "category": "datetime", "desc": "YYYY-MM-DD HH:MM:SS", "flags": { "g": true } }, - "username": { "label": "ユーザー名", "regex": "^[a-zA-Z][a-zA-Z0-9_]{3,15}$", "category": "account", "desc": "4-16文字、英字で開始", "flags": { "g": true } }, - "password": { "label": "強力なパスワード", "regex": "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[\\s\\S]{8,}$", "category": "account", "desc": "8文字以上、大文字・小文字・数字を含む", "flags": { "g": true } }, - "imageFile": { "label": "画像ファイル", "regex": "\\.(jpg|jpeg|png|gif|bmp|svg)$", "category": "file", "desc": "一般的な画像形式", "flags": { "g": true, "i": true } }, - "docFile": { "label": "文書ファイル", "regex": "\\.(doc|docx|pdf|txt|xls|xlsx)$", "category": "file", "desc": "一般的な文書形式", "flags": { "g": true, "i": true } }, - "videoFile": { "label": "動画ファイル", "regex": "\\.(mp4|avi|mov|wmv|flv|mkv)$", "category": "file", "desc": "一般的な動画形式", "flags": { "g": true, "i": true } }, - "chinese": { "label": "中国語文字", "regex": "^[\\u4e00-\\u9fa5]+$", "category": "other", "desc": "中国語文字のみ", "flags": { "g": true } }, - "english": { "label": "英字", "regex": "^[a-zA-Z]+$", "category": "other", "desc": "英字のみ", "flags": { "g": true } }, - "htmlTag": { "label": "HTMLタグ", "regex": "<[^>]+>", "category": "other", "desc": "HTMLタグ", "flags": { "g": true } }, - "hexColor": { "label": "16進カラー", "regex": "^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$", "category": "other", "desc": "#RGBまたは#RRGGBB形式", "flags": { "g": true, "i": true } }, - "plateNumber": { "label": "番号プレート", "regex": "^[\\u4e00-\\u9fa5][A-Z][A-Z0-9]{5}$", "category": "other", "desc": "中国の車両番号", "flags": { "g": true } }, - "wechat": { "label": "WeChat ID", "regex": "^[a-zA-Z][-_a-zA-Z0-9]{5,19}$", "category": "other", "desc": "6-20文字、英字で開始", "flags": { "g": true } }, - "qq": { "label": "QQ番号", "regex": "^[1-9][0-9]{4,10}$", "category": "other", "desc": "5-11桁のQQ番号", "flags": { "g": true } } + "phone": { + "label": "電話番号", + "regex": "^1[3-9]\\d{9}$", + "category": "basic", + "desc": "中国の11桁携帯電話番号", + "flags": { + "g": true + } + }, + "email": { + "label": "メールアドレス", + "regex": "^[\\w-]+@[\\w-]+\\.[a-z]{2,}$", + "category": "basic", + "desc": "メールアドレス", + "flags": { + "g": true, + "i": true + } + }, + "idCard": { + "label": "身分証番号", + "regex": "^[1-9]\\d{5}(19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[\\dXx]$", + "category": "basic", + "desc": "18桁身分証番号", + "flags": { + "g": true + } + }, + "bankCard": { + "label": "銀行カード", + "regex": "^\\d{16,19}$", + "category": "basic", + "desc": "16-19桁銀行カード番号", + "flags": { + "g": true + } + }, + "telephone": { + "label": "固定電話", + "regex": "^\\d{3,4}-?\\d{7,8}$", + "category": "basic", + "desc": "市外局番付き固定電話", + "flags": { + "g": true + } + }, + "zipCode": { + "label": "郵便番号", + "regex": "^[1-9]\\d{5}$", + "category": "basic", + "desc": "6桁郵便番号", + "flags": { + "g": true + } + }, + "url": { + "label": "URL", + "regex": "^https?:\\/\\/[\\w\\.-]+\\.[a-z]{2,}(\\/\\S*)?$", + "category": "network", + "desc": "HTTP/HTTPS URL", + "flags": { + "g": true, + "i": true + } + }, + "ip": { + "label": "IPアドレス", + "regex": "^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)$", + "category": "network", + "desc": "IPv4アドレス", + "flags": { + "g": true + } + }, + "domain": { + "label": "ドメイン", + "regex": "^[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+$", + "category": "network", + "desc": "ドメイン名", + "flags": { + "g": true, + "i": true + } + }, + "mac": { + "label": "MACアドレス", + "regex": "^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$", + "category": "network", + "desc": "MACアドレス", + "flags": { + "g": true, + "i": true + } + }, + "number": { + "label": "数値", + "regex": "^-?\\d+(\\.\\d+)?$", + "category": "number", + "desc": "正負の整数または小数", + "flags": { + "g": true + } + }, + "integer": { + "label": "整数", + "regex": "^-?\\d+$", + "category": "number", + "desc": "正負の整数", + "flags": { + "g": true + } + }, + "positiveInteger": { + "label": "正の整数", + "regex": "^[1-9]\\d*$", + "category": "number", + "desc": "0より大きい整数", + "flags": { + "g": true + } + }, + "negativeInteger": { + "label": "負の整数", + "regex": "^-[1-9]\\d*$", + "category": "number", + "desc": "0より小さい整数", + "flags": { + "g": true + } + }, + "float": { + "label": "浮動小数点", + "regex": "^-?\\d+\\.\\d+$", + "category": "number", + "desc": "正負の小数", + "flags": { + "g": true + } + }, + "date": { + "label": "日付", + "regex": "^\\d{4}-\\d{2}-\\d{2}$", + "category": "datetime", + "desc": "YYYY-MM-DD形式", + "flags": { + "g": true + } + }, + "time": { + "label": "時刻", + "regex": "^([01]\\d|2[0-3]):[0-5]\\d(:[0-5]\\d)?$", + "category": "datetime", + "desc": "HH:MM:SS形式", + "flags": { + "g": true + } + }, + "datetime": { + "label": "日時", + "regex": "^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$", + "category": "datetime", + "desc": "YYYY-MM-DD HH:MM:SS", + "flags": { + "g": true + } + }, + "username": { + "label": "ユーザー名", + "regex": "^[a-zA-Z][a-zA-Z0-9_]{3,15}$", + "category": "account", + "desc": "4-16文字、英字で開始", + "flags": { + "g": true + } + }, + "password": { + "label": "強力なパスワード", + "regex": "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[\\s\\S]{8,}$", + "category": "account", + "desc": "8文字以上、大文字・小文字・数字を含む", + "flags": { + "g": true + } + }, + "imageFile": { + "label": "画像ファイル", + "regex": "\\.(jpg|jpeg|png|gif|bmp|svg)$", + "category": "file", + "desc": "一般的な画像形式", + "flags": { + "g": true, + "i": true + } + }, + "docFile": { + "label": "文書ファイル", + "regex": "\\.(doc|docx|pdf|txt|xls|xlsx)$", + "category": "file", + "desc": "一般的な文書形式", + "flags": { + "g": true, + "i": true + } + }, + "videoFile": { + "label": "動画ファイル", + "regex": "\\.(mp4|avi|mov|wmv|flv|mkv)$", + "category": "file", + "desc": "一般的な動画形式", + "flags": { + "g": true, + "i": true + } + }, + "chinese": { + "label": "中国語文字", + "regex": "^[\\u4e00-\\u9fa5]+$", + "category": "other", + "desc": "中国語文字のみ", + "flags": { + "g": true + } + }, + "english": { + "label": "英字", + "regex": "^[a-zA-Z]+$", + "category": "other", + "desc": "英字のみ", + "flags": { + "g": true + } + }, + "htmlTag": { + "label": "HTMLタグ", + "regex": "<[^>]+>", + "category": "other", + "desc": "HTMLタグ", + "flags": { + "g": true + } + }, + "hexColor": { + "label": "16進カラー", + "regex": "^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$", + "category": "other", + "desc": "#RGBまたは#RRGGBB形式", + "flags": { + "g": true, + "i": true + } + }, + "plateNumber": { + "label": "番号プレート", + "regex": "^[\\u4e00-\\u9fa5][A-Z][A-Z0-9]{5}$", + "category": "other", + "desc": "中国の車両番号", + "flags": { + "g": true + } + }, + "wechat": { + "label": "WeChat ID", + "regex": "^[a-zA-Z][-_a-zA-Z0-9]{5,19}$", + "category": "other", + "desc": "6-20文字、英字で開始", + "flags": { + "g": true + } + }, + "qq": { + "label": "QQ番号", + "regex": "^[1-9][0-9]{4,10}$", + "category": "other", + "desc": "5-11桁のQQ番号", + "flags": { + "g": true + } + } }, "matchCount": "{{count}} 件マッチ", "resultPos": "位置", @@ -2598,7 +2869,8 @@ "downloads": "ダウンロード数", "noMaterials": "コース資料なし", "noVideo": "動画チュートリアルなし", - "videoNotSupported": "お使いのブラウザは動画再生をサポートしていません" + "videoNotSupported": "お使いのブラウザは動画再生をサポートしていません", + "minutes": "分" }, "codeFormatter": { "history": { @@ -2793,5 +3065,13 @@ "copied": "クリップボードにコピーしました", "copyFailed": "コピーに失敗しました" } + }, + "codeRunner": { + "run": "実行", + "clear": "クリア", + "outputEmpty": "実行をクリックして出力を確認", + "practice": "オンライン練習", + "pageTitle": "コードオンライン実行", + "pageDesc": "ブラウザサンドボックスで JavaScript と Python を実行、学びながら即練習" } } diff --git a/src/locales/ko.json b/src/locales/ko.json index 5452ff2..940ddbf 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -266,7 +266,11 @@ "desc": "플랫폼의 최신 기능과 개선 사항 알아보기" }, "viewAll": "전체 보기", - "more": "더보기" + "more": "더보기", + "hotTools": { + "title": "인기 도구 순위", + "desc": "모두가 사용하는 효율 도구" + } }, "update": { "newFeature": "새 기능", @@ -365,6 +369,18 @@ }, "common": { "viewDetails": "상세 보기" + }, + "checkin": { + "title": "매일 출석 체크", + "notSignedToday": "오늘 아직 출석하지 않았어요", + "signedToday": "오늘 출석 완료", + "weekProgress": "이번 주 {count}일 완료", + "loginHint": "매일 출석하고 포인트·코인·경험치를 받으세요", + "loginBtn": "로그인 후 출석", + "btn": "출석하기", + "signed": "완료", + "success": "출석 성공!", + "pointsUnit": "P" } }, "tools": { @@ -596,7 +612,8 @@ "newest": "최신", "mostViews": "조회수最多的", "mostLikes": "좋아요最多的", - "mostComments": "댓글最多的" + "mostComments": "댓글最多的", + "following": "팔로잉" }, "pagination": { "total": "{{count}}개의 아티클", @@ -630,6 +647,12 @@ "following": "팔로우 중", "follow": "+ 팔로우", "updated": "수정 시간" + }, + "empty": { + "title": "게시글이 없습니다", + "hint": "다른 조건으로 시도해 보세요", + "followingTitle": "팔로우한 작가가 없습니다", + "followingHint": "작가를 팔로우하면 여기에 표시됩니다" } }, "taskCenter": { @@ -2826,7 +2849,8 @@ "downloads": "다운로드 수", "noMaterials": "코스 자료 없음", "noVideo": "동영상 튜토리얼 없음", - "videoNotSupported": "브라우저가 동영상 재생을 지원하지 않습니다" + "videoNotSupported": "브라우저가 동영상 재생을 지원하지 않습니다", + "minutes": "분" }, "codeFormatter": { "history": { @@ -3021,5 +3045,13 @@ "copied": "클립보드에 복사되었습니다", "copyFailed": "복사에 실패했습니다" } + }, + "codeRunner": { + "run": "실행", + "clear": "지우기", + "outputEmpty": "실행을 눌러 출력을 확인하세요", + "practice": "온라인 연습", + "pageTitle": "코드 온라인 실행", + "pageDesc": "브라우저 샌드박스에서 JavaScript와 Python을 실행하고 배우면서 바로 연습하세요" } } diff --git a/src/locales/ru.json b/src/locales/ru.json index 918f560..48d92c5 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -266,7 +266,11 @@ "desc": "Узнайте о новых функциях и улучшениях платформы" }, "viewAll": "Показать все", - "more": "Еще" + "more": "Еще", + "hotTools": { + "title": "Популярные инструменты", + "desc": "Самые используемые инструменты" + } }, "update": { "newFeature": "Новая функция", @@ -365,6 +369,18 @@ }, "common": { "viewDetails": "Посмотреть детали" + }, + "checkin": { + "title": "Ежедневная отметка", + "notSignedToday": "Сегодня ещё не отмечались", + "signedToday": "Сегодня уже отмечались", + "weekProgress": "{count} дн. на этой неделе", + "loginHint": "Отмечайтесь ежедневно и получайте очки, монеты и опыт", + "loginBtn": "Войдите, чтобы отметить", + "btn": "Отметиться", + "signed": "Отмечено", + "success": "Успешно!", + "pointsUnit": "очк." } }, "tools": { @@ -596,7 +612,8 @@ "newest": "Последние", "mostViews": "По просмотрам", "mostLikes": "По лайкам", - "mostComments": "По комментариям" + "mostComments": "По комментариям", + "following": "Подписки" }, "pagination": { "total": "{{count}} статей", @@ -630,6 +647,12 @@ "following": "Подписки", "follow": "+ Подписаться", "updated": "Обновлено" + }, + "empty": { + "title": "Статей пока нет", + "hint": "Попробуйте другой фильтр", + "followingTitle": "Вы пока ни на кого не подписаны", + "followingHint": "Подпишитесь на авторов, и их статьи появятся здесь" } }, "invite": { @@ -2120,36 +2143,284 @@ "other": "Прочее" }, "templates": { - "phone": { "label": "Телефон", "regex": "^1[3-9]\\d{9}$", "category": "basic", "desc": "11-значный китайский мобильный", "flags": { "g": true } }, - "email": { "label": "Email", "regex": "^[\\w-]+@[\\w-]+\\.[a-z]{2,}$", "category": "basic", "desc": "Email адрес", "flags": { "g": true, "i": true } }, - "idCard": { "label": "Удостоверение", "regex": "^[1-9]\\d{5}(19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[\\dXx]$", "category": "basic", "desc": "18-значный номер удостоверения", "flags": { "g": true } }, - "bankCard": { "label": "Банковская карта", "regex": "^\\d{16,19}$", "category": "basic", "desc": "16-19 цифр банковской карты", "flags": { "g": true } }, - "telephone": { "label": "Стационарный", "regex": "^\\d{3,4}-?\\d{7,8}$", "category": "basic", "desc": "Стационарный телефон с кодом города", "flags": { "g": true } }, - "zipCode": { "label": "Почтовый индекс", "regex": "^[1-9]\\d{5}$", "category": "basic", "desc": "6-значный почтовый индекс", "flags": { "g": true } }, - "url": { "label": "URL", "regex": "^https?:\\/\\/[\\w\\.-]+\\.[a-z]{2,}(\\/\\S*)?$", "category": "network", "desc": "HTTP/HTTPS адрес", "flags": { "g": true, "i": true } }, - "ip": { "label": "IP-адрес", "regex": "^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)$", "category": "network", "desc": "IPv4 адрес", "flags": { "g": true } }, - "domain": { "label": "Домен", "regex": "^[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+$", "category": "network", "desc": "Доменное имя", "flags": { "g": true, "i": true } }, - "mac": { "label": "MAC-адрес", "regex": "^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$", "category": "network", "desc": "MAC адрес", "flags": { "g": true, "i": true } }, - "number": { "label": "Число", "regex": "^-?\\d+(\\.\\d+)?$", "category": "number", "desc": "Положительное/отрицательное целое или десятичное", "flags": { "g": true } }, - "integer": { "label": "Целое", "regex": "^-?\\d+$", "category": "number", "desc": "Положительное/отрицательное целое", "flags": { "g": true } }, - "positiveInteger": { "label": "Положительное", "regex": "^[1-9]\\d*$", "category": "number", "desc": "Больше 0", "flags": { "g": true } }, - "negativeInteger": { "label": "Отрицательное", "regex": "^-[1-9]\\d*$", "category": "number", "desc": "Меньше 0", "flags": { "g": true } }, - "float": { "label": "Десятичное", "regex": "^-?\\d+\\.\\d+$", "category": "number", "desc": "Положительное/отрицательное десятичное", "flags": { "g": true } }, - "date": { "label": "Дата", "regex": "^\\d{4}-\\d{2}-\\d{2}$", "category": "datetime", "desc": "ГГГГ-ММ-ДД формат", "flags": { "g": true } }, - "time": { "label": "Время", "regex": "^([01]\\d|2[0-3]):[0-5]\\d(:[0-5]\\d)?$", "category": "datetime", "desc": "ЧЧ:ММ:СС формат", "flags": { "g": true } }, - "datetime": { "label": "Дата и время", "regex": "^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$", "category": "datetime", "desc": "ГГГГ-ММ-ДД ЧЧ:ММ:СС", "flags": { "g": true } }, - "username": { "label": "Имя пользователя", "regex": "^[a-zA-Z][a-zA-Z0-9_]{3,15}$", "category": "account", "desc": "4-16 символов, начинается с буквы", "flags": { "g": true } }, - "password": { "label": "Надёжный пароль", "regex": "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[\\s\\S]{8,}$", "category": "account", "desc": "8+ символов с верхним, нижним регистром и цифрой", "flags": { "g": true } }, - "imageFile": { "label": "Изображение", "regex": "\\.(jpg|jpeg|png|gif|bmp|svg)$", "category": "file", "desc": "Распространённые форматы изображений", "flags": { "g": true, "i": true } }, - "docFile": { "label": "Документ", "regex": "\\.(doc|docx|pdf|txt|xls|xlsx)$", "category": "file", "desc": "Распространённые форматы документов", "flags": { "g": true, "i": true } }, - "videoFile": { "label": "Видео", "regex": "\\.(mp4|avi|mov|wmv|flv|mkv)$", "category": "file", "desc": "Распространённые форматы видео", "flags": { "g": true, "i": true } }, - "chinese": { "label": "Китайские", "regex": "^[\\u4e00-\\u9fa5]+$", "category": "other", "desc": "Только китайские символы", "flags": { "g": true } }, - "english": { "label": "Английские", "regex": "^[a-zA-Z]+$", "category": "other", "desc": "Только английские буквы", "flags": { "g": true } }, - "htmlTag": { "label": "HTML-тег", "regex": "<[^>]+>", "category": "other", "desc": "HTML тег", "flags": { "g": true } }, - "hexColor": { "label": "Hex-цвет", "regex": "^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$", "category": "other", "desc": "#RGB или #RRGGBB формат", "flags": { "g": true, "i": true } }, - "plateNumber": { "label": "Номер авто", "regex": "^[\\u4e00-\\u9fa5][A-Z][A-Z0-9]{5}$", "category": "other", "desc": "Китайский номер автомобиля", "flags": { "g": true } }, - "wechat": { "label": "WeChat", "regex": "^[a-zA-Z][-_a-zA-Z0-9]{5,19}$", "category": "other", "desc": "6-20 символов, начинается с буквы", "flags": { "g": true } }, - "qq": { "label": "QQ", "regex": "^[1-9][0-9]{4,10}$", "category": "other", "desc": "5-11 цифр QQ номер", "flags": { "g": true } } + "phone": { + "label": "Телефон", + "regex": "^1[3-9]\\d{9}$", + "category": "basic", + "desc": "11-значный китайский мобильный", + "flags": { + "g": true + } + }, + "email": { + "label": "Email", + "regex": "^[\\w-]+@[\\w-]+\\.[a-z]{2,}$", + "category": "basic", + "desc": "Email адрес", + "flags": { + "g": true, + "i": true + } + }, + "idCard": { + "label": "Удостоверение", + "regex": "^[1-9]\\d{5}(19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[\\dXx]$", + "category": "basic", + "desc": "18-значный номер удостоверения", + "flags": { + "g": true + } + }, + "bankCard": { + "label": "Банковская карта", + "regex": "^\\d{16,19}$", + "category": "basic", + "desc": "16-19 цифр банковской карты", + "flags": { + "g": true + } + }, + "telephone": { + "label": "Стационарный", + "regex": "^\\d{3,4}-?\\d{7,8}$", + "category": "basic", + "desc": "Стационарный телефон с кодом города", + "flags": { + "g": true + } + }, + "zipCode": { + "label": "Почтовый индекс", + "regex": "^[1-9]\\d{5}$", + "category": "basic", + "desc": "6-значный почтовый индекс", + "flags": { + "g": true + } + }, + "url": { + "label": "URL", + "regex": "^https?:\\/\\/[\\w\\.-]+\\.[a-z]{2,}(\\/\\S*)?$", + "category": "network", + "desc": "HTTP/HTTPS адрес", + "flags": { + "g": true, + "i": true + } + }, + "ip": { + "label": "IP-адрес", + "regex": "^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)$", + "category": "network", + "desc": "IPv4 адрес", + "flags": { + "g": true + } + }, + "domain": { + "label": "Домен", + "regex": "^[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+$", + "category": "network", + "desc": "Доменное имя", + "flags": { + "g": true, + "i": true + } + }, + "mac": { + "label": "MAC-адрес", + "regex": "^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$", + "category": "network", + "desc": "MAC адрес", + "flags": { + "g": true, + "i": true + } + }, + "number": { + "label": "Число", + "regex": "^-?\\d+(\\.\\d+)?$", + "category": "number", + "desc": "Положительное/отрицательное целое или десятичное", + "flags": { + "g": true + } + }, + "integer": { + "label": "Целое", + "regex": "^-?\\d+$", + "category": "number", + "desc": "Положительное/отрицательное целое", + "flags": { + "g": true + } + }, + "positiveInteger": { + "label": "Положительное", + "regex": "^[1-9]\\d*$", + "category": "number", + "desc": "Больше 0", + "flags": { + "g": true + } + }, + "negativeInteger": { + "label": "Отрицательное", + "regex": "^-[1-9]\\d*$", + "category": "number", + "desc": "Меньше 0", + "flags": { + "g": true + } + }, + "float": { + "label": "Десятичное", + "regex": "^-?\\d+\\.\\d+$", + "category": "number", + "desc": "Положительное/отрицательное десятичное", + "flags": { + "g": true + } + }, + "date": { + "label": "Дата", + "regex": "^\\d{4}-\\d{2}-\\d{2}$", + "category": "datetime", + "desc": "ГГГГ-ММ-ДД формат", + "flags": { + "g": true + } + }, + "time": { + "label": "Время", + "regex": "^([01]\\d|2[0-3]):[0-5]\\d(:[0-5]\\d)?$", + "category": "datetime", + "desc": "ЧЧ:ММ:СС формат", + "flags": { + "g": true + } + }, + "datetime": { + "label": "Дата и время", + "regex": "^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$", + "category": "datetime", + "desc": "ГГГГ-ММ-ДД ЧЧ:ММ:СС", + "flags": { + "g": true + } + }, + "username": { + "label": "Имя пользователя", + "regex": "^[a-zA-Z][a-zA-Z0-9_]{3,15}$", + "category": "account", + "desc": "4-16 символов, начинается с буквы", + "flags": { + "g": true + } + }, + "password": { + "label": "Надёжный пароль", + "regex": "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[\\s\\S]{8,}$", + "category": "account", + "desc": "8+ символов с верхним, нижним регистром и цифрой", + "flags": { + "g": true + } + }, + "imageFile": { + "label": "Изображение", + "regex": "\\.(jpg|jpeg|png|gif|bmp|svg)$", + "category": "file", + "desc": "Распространённые форматы изображений", + "flags": { + "g": true, + "i": true + } + }, + "docFile": { + "label": "Документ", + "regex": "\\.(doc|docx|pdf|txt|xls|xlsx)$", + "category": "file", + "desc": "Распространённые форматы документов", + "flags": { + "g": true, + "i": true + } + }, + "videoFile": { + "label": "Видео", + "regex": "\\.(mp4|avi|mov|wmv|flv|mkv)$", + "category": "file", + "desc": "Распространённые форматы видео", + "flags": { + "g": true, + "i": true + } + }, + "chinese": { + "label": "Китайские", + "regex": "^[\\u4e00-\\u9fa5]+$", + "category": "other", + "desc": "Только китайские символы", + "flags": { + "g": true + } + }, + "english": { + "label": "Английские", + "regex": "^[a-zA-Z]+$", + "category": "other", + "desc": "Только английские буквы", + "flags": { + "g": true + } + }, + "htmlTag": { + "label": "HTML-тег", + "regex": "<[^>]+>", + "category": "other", + "desc": "HTML тег", + "flags": { + "g": true + } + }, + "hexColor": { + "label": "Hex-цвет", + "regex": "^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$", + "category": "other", + "desc": "#RGB или #RRGGBB формат", + "flags": { + "g": true, + "i": true + } + }, + "plateNumber": { + "label": "Номер авто", + "regex": "^[\\u4e00-\\u9fa5][A-Z][A-Z0-9]{5}$", + "category": "other", + "desc": "Китайский номер автомобиля", + "flags": { + "g": true + } + }, + "wechat": { + "label": "WeChat", + "regex": "^[a-zA-Z][-_a-zA-Z0-9]{5,19}$", + "category": "other", + "desc": "6-20 символов, начинается с буквы", + "flags": { + "g": true + } + }, + "qq": { + "label": "QQ", + "regex": "^[1-9][0-9]{4,10}$", + "category": "other", + "desc": "5-11 цифр QQ номер", + "flags": { + "g": true + } + } }, "matchCount": "Совпадений: {{count}}", "resultPos": "Позиция", @@ -2586,7 +2857,8 @@ "downloads": "Загрузки", "noMaterials": "Нет материалов курса", "noVideo": "Нет видеоурока", - "videoNotSupported": "Ваш браузер не поддерживает воспроизведение видео" + "videoNotSupported": "Ваш браузер не поддерживает воспроизведение видео", + "minutes": "мин" }, "codeFormatter": { "history": { @@ -2781,5 +3053,13 @@ "copied": "Скопировано в буфер обмена", "copyFailed": "Не удалось скопировать" } + }, + "codeRunner": { + "run": "Запустить", + "clear": "Очистить", + "outputEmpty": "Нажмите «Запустить», чтобы увидеть вывод", + "practice": "Практика", + "pageTitle": "Запуск кода онлайн", + "pageDesc": "Запускайте JavaScript и Python в песочнице браузера — учитесь и практикуйтесь сразу" } } diff --git a/src/locales/zh-TW.json b/src/locales/zh-TW.json index 1f2835e..bfca768 100644 --- a/src/locales/zh-TW.json +++ b/src/locales/zh-TW.json @@ -266,7 +266,11 @@ "desc": "了解平台的最新功能和改進" }, "viewAll": "查看全部", - "more": "更多" + "more": "更多", + "hotTools": { + "title": "熱門工具榜", + "desc": "大家都在用的效率工具" + } }, "update": { "newFeature": "新功能", @@ -365,6 +369,18 @@ }, "common": { "viewDetails": "查看詳情" + }, + "checkin": { + "title": "每日簽到", + "notSignedToday": "今日還未簽到", + "signedToday": "今日已簽到", + "weekProgress": "本週已簽到 {count} 天", + "loginHint": "連續簽到領積分、金幣和經驗", + "loginBtn": "登入後簽到", + "btn": "立即簽到", + "signed": "已簽到", + "success": "簽到成功!", + "pointsUnit": "積分" } }, "tools": { @@ -574,7 +590,8 @@ "newest": "最新發布", "mostViews": "最多瀏覽", "mostLikes": "最多喜歡", - "mostComments": "最多評論" + "mostComments": "最多評論", + "following": "關注" }, "pagination": { "total": "共 {{count}} 篇文章", @@ -608,6 +625,12 @@ "following": "已關注", "follow": "+ 關注", "updated": "更新時間" + }, + "empty": { + "title": "暫無文章", + "hint": "換個篩選條件試試", + "followingTitle": "還沒有關注任何作者", + "followingHint": "去關注感興趣的作者,這裡只顯示他們的文章" } }, "invite": { @@ -2661,7 +2684,8 @@ "downloads": "下載次數", "noMaterials": "暫無課程資料", "noVideo": "暫無視頻教程", - "videoNotSupported": "您的瀏覽器不支持視頻播放" + "videoNotSupported": "您的瀏覽器不支持視頻播放", + "minutes": "分鐘" }, "codeFormatter": { "history": { @@ -2856,5 +2880,13 @@ "copied": "已複製到剪貼簿", "copyFailed": "複製失敗" } + }, + "codeRunner": { + "run": "執行", + "clear": "清空", + "outputEmpty": "點擊執行查看輸出", + "practice": "線上練習", + "pageTitle": "程式碼線上執行", + "pageDesc": "在瀏覽器沙箱中執行 JavaScript 與 Python 程式碼,學習時即寫即練" } } diff --git a/src/locales/zh.json b/src/locales/zh.json index 663a79a..afbb08f 100644 --- a/src/locales/zh.json +++ b/src/locales/zh.json @@ -266,7 +266,11 @@ "desc": "了解平台的最新功能和改进" }, "viewAll": "查看全部", - "more": "更多" + "more": "更多", + "hotTools": { + "title": "热门工具榜", + "desc": "大家都在用的效率工具" + } }, "update": { "newFeature": "新功能", @@ -365,6 +369,18 @@ }, "common": { "viewDetails": "查看详情" + }, + "checkin": { + "title": "每日签到", + "notSignedToday": "今日还未签到", + "signedToday": "今日已签到", + "weekProgress": "本周已签到 {count} 天", + "loginHint": "连续签到领积分、金币和经验", + "loginBtn": "登录后签到", + "btn": "立即签到", + "signed": "已签到", + "success": "签到成功!", + "pointsUnit": "积分" } }, "tools": { @@ -624,7 +640,8 @@ "downloads": "下载次数", "noMaterials": "暂无课程资料", "noVideo": "暂无视频教程", - "videoNotSupported": "您的浏览器不支持视频播放" + "videoNotSupported": "您的浏览器不支持视频播放", + "minutes": "分钟" }, "articles": { "hero": { @@ -687,7 +704,8 @@ "newest": "最新发布", "mostViews": "最多浏览", "mostLikes": "最多喜欢", - "mostComments": "最多评论" + "mostComments": "最多评论", + "following": "关注" }, "pagination": { "total": "共 {{count}} 篇文章", @@ -721,6 +739,12 @@ "following": "已关注", "follow": "+ 关注", "updated": "更新时间" + }, + "empty": { + "title": "暂无文章", + "hint": "换个筛选条件试试", + "followingTitle": "还没有关注任何作者", + "followingHint": "去关注感兴趣的作者,这里只显示他们的文章" } }, "invite": { @@ -2499,78 +2523,326 @@ "historyCategory": "设计" }, "regexTool": { - "heroTitle": "正则表达式测试", - "heroSubtitle": "在线正则测试、匹配高亮与常用正则生成", - "backToTools": "返回", - "copyRegex": "复制正则", - "copied": "已复制", - "clear": "清空", - "panelRegex": "正则表达式", - "panelTestText": "测试文本与结果", - "placeholderRegex": "输入正则表达式...", - "placeholderTestText": "输入测试文本...", - "flagG": "g (全局)", - "flagI": "i (忽略大小写)", - "flagM": "m (多行)", - "flagS": "s (点匹配换行)", - "presetTitle": "常用正则模板", - "searchPlaceholder": "搜索正则模板...", - "searchResult": "找到 {{count}} 个模板", - "noSearchResult": "未找到匹配的模板", - "categories": { - "basic": "基础验证", - "network": "网络相关", - "number": "数字格式", - "datetime": "日期时间", - "account": "用户名密码", - "file": "文件格式", - "other": "其他" + "heroTitle": "正则表达式测试", + "heroSubtitle": "在线正则测试、匹配高亮与常用正则生成", + "backToTools": "返回", + "copyRegex": "复制正则", + "copied": "已复制", + "clear": "清空", + "panelRegex": "正则表达式", + "panelTestText": "测试文本与结果", + "placeholderRegex": "输入正则表达式...", + "placeholderTestText": "输入测试文本...", + "flagG": "g (全局)", + "flagI": "i (忽略大小写)", + "flagM": "m (多行)", + "flagS": "s (点匹配换行)", + "presetTitle": "常用正则模板", + "searchPlaceholder": "搜索正则模板...", + "searchResult": "找到 {{count}} 个模板", + "noSearchResult": "未找到匹配的模板", + "categories": { + "basic": "基础验证", + "network": "网络相关", + "number": "数字格式", + "datetime": "日期时间", + "account": "用户名密码", + "file": "文件格式", + "other": "其他" + }, + "templates": { + "phone": { + "label": "手机号", + "regex": "^1[3-9]\\d{9}$", + "category": "basic", + "desc": "中国大陆11位手机号码", + "flags": { + "g": true + } }, - "templates": { - "phone": { "label": "手机号", "regex": "^1[3-9]\\d{9}$", "category": "basic", "desc": "中国大陆11位手机号码", "flags": { "g": true } }, - "email": { "label": "邮箱", "regex": "^[\\w-]+@[\\w-]+\\.[a-z]{2,}$", "category": "basic", "desc": "电子邮箱地址", "flags": { "g": true, "i": true } }, - "idCard": { "label": "身份证", "regex": "^[1-9]\\d{5}(19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[\\dXx]$", "category": "basic", "desc": "18位身份证号码", "flags": { "g": true } }, - "bankCard": { "label": "银行卡", "regex": "^\\d{16,19}$", "category": "basic", "desc": "16-19位银行卡号", "flags": { "g": true } }, - "telephone": { "label": "固定电话", "regex": "^\\d{3,4}-?\\d{7,8}$", "category": "basic", "desc": "带区号的固定电话", "flags": { "g": true } }, - "zipCode": { "label": "邮政编码", "regex": "^[1-9]\\d{5}$", "category": "basic", "desc": "6位邮政编码", "flags": { "g": true } }, - "url": { "label": "URL", "regex": "^https?:\\/\\/[\\w\\.-]+\\.[a-z]{2,}(\\/\\S*)?$", "category": "network", "desc": "HTTP/HTTPS网址", "flags": { "g": true, "i": true } }, - "ip": { "label": "IP地址", "regex": "^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)$", "category": "network", "desc": "IPv4地址", "flags": { "g": true } }, - "domain": { "label": "域名", "regex": "^[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+$", "category": "network", "desc": "域名地址", "flags": { "g": true, "i": true } }, - "mac": { "label": "MAC地址", "regex": "^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$", "category": "network", "desc": "MAC物理地址", "flags": { "g": true, "i": true } }, - "number": { "label": "数字", "regex": "^-?\\d+(\\.\\d+)?$", "category": "number", "desc": "正负整数或小数", "flags": { "g": true } }, - "integer": { "label": "整数", "regex": "^-?\\d+$", "category": "number", "desc": "正负整数", "flags": { "g": true } }, - "positiveInteger": { "label": "正整数", "regex": "^[1-9]\\d*$", "category": "number", "desc": "大于0的整数", "flags": { "g": true } }, - "negativeInteger": { "label": "负整数", "regex": "^-[1-9]\\d*$", "category": "number", "desc": "小于0的整数", "flags": { "g": true } }, - "float": { "label": "浮点数", "regex": "^-?\\d+\\.\\d+$", "category": "number", "desc": "正负小数", "flags": { "g": true } }, - "date": { "label": "日期", "regex": "^\\d{4}-\\d{2}-\\d{2}$", "category": "datetime", "desc": "YYYY-MM-DD格式", "flags": { "g": true } }, - "time": { "label": "时间", "regex": "^([01]\\d|2[0-3]):[0-5]\\d(:[0-5]\\d)?$", "category": "datetime", "desc": "HH:MM:SS格式", "flags": { "g": true } }, - "datetime": { "label": "日期时间", "regex": "^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$", "category": "datetime", "desc": "YYYY-MM-DD HH:MM:SS", "flags": { "g": true } }, - "username": { "label": "用户名", "regex": "^[a-zA-Z][a-zA-Z0-9_]{3,15}$", "category": "account", "desc": "4-16位字母开头", "flags": { "g": true } }, - "password": { "label": "强密码", "regex": "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[\\s\\S]{8,}$", "category": "account", "desc": "8位以上含大小写字母和数字", "flags": { "g": true } }, - "imageFile": { "label": "图片文件", "regex": "\\.(jpg|jpeg|png|gif|bmp|svg)$", "category": "file", "desc": "常见图片格式", "flags": { "g": true, "i": true } }, - "docFile": { "label": "文档文件", "regex": "\\.(doc|docx|pdf|txt|xls|xlsx)$", "category": "file", "desc": "常见文档格式", "flags": { "g": true, "i": true } }, - "videoFile": { "label": "视频文件", "regex": "\\.(mp4|avi|mov|wmv|flv|mkv)$", "category": "file", "desc": "常见视频格式", "flags": { "g": true, "i": true } }, - "chinese": { "label": "中文字符", "regex": "^[\\u4e00-\\u9fa5]+$", "category": "other", "desc": "纯中文字符", "flags": { "g": true } }, - "english": { "label": "英文字母", "regex": "^[a-zA-Z]+$", "category": "other", "desc": "纯英文字母", "flags": { "g": true } }, - "htmlTag": { "label": "HTML标签", "regex": "<[^>]+>", "category": "other", "desc": "HTML标签", "flags": { "g": true } }, - "hexColor": { "label": "十六进制颜色", "regex": "^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$", "category": "other", "desc": "#RGB或#RRGGBB格式", "flags": { "g": true, "i": true } }, - "plateNumber": { "label": "车牌号", "regex": "^[\\u4e00-\\u9fa5][A-Z][A-Z0-9]{5}$", "category": "other", "desc": "中国车牌号", "flags": { "g": true } }, - "wechat": { "label": "微信号", "regex": "^[a-zA-Z][-_a-zA-Z0-9]{5,19}$", "category": "other", "desc": "6-20位字母开头", "flags": { "g": true } }, - "qq": { "label": "QQ号", "regex": "^[1-9][0-9]{4,10}$", "category": "other", "desc": "5-11位数字", "flags": { "g": true } } + "email": { + "label": "邮箱", + "regex": "^[\\w-]+@[\\w-]+\\.[a-z]{2,}$", + "category": "basic", + "desc": "电子邮箱地址", + "flags": { + "g": true, + "i": true + } }, - "matchCount": "匹配 {{count}} 个", - "resultPos": "位置", - "noMatch": "无匹配结果", - "msg": { - "enterRegex": "请先输入正则表达式", - "copied": "已复制到剪贴板" + "idCard": { + "label": "身份证", + "regex": "^[1-9]\\d{5}(19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[\\dXx]$", + "category": "basic", + "desc": "18位身份证号码", + "flags": { + "g": true + } }, - "record": { - "title": "正则表达式测试", - "description": "在线正则测试、匹配高亮与常用正则生成", - "category": "开发" + "bankCard": { + "label": "银行卡", + "regex": "^\\d{16,19}$", + "category": "basic", + "desc": "16-19位银行卡号", + "flags": { + "g": true + } + }, + "telephone": { + "label": "固定电话", + "regex": "^\\d{3,4}-?\\d{7,8}$", + "category": "basic", + "desc": "带区号的固定电话", + "flags": { + "g": true + } + }, + "zipCode": { + "label": "邮政编码", + "regex": "^[1-9]\\d{5}$", + "category": "basic", + "desc": "6位邮政编码", + "flags": { + "g": true + } + }, + "url": { + "label": "URL", + "regex": "^https?:\\/\\/[\\w\\.-]+\\.[a-z]{2,}(\\/\\S*)?$", + "category": "network", + "desc": "HTTP/HTTPS网址", + "flags": { + "g": true, + "i": true + } + }, + "ip": { + "label": "IP地址", + "regex": "^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)$", + "category": "network", + "desc": "IPv4地址", + "flags": { + "g": true + } + }, + "domain": { + "label": "域名", + "regex": "^[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+$", + "category": "network", + "desc": "域名地址", + "flags": { + "g": true, + "i": true + } + }, + "mac": { + "label": "MAC地址", + "regex": "^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$", + "category": "network", + "desc": "MAC物理地址", + "flags": { + "g": true, + "i": true + } + }, + "number": { + "label": "数字", + "regex": "^-?\\d+(\\.\\d+)?$", + "category": "number", + "desc": "正负整数或小数", + "flags": { + "g": true + } + }, + "integer": { + "label": "整数", + "regex": "^-?\\d+$", + "category": "number", + "desc": "正负整数", + "flags": { + "g": true + } + }, + "positiveInteger": { + "label": "正整数", + "regex": "^[1-9]\\d*$", + "category": "number", + "desc": "大于0的整数", + "flags": { + "g": true + } + }, + "negativeInteger": { + "label": "负整数", + "regex": "^-[1-9]\\d*$", + "category": "number", + "desc": "小于0的整数", + "flags": { + "g": true + } + }, + "float": { + "label": "浮点数", + "regex": "^-?\\d+\\.\\d+$", + "category": "number", + "desc": "正负小数", + "flags": { + "g": true + } + }, + "date": { + "label": "日期", + "regex": "^\\d{4}-\\d{2}-\\d{2}$", + "category": "datetime", + "desc": "YYYY-MM-DD格式", + "flags": { + "g": true + } + }, + "time": { + "label": "时间", + "regex": "^([01]\\d|2[0-3]):[0-5]\\d(:[0-5]\\d)?$", + "category": "datetime", + "desc": "HH:MM:SS格式", + "flags": { + "g": true + } + }, + "datetime": { + "label": "日期时间", + "regex": "^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$", + "category": "datetime", + "desc": "YYYY-MM-DD HH:MM:SS", + "flags": { + "g": true + } + }, + "username": { + "label": "用户名", + "regex": "^[a-zA-Z][a-zA-Z0-9_]{3,15}$", + "category": "account", + "desc": "4-16位字母开头", + "flags": { + "g": true + } + }, + "password": { + "label": "强密码", + "regex": "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[\\s\\S]{8,}$", + "category": "account", + "desc": "8位以上含大小写字母和数字", + "flags": { + "g": true + } + }, + "imageFile": { + "label": "图片文件", + "regex": "\\.(jpg|jpeg|png|gif|bmp|svg)$", + "category": "file", + "desc": "常见图片格式", + "flags": { + "g": true, + "i": true + } + }, + "docFile": { + "label": "文档文件", + "regex": "\\.(doc|docx|pdf|txt|xls|xlsx)$", + "category": "file", + "desc": "常见文档格式", + "flags": { + "g": true, + "i": true + } + }, + "videoFile": { + "label": "视频文件", + "regex": "\\.(mp4|avi|mov|wmv|flv|mkv)$", + "category": "file", + "desc": "常见视频格式", + "flags": { + "g": true, + "i": true + } + }, + "chinese": { + "label": "中文字符", + "regex": "^[\\u4e00-\\u9fa5]+$", + "category": "other", + "desc": "纯中文字符", + "flags": { + "g": true + } + }, + "english": { + "label": "英文字母", + "regex": "^[a-zA-Z]+$", + "category": "other", + "desc": "纯英文字母", + "flags": { + "g": true + } + }, + "htmlTag": { + "label": "HTML标签", + "regex": "<[^>]+>", + "category": "other", + "desc": "HTML标签", + "flags": { + "g": true + } + }, + "hexColor": { + "label": "十六进制颜色", + "regex": "^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$", + "category": "other", + "desc": "#RGB或#RRGGBB格式", + "flags": { + "g": true, + "i": true + } + }, + "plateNumber": { + "label": "车牌号", + "regex": "^[\\u4e00-\\u9fa5][A-Z][A-Z0-9]{5}$", + "category": "other", + "desc": "中国车牌号", + "flags": { + "g": true + } + }, + "wechat": { + "label": "微信号", + "regex": "^[a-zA-Z][-_a-zA-Z0-9]{5,19}$", + "category": "other", + "desc": "6-20位字母开头", + "flags": { + "g": true + } + }, + "qq": { + "label": "QQ号", + "regex": "^[1-9][0-9]{4,10}$", + "category": "other", + "desc": "5-11位数字", + "flags": { + "g": true + } } }, + "matchCount": "匹配 {{count}} 个", + "resultPos": "位置", + "noMatch": "无匹配结果", + "msg": { + "enterRegex": "请先输入正则表达式", + "copied": "已复制到剪贴板" + }, + "record": { + "title": "正则表达式测试", + "description": "在线正则测试、匹配高亮与常用正则生成", + "category": "开发" + } + }, "timestamp": { "pageTitle": "时间戳转换", "pageDescription": "Unix时间戳与日期时间快速互转", @@ -2968,17 +3240,17 @@ "exportQuality": "导出质量" }, "filter": { - "none": "原图", - "gray": "黑白", - "sepia": "复古", - "invert": "反色", - "brightness": "明亮", - "contrast": "高对比", - "blur": "模糊", - "warm": "暖色调", - "cool": "冷色调", - "vintage": "胶片" - }, + "none": "原图", + "gray": "黑白", + "sepia": "复古", + "invert": "反色", + "brightness": "明亮", + "contrast": "高对比", + "blur": "模糊", + "warm": "暖色调", + "cool": "冷色调", + "vintage": "胶片" + }, "format": { "png": "PNG", "jpeg": "JPEG" @@ -3169,5 +3441,13 @@ "codeExists": "该短码已被使用,请更换", "codeInvalid": "自定义短码仅允许字母、数字、连字符、下划线,长度3-20字符" } + }, + "codeRunner": { + "run": "运行", + "clear": "清空", + "outputEmpty": "点击运行查看输出", + "practice": "在线练习", + "pageTitle": "代码在线运行", + "pageDesc": "在浏览器沙箱中运行 JavaScript 与 Python 代码,学习时即写即练" } } diff --git a/src/qrcode.d.ts b/src/qrcode.d.ts new file mode 100644 index 0000000..f2ba7cd --- /dev/null +++ b/src/qrcode.d.ts @@ -0,0 +1,17 @@ +declare module 'qrcode' { + export interface QRCode { + modules: BitMatrix; + } + export interface BitMatrix { + size: number; + get(row: number, col: number): number; + } + export type QRCodeErrorCorrectionLevel = 'L' | 'M' | 'Q' | 'H'; + export function create(text: string, options?: object): QRCode; + const _default: { + create(text: string, options?: object): QRCode; + toCanvas(canvas: HTMLCanvasElement, text: string, options?: object): Promise; + toDataURL(text: string, options?: object): Promise; + }; + export default _default; +} diff --git a/tests/e01-visual.spec.ts b/tests/e01-visual.spec.ts new file mode 100644 index 0000000..6cd9d4d --- /dev/null +++ b/tests/e01-visual.spec.ts @@ -0,0 +1,32 @@ +import { test, expect } from '@playwright/test'; + +// E-01 视觉验收:登录 → /report → Canvas 750×1000 + 邀请码 + 二维码区 + 保存按钮 +const BE = 'http://localhost:8756'; +const FE = 'http://localhost:5173'; + +test('E-01 战报页渲染与出图', async ({ page }) => { + const name = 'e01shot_' + Math.random().toString(36).slice(2, 8); + // 注册拿 token(经后端直调) + const reg = await page.request.post(BE + '/api/auth/register', { data: { username: name, password: 'e2ePass123' } }); + expect(reg.status()).toBe(200); + const { token } = await reg.json(); + // token 注入(前端 tokenStore 键名:ed_auth) + await page.goto(FE + '/login'); + await page.evaluate((t) => { + localStorage.setItem('ed_auth', t); + localStorage.setItem('ed_user_hint', JSON.stringify({ username: 'shot' })); + }, token); + await page.goto(FE + '/report'); + await expect(page.getByRole('heading', { name: /本周学习周报/ })).toBeVisible({ timeout: 10000 }); + const canvas = page.locator('canvas[aria-label="学习周报图片预览"]'); + await expect(canvas).toBeVisible(); + const box = await canvas.boundingBox(); + console.log('canvas-css-box:', JSON.stringify(box)); + // Canvas 位图必须 1500×2000(750×1000 @2x) + const size = await canvas.evaluate((c: HTMLCanvasElement) => ({ w: c.width, h: c.height })); + console.log('canvas-bitmap:', JSON.stringify(size)); + expect(size.w).toBe(1500); + expect(size.h).toBe(2000); + await expect(page.getByRole('button', { name: /分享 \/ 保存图片/ })).toBeVisible(); + await page.screenshot({ path: 'test-results/e01-report.png', fullPage: true }); +});