├── .gitignore
├── .vscode
└── extensions.json
├── LICENSE
├── README.md
├── README.zh_CN.md
├── index.html
├── package-lock.json
├── package.json
├── src
├── App.vue
├── assets
│ └── styles
│ │ └── styles.css
├── components
│ ├── CleanHiddenTextButton.vue
│ ├── ClearableTextarea.vue
│ ├── CopyButton.vue
│ ├── EmojiSelector.vue
│ ├── LanguageSelector.vue
│ └── TextSelector.vue
├── composables
│ └── useCursorPosition.js
├── i18n
│ ├── index.js
│ └── locales
│ │ ├── en.js
│ │ └── zh.js
├── main.js
├── store
│ └── index.js
├── utils
│ ├── cleanText.js
│ ├── embedCode.js
│ ├── emoji.js
│ └── encoding.js
└── views
│ ├── components
│ ├── CarrierTextPanel.vue
│ ├── EmbedCodePanel.vue
│ ├── EmojiPanel.vue
│ ├── FooterSection.vue
│ ├── InputPanel.vue
│ ├── ModeToggle.vue
│ └── OutputPanel.vue
│ └── index.vue
└── vite.config.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "Vue.volar"
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2025 Antkites
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [中文文档](./README.zh_CN.md) | [English](#)
2 |
3 | # Hidden Word
4 |
5 | A Unicode-based text digital watermarking tool for embedding invisible copyright marks and metadata in text content.
6 |
7 | ## Features
8 |
9 | - **Copyright Protection**: Embed invisible watermarks in articles to effectively protect original content
10 | - **Metadata Embedding**: Securely embed structured information in text for content verification
11 | - **Source Tracking**: Verify the original source of content through embedded watermark information
12 | - **Cross-platform Support**: Works on any platform that supports Unicode
13 | - **Website Integration**: Provides standardized embedding solutions to automatically add watermarks to website content
14 |
15 | ## Use Cases
16 |
17 | 1. **Content Creators**: Add digital watermarks to original content to protect intellectual property
18 | 2. **Copyright Management**: Add invisible copyright marks to digital content
19 | 3. **Content Verification**: Embed verification information in public texts to ensure content integrity
20 | 4. **Information Tracing**: Identify and track the dissemination path of digital content
21 |
22 | ## Quick Start
23 |
24 | ### Clone Repository
25 |
26 | ```bash
27 | git clone https://github.com/Ackites/hidden-word.git
28 |
29 | cd hidden-word
30 | ```
31 |
32 | ### Install Dependencies
33 |
34 | ```bash
35 | npm install
36 | ```
37 |
38 | ### Development
39 |
40 | ```bash
41 | npm run dev
42 | ```
43 |
44 | ### Build
45 |
46 | ```bash
47 | npm run build
48 | ```
49 |
50 | ## License
51 |
52 | [MIT](LICENSE)
53 |
54 | ## Star History
55 |
56 | [](https://www.star-history.com/#Ackites/hidden-word&Date)
--------------------------------------------------------------------------------
/README.zh_CN.md:
--------------------------------------------------------------------------------
1 | # Hidden Word
2 |
3 | 一个基于Unicode的文本数字水印工具,用于在文本内容中嵌入不可见的版权标识和元数据信息。
4 |
5 | ## 功能特点
6 |
7 | - **版权保护**:在文章中嵌入不可见水印,有效保护原创内容
8 | - **元数据嵌入**:在文本中安全地嵌入结构化信息,用于内容验证
9 | - **来源追踪**:通过嵌入的水印信息,可以验证内容的原始来源
10 | - **跨平台支持**:可在任何支持 Unicode 的平台上使用
11 | - **网站集成**:提供标准化的嵌入方案,可自动为网站内容添加水印
12 |
13 | ## 使用场景
14 |
15 | 1. **内容创作者**:为原创内容添加数字水印,保护知识产权
16 | 2. **版权管理**:为数字内容添加不可见的版权标识
17 | 3. **内容验证**:在公开文本中嵌入验证信息,确保内容完整性
18 | 4. **信息溯源**:识别和追踪数字内容的传播路径
19 |
20 | ## 快速开始
21 |
22 | ### 克隆仓库
23 |
24 | ```bash
25 | git clone https://github.com/Ackites/hidden-word.git
26 |
27 | cd hidden-word
28 | ```
29 |
30 | ### 安装依赖
31 |
32 | ```bash
33 | npm install
34 | ```
35 |
36 | ### 开发模式
37 |
38 | ```bash
39 | npm run dev
40 | ```
41 |
42 | ### 构建生产版本
43 |
44 | ```bash
45 | npm run build
46 | ```
47 |
48 | ## 许可证
49 |
50 | [MIT](LICENSE)
51 |
52 | ## Star History
53 |
54 | [](https://www.star-history.com/#Ackites/hidden-word&Date)
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 |
11 | Hidden Word
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hidden-word",
3 | "version": "0.0.0",
4 | "lockfileVersion": 3,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "hidden-word",
9 | "version": "0.0.0",
10 | "dependencies": {
11 | "@emoji-mart/data": "^1.2.1",
12 | "@tailwindcss/vite": "^4.0.12",
13 | "emoji-mart": "^5.6.0",
14 | "pinia": "^3.0.1",
15 | "tailwindcss": "^4.0.12",
16 | "vue": "^3.5.13",
17 | "vue-i18n": "^9.14.3"
18 | },
19 | "devDependencies": {
20 | "@vitejs/plugin-vue": "^5.2.1",
21 | "vite": "^6.2.0"
22 | }
23 | },
24 | "node_modules/@babel/helper-string-parser": {
25 | "version": "7.25.9",
26 | "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz",
27 | "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==",
28 | "engines": {
29 | "node": ">=6.9.0"
30 | }
31 | },
32 | "node_modules/@babel/helper-validator-identifier": {
33 | "version": "7.25.9",
34 | "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
35 | "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
36 | "engines": {
37 | "node": ">=6.9.0"
38 | }
39 | },
40 | "node_modules/@babel/parser": {
41 | "version": "7.26.10",
42 | "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.26.10.tgz",
43 | "integrity": "sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA==",
44 | "dependencies": {
45 | "@babel/types": "^7.26.10"
46 | },
47 | "bin": {
48 | "parser": "bin/babel-parser.js"
49 | },
50 | "engines": {
51 | "node": ">=6.0.0"
52 | }
53 | },
54 | "node_modules/@babel/types": {
55 | "version": "7.26.10",
56 | "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.26.10.tgz",
57 | "integrity": "sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==",
58 | "dependencies": {
59 | "@babel/helper-string-parser": "^7.25.9",
60 | "@babel/helper-validator-identifier": "^7.25.9"
61 | },
62 | "engines": {
63 | "node": ">=6.9.0"
64 | }
65 | },
66 | "node_modules/@emoji-mart/data": {
67 | "version": "1.2.1",
68 | "resolved": "https://registry.npmmirror.com/@emoji-mart/data/-/data-1.2.1.tgz",
69 | "integrity": "sha512-no2pQMWiBy6gpBEiqGeU77/bFejDqUTRY7KX+0+iur13op3bqUsXdnwoZs6Xb1zbv0gAj5VvS1PWoUUckSr5Dw=="
70 | },
71 | "node_modules/@esbuild/aix-ppc64": {
72 | "version": "0.25.1",
73 | "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.1.tgz",
74 | "integrity": "sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ==",
75 | "cpu": [
76 | "ppc64"
77 | ],
78 | "optional": true,
79 | "os": [
80 | "aix"
81 | ],
82 | "engines": {
83 | "node": ">=18"
84 | }
85 | },
86 | "node_modules/@esbuild/android-arm": {
87 | "version": "0.25.1",
88 | "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.25.1.tgz",
89 | "integrity": "sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==",
90 | "cpu": [
91 | "arm"
92 | ],
93 | "optional": true,
94 | "os": [
95 | "android"
96 | ],
97 | "engines": {
98 | "node": ">=18"
99 | }
100 | },
101 | "node_modules/@esbuild/android-arm64": {
102 | "version": "0.25.1",
103 | "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.25.1.tgz",
104 | "integrity": "sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==",
105 | "cpu": [
106 | "arm64"
107 | ],
108 | "optional": true,
109 | "os": [
110 | "android"
111 | ],
112 | "engines": {
113 | "node": ">=18"
114 | }
115 | },
116 | "node_modules/@esbuild/android-x64": {
117 | "version": "0.25.1",
118 | "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.25.1.tgz",
119 | "integrity": "sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==",
120 | "cpu": [
121 | "x64"
122 | ],
123 | "optional": true,
124 | "os": [
125 | "android"
126 | ],
127 | "engines": {
128 | "node": ">=18"
129 | }
130 | },
131 | "node_modules/@esbuild/darwin-arm64": {
132 | "version": "0.25.1",
133 | "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.1.tgz",
134 | "integrity": "sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==",
135 | "cpu": [
136 | "arm64"
137 | ],
138 | "optional": true,
139 | "os": [
140 | "darwin"
141 | ],
142 | "engines": {
143 | "node": ">=18"
144 | }
145 | },
146 | "node_modules/@esbuild/darwin-x64": {
147 | "version": "0.25.1",
148 | "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.25.1.tgz",
149 | "integrity": "sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==",
150 | "cpu": [
151 | "x64"
152 | ],
153 | "optional": true,
154 | "os": [
155 | "darwin"
156 | ],
157 | "engines": {
158 | "node": ">=18"
159 | }
160 | },
161 | "node_modules/@esbuild/freebsd-arm64": {
162 | "version": "0.25.1",
163 | "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.1.tgz",
164 | "integrity": "sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==",
165 | "cpu": [
166 | "arm64"
167 | ],
168 | "optional": true,
169 | "os": [
170 | "freebsd"
171 | ],
172 | "engines": {
173 | "node": ">=18"
174 | }
175 | },
176 | "node_modules/@esbuild/freebsd-x64": {
177 | "version": "0.25.1",
178 | "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.1.tgz",
179 | "integrity": "sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==",
180 | "cpu": [
181 | "x64"
182 | ],
183 | "optional": true,
184 | "os": [
185 | "freebsd"
186 | ],
187 | "engines": {
188 | "node": ">=18"
189 | }
190 | },
191 | "node_modules/@esbuild/linux-arm": {
192 | "version": "0.25.1",
193 | "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.25.1.tgz",
194 | "integrity": "sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==",
195 | "cpu": [
196 | "arm"
197 | ],
198 | "optional": true,
199 | "os": [
200 | "linux"
201 | ],
202 | "engines": {
203 | "node": ">=18"
204 | }
205 | },
206 | "node_modules/@esbuild/linux-arm64": {
207 | "version": "0.25.1",
208 | "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.25.1.tgz",
209 | "integrity": "sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==",
210 | "cpu": [
211 | "arm64"
212 | ],
213 | "optional": true,
214 | "os": [
215 | "linux"
216 | ],
217 | "engines": {
218 | "node": ">=18"
219 | }
220 | },
221 | "node_modules/@esbuild/linux-ia32": {
222 | "version": "0.25.1",
223 | "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.25.1.tgz",
224 | "integrity": "sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==",
225 | "cpu": [
226 | "ia32"
227 | ],
228 | "optional": true,
229 | "os": [
230 | "linux"
231 | ],
232 | "engines": {
233 | "node": ">=18"
234 | }
235 | },
236 | "node_modules/@esbuild/linux-loong64": {
237 | "version": "0.25.1",
238 | "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.25.1.tgz",
239 | "integrity": "sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==",
240 | "cpu": [
241 | "loong64"
242 | ],
243 | "optional": true,
244 | "os": [
245 | "linux"
246 | ],
247 | "engines": {
248 | "node": ">=18"
249 | }
250 | },
251 | "node_modules/@esbuild/linux-mips64el": {
252 | "version": "0.25.1",
253 | "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.1.tgz",
254 | "integrity": "sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==",
255 | "cpu": [
256 | "mips64el"
257 | ],
258 | "optional": true,
259 | "os": [
260 | "linux"
261 | ],
262 | "engines": {
263 | "node": ">=18"
264 | }
265 | },
266 | "node_modules/@esbuild/linux-ppc64": {
267 | "version": "0.25.1",
268 | "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.1.tgz",
269 | "integrity": "sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==",
270 | "cpu": [
271 | "ppc64"
272 | ],
273 | "optional": true,
274 | "os": [
275 | "linux"
276 | ],
277 | "engines": {
278 | "node": ">=18"
279 | }
280 | },
281 | "node_modules/@esbuild/linux-riscv64": {
282 | "version": "0.25.1",
283 | "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.1.tgz",
284 | "integrity": "sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==",
285 | "cpu": [
286 | "riscv64"
287 | ],
288 | "optional": true,
289 | "os": [
290 | "linux"
291 | ],
292 | "engines": {
293 | "node": ">=18"
294 | }
295 | },
296 | "node_modules/@esbuild/linux-s390x": {
297 | "version": "0.25.1",
298 | "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.25.1.tgz",
299 | "integrity": "sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==",
300 | "cpu": [
301 | "s390x"
302 | ],
303 | "optional": true,
304 | "os": [
305 | "linux"
306 | ],
307 | "engines": {
308 | "node": ">=18"
309 | }
310 | },
311 | "node_modules/@esbuild/linux-x64": {
312 | "version": "0.25.1",
313 | "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.25.1.tgz",
314 | "integrity": "sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA==",
315 | "cpu": [
316 | "x64"
317 | ],
318 | "optional": true,
319 | "os": [
320 | "linux"
321 | ],
322 | "engines": {
323 | "node": ">=18"
324 | }
325 | },
326 | "node_modules/@esbuild/netbsd-arm64": {
327 | "version": "0.25.1",
328 | "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.1.tgz",
329 | "integrity": "sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==",
330 | "cpu": [
331 | "arm64"
332 | ],
333 | "optional": true,
334 | "os": [
335 | "netbsd"
336 | ],
337 | "engines": {
338 | "node": ">=18"
339 | }
340 | },
341 | "node_modules/@esbuild/netbsd-x64": {
342 | "version": "0.25.1",
343 | "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.1.tgz",
344 | "integrity": "sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==",
345 | "cpu": [
346 | "x64"
347 | ],
348 | "optional": true,
349 | "os": [
350 | "netbsd"
351 | ],
352 | "engines": {
353 | "node": ">=18"
354 | }
355 | },
356 | "node_modules/@esbuild/openbsd-arm64": {
357 | "version": "0.25.1",
358 | "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.1.tgz",
359 | "integrity": "sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==",
360 | "cpu": [
361 | "arm64"
362 | ],
363 | "optional": true,
364 | "os": [
365 | "openbsd"
366 | ],
367 | "engines": {
368 | "node": ">=18"
369 | }
370 | },
371 | "node_modules/@esbuild/openbsd-x64": {
372 | "version": "0.25.1",
373 | "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.1.tgz",
374 | "integrity": "sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==",
375 | "cpu": [
376 | "x64"
377 | ],
378 | "optional": true,
379 | "os": [
380 | "openbsd"
381 | ],
382 | "engines": {
383 | "node": ">=18"
384 | }
385 | },
386 | "node_modules/@esbuild/sunos-x64": {
387 | "version": "0.25.1",
388 | "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.25.1.tgz",
389 | "integrity": "sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==",
390 | "cpu": [
391 | "x64"
392 | ],
393 | "optional": true,
394 | "os": [
395 | "sunos"
396 | ],
397 | "engines": {
398 | "node": ">=18"
399 | }
400 | },
401 | "node_modules/@esbuild/win32-arm64": {
402 | "version": "0.25.1",
403 | "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.25.1.tgz",
404 | "integrity": "sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==",
405 | "cpu": [
406 | "arm64"
407 | ],
408 | "optional": true,
409 | "os": [
410 | "win32"
411 | ],
412 | "engines": {
413 | "node": ">=18"
414 | }
415 | },
416 | "node_modules/@esbuild/win32-ia32": {
417 | "version": "0.25.1",
418 | "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.25.1.tgz",
419 | "integrity": "sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==",
420 | "cpu": [
421 | "ia32"
422 | ],
423 | "optional": true,
424 | "os": [
425 | "win32"
426 | ],
427 | "engines": {
428 | "node": ">=18"
429 | }
430 | },
431 | "node_modules/@esbuild/win32-x64": {
432 | "version": "0.25.1",
433 | "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.25.1.tgz",
434 | "integrity": "sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==",
435 | "cpu": [
436 | "x64"
437 | ],
438 | "optional": true,
439 | "os": [
440 | "win32"
441 | ],
442 | "engines": {
443 | "node": ">=18"
444 | }
445 | },
446 | "node_modules/@intlify/core-base": {
447 | "version": "9.14.3",
448 | "resolved": "https://registry.npmmirror.com/@intlify/core-base/-/core-base-9.14.3.tgz",
449 | "integrity": "sha512-nbJ7pKTlXFnaXPblyfiH6awAx1C0PWNNuqXAR74yRwgi5A/Re/8/5fErLY0pv4R8+EHj3ZaThMHdnuC/5OBa6g==",
450 | "dependencies": {
451 | "@intlify/message-compiler": "9.14.3",
452 | "@intlify/shared": "9.14.3"
453 | },
454 | "engines": {
455 | "node": ">= 16"
456 | },
457 | "funding": {
458 | "url": "https://github.com/sponsors/kazupon"
459 | }
460 | },
461 | "node_modules/@intlify/message-compiler": {
462 | "version": "9.14.3",
463 | "resolved": "https://registry.npmmirror.com/@intlify/message-compiler/-/message-compiler-9.14.3.tgz",
464 | "integrity": "sha512-ANwC226BQdd+MpJ36rOYkChSESfPwu3Ss2Faw0RHTOknYLoHTX6V6e/JjIKVDMbzs0/H/df/rO6yU0SPiWHqNg==",
465 | "dependencies": {
466 | "@intlify/shared": "9.14.3",
467 | "source-map-js": "^1.0.2"
468 | },
469 | "engines": {
470 | "node": ">= 16"
471 | },
472 | "funding": {
473 | "url": "https://github.com/sponsors/kazupon"
474 | }
475 | },
476 | "node_modules/@intlify/shared": {
477 | "version": "9.14.3",
478 | "resolved": "https://registry.npmmirror.com/@intlify/shared/-/shared-9.14.3.tgz",
479 | "integrity": "sha512-hJXz9LA5VG7qNE00t50bdzDv8Z4q9fpcL81wj4y4duKavrv0KM8YNLTwXNEFINHjTsfrG9TXvPuEjVaAvZ7yWg==",
480 | "engines": {
481 | "node": ">= 16"
482 | },
483 | "funding": {
484 | "url": "https://github.com/sponsors/kazupon"
485 | }
486 | },
487 | "node_modules/@jridgewell/sourcemap-codec": {
488 | "version": "1.5.0",
489 | "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
490 | "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="
491 | },
492 | "node_modules/@rollup/rollup-android-arm-eabi": {
493 | "version": "4.35.0",
494 | "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.35.0.tgz",
495 | "integrity": "sha512-uYQ2WfPaqz5QtVgMxfN6NpLD+no0MYHDBywl7itPYd3K5TjjSghNKmX8ic9S8NU8w81NVhJv/XojcHptRly7qQ==",
496 | "cpu": [
497 | "arm"
498 | ],
499 | "optional": true,
500 | "os": [
501 | "android"
502 | ]
503 | },
504 | "node_modules/@rollup/rollup-android-arm64": {
505 | "version": "4.35.0",
506 | "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.35.0.tgz",
507 | "integrity": "sha512-FtKddj9XZudurLhdJnBl9fl6BwCJ3ky8riCXjEw3/UIbjmIY58ppWwPEvU3fNu+W7FUsAsB1CdH+7EQE6CXAPA==",
508 | "cpu": [
509 | "arm64"
510 | ],
511 | "optional": true,
512 | "os": [
513 | "android"
514 | ]
515 | },
516 | "node_modules/@rollup/rollup-darwin-arm64": {
517 | "version": "4.35.0",
518 | "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.35.0.tgz",
519 | "integrity": "sha512-Uk+GjOJR6CY844/q6r5DR/6lkPFOw0hjfOIzVx22THJXMxktXG6CbejseJFznU8vHcEBLpiXKY3/6xc+cBm65Q==",
520 | "cpu": [
521 | "arm64"
522 | ],
523 | "optional": true,
524 | "os": [
525 | "darwin"
526 | ]
527 | },
528 | "node_modules/@rollup/rollup-darwin-x64": {
529 | "version": "4.35.0",
530 | "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.35.0.tgz",
531 | "integrity": "sha512-3IrHjfAS6Vkp+5bISNQnPogRAW5GAV1n+bNCrDwXmfMHbPl5EhTmWtfmwlJxFRUCBZ+tZ/OxDyU08aF6NI/N5Q==",
532 | "cpu": [
533 | "x64"
534 | ],
535 | "optional": true,
536 | "os": [
537 | "darwin"
538 | ]
539 | },
540 | "node_modules/@rollup/rollup-freebsd-arm64": {
541 | "version": "4.35.0",
542 | "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.35.0.tgz",
543 | "integrity": "sha512-sxjoD/6F9cDLSELuLNnY0fOrM9WA0KrM0vWm57XhrIMf5FGiN8D0l7fn+bpUeBSU7dCgPV2oX4zHAsAXyHFGcQ==",
544 | "cpu": [
545 | "arm64"
546 | ],
547 | "optional": true,
548 | "os": [
549 | "freebsd"
550 | ]
551 | },
552 | "node_modules/@rollup/rollup-freebsd-x64": {
553 | "version": "4.35.0",
554 | "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.35.0.tgz",
555 | "integrity": "sha512-2mpHCeRuD1u/2kruUiHSsnjWtHjqVbzhBkNVQ1aVD63CcexKVcQGwJ2g5VphOd84GvxfSvnnlEyBtQCE5hxVVw==",
556 | "cpu": [
557 | "x64"
558 | ],
559 | "optional": true,
560 | "os": [
561 | "freebsd"
562 | ]
563 | },
564 | "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
565 | "version": "4.35.0",
566 | "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.35.0.tgz",
567 | "integrity": "sha512-mrA0v3QMy6ZSvEuLs0dMxcO2LnaCONs1Z73GUDBHWbY8tFFocM6yl7YyMu7rz4zS81NDSqhrUuolyZXGi8TEqg==",
568 | "cpu": [
569 | "arm"
570 | ],
571 | "optional": true,
572 | "os": [
573 | "linux"
574 | ]
575 | },
576 | "node_modules/@rollup/rollup-linux-arm-musleabihf": {
577 | "version": "4.35.0",
578 | "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.35.0.tgz",
579 | "integrity": "sha512-DnYhhzcvTAKNexIql8pFajr0PiDGrIsBYPRvCKlA5ixSS3uwo/CWNZxB09jhIapEIg945KOzcYEAGGSmTSpk7A==",
580 | "cpu": [
581 | "arm"
582 | ],
583 | "optional": true,
584 | "os": [
585 | "linux"
586 | ]
587 | },
588 | "node_modules/@rollup/rollup-linux-arm64-gnu": {
589 | "version": "4.35.0",
590 | "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.35.0.tgz",
591 | "integrity": "sha512-uagpnH2M2g2b5iLsCTZ35CL1FgyuzzJQ8L9VtlJ+FckBXroTwNOaD0z0/UF+k5K3aNQjbm8LIVpxykUOQt1m/A==",
592 | "cpu": [
593 | "arm64"
594 | ],
595 | "optional": true,
596 | "os": [
597 | "linux"
598 | ]
599 | },
600 | "node_modules/@rollup/rollup-linux-arm64-musl": {
601 | "version": "4.35.0",
602 | "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.35.0.tgz",
603 | "integrity": "sha512-XQxVOCd6VJeHQA/7YcqyV0/88N6ysSVzRjJ9I9UA/xXpEsjvAgDTgH3wQYz5bmr7SPtVK2TsP2fQ2N9L4ukoUg==",
604 | "cpu": [
605 | "arm64"
606 | ],
607 | "optional": true,
608 | "os": [
609 | "linux"
610 | ]
611 | },
612 | "node_modules/@rollup/rollup-linux-loongarch64-gnu": {
613 | "version": "4.35.0",
614 | "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.35.0.tgz",
615 | "integrity": "sha512-5pMT5PzfgwcXEwOaSrqVsz/LvjDZt+vQ8RT/70yhPU06PTuq8WaHhfT1LW+cdD7mW6i/J5/XIkX/1tCAkh1W6g==",
616 | "cpu": [
617 | "loong64"
618 | ],
619 | "optional": true,
620 | "os": [
621 | "linux"
622 | ]
623 | },
624 | "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
625 | "version": "4.35.0",
626 | "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.35.0.tgz",
627 | "integrity": "sha512-c+zkcvbhbXF98f4CtEIP1EBA/lCic5xB0lToneZYvMeKu5Kamq3O8gqrxiYYLzlZH6E3Aq+TSW86E4ay8iD8EA==",
628 | "cpu": [
629 | "ppc64"
630 | ],
631 | "optional": true,
632 | "os": [
633 | "linux"
634 | ]
635 | },
636 | "node_modules/@rollup/rollup-linux-riscv64-gnu": {
637 | "version": "4.35.0",
638 | "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.35.0.tgz",
639 | "integrity": "sha512-s91fuAHdOwH/Tad2tzTtPX7UZyytHIRR6V4+2IGlV0Cej5rkG0R61SX4l4y9sh0JBibMiploZx3oHKPnQBKe4g==",
640 | "cpu": [
641 | "riscv64"
642 | ],
643 | "optional": true,
644 | "os": [
645 | "linux"
646 | ]
647 | },
648 | "node_modules/@rollup/rollup-linux-s390x-gnu": {
649 | "version": "4.35.0",
650 | "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.35.0.tgz",
651 | "integrity": "sha512-hQRkPQPLYJZYGP+Hj4fR9dDBMIM7zrzJDWFEMPdTnTy95Ljnv0/4w/ixFw3pTBMEuuEuoqtBINYND4M7ujcuQw==",
652 | "cpu": [
653 | "s390x"
654 | ],
655 | "optional": true,
656 | "os": [
657 | "linux"
658 | ]
659 | },
660 | "node_modules/@rollup/rollup-linux-x64-gnu": {
661 | "version": "4.35.0",
662 | "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.35.0.tgz",
663 | "integrity": "sha512-Pim1T8rXOri+0HmV4CdKSGrqcBWX0d1HoPnQ0uw0bdp1aP5SdQVNBy8LjYncvnLgu3fnnCt17xjWGd4cqh8/hA==",
664 | "cpu": [
665 | "x64"
666 | ],
667 | "optional": true,
668 | "os": [
669 | "linux"
670 | ]
671 | },
672 | "node_modules/@rollup/rollup-linux-x64-musl": {
673 | "version": "4.35.0",
674 | "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.35.0.tgz",
675 | "integrity": "sha512-QysqXzYiDvQWfUiTm8XmJNO2zm9yC9P/2Gkrwg2dH9cxotQzunBHYr6jk4SujCTqnfGxduOmQcI7c2ryuW8XVg==",
676 | "cpu": [
677 | "x64"
678 | ],
679 | "optional": true,
680 | "os": [
681 | "linux"
682 | ]
683 | },
684 | "node_modules/@rollup/rollup-win32-arm64-msvc": {
685 | "version": "4.35.0",
686 | "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.35.0.tgz",
687 | "integrity": "sha512-OUOlGqPkVJCdJETKOCEf1mw848ZyJ5w50/rZ/3IBQVdLfR5jk/6Sr5m3iO2tdPgwo0x7VcncYuOvMhBWZq8ayg==",
688 | "cpu": [
689 | "arm64"
690 | ],
691 | "optional": true,
692 | "os": [
693 | "win32"
694 | ]
695 | },
696 | "node_modules/@rollup/rollup-win32-ia32-msvc": {
697 | "version": "4.35.0",
698 | "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.35.0.tgz",
699 | "integrity": "sha512-2/lsgejMrtwQe44glq7AFFHLfJBPafpsTa6JvP2NGef/ifOa4KBoglVf7AKN7EV9o32evBPRqfg96fEHzWo5kw==",
700 | "cpu": [
701 | "ia32"
702 | ],
703 | "optional": true,
704 | "os": [
705 | "win32"
706 | ]
707 | },
708 | "node_modules/@rollup/rollup-win32-x64-msvc": {
709 | "version": "4.35.0",
710 | "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.35.0.tgz",
711 | "integrity": "sha512-PIQeY5XDkrOysbQblSW7v3l1MDZzkTEzAfTPkj5VAu3FW8fS4ynyLg2sINp0fp3SjZ8xkRYpLqoKcYqAkhU1dw==",
712 | "cpu": [
713 | "x64"
714 | ],
715 | "optional": true,
716 | "os": [
717 | "win32"
718 | ]
719 | },
720 | "node_modules/@tailwindcss/node": {
721 | "version": "4.0.12",
722 | "resolved": "https://registry.npmmirror.com/@tailwindcss/node/-/node-4.0.12.tgz",
723 | "integrity": "sha512-a6J11K1Ztdln9OrGfoM75/hChYPcHYGNYimqciMrvKXRmmPaS8XZTHhdvb5a3glz4Kd4ZxE1MnuFE2c0fGGmtg==",
724 | "dependencies": {
725 | "enhanced-resolve": "^5.18.1",
726 | "jiti": "^2.4.2",
727 | "tailwindcss": "4.0.12"
728 | }
729 | },
730 | "node_modules/@tailwindcss/oxide": {
731 | "version": "4.0.12",
732 | "resolved": "https://registry.npmmirror.com/@tailwindcss/oxide/-/oxide-4.0.12.tgz",
733 | "integrity": "sha512-DWb+myvJB9xJwelwT9GHaMc1qJj6MDXRDR0CS+T8IdkejAtu8ctJAgV4r1drQJLPeS7mNwq2UHW2GWrudTf63A==",
734 | "engines": {
735 | "node": ">= 10"
736 | },
737 | "optionalDependencies": {
738 | "@tailwindcss/oxide-android-arm64": "4.0.12",
739 | "@tailwindcss/oxide-darwin-arm64": "4.0.12",
740 | "@tailwindcss/oxide-darwin-x64": "4.0.12",
741 | "@tailwindcss/oxide-freebsd-x64": "4.0.12",
742 | "@tailwindcss/oxide-linux-arm-gnueabihf": "4.0.12",
743 | "@tailwindcss/oxide-linux-arm64-gnu": "4.0.12",
744 | "@tailwindcss/oxide-linux-arm64-musl": "4.0.12",
745 | "@tailwindcss/oxide-linux-x64-gnu": "4.0.12",
746 | "@tailwindcss/oxide-linux-x64-musl": "4.0.12",
747 | "@tailwindcss/oxide-win32-arm64-msvc": "4.0.12",
748 | "@tailwindcss/oxide-win32-x64-msvc": "4.0.12"
749 | }
750 | },
751 | "node_modules/@tailwindcss/oxide-android-arm64": {
752 | "version": "4.0.12",
753 | "resolved": "https://registry.npmmirror.com/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.0.12.tgz",
754 | "integrity": "sha512-dAXCaemu3mHLXcA5GwGlQynX8n7tTdvn5i1zAxRvZ5iC9fWLl5bGnjZnzrQqT7ttxCvRwdVf3IHUnMVdDBO/kQ==",
755 | "cpu": [
756 | "arm64"
757 | ],
758 | "optional": true,
759 | "os": [
760 | "android"
761 | ],
762 | "engines": {
763 | "node": ">= 10"
764 | }
765 | },
766 | "node_modules/@tailwindcss/oxide-darwin-arm64": {
767 | "version": "4.0.12",
768 | "resolved": "https://registry.npmmirror.com/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.0.12.tgz",
769 | "integrity": "sha512-vPNI+TpJQ7sizselDXIJdYkx9Cu6JBdtmRWujw9pVIxW8uz3O2PjgGGzL/7A0sXI8XDjSyRChrUnEW9rQygmJQ==",
770 | "cpu": [
771 | "arm64"
772 | ],
773 | "optional": true,
774 | "os": [
775 | "darwin"
776 | ],
777 | "engines": {
778 | "node": ">= 10"
779 | }
780 | },
781 | "node_modules/@tailwindcss/oxide-darwin-x64": {
782 | "version": "4.0.12",
783 | "resolved": "https://registry.npmmirror.com/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.0.12.tgz",
784 | "integrity": "sha512-RL/9jM41Fdq4Efr35C5wgLx98BirnrfwuD+zgMFK6Ir68HeOSqBhW9jsEeC7Y/JcGyPd3MEoJVIU4fAb7YLg7A==",
785 | "cpu": [
786 | "x64"
787 | ],
788 | "optional": true,
789 | "os": [
790 | "darwin"
791 | ],
792 | "engines": {
793 | "node": ">= 10"
794 | }
795 | },
796 | "node_modules/@tailwindcss/oxide-freebsd-x64": {
797 | "version": "4.0.12",
798 | "resolved": "https://registry.npmmirror.com/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.0.12.tgz",
799 | "integrity": "sha512-7WzWiax+LguJcMEimY0Q4sBLlFXu1tYxVka3+G2M9KmU/3m84J3jAIV4KZWnockbHsbb2XgrEjtlJKVwHQCoRA==",
800 | "cpu": [
801 | "x64"
802 | ],
803 | "optional": true,
804 | "os": [
805 | "freebsd"
806 | ],
807 | "engines": {
808 | "node": ">= 10"
809 | }
810 | },
811 | "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
812 | "version": "4.0.12",
813 | "resolved": "https://registry.npmmirror.com/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.0.12.tgz",
814 | "integrity": "sha512-X9LRC7jjE1QlfIaBbXjY0PGeQP87lz5mEfLSVs2J1yRc9PSg1tEPS9NBqY4BU9v5toZgJgzKeaNltORyTs22TQ==",
815 | "cpu": [
816 | "arm"
817 | ],
818 | "optional": true,
819 | "os": [
820 | "linux"
821 | ],
822 | "engines": {
823 | "node": ">= 10"
824 | }
825 | },
826 | "node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
827 | "version": "4.0.12",
828 | "resolved": "https://registry.npmmirror.com/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.0.12.tgz",
829 | "integrity": "sha512-i24IFNq2402zfDdoWKypXz0ZNS2G4NKaA82tgBlE2OhHIE+4mg2JDb5wVfyP6R+MCm5grgXvurcIcKWvo44QiQ==",
830 | "cpu": [
831 | "arm64"
832 | ],
833 | "optional": true,
834 | "os": [
835 | "linux"
836 | ],
837 | "engines": {
838 | "node": ">= 10"
839 | }
840 | },
841 | "node_modules/@tailwindcss/oxide-linux-arm64-musl": {
842 | "version": "4.0.12",
843 | "resolved": "https://registry.npmmirror.com/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.0.12.tgz",
844 | "integrity": "sha512-LmOdshJBfAGIBG0DdBWhI0n5LTMurnGGJCHcsm9F//ISfsHtCnnYIKgYQui5oOz1SUCkqsMGfkAzWyNKZqbGNw==",
845 | "cpu": [
846 | "arm64"
847 | ],
848 | "optional": true,
849 | "os": [
850 | "linux"
851 | ],
852 | "engines": {
853 | "node": ">= 10"
854 | }
855 | },
856 | "node_modules/@tailwindcss/oxide-linux-x64-gnu": {
857 | "version": "4.0.12",
858 | "resolved": "https://registry.npmmirror.com/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.0.12.tgz",
859 | "integrity": "sha512-OSK667qZRH30ep8RiHbZDQfqkXjnzKxdn0oRwWzgCO8CoTxV+MvIkd0BWdQbYtYuM1wrakARV/Hwp0eA/qzdbw==",
860 | "cpu": [
861 | "x64"
862 | ],
863 | "optional": true,
864 | "os": [
865 | "linux"
866 | ],
867 | "engines": {
868 | "node": ">= 10"
869 | }
870 | },
871 | "node_modules/@tailwindcss/oxide-linux-x64-musl": {
872 | "version": "4.0.12",
873 | "resolved": "https://registry.npmmirror.com/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.0.12.tgz",
874 | "integrity": "sha512-uylhWq6OWQ8krV8Jk+v0H/3AZKJW6xYMgNMyNnUbbYXWi7hIVdxRKNUB5UvrlC3RxtgsK5EAV2i1CWTRsNcAnA==",
875 | "cpu": [
876 | "x64"
877 | ],
878 | "optional": true,
879 | "os": [
880 | "linux"
881 | ],
882 | "engines": {
883 | "node": ">= 10"
884 | }
885 | },
886 | "node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
887 | "version": "4.0.12",
888 | "resolved": "https://registry.npmmirror.com/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.0.12.tgz",
889 | "integrity": "sha512-XDLnhMoXZEEOir1LK43/gHHwK84V1GlV8+pAncUAIN2wloeD+nNciI9WRIY/BeFTqES22DhTIGoilSO39xDb2g==",
890 | "cpu": [
891 | "arm64"
892 | ],
893 | "optional": true,
894 | "os": [
895 | "win32"
896 | ],
897 | "engines": {
898 | "node": ">= 10"
899 | }
900 | },
901 | "node_modules/@tailwindcss/oxide-win32-x64-msvc": {
902 | "version": "4.0.12",
903 | "resolved": "https://registry.npmmirror.com/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.0.12.tgz",
904 | "integrity": "sha512-I/BbjCLpKDQucvtn6rFuYLst1nfFwSMYyPzkx/095RE+tuzk5+fwXuzQh7T3fIBTcbn82qH/sFka7yPGA50tLw==",
905 | "cpu": [
906 | "x64"
907 | ],
908 | "optional": true,
909 | "os": [
910 | "win32"
911 | ],
912 | "engines": {
913 | "node": ">= 10"
914 | }
915 | },
916 | "node_modules/@tailwindcss/vite": {
917 | "version": "4.0.12",
918 | "resolved": "https://registry.npmmirror.com/@tailwindcss/vite/-/vite-4.0.12.tgz",
919 | "integrity": "sha512-JM3gp601UJiryIZ9R2bSqalzcOy15RCybQ1Q+BJqDEwVyo4LkWKeqQAcrpHapWXY31OJFTuOUVBFDWMhzHm2Bg==",
920 | "dependencies": {
921 | "@tailwindcss/node": "4.0.12",
922 | "@tailwindcss/oxide": "4.0.12",
923 | "lightningcss": "^1.29.1",
924 | "tailwindcss": "4.0.12"
925 | },
926 | "peerDependencies": {
927 | "vite": "^5.2.0 || ^6"
928 | }
929 | },
930 | "node_modules/@types/estree": {
931 | "version": "1.0.6",
932 | "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.6.tgz",
933 | "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="
934 | },
935 | "node_modules/@vitejs/plugin-vue": {
936 | "version": "5.2.1",
937 | "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.2.1.tgz",
938 | "integrity": "sha512-cxh314tzaWwOLqVes2gnnCtvBDcM1UMdn+iFR+UjAn411dPT3tOmqrJjbMd7koZpMAmBM/GqeV4n9ge7JSiJJQ==",
939 | "dev": true,
940 | "engines": {
941 | "node": "^18.0.0 || >=20.0.0"
942 | },
943 | "peerDependencies": {
944 | "vite": "^5.0.0 || ^6.0.0",
945 | "vue": "^3.2.25"
946 | }
947 | },
948 | "node_modules/@vue/compiler-core": {
949 | "version": "3.5.13",
950 | "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.13.tgz",
951 | "integrity": "sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==",
952 | "dependencies": {
953 | "@babel/parser": "^7.25.3",
954 | "@vue/shared": "3.5.13",
955 | "entities": "^4.5.0",
956 | "estree-walker": "^2.0.2",
957 | "source-map-js": "^1.2.0"
958 | }
959 | },
960 | "node_modules/@vue/compiler-dom": {
961 | "version": "3.5.13",
962 | "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz",
963 | "integrity": "sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==",
964 | "dependencies": {
965 | "@vue/compiler-core": "3.5.13",
966 | "@vue/shared": "3.5.13"
967 | }
968 | },
969 | "node_modules/@vue/compiler-sfc": {
970 | "version": "3.5.13",
971 | "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.13.tgz",
972 | "integrity": "sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==",
973 | "dependencies": {
974 | "@babel/parser": "^7.25.3",
975 | "@vue/compiler-core": "3.5.13",
976 | "@vue/compiler-dom": "3.5.13",
977 | "@vue/compiler-ssr": "3.5.13",
978 | "@vue/shared": "3.5.13",
979 | "estree-walker": "^2.0.2",
980 | "magic-string": "^0.30.11",
981 | "postcss": "^8.4.48",
982 | "source-map-js": "^1.2.0"
983 | }
984 | },
985 | "node_modules/@vue/compiler-ssr": {
986 | "version": "3.5.13",
987 | "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.13.tgz",
988 | "integrity": "sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==",
989 | "dependencies": {
990 | "@vue/compiler-dom": "3.5.13",
991 | "@vue/shared": "3.5.13"
992 | }
993 | },
994 | "node_modules/@vue/devtools-api": {
995 | "version": "7.7.2",
996 | "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-7.7.2.tgz",
997 | "integrity": "sha512-1syn558KhyN+chO5SjlZIwJ8bV/bQ1nOVTG66t2RbG66ZGekyiYNmRO7X9BJCXQqPsFHlnksqvPhce2qpzxFnA==",
998 | "dependencies": {
999 | "@vue/devtools-kit": "^7.7.2"
1000 | }
1001 | },
1002 | "node_modules/@vue/devtools-kit": {
1003 | "version": "7.7.2",
1004 | "resolved": "https://registry.npmmirror.com/@vue/devtools-kit/-/devtools-kit-7.7.2.tgz",
1005 | "integrity": "sha512-CY0I1JH3Z8PECbn6k3TqM1Bk9ASWxeMtTCvZr7vb+CHi+X/QwQm5F1/fPagraamKMAHVfuuCbdcnNg1A4CYVWQ==",
1006 | "dependencies": {
1007 | "@vue/devtools-shared": "^7.7.2",
1008 | "birpc": "^0.2.19",
1009 | "hookable": "^5.5.3",
1010 | "mitt": "^3.0.1",
1011 | "perfect-debounce": "^1.0.0",
1012 | "speakingurl": "^14.0.1",
1013 | "superjson": "^2.2.1"
1014 | }
1015 | },
1016 | "node_modules/@vue/devtools-shared": {
1017 | "version": "7.7.2",
1018 | "resolved": "https://registry.npmmirror.com/@vue/devtools-shared/-/devtools-shared-7.7.2.tgz",
1019 | "integrity": "sha512-uBFxnp8gwW2vD6FrJB8JZLUzVb6PNRG0B0jBnHsOH8uKyva2qINY8PTF5Te4QlTbMDqU5K6qtJDr6cNsKWhbOA==",
1020 | "dependencies": {
1021 | "rfdc": "^1.4.1"
1022 | }
1023 | },
1024 | "node_modules/@vue/reactivity": {
1025 | "version": "3.5.13",
1026 | "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.13.tgz",
1027 | "integrity": "sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==",
1028 | "dependencies": {
1029 | "@vue/shared": "3.5.13"
1030 | }
1031 | },
1032 | "node_modules/@vue/runtime-core": {
1033 | "version": "3.5.13",
1034 | "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.13.tgz",
1035 | "integrity": "sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==",
1036 | "dependencies": {
1037 | "@vue/reactivity": "3.5.13",
1038 | "@vue/shared": "3.5.13"
1039 | }
1040 | },
1041 | "node_modules/@vue/runtime-dom": {
1042 | "version": "3.5.13",
1043 | "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.13.tgz",
1044 | "integrity": "sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==",
1045 | "dependencies": {
1046 | "@vue/reactivity": "3.5.13",
1047 | "@vue/runtime-core": "3.5.13",
1048 | "@vue/shared": "3.5.13",
1049 | "csstype": "^3.1.3"
1050 | }
1051 | },
1052 | "node_modules/@vue/server-renderer": {
1053 | "version": "3.5.13",
1054 | "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.13.tgz",
1055 | "integrity": "sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==",
1056 | "dependencies": {
1057 | "@vue/compiler-ssr": "3.5.13",
1058 | "@vue/shared": "3.5.13"
1059 | },
1060 | "peerDependencies": {
1061 | "vue": "3.5.13"
1062 | }
1063 | },
1064 | "node_modules/@vue/shared": {
1065 | "version": "3.5.13",
1066 | "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.13.tgz",
1067 | "integrity": "sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ=="
1068 | },
1069 | "node_modules/birpc": {
1070 | "version": "0.2.19",
1071 | "resolved": "https://registry.npmmirror.com/birpc/-/birpc-0.2.19.tgz",
1072 | "integrity": "sha512-5WeXXAvTmitV1RqJFppT5QtUiz2p1mRSYU000Jkft5ZUCLJIk4uQriYNO50HknxKwM6jd8utNc66K1qGIwwWBQ==",
1073 | "funding": {
1074 | "url": "https://github.com/sponsors/antfu"
1075 | }
1076 | },
1077 | "node_modules/copy-anything": {
1078 | "version": "3.0.5",
1079 | "resolved": "https://registry.npmmirror.com/copy-anything/-/copy-anything-3.0.5.tgz",
1080 | "integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==",
1081 | "dependencies": {
1082 | "is-what": "^4.1.8"
1083 | },
1084 | "engines": {
1085 | "node": ">=12.13"
1086 | },
1087 | "funding": {
1088 | "url": "https://github.com/sponsors/mesqueeb"
1089 | }
1090 | },
1091 | "node_modules/csstype": {
1092 | "version": "3.1.3",
1093 | "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.1.3.tgz",
1094 | "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
1095 | },
1096 | "node_modules/detect-libc": {
1097 | "version": "2.0.3",
1098 | "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-2.0.3.tgz",
1099 | "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
1100 | "engines": {
1101 | "node": ">=8"
1102 | }
1103 | },
1104 | "node_modules/emoji-mart": {
1105 | "version": "5.6.0",
1106 | "resolved": "https://registry.npmmirror.com/emoji-mart/-/emoji-mart-5.6.0.tgz",
1107 | "integrity": "sha512-eJp3QRe79pjwa+duv+n7+5YsNhRcMl812EcFVwrnRvYKoNPoQb5qxU8DG6Bgwji0akHdp6D4Ln6tYLG58MFSow=="
1108 | },
1109 | "node_modules/enhanced-resolve": {
1110 | "version": "5.18.1",
1111 | "resolved": "https://registry.npmmirror.com/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz",
1112 | "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==",
1113 | "dependencies": {
1114 | "graceful-fs": "^4.2.4",
1115 | "tapable": "^2.2.0"
1116 | },
1117 | "engines": {
1118 | "node": ">=10.13.0"
1119 | }
1120 | },
1121 | "node_modules/entities": {
1122 | "version": "4.5.0",
1123 | "resolved": "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz",
1124 | "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
1125 | "engines": {
1126 | "node": ">=0.12"
1127 | },
1128 | "funding": {
1129 | "url": "https://github.com/fb55/entities?sponsor=1"
1130 | }
1131 | },
1132 | "node_modules/esbuild": {
1133 | "version": "0.25.1",
1134 | "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.25.1.tgz",
1135 | "integrity": "sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==",
1136 | "hasInstallScript": true,
1137 | "bin": {
1138 | "esbuild": "bin/esbuild"
1139 | },
1140 | "engines": {
1141 | "node": ">=18"
1142 | },
1143 | "optionalDependencies": {
1144 | "@esbuild/aix-ppc64": "0.25.1",
1145 | "@esbuild/android-arm": "0.25.1",
1146 | "@esbuild/android-arm64": "0.25.1",
1147 | "@esbuild/android-x64": "0.25.1",
1148 | "@esbuild/darwin-arm64": "0.25.1",
1149 | "@esbuild/darwin-x64": "0.25.1",
1150 | "@esbuild/freebsd-arm64": "0.25.1",
1151 | "@esbuild/freebsd-x64": "0.25.1",
1152 | "@esbuild/linux-arm": "0.25.1",
1153 | "@esbuild/linux-arm64": "0.25.1",
1154 | "@esbuild/linux-ia32": "0.25.1",
1155 | "@esbuild/linux-loong64": "0.25.1",
1156 | "@esbuild/linux-mips64el": "0.25.1",
1157 | "@esbuild/linux-ppc64": "0.25.1",
1158 | "@esbuild/linux-riscv64": "0.25.1",
1159 | "@esbuild/linux-s390x": "0.25.1",
1160 | "@esbuild/linux-x64": "0.25.1",
1161 | "@esbuild/netbsd-arm64": "0.25.1",
1162 | "@esbuild/netbsd-x64": "0.25.1",
1163 | "@esbuild/openbsd-arm64": "0.25.1",
1164 | "@esbuild/openbsd-x64": "0.25.1",
1165 | "@esbuild/sunos-x64": "0.25.1",
1166 | "@esbuild/win32-arm64": "0.25.1",
1167 | "@esbuild/win32-ia32": "0.25.1",
1168 | "@esbuild/win32-x64": "0.25.1"
1169 | }
1170 | },
1171 | "node_modules/estree-walker": {
1172 | "version": "2.0.2",
1173 | "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz",
1174 | "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
1175 | },
1176 | "node_modules/fsevents": {
1177 | "version": "2.3.3",
1178 | "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz",
1179 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
1180 | "hasInstallScript": true,
1181 | "optional": true,
1182 | "os": [
1183 | "darwin"
1184 | ],
1185 | "engines": {
1186 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
1187 | }
1188 | },
1189 | "node_modules/graceful-fs": {
1190 | "version": "4.2.11",
1191 | "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz",
1192 | "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
1193 | },
1194 | "node_modules/hookable": {
1195 | "version": "5.5.3",
1196 | "resolved": "https://registry.npmmirror.com/hookable/-/hookable-5.5.3.tgz",
1197 | "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="
1198 | },
1199 | "node_modules/is-what": {
1200 | "version": "4.1.16",
1201 | "resolved": "https://registry.npmmirror.com/is-what/-/is-what-4.1.16.tgz",
1202 | "integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==",
1203 | "engines": {
1204 | "node": ">=12.13"
1205 | },
1206 | "funding": {
1207 | "url": "https://github.com/sponsors/mesqueeb"
1208 | }
1209 | },
1210 | "node_modules/jiti": {
1211 | "version": "2.4.2",
1212 | "resolved": "https://registry.npmmirror.com/jiti/-/jiti-2.4.2.tgz",
1213 | "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==",
1214 | "bin": {
1215 | "jiti": "lib/jiti-cli.mjs"
1216 | }
1217 | },
1218 | "node_modules/lightningcss": {
1219 | "version": "1.29.2",
1220 | "resolved": "https://registry.npmmirror.com/lightningcss/-/lightningcss-1.29.2.tgz",
1221 | "integrity": "sha512-6b6gd/RUXKaw5keVdSEtqFVdzWnU5jMxTUjA2bVcMNPLwSQ08Sv/UodBVtETLCn7k4S1Ibxwh7k68IwLZPgKaA==",
1222 | "dependencies": {
1223 | "detect-libc": "^2.0.3"
1224 | },
1225 | "engines": {
1226 | "node": ">= 12.0.0"
1227 | },
1228 | "funding": {
1229 | "type": "opencollective",
1230 | "url": "https://opencollective.com/parcel"
1231 | },
1232 | "optionalDependencies": {
1233 | "lightningcss-darwin-arm64": "1.29.2",
1234 | "lightningcss-darwin-x64": "1.29.2",
1235 | "lightningcss-freebsd-x64": "1.29.2",
1236 | "lightningcss-linux-arm-gnueabihf": "1.29.2",
1237 | "lightningcss-linux-arm64-gnu": "1.29.2",
1238 | "lightningcss-linux-arm64-musl": "1.29.2",
1239 | "lightningcss-linux-x64-gnu": "1.29.2",
1240 | "lightningcss-linux-x64-musl": "1.29.2",
1241 | "lightningcss-win32-arm64-msvc": "1.29.2",
1242 | "lightningcss-win32-x64-msvc": "1.29.2"
1243 | }
1244 | },
1245 | "node_modules/lightningcss-darwin-arm64": {
1246 | "version": "1.29.2",
1247 | "resolved": "https://registry.npmmirror.com/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.29.2.tgz",
1248 | "integrity": "sha512-cK/eMabSViKn/PG8U/a7aCorpeKLMlK0bQeNHmdb7qUnBkNPnL+oV5DjJUo0kqWsJUapZsM4jCfYItbqBDvlcA==",
1249 | "cpu": [
1250 | "arm64"
1251 | ],
1252 | "optional": true,
1253 | "os": [
1254 | "darwin"
1255 | ],
1256 | "engines": {
1257 | "node": ">= 12.0.0"
1258 | },
1259 | "funding": {
1260 | "type": "opencollective",
1261 | "url": "https://opencollective.com/parcel"
1262 | }
1263 | },
1264 | "node_modules/lightningcss-darwin-x64": {
1265 | "version": "1.29.2",
1266 | "resolved": "https://registry.npmmirror.com/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.29.2.tgz",
1267 | "integrity": "sha512-j5qYxamyQw4kDXX5hnnCKMf3mLlHvG44f24Qyi2965/Ycz829MYqjrVg2H8BidybHBp9kom4D7DR5VqCKDXS0w==",
1268 | "cpu": [
1269 | "x64"
1270 | ],
1271 | "optional": true,
1272 | "os": [
1273 | "darwin"
1274 | ],
1275 | "engines": {
1276 | "node": ">= 12.0.0"
1277 | },
1278 | "funding": {
1279 | "type": "opencollective",
1280 | "url": "https://opencollective.com/parcel"
1281 | }
1282 | },
1283 | "node_modules/lightningcss-freebsd-x64": {
1284 | "version": "1.29.2",
1285 | "resolved": "https://registry.npmmirror.com/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.29.2.tgz",
1286 | "integrity": "sha512-wDk7M2tM78Ii8ek9YjnY8MjV5f5JN2qNVO+/0BAGZRvXKtQrBC4/cn4ssQIpKIPP44YXw6gFdpUF+Ps+RGsCwg==",
1287 | "cpu": [
1288 | "x64"
1289 | ],
1290 | "optional": true,
1291 | "os": [
1292 | "freebsd"
1293 | ],
1294 | "engines": {
1295 | "node": ">= 12.0.0"
1296 | },
1297 | "funding": {
1298 | "type": "opencollective",
1299 | "url": "https://opencollective.com/parcel"
1300 | }
1301 | },
1302 | "node_modules/lightningcss-linux-arm-gnueabihf": {
1303 | "version": "1.29.2",
1304 | "resolved": "https://registry.npmmirror.com/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.29.2.tgz",
1305 | "integrity": "sha512-IRUrOrAF2Z+KExdExe3Rz7NSTuuJ2HvCGlMKoquK5pjvo2JY4Rybr+NrKnq0U0hZnx5AnGsuFHjGnNT14w26sg==",
1306 | "cpu": [
1307 | "arm"
1308 | ],
1309 | "optional": true,
1310 | "os": [
1311 | "linux"
1312 | ],
1313 | "engines": {
1314 | "node": ">= 12.0.0"
1315 | },
1316 | "funding": {
1317 | "type": "opencollective",
1318 | "url": "https://opencollective.com/parcel"
1319 | }
1320 | },
1321 | "node_modules/lightningcss-linux-arm64-gnu": {
1322 | "version": "1.29.2",
1323 | "resolved": "https://registry.npmmirror.com/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.29.2.tgz",
1324 | "integrity": "sha512-KKCpOlmhdjvUTX/mBuaKemp0oeDIBBLFiU5Fnqxh1/DZ4JPZi4evEH7TKoSBFOSOV3J7iEmmBaw/8dpiUvRKlQ==",
1325 | "cpu": [
1326 | "arm64"
1327 | ],
1328 | "optional": true,
1329 | "os": [
1330 | "linux"
1331 | ],
1332 | "engines": {
1333 | "node": ">= 12.0.0"
1334 | },
1335 | "funding": {
1336 | "type": "opencollective",
1337 | "url": "https://opencollective.com/parcel"
1338 | }
1339 | },
1340 | "node_modules/lightningcss-linux-arm64-musl": {
1341 | "version": "1.29.2",
1342 | "resolved": "https://registry.npmmirror.com/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.29.2.tgz",
1343 | "integrity": "sha512-Q64eM1bPlOOUgxFmoPUefqzY1yV3ctFPE6d/Vt7WzLW4rKTv7MyYNky+FWxRpLkNASTnKQUaiMJ87zNODIrrKQ==",
1344 | "cpu": [
1345 | "arm64"
1346 | ],
1347 | "optional": true,
1348 | "os": [
1349 | "linux"
1350 | ],
1351 | "engines": {
1352 | "node": ">= 12.0.0"
1353 | },
1354 | "funding": {
1355 | "type": "opencollective",
1356 | "url": "https://opencollective.com/parcel"
1357 | }
1358 | },
1359 | "node_modules/lightningcss-linux-x64-gnu": {
1360 | "version": "1.29.2",
1361 | "resolved": "https://registry.npmmirror.com/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.29.2.tgz",
1362 | "integrity": "sha512-0v6idDCPG6epLXtBH/RPkHvYx74CVziHo6TMYga8O2EiQApnUPZsbR9nFNrg2cgBzk1AYqEd95TlrsL7nYABQg==",
1363 | "cpu": [
1364 | "x64"
1365 | ],
1366 | "optional": true,
1367 | "os": [
1368 | "linux"
1369 | ],
1370 | "engines": {
1371 | "node": ">= 12.0.0"
1372 | },
1373 | "funding": {
1374 | "type": "opencollective",
1375 | "url": "https://opencollective.com/parcel"
1376 | }
1377 | },
1378 | "node_modules/lightningcss-linux-x64-musl": {
1379 | "version": "1.29.2",
1380 | "resolved": "https://registry.npmmirror.com/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.29.2.tgz",
1381 | "integrity": "sha512-rMpz2yawkgGT8RULc5S4WiZopVMOFWjiItBT7aSfDX4NQav6M44rhn5hjtkKzB+wMTRlLLqxkeYEtQ3dd9696w==",
1382 | "cpu": [
1383 | "x64"
1384 | ],
1385 | "optional": true,
1386 | "os": [
1387 | "linux"
1388 | ],
1389 | "engines": {
1390 | "node": ">= 12.0.0"
1391 | },
1392 | "funding": {
1393 | "type": "opencollective",
1394 | "url": "https://opencollective.com/parcel"
1395 | }
1396 | },
1397 | "node_modules/lightningcss-win32-arm64-msvc": {
1398 | "version": "1.29.2",
1399 | "resolved": "https://registry.npmmirror.com/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.29.2.tgz",
1400 | "integrity": "sha512-nL7zRW6evGQqYVu/bKGK+zShyz8OVzsCotFgc7judbt6wnB2KbiKKJwBE4SGoDBQ1O94RjW4asrCjQL4i8Fhbw==",
1401 | "cpu": [
1402 | "arm64"
1403 | ],
1404 | "optional": true,
1405 | "os": [
1406 | "win32"
1407 | ],
1408 | "engines": {
1409 | "node": ">= 12.0.0"
1410 | },
1411 | "funding": {
1412 | "type": "opencollective",
1413 | "url": "https://opencollective.com/parcel"
1414 | }
1415 | },
1416 | "node_modules/lightningcss-win32-x64-msvc": {
1417 | "version": "1.29.2",
1418 | "resolved": "https://registry.npmmirror.com/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.29.2.tgz",
1419 | "integrity": "sha512-EdIUW3B2vLuHmv7urfzMI/h2fmlnOQBk1xlsDxkN1tCWKjNFjfLhGxYk8C8mzpSfr+A6jFFIi8fU6LbQGsRWjA==",
1420 | "cpu": [
1421 | "x64"
1422 | ],
1423 | "optional": true,
1424 | "os": [
1425 | "win32"
1426 | ],
1427 | "engines": {
1428 | "node": ">= 12.0.0"
1429 | },
1430 | "funding": {
1431 | "type": "opencollective",
1432 | "url": "https://opencollective.com/parcel"
1433 | }
1434 | },
1435 | "node_modules/magic-string": {
1436 | "version": "0.30.17",
1437 | "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.17.tgz",
1438 | "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
1439 | "dependencies": {
1440 | "@jridgewell/sourcemap-codec": "^1.5.0"
1441 | }
1442 | },
1443 | "node_modules/mitt": {
1444 | "version": "3.0.1",
1445 | "resolved": "https://registry.npmmirror.com/mitt/-/mitt-3.0.1.tgz",
1446 | "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="
1447 | },
1448 | "node_modules/nanoid": {
1449 | "version": "3.3.9",
1450 | "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.9.tgz",
1451 | "integrity": "sha512-SppoicMGpZvbF1l3z4x7No3OlIjP7QJvC9XR7AhZr1kL133KHnKPztkKDc+Ir4aJ/1VhTySrtKhrsycmrMQfvg==",
1452 | "funding": [
1453 | {
1454 | "type": "github",
1455 | "url": "https://github.com/sponsors/ai"
1456 | }
1457 | ],
1458 | "bin": {
1459 | "nanoid": "bin/nanoid.cjs"
1460 | },
1461 | "engines": {
1462 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
1463 | }
1464 | },
1465 | "node_modules/perfect-debounce": {
1466 | "version": "1.0.0",
1467 | "resolved": "https://registry.npmmirror.com/perfect-debounce/-/perfect-debounce-1.0.0.tgz",
1468 | "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA=="
1469 | },
1470 | "node_modules/picocolors": {
1471 | "version": "1.1.1",
1472 | "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz",
1473 | "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
1474 | },
1475 | "node_modules/pinia": {
1476 | "version": "3.0.1",
1477 | "resolved": "https://registry.npmmirror.com/pinia/-/pinia-3.0.1.tgz",
1478 | "integrity": "sha512-WXglsDzztOTH6IfcJ99ltYZin2mY8XZCXujkYWVIJlBjqsP6ST7zw+Aarh63E1cDVYeyUcPCxPHzJpEOmzB6Wg==",
1479 | "dependencies": {
1480 | "@vue/devtools-api": "^7.7.2"
1481 | },
1482 | "funding": {
1483 | "url": "https://github.com/sponsors/posva"
1484 | },
1485 | "peerDependencies": {
1486 | "typescript": ">=4.4.4",
1487 | "vue": "^2.7.0 || ^3.5.11"
1488 | },
1489 | "peerDependenciesMeta": {
1490 | "typescript": {
1491 | "optional": true
1492 | }
1493 | }
1494 | },
1495 | "node_modules/postcss": {
1496 | "version": "8.5.3",
1497 | "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.3.tgz",
1498 | "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==",
1499 | "funding": [
1500 | {
1501 | "type": "opencollective",
1502 | "url": "https://opencollective.com/postcss/"
1503 | },
1504 | {
1505 | "type": "tidelift",
1506 | "url": "https://tidelift.com/funding/github/npm/postcss"
1507 | },
1508 | {
1509 | "type": "github",
1510 | "url": "https://github.com/sponsors/ai"
1511 | }
1512 | ],
1513 | "dependencies": {
1514 | "nanoid": "^3.3.8",
1515 | "picocolors": "^1.1.1",
1516 | "source-map-js": "^1.2.1"
1517 | },
1518 | "engines": {
1519 | "node": "^10 || ^12 || >=14"
1520 | }
1521 | },
1522 | "node_modules/rfdc": {
1523 | "version": "1.4.1",
1524 | "resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.4.1.tgz",
1525 | "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="
1526 | },
1527 | "node_modules/rollup": {
1528 | "version": "4.35.0",
1529 | "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.35.0.tgz",
1530 | "integrity": "sha512-kg6oI4g+vc41vePJyO6dHt/yl0Rz3Thv0kJeVQ3D1kS3E5XSuKbPc29G4IpT/Kv1KQwgHVcN+HtyS+HYLNSvQg==",
1531 | "dependencies": {
1532 | "@types/estree": "1.0.6"
1533 | },
1534 | "bin": {
1535 | "rollup": "dist/bin/rollup"
1536 | },
1537 | "engines": {
1538 | "node": ">=18.0.0",
1539 | "npm": ">=8.0.0"
1540 | },
1541 | "optionalDependencies": {
1542 | "@rollup/rollup-android-arm-eabi": "4.35.0",
1543 | "@rollup/rollup-android-arm64": "4.35.0",
1544 | "@rollup/rollup-darwin-arm64": "4.35.0",
1545 | "@rollup/rollup-darwin-x64": "4.35.0",
1546 | "@rollup/rollup-freebsd-arm64": "4.35.0",
1547 | "@rollup/rollup-freebsd-x64": "4.35.0",
1548 | "@rollup/rollup-linux-arm-gnueabihf": "4.35.0",
1549 | "@rollup/rollup-linux-arm-musleabihf": "4.35.0",
1550 | "@rollup/rollup-linux-arm64-gnu": "4.35.0",
1551 | "@rollup/rollup-linux-arm64-musl": "4.35.0",
1552 | "@rollup/rollup-linux-loongarch64-gnu": "4.35.0",
1553 | "@rollup/rollup-linux-powerpc64le-gnu": "4.35.0",
1554 | "@rollup/rollup-linux-riscv64-gnu": "4.35.0",
1555 | "@rollup/rollup-linux-s390x-gnu": "4.35.0",
1556 | "@rollup/rollup-linux-x64-gnu": "4.35.0",
1557 | "@rollup/rollup-linux-x64-musl": "4.35.0",
1558 | "@rollup/rollup-win32-arm64-msvc": "4.35.0",
1559 | "@rollup/rollup-win32-ia32-msvc": "4.35.0",
1560 | "@rollup/rollup-win32-x64-msvc": "4.35.0",
1561 | "fsevents": "~2.3.2"
1562 | }
1563 | },
1564 | "node_modules/source-map-js": {
1565 | "version": "1.2.1",
1566 | "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz",
1567 | "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
1568 | "engines": {
1569 | "node": ">=0.10.0"
1570 | }
1571 | },
1572 | "node_modules/speakingurl": {
1573 | "version": "14.0.1",
1574 | "resolved": "https://registry.npmmirror.com/speakingurl/-/speakingurl-14.0.1.tgz",
1575 | "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==",
1576 | "engines": {
1577 | "node": ">=0.10.0"
1578 | }
1579 | },
1580 | "node_modules/superjson": {
1581 | "version": "2.2.2",
1582 | "resolved": "https://registry.npmmirror.com/superjson/-/superjson-2.2.2.tgz",
1583 | "integrity": "sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==",
1584 | "dependencies": {
1585 | "copy-anything": "^3.0.2"
1586 | },
1587 | "engines": {
1588 | "node": ">=16"
1589 | }
1590 | },
1591 | "node_modules/tailwindcss": {
1592 | "version": "4.0.12",
1593 | "resolved": "https://registry.npmmirror.com/tailwindcss/-/tailwindcss-4.0.12.tgz",
1594 | "integrity": "sha512-bT0hJo91FtncsAMSsMzUkoo/iEU0Xs5xgFgVC9XmdM9bw5MhZuQFjPNl6wxAE0SiQF/YTZJa+PndGWYSDtuxAg=="
1595 | },
1596 | "node_modules/tapable": {
1597 | "version": "2.2.1",
1598 | "resolved": "https://registry.npmmirror.com/tapable/-/tapable-2.2.1.tgz",
1599 | "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
1600 | "engines": {
1601 | "node": ">=6"
1602 | }
1603 | },
1604 | "node_modules/vite": {
1605 | "version": "6.2.1",
1606 | "resolved": "https://registry.npmmirror.com/vite/-/vite-6.2.1.tgz",
1607 | "integrity": "sha512-n2GnqDb6XPhlt9B8olZPrgMD/es/Nd1RdChF6CBD/fHW6pUyUTt2sQW2fPRX5GiD9XEa6+8A6A4f2vT6pSsE7Q==",
1608 | "dependencies": {
1609 | "esbuild": "^0.25.0",
1610 | "postcss": "^8.5.3",
1611 | "rollup": "^4.30.1"
1612 | },
1613 | "bin": {
1614 | "vite": "bin/vite.js"
1615 | },
1616 | "engines": {
1617 | "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
1618 | },
1619 | "funding": {
1620 | "url": "https://github.com/vitejs/vite?sponsor=1"
1621 | },
1622 | "optionalDependencies": {
1623 | "fsevents": "~2.3.3"
1624 | },
1625 | "peerDependencies": {
1626 | "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
1627 | "jiti": ">=1.21.0",
1628 | "less": "*",
1629 | "lightningcss": "^1.21.0",
1630 | "sass": "*",
1631 | "sass-embedded": "*",
1632 | "stylus": "*",
1633 | "sugarss": "*",
1634 | "terser": "^5.16.0",
1635 | "tsx": "^4.8.1",
1636 | "yaml": "^2.4.2"
1637 | },
1638 | "peerDependenciesMeta": {
1639 | "@types/node": {
1640 | "optional": true
1641 | },
1642 | "jiti": {
1643 | "optional": true
1644 | },
1645 | "less": {
1646 | "optional": true
1647 | },
1648 | "lightningcss": {
1649 | "optional": true
1650 | },
1651 | "sass": {
1652 | "optional": true
1653 | },
1654 | "sass-embedded": {
1655 | "optional": true
1656 | },
1657 | "stylus": {
1658 | "optional": true
1659 | },
1660 | "sugarss": {
1661 | "optional": true
1662 | },
1663 | "terser": {
1664 | "optional": true
1665 | },
1666 | "tsx": {
1667 | "optional": true
1668 | },
1669 | "yaml": {
1670 | "optional": true
1671 | }
1672 | }
1673 | },
1674 | "node_modules/vue": {
1675 | "version": "3.5.13",
1676 | "resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.13.tgz",
1677 | "integrity": "sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==",
1678 | "dependencies": {
1679 | "@vue/compiler-dom": "3.5.13",
1680 | "@vue/compiler-sfc": "3.5.13",
1681 | "@vue/runtime-dom": "3.5.13",
1682 | "@vue/server-renderer": "3.5.13",
1683 | "@vue/shared": "3.5.13"
1684 | },
1685 | "peerDependencies": {
1686 | "typescript": "*"
1687 | },
1688 | "peerDependenciesMeta": {
1689 | "typescript": {
1690 | "optional": true
1691 | }
1692 | }
1693 | },
1694 | "node_modules/vue-i18n": {
1695 | "version": "9.14.3",
1696 | "resolved": "https://registry.npmmirror.com/vue-i18n/-/vue-i18n-9.14.3.tgz",
1697 | "integrity": "sha512-C+E0KE8ihKjdYCQx8oUkXX+8tBItrYNMnGJuzEPevBARQFUN2tKez6ZVOvBrWH0+KT5wEk3vOWjNk7ygb2u9ig==",
1698 | "dependencies": {
1699 | "@intlify/core-base": "9.14.3",
1700 | "@intlify/shared": "9.14.3",
1701 | "@vue/devtools-api": "^6.5.0"
1702 | },
1703 | "engines": {
1704 | "node": ">= 16"
1705 | },
1706 | "funding": {
1707 | "url": "https://github.com/sponsors/kazupon"
1708 | },
1709 | "peerDependencies": {
1710 | "vue": "^3.0.0"
1711 | }
1712 | },
1713 | "node_modules/vue-i18n/node_modules/@vue/devtools-api": {
1714 | "version": "6.6.4",
1715 | "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz",
1716 | "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g=="
1717 | }
1718 | }
1719 | }
1720 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hidden-word",
3 | "private": true,
4 | "version": "1.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "preview": "vite preview"
10 | },
11 | "dependencies": {
12 | "@emoji-mart/data": "^1.2.1",
13 | "@tailwindcss/vite": "^4.0.12",
14 | "emoji-mart": "^5.6.0",
15 | "pinia": "^3.0.1",
16 | "tailwindcss": "^4.0.12",
17 | "vue": "^3.5.13",
18 | "vue-i18n": "^9.14.3"
19 | },
20 | "devDependencies": {
21 | "@vitejs/plugin-vue": "^5.2.1",
22 | "vite": "^6.2.0"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/assets/styles/styles.css:
--------------------------------------------------------------------------------
1 | @import "tailwindcss";
2 |
3 | /* 自定义滚动条样式 */
4 | ::-webkit-scrollbar {
5 | width: 8px;
6 | height: 8px;
7 | }
8 |
9 | ::-webkit-scrollbar-track {
10 | background: #f1f5f9;
11 | border-radius: 10px;
12 | }
13 |
14 | ::-webkit-scrollbar-thumb {
15 | background: #cbd5e1;
16 | border-radius: 10px;
17 | }
18 |
19 | ::-webkit-scrollbar-thumb:hover {
20 | background: #94a3b8;
21 | }
22 |
23 | /* 确保Firefox也有自定义滚动条 */
24 | * {
25 | scrollbar-width: thin;
26 | scrollbar-color: #cbd5e1 #f1f5f9;
27 | }
28 |
--------------------------------------------------------------------------------
/src/components/CleanHiddenTextButton.vue:
--------------------------------------------------------------------------------
1 |
35 |
36 |
37 |
43 |
44 |
--------------------------------------------------------------------------------
/src/components/ClearableTextarea.vue:
--------------------------------------------------------------------------------
1 |
44 |
45 |
46 |
47 |
51 |
52 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/src/components/CopyButton.vue:
--------------------------------------------------------------------------------
1 |
47 |
48 |
49 |
55 |
56 |
--------------------------------------------------------------------------------
/src/components/EmojiSelector.vue:
--------------------------------------------------------------------------------
1 |
29 |
30 |
31 |
32 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/src/components/LanguageSelector.vue:
--------------------------------------------------------------------------------
1 |
25 |
26 |
27 |
29 | {{ t('language.title') }}:
30 |
31 |
38 |
39 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/src/components/TextSelector.vue:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/composables/useCursorPosition.js:
--------------------------------------------------------------------------------
1 | import {nextTick} from 'vue';
2 | import {useAppStore} from '@/store/index.js';
3 |
4 | /**
5 | * 用于管理文本输入区域的光标位置和文本插入功能的组合式函数
6 | * @param {Object} options 配置选项
7 | * @param {string} [options.selector] 用于选择textarea元素的CSS选择器,默认为'.carrierTextarea textarea'
8 | * @param {Object} [options.modelValue] defineModel返回的响应式对象
9 | * @param {Function} [options.onPositionChange] 可选的光标位置变化回调函数
10 | * @returns {Object} 包含光标位置状态和处理方法的对象
11 | */
12 | export function useCursorPosition(options) {
13 | const {selector = '.carrierTextarea textarea', modelValue, onPositionChange} = options || {};
14 | const store = useAppStore();
15 |
16 | const textareaRef = {
17 | get value() {
18 | return document.querySelector(selector);
19 | }
20 | };
21 |
22 | const handleTextareaSelect = (event) => {
23 | const newPosition = {
24 | start: event.target.selectionStart,
25 | end: event.target.selectionEnd
26 | };
27 |
28 | store.updateCursorPosition(newPosition);
29 |
30 | if (onPositionChange) {
31 | onPositionChange(newPosition);
32 | }
33 | };
34 |
35 | const getCurrentText = () => {
36 | if (modelValue !== undefined) {
37 | return modelValue.value;
38 | }
39 | return store.carrierText;
40 | };
41 |
42 | const updateCurrentText = (newText) => {
43 | if (modelValue !== undefined) {
44 | modelValue.value = newText;
45 | return;
46 | }
47 | store.updateCarrierText(newText);
48 | };
49 |
50 | const insertTextAtCursor = (text) => {
51 | const currentText = getCurrentText();
52 | const position = store.cursorPositions;
53 | const textarea = textareaRef.value;
54 |
55 | if (position.start !== undefined && position.end !== undefined) {
56 | const before = currentText.substring(0, position.start);
57 | const after = currentText.substring(position.end);
58 | updateCurrentText(before + text + after);
59 |
60 | const newPosition = position.start + text.length;
61 |
62 | store.updateCursorPosition({
63 | start: newPosition,
64 | end: newPosition
65 | });
66 |
67 | nextTick(() => {
68 | if (textarea && typeof textarea.focus === 'function' && typeof textarea.setSelectionRange === 'function') {
69 | textarea.focus();
70 | textarea.setSelectionRange(newPosition, newPosition);
71 | }
72 | });
73 | } else {
74 | updateCurrentText(currentText + text);
75 |
76 | nextTick(() => {
77 | const newPosition = currentText.length + text.length;
78 | if (textarea && typeof textarea.focus === 'function' && typeof textarea.setSelectionRange === 'function') {
79 | textarea.focus();
80 | textarea.setSelectionRange(newPosition, newPosition);
81 | }
82 | });
83 | }
84 | };
85 |
86 | return {
87 | textareaRef,
88 | handleTextareaSelect,
89 | insertTextAtCursor
90 | };
91 | }
92 |
--------------------------------------------------------------------------------
/src/i18n/index.js:
--------------------------------------------------------------------------------
1 | import {createI18n} from 'vue-i18n';
2 | import zh from './locales/zh.js';
3 | import en from './locales/en.js';
4 |
5 | const i18n = createI18n({
6 | legacy: false, // 使用组合式API
7 | locale: localStorage.getItem('locale') || 'zh', // 默认语言
8 | fallbackLocale: 'zh', // 回退语言
9 | messages: {
10 | zh,
11 | en
12 | }
13 | });
14 |
15 | export default i18n;
16 |
--------------------------------------------------------------------------------
/src/i18n/locales/en.js:
--------------------------------------------------------------------------------
1 | export default {
2 | appTitle: 'Hidden Word',
3 | appDescription: 'Hide secret messages in plain text',
4 | mode: {
5 | decode: 'Decode',
6 | encode: 'Encode'
7 | },
8 | carrier: {
9 | title: 'Original Text',
10 | placeholder: 'Enter or select preset text',
11 | presets: 'Preset Text'
12 | },
13 | emoji: {
14 | title: 'Select Emoji',
15 | alphabet: 'Or Select Alphabet'
16 | },
17 | input: {
18 | encodeTitle: 'Text to Hide',
19 | decodeTitle: 'Text with Hidden Message',
20 | encodePlaceholder: 'Enter text to hide',
21 | decodePlaceholder: 'Paste text with hidden message'
22 | },
23 | output: {
24 | encodeTitle: 'Encoding Result',
25 | decodeTitle: 'Decoding Result',
26 | placeholder: 'Result will be displayed here'
27 | },
28 | error: {
29 | encode: 'Encoding error: Invalid input',
30 | decode: 'Decoding error: Invalid input'
31 | },
32 | copy: {
33 | default: 'Copy',
34 | success: 'Copied!'
35 | },
36 | clean: {
37 | default: 'Clean Hidden Text',
38 | success: 'Cleaned!'
39 | },
40 | footer: {
41 | description: 'Hidden Text Tool - Hide secret messages in plain text'
42 | },
43 | language: {
44 | title: 'Language',
45 | zh: 'Chinese',
46 | en: 'English'
47 | },
48 | embed: {
49 | title: 'Embed Code',
50 | description: 'Embed this code into your website to automatically encrypt all text content.',
51 | usingInputText: 'Using content from "Text to Hide" as the hidden text in embed code'
52 | }
53 | };
54 |
--------------------------------------------------------------------------------
/src/i18n/locales/zh.js:
--------------------------------------------------------------------------------
1 | export default {
2 | appTitle: 'Hidden Word',
3 | appDescription: '将秘密信息隐藏在普通文本中',
4 | mode: {
5 | decode: '解码',
6 | encode: '编码'
7 | },
8 | carrier: {
9 | title: '原始文本',
10 | placeholder: '输入或选择预设文本',
11 | presets: '预设文本'
12 | },
13 | emoji: {
14 | title: '选择表情',
15 | alphabet: '或选择字母'
16 | },
17 | input: {
18 | encodeTitle: '要隐藏的文本',
19 | decodeTitle: '包含隐藏信息的文本',
20 | encodePlaceholder: '输入要隐藏的文本',
21 | decodePlaceholder: '粘贴包含隐藏信息的文本'
22 | },
23 | output: {
24 | encodeTitle: '编码结果',
25 | decodeTitle: '解码结果',
26 | placeholder: '结果将显示在这里'
27 | },
28 | error: {
29 | encode: '编码错误: 无效输入',
30 | decode: '解码错误: 无效输入'
31 | },
32 | copy: {
33 | default: '复制',
34 | success: '已复制!'
35 | },
36 | clean: {
37 | default: '清除隐藏文本',
38 | success: '已清除!'
39 | },
40 | footer: {
41 | description: '隐藏文字工具 - 将秘密信息隐藏在普通文本中'
42 | },
43 | language: {
44 | title: '语言',
45 | zh: '中文',
46 | en: '英文'
47 | },
48 | embed: {
49 | title: '嵌入代码',
50 | description: '将此代码嵌入到您的网站中,可以自动加密网站上的所有文本内容。',
51 | usingInputText: '使用"要隐藏的文本"中的内容作为嵌入代码的隐藏文本'
52 | }
53 | };
54 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import {createApp} from 'vue'
2 | import {createPinia} from 'pinia'
3 | import App from './App.vue'
4 | import './assets/styles/styles.css'
5 | import i18n from './i18n'
6 |
7 | const app = createApp(App)
8 | const pinia = createPinia()
9 |
10 | app.use(pinia)
11 | app.use(i18n)
12 | app.mount('#app')
13 |
--------------------------------------------------------------------------------
/src/store/index.js:
--------------------------------------------------------------------------------
1 | import {defineStore} from 'pinia';
2 | import {computed, ref, watch} from 'vue';
3 | import {decode, encode} from '../utils/encoding.js';
4 | import {useI18n} from 'vue-i18n';
5 |
6 | /**
7 | * 主应用状态存储
8 | */
9 | export const useAppStore = defineStore('app', () => {
10 | // 状态
11 | const mode = ref('encode'); // encode 或 decode
12 | const inputText = ref('');
13 | const carrierText = ref(''); // 载体文本
14 | const outputText = ref('');
15 | const errorText = ref('');
16 | const {t} = useI18n();
17 |
18 | // 光标位置状态
19 | const cursorPositions = ref({
20 | start: 0,
21 | end: 0,
22 | });
23 |
24 | const isEncoding = computed(() => mode.value === 'encode');
25 |
26 | function toggleMode() {
27 | mode.value = isEncoding.value ? 'decode' : 'encode';
28 | inputText.value = '';
29 | outputText.value = '';
30 | errorText.value = '';
31 | }
32 |
33 | watch([mode, inputText, carrierText], () => {
34 | try {
35 | if (isEncoding.value) {
36 | if (inputText.value && carrierText.value) {
37 | outputText.value = encode(inputText.value, carrierText.value);
38 | } else {
39 | outputText.value = '';
40 | }
41 | } else {
42 | if (inputText.value) {
43 | outputText.value = decode(inputText.value);
44 | } else {
45 | outputText.value = '';
46 | }
47 | }
48 | errorText.value = '';
49 | } catch (e) {
50 | outputText.value = '';
51 | errorText.value = isEncoding.value ? t('error.encode') : t('error.decode');
52 | }
53 | });
54 |
55 | function updateCursorPosition(newPosition) {
56 | cursorPositions.value.start = newPosition.start;
57 | cursorPositions.value.end = newPosition.end;
58 | }
59 |
60 | function updateCarrierText(newText) {
61 | carrierText.value = newText;
62 | }
63 |
64 | return {
65 | mode,
66 | inputText,
67 | carrierText,
68 | outputText,
69 | errorText,
70 | cursorPositions,
71 | isEncoding,
72 | toggleMode,
73 | updateCursorPosition,
74 | updateCarrierText
75 | };
76 | });
77 |
--------------------------------------------------------------------------------
/src/utils/cleanText.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 清除文本中的隐藏内容(变体选择器)
3 | * @param {string} text - 包含隐藏内容的文本
4 | * @returns {string} - 清除隐藏内容后的文本
5 | */
6 | export function cleanHiddenText(text) {
7 | if (!text) return '';
8 |
9 | const VARIATION_SELECTOR_START = 0xfe00;
10 | const VARIATION_SELECTOR_END = 0xfe0f;
11 | const VARIATION_SELECTOR_SUPPLEMENT_START = 0xe0100;
12 | const VARIATION_SELECTOR_SUPPLEMENT_END = 0xe01ef;
13 |
14 | const chars = Array.from(text);
15 | let result = '';
16 |
17 | for (let i = 0; i < chars.length; i++) {
18 | const char = chars[i];
19 | const codePoint = char.codePointAt(0);
20 |
21 | // 添加非变体选择器字符到结果中
22 | if (!(
23 | (codePoint >= VARIATION_SELECTOR_START && codePoint <= VARIATION_SELECTOR_END) ||
24 | (codePoint >= VARIATION_SELECTOR_SUPPLEMENT_START && codePoint <= VARIATION_SELECTOR_SUPPLEMENT_END)
25 | )) {
26 | result += char;
27 | }
28 | }
29 |
30 | return result;
31 | }
--------------------------------------------------------------------------------
/src/utils/embedCode.js:
--------------------------------------------------------------------------------
1 | export function generateEmbedCode(customMessage = 'Hidden Word 已加密此内容') {
2 | // 压缩后的基本代码
3 | const code = `(function(){const a=0xfe00,b=0xfe0f,c=0xe0100,d=0xe01ef;function e(n){return n>=0&&n<16?String.fromCodePoint(a+n):n>=16&&n<256?String.fromCodePoint(c+n-16):null}function f(n){return n>=a&&n<=b?n-a:n>=c&&n<=d?n-c+16:null}function g(t,h){const i=new TextEncoder().encode(t);if(!h||h.length===0)h="A";const j=Array.from(h);let k="";if(i.length<=j.length){const l=[];for(let m=0;m0;m--){const n=Math.floor(Math.random()*(m+1));[l[m],l[n]]=[l[n],l[m]]}const o=l.slice(0,i.length);o.sort((a,b)=>a-b);let p=0;for(let m=0;m{const x=v.nodeValue;if(x.trim().length>0)v.nodeValue=g(s,x)})}document.readyState==='loading'?document.addEventListener('DOMContentLoaded',r):r();`;
7 |
8 | return code + autoEncryptFunction + '})();';
9 | }
10 |
11 | export function generateHtmlSnippet(customMessage = 'Hidden Word 已加密此内容') {
12 | const jsCode = generateEmbedCode(customMessage);
13 | return ``;
14 | }
--------------------------------------------------------------------------------
/src/utils/emoji.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 可用于编码的表情列表
3 | */
4 | export const EMOJI_LIST = [
5 | "😀",
6 | "😂",
7 | "🥰",
8 | "😎",
9 | "🤔",
10 | "👍",
11 | "👎",
12 | "👏",
13 | "😅",
14 | "🤝",
15 | "🎉",
16 | "🎂",
17 | "🍕",
18 | "🌈",
19 | "🌞",
20 | "🌙",
21 | "🔥",
22 | "💯",
23 | "🚀",
24 | "👀",
25 | "💀",
26 | "🥹",
27 | "...",
28 | ];
29 |
30 | /**
31 | * 可用于编码的字母列表
32 | */
33 | export const ALPHABET_LIST = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
34 |
35 | /**
36 | * 常用的载体文本列表
37 | */
38 | export const CARRIER_TEXT_LIST = [
39 | "你好,世界",
40 | "Hello World",
41 | "这是一段普通文本",
42 | "This is a normal text",
43 | "隐藏信息的艺术",
44 | "The art of hiding information",
45 | ];
--------------------------------------------------------------------------------
/src/utils/encoding.js:
--------------------------------------------------------------------------------
1 | const VARIATION_SELECTOR_START = 0xfe00;
2 | const VARIATION_SELECTOR_END = 0xfe0f;
3 |
4 | const VARIATION_SELECTOR_SUPPLEMENT_START = 0xe0100;
5 | const VARIATION_SELECTOR_SUPPLEMENT_END = 0xe01ef;
6 |
7 | /**
8 | * 将字节转换为变体选择器
9 | * @param {number} byte - 要转换的字节
10 | * @returns {string|null} - 变体选择器字符或null
11 | */
12 | export function toVariationSelector(byte) {
13 | if (byte >= 0 && byte < 16) {
14 | return String.fromCodePoint(VARIATION_SELECTOR_START + byte);
15 | } else if (byte >= 16 && byte < 256) {
16 | return String.fromCodePoint(VARIATION_SELECTOR_SUPPLEMENT_START + byte - 16);
17 | } else {
18 | return null;
19 | }
20 | }
21 |
22 | /**
23 | * 从变体选择器转换为字节
24 | * @param {number} codePoint - 变体选择器的码点
25 | * @returns {number|null} - 字节或null
26 | */
27 | export function fromVariationSelector(codePoint) {
28 | if (codePoint >= VARIATION_SELECTOR_START && codePoint <= VARIATION_SELECTOR_END) {
29 | return codePoint - VARIATION_SELECTOR_START;
30 | } else if (
31 | codePoint >= VARIATION_SELECTOR_SUPPLEMENT_START &&
32 | codePoint <= VARIATION_SELECTOR_SUPPLEMENT_END
33 | ) {
34 | return codePoint - VARIATION_SELECTOR_SUPPLEMENT_START + 16;
35 | } else {
36 | return null;
37 | }
38 | }
39 |
40 | /**
41 | * 将文本编码到一段文本中
42 | * @param {string} text - 要隐藏的文本
43 | * @param {string} carrier - 承载隐藏文本的文本
44 | * @returns {string} - 编码后的文本
45 | */
46 | export function encode(text, carrier) {
47 | // 将字符串转换为utf-8字节
48 | const bytes = new TextEncoder().encode(text);
49 |
50 | // 如果carrier是空字符串,使用默认字符
51 | if (!carrier || carrier.length === 0) {
52 | carrier = "A";
53 | }
54 |
55 | // 将字节分布到carrier的每个字符中
56 | const carrierChars = Array.from(carrier);
57 | let result = "";
58 |
59 | // 如果隐藏文字字节少于载体文本,使用随机算法分散
60 | if (bytes.length <= carrierChars.length) {
61 | // 创建一个随机位置数组,用于随机分布字节
62 | const positions = [];
63 | for (let i = 0; i < carrierChars.length; i++) {
64 | positions.push(i);
65 | }
66 |
67 | // 随机打乱位置数组
68 | for (let i = positions.length - 1; i > 0; i--) {
69 | const j = Math.floor(Math.random() * (i + 1));
70 | [positions[i], positions[j]] = [positions[j], positions[i]];
71 | }
72 |
73 | // 选择前bytes.length个位置用于插入变体选择器
74 | const selectedPositions = positions.slice(0, bytes.length);
75 | selectedPositions.sort((a, b) => a - b); // 重新排序,以便按顺序处理
76 |
77 | // 构建结果字符串,在选定的位置插入变体选择器
78 | let byteIndex = 0;
79 | for (let i = 0; i < carrierChars.length; i++) {
80 | console.log(result);
81 | result += carrierChars[i];
82 |
83 | // 检查当前位置是否是选定的位置之一
84 | if (selectedPositions.includes(i) && byteIndex < bytes.length) {
85 | const selector = toVariationSelector(bytes[byteIndex]);
86 | if (selector) {
87 | result += selector;
88 | }
89 | byteIndex++;
90 | }
91 | }
92 | } else {
93 | // 如果隐藏文字字节多于载体文本,将多余的字节叠加到最后一个字符
94 | let byteIndex = 0;
95 |
96 | // 先处理能均匀分配到载体字符的字节
97 | for (let i = 0; i < carrierChars.length; i++) {
98 | result += carrierChars[i];
99 |
100 | // 如果还有字节需要处理
101 | if (byteIndex < bytes.length) {
102 | const selector = toVariationSelector(bytes[byteIndex]);
103 | if (selector) {
104 | result += selector;
105 | }
106 | byteIndex++;
107 | }
108 | }
109 |
110 | // 将剩余的字节全部叠加到最后一个字符
111 | while (byteIndex < bytes.length) {
112 | const selector = toVariationSelector(bytes[byteIndex]);
113 | if (selector) {
114 | result += selector;
115 | }
116 | byteIndex++;
117 | }
118 | }
119 |
120 | return result;
121 | }
122 |
123 | /**
124 | * 从编码文本中解码隐藏的文本
125 | * @param {string} encodedText - 编码后的文本
126 | * @returns {string} - 解码后的文本
127 | */
128 | export function decode(encodedText) {
129 | const decoded = [];
130 | const chars = Array.from(encodedText);
131 |
132 | // 遍历每个字符,检查其后是否有变体选择器
133 | for (let i = 0; i < chars.length; i++) {
134 | // 检查当前字符后的所有连续变体选择器
135 | while (i + 1 < chars.length) {
136 | const nextChar = chars[i + 1];
137 | const byte = fromVariationSelector(nextChar.codePointAt(0));
138 |
139 | if (byte !== null) {
140 | decoded.push(byte);
141 | i++; // 跳过已处理的变体选择器
142 | } else {
143 | break; // 如果不是变体选择器,退出内部循环
144 | }
145 | }
146 | }
147 |
148 | // 将字节数组转换回字符串
149 | const decodedArray = new Uint8Array(decoded);
150 | return new TextDecoder().decode(decodedArray);
151 | }
152 |
--------------------------------------------------------------------------------
/src/views/components/CarrierTextPanel.vue:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
22 |
23 |
24 |
25 |
26 |
{{ t('carrier.title') }}
27 |
28 |
29 |
30 |
31 |
32 |
35 |
36 |
37 |
38 |
39 |
{{ t('carrier.presets') }}
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/src/views/components/EmbedCodePanel.vue:
--------------------------------------------------------------------------------
1 |
28 |
29 |
30 |
32 |
33 |
34 |
35 |
36 |
{{ t('embed.title') }}
37 |
38 |
39 |
45 |
46 |
47 |
49 |
{{ htmlSnippet }}
50 |
51 |
52 |
53 |
54 |
55 | {{ t('embed.usingInputText') }}
56 |
57 |
58 |
59 |
60 |
61 |
62 | {{ t('embed.description') }}
63 |
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/src/views/components/EmojiPanel.vue:
--------------------------------------------------------------------------------
1 |
78 |
79 |
80 |
83 |
84 |
85 |
86 |
{{ t('emoji.title') }}
87 |
88 |
89 |
90 |
92 |
93 |
94 |
95 |
96 |
{{ t('emoji.alphabet') }}
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
110 |
113 |
114 |
115 |
116 |
117 |
--------------------------------------------------------------------------------
/src/views/components/FooterSection.vue:
--------------------------------------------------------------------------------
1 |
20 |
21 |
22 |
23 |
37 |
38 |
39 |
Made with
40 |
41 |
and
42 |
43 |
by
44 |
50 |
51 | Ackites
52 |
53 |
54 |
55 |
56 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/src/views/components/InputPanel.vue:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
19 |
20 |
21 |
22 |
24 |
25 | {{ store.isEncoding ? t('input.encodeTitle') : t('input.decodeTitle') }}
26 |
27 |
28 |
29 |
30 |
31 |
33 |
34 |
35 |
36 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/src/views/components/ModeToggle.vue:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
13 |
17 | {{ t('mode.decode') }}
18 |
19 |
20 |
32 |
33 |
37 | {{ t('mode.encode') }}
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/src/views/components/OutputPanel.vue:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
13 |
14 |
15 |
16 |
18 |
19 | {{ store.isEncoding ? t('output.encodeTitle') : t('output.decodeTitle') }}
20 |
21 |
22 |
23 |
24 |
25 |
26 |
28 |
{{
30 | store.outputText
31 | }}
32 |
33 | {{ t('output.placeholder') }}
34 |
35 |
36 |
37 |
38 |
42 |
43 |
44 | {{ store.errorText }}
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/src/views/index.vue:
--------------------------------------------------------------------------------
1 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | {{ t('appTitle') }}
22 | 🎭
23 |
24 |
{{ t('appDescription') }}
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/vite.config.js:
--------------------------------------------------------------------------------
1 | import {defineConfig} from 'vite'
2 | import vue from '@vitejs/plugin-vue'
3 | import tailwindcss from '@tailwindcss/vite'
4 | import {fileURLToPath, URL} from 'node:url'
5 |
6 |
7 | // https://vite.dev/config/
8 | export default defineConfig({
9 | plugins: [vue(), tailwindcss(),],
10 | resolve: {
11 | alias: {
12 | '@': fileURLToPath(new URL('./src', import.meta.url))
13 | }
14 | },
15 | server: {
16 | host: '0.0.0.0'
17 | },
18 | base: process.env.NODE_ENV === 'production' ? './' : '/'
19 | })
20 |
--------------------------------------------------------------------------------