@cnc_cbz/usefultools-plugin-official 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -0
- package/dist/base-converter.mjs +333 -0
- package/dist/case-converter.mjs +142 -0
- package/dist/chmod-calculator.mjs +286 -0
- package/dist/color-converter.mjs +211 -0
- package/dist/cron-expression.mjs +487 -0
- package/dist/cyber-chef.mjs +24885 -0
- package/dist/hash-generator.mjs +239 -0
- package/dist/html-entity.mjs +187 -0
- package/dist/image-compressor.mjs +337 -0
- package/dist/ip-subnet.mjs +222 -0
- package/dist/js-runner.mjs +39973 -0
- package/dist/json-diff.mjs +704 -0
- package/dist/json-formatter.mjs +1138 -0
- package/dist/json-yaml.mjs +256 -0
- package/dist/jwt-parser.mjs +405 -0
- package/dist/lorem-ipsum.mjs +246 -0
- package/dist/markdown-preview.mjs +184 -0
- package/dist/password-generator.mjs +254 -0
- package/dist/qr-generator.mjs +238 -0
- package/dist/regex-tester.mjs +424 -0
- package/dist/sql-formatter.mjs +242 -0
- package/dist/text-diff.mjs +940 -0
- package/dist/text-stats.mjs +205 -0
- package/dist/timestamp-converter.mjs +339 -0
- package/dist/translator.mjs +667 -0
- package/dist/url-codec.mjs +179 -0
- package/dist/uuid-generator.mjs +165 -0
- package/package.json +56 -0
- package/plugin.json +31 -0
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import { defineComponent, ref, computed, openBlock, createElementBlock, createElementVNode, Fragment, renderList, normalizeClass, toDisplayString, withDirectives, vModelText } from "vue";
|
|
2
|
+
const _hoisted_1 = { class: "flex flex-col h-full gap-5" };
|
|
3
|
+
const _hoisted_2 = { class: "bg-deep-charcoal border-4 border-black rounded-xl p-4 shadow-hard" };
|
|
4
|
+
const _hoisted_3 = { class: "flex flex-wrap items-center gap-3" };
|
|
5
|
+
const _hoisted_4 = { class: "flex gap-2" };
|
|
6
|
+
const _hoisted_5 = ["onClick"];
|
|
7
|
+
const _hoisted_6 = { class: "flex items-center gap-2" };
|
|
8
|
+
const _hoisted_7 = { class: "flex-1 overflow-auto bg-deep-charcoal border-4 border-black rounded-xl p-5 shadow-hard" };
|
|
9
|
+
const _hoisted_8 = { class: "text-gray-200 text-sm leading-relaxed whitespace-pre-wrap select-all" };
|
|
10
|
+
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
11
|
+
__name: "index",
|
|
12
|
+
setup(__props) {
|
|
13
|
+
const count = ref(3);
|
|
14
|
+
const unit = ref("paragraphs");
|
|
15
|
+
const copyField = ref("");
|
|
16
|
+
const words = [
|
|
17
|
+
"lorem",
|
|
18
|
+
"ipsum",
|
|
19
|
+
"dolor",
|
|
20
|
+
"sit",
|
|
21
|
+
"amet",
|
|
22
|
+
"consectetur",
|
|
23
|
+
"adipiscing",
|
|
24
|
+
"elit",
|
|
25
|
+
"sed",
|
|
26
|
+
"do",
|
|
27
|
+
"eiusmod",
|
|
28
|
+
"tempor",
|
|
29
|
+
"incididunt",
|
|
30
|
+
"ut",
|
|
31
|
+
"labore",
|
|
32
|
+
"et",
|
|
33
|
+
"dolore",
|
|
34
|
+
"magna",
|
|
35
|
+
"aliqua",
|
|
36
|
+
"enim",
|
|
37
|
+
"ad",
|
|
38
|
+
"minim",
|
|
39
|
+
"veniam",
|
|
40
|
+
"quis",
|
|
41
|
+
"nostrud",
|
|
42
|
+
"exercitation",
|
|
43
|
+
"ullamco",
|
|
44
|
+
"laboris",
|
|
45
|
+
"nisi",
|
|
46
|
+
"aliquip",
|
|
47
|
+
"ex",
|
|
48
|
+
"ea",
|
|
49
|
+
"commodo",
|
|
50
|
+
"consequat",
|
|
51
|
+
"duis",
|
|
52
|
+
"aute",
|
|
53
|
+
"irure",
|
|
54
|
+
"in",
|
|
55
|
+
"reprehenderit",
|
|
56
|
+
"voluptate",
|
|
57
|
+
"velit",
|
|
58
|
+
"esse",
|
|
59
|
+
"cillum",
|
|
60
|
+
"fugiat",
|
|
61
|
+
"nulla",
|
|
62
|
+
"pariatur",
|
|
63
|
+
"excepteur",
|
|
64
|
+
"sint",
|
|
65
|
+
"occaecat",
|
|
66
|
+
"cupidatat",
|
|
67
|
+
"non",
|
|
68
|
+
"proident",
|
|
69
|
+
"sunt",
|
|
70
|
+
"culpa",
|
|
71
|
+
"qui",
|
|
72
|
+
"officia",
|
|
73
|
+
"deserunt",
|
|
74
|
+
"mollit",
|
|
75
|
+
"anim",
|
|
76
|
+
"id",
|
|
77
|
+
"est",
|
|
78
|
+
"laborum",
|
|
79
|
+
"perspiciatis",
|
|
80
|
+
"unde",
|
|
81
|
+
"omnis",
|
|
82
|
+
"iste",
|
|
83
|
+
"natus",
|
|
84
|
+
"error",
|
|
85
|
+
"voluptatem",
|
|
86
|
+
"accusantium",
|
|
87
|
+
"doloremque",
|
|
88
|
+
"laudantium",
|
|
89
|
+
"totam",
|
|
90
|
+
"rem",
|
|
91
|
+
"aperiam",
|
|
92
|
+
"eaque",
|
|
93
|
+
"ipsa",
|
|
94
|
+
"quae",
|
|
95
|
+
"ab",
|
|
96
|
+
"illo",
|
|
97
|
+
"inventore",
|
|
98
|
+
"veritatis",
|
|
99
|
+
"quasi",
|
|
100
|
+
"architecto",
|
|
101
|
+
"beatae",
|
|
102
|
+
"vitae",
|
|
103
|
+
"dicta",
|
|
104
|
+
"explicabo",
|
|
105
|
+
"nemo",
|
|
106
|
+
"ipsam",
|
|
107
|
+
"quia",
|
|
108
|
+
"voluptas",
|
|
109
|
+
"aspernatur",
|
|
110
|
+
"aut",
|
|
111
|
+
"odit",
|
|
112
|
+
"fugit",
|
|
113
|
+
"consequuntur",
|
|
114
|
+
"magni",
|
|
115
|
+
"dolores",
|
|
116
|
+
"eos",
|
|
117
|
+
"ratione",
|
|
118
|
+
"sequi",
|
|
119
|
+
"nesciunt"
|
|
120
|
+
];
|
|
121
|
+
function randomWord() {
|
|
122
|
+
return words[Math.floor(Math.random() * words.length)];
|
|
123
|
+
}
|
|
124
|
+
function generateSentence() {
|
|
125
|
+
const len = 8 + Math.floor(Math.random() * 12);
|
|
126
|
+
const s = Array.from({ length: len }, () => randomWord()).join(" ");
|
|
127
|
+
return s.charAt(0).toUpperCase() + s.slice(1) + ".";
|
|
128
|
+
}
|
|
129
|
+
function generateParagraph() {
|
|
130
|
+
const len = 3 + Math.floor(Math.random() * 4);
|
|
131
|
+
return Array.from({ length: len }, () => generateSentence()).join(" ");
|
|
132
|
+
}
|
|
133
|
+
const output = computed(() => {
|
|
134
|
+
if (unit.value === "words") {
|
|
135
|
+
return Array.from({ length: count.value }, () => randomWord()).join(" ");
|
|
136
|
+
}
|
|
137
|
+
if (unit.value === "sentences") {
|
|
138
|
+
return Array.from({ length: count.value }, () => generateSentence()).join(" ");
|
|
139
|
+
}
|
|
140
|
+
return Array.from({ length: count.value }, () => generateParagraph()).join("\n\n");
|
|
141
|
+
});
|
|
142
|
+
const regenerateKey = ref(0);
|
|
143
|
+
function regenerate() {
|
|
144
|
+
regenerateKey.value++;
|
|
145
|
+
}
|
|
146
|
+
const displayText = computed(() => {
|
|
147
|
+
regenerateKey.value;
|
|
148
|
+
return output.value;
|
|
149
|
+
});
|
|
150
|
+
async function copy(text, field) {
|
|
151
|
+
await navigator.clipboard.writeText(text);
|
|
152
|
+
copyField.value = field;
|
|
153
|
+
setTimeout(() => {
|
|
154
|
+
copyField.value = "";
|
|
155
|
+
}, 1200);
|
|
156
|
+
}
|
|
157
|
+
return (_ctx, _cache) => {
|
|
158
|
+
return openBlock(), createElementBlock("div", _hoisted_1, [
|
|
159
|
+
createElementVNode("div", _hoisted_2, [
|
|
160
|
+
_cache[3] || (_cache[3] = createElementVNode(
|
|
161
|
+
"div",
|
|
162
|
+
{ class: "flex items-center gap-2 mb-3" },
|
|
163
|
+
[
|
|
164
|
+
createElementVNode("span", { class: "material-icons text-primary text-lg" }, "notes"),
|
|
165
|
+
createElementVNode("span", { class: "text-sm font-bold text-gray-400 uppercase tracking-wider" }, "Lorem Ipsum 生成器")
|
|
166
|
+
],
|
|
167
|
+
-1
|
|
168
|
+
/* CACHED */
|
|
169
|
+
)),
|
|
170
|
+
createElementVNode("div", _hoisted_3, [
|
|
171
|
+
createElementVNode("div", _hoisted_4, [
|
|
172
|
+
(openBlock(), createElementBlock(
|
|
173
|
+
Fragment,
|
|
174
|
+
null,
|
|
175
|
+
renderList(["paragraphs", "sentences", "words"], (u) => {
|
|
176
|
+
return createElementVNode("button", {
|
|
177
|
+
key: u,
|
|
178
|
+
onClick: ($event) => unit.value = u,
|
|
179
|
+
class: normalizeClass(["h-9 px-3 font-bold border-2 border-black rounded text-xs transition-all", unit.value === u ? "bg-primary text-black shadow-none translate-x-0.5 translate-y-0.5" : "bg-bg-dark text-gray-400 shadow-hard-sm hover:shadow-none hover:translate-x-0.5 hover:translate-y-0.5"])
|
|
180
|
+
}, toDisplayString(u === "paragraphs" ? "段落" : u === "sentences" ? "句子" : "单词"), 11, _hoisted_5);
|
|
181
|
+
}),
|
|
182
|
+
64
|
|
183
|
+
/* STABLE_FRAGMENT */
|
|
184
|
+
))
|
|
185
|
+
]),
|
|
186
|
+
createElementVNode("div", _hoisted_6, [
|
|
187
|
+
_cache[2] || (_cache[2] = createElementVNode(
|
|
188
|
+
"span",
|
|
189
|
+
{ class: "text-xs text-gray-500" },
|
|
190
|
+
"数量:",
|
|
191
|
+
-1
|
|
192
|
+
/* CACHED */
|
|
193
|
+
)),
|
|
194
|
+
withDirectives(createElementVNode(
|
|
195
|
+
"input",
|
|
196
|
+
{
|
|
197
|
+
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => count.value = $event),
|
|
198
|
+
type: "number",
|
|
199
|
+
min: "1",
|
|
200
|
+
max: "100",
|
|
201
|
+
class: "w-16 h-9 bg-bg-dark text-gray-100 border-2 border-black rounded px-2 font-mono text-sm text-center outline-none focus:border-primary"
|
|
202
|
+
},
|
|
203
|
+
null,
|
|
204
|
+
512
|
|
205
|
+
/* NEED_PATCH */
|
|
206
|
+
), [
|
|
207
|
+
[
|
|
208
|
+
vModelText,
|
|
209
|
+
count.value,
|
|
210
|
+
void 0,
|
|
211
|
+
{ number: true }
|
|
212
|
+
]
|
|
213
|
+
])
|
|
214
|
+
]),
|
|
215
|
+
createElementVNode("button", {
|
|
216
|
+
onClick: regenerate,
|
|
217
|
+
class: "h-9 px-4 bg-primary text-black font-bold border-2 border-black rounded shadow-hard-sm hover:shadow-none hover:translate-x-0.5 hover:translate-y-0.5 transition-all text-xs"
|
|
218
|
+
}, " 重新生成 "),
|
|
219
|
+
createElementVNode(
|
|
220
|
+
"button",
|
|
221
|
+
{
|
|
222
|
+
onClick: _cache[1] || (_cache[1] = ($event) => copy(displayText.value, "text")),
|
|
223
|
+
class: "h-9 px-3 bg-bg-dark text-gray-400 font-bold border-2 border-black rounded shadow-hard-sm hover:shadow-none hover:translate-x-0.5 hover:translate-y-0.5 transition-all text-xs"
|
|
224
|
+
},
|
|
225
|
+
toDisplayString(copyField.value === "text" ? "已复制" : "复制"),
|
|
226
|
+
1
|
|
227
|
+
/* TEXT */
|
|
228
|
+
)
|
|
229
|
+
])
|
|
230
|
+
]),
|
|
231
|
+
createElementVNode("div", _hoisted_7, [
|
|
232
|
+
createElementVNode(
|
|
233
|
+
"div",
|
|
234
|
+
_hoisted_8,
|
|
235
|
+
toDisplayString(displayText.value),
|
|
236
|
+
1
|
|
237
|
+
/* TEXT */
|
|
238
|
+
)
|
|
239
|
+
])
|
|
240
|
+
]);
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
export {
|
|
245
|
+
_sfc_main as default
|
|
246
|
+
};
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { defineComponent, ref, computed, openBlock, createElementBlock, createElementVNode, toDisplayString, createCommentVNode, withDirectives, vModelText } from "vue";
|
|
2
|
+
const _hoisted_1 = { class: "flex flex-col h-full gap-4" };
|
|
3
|
+
const _hoisted_2 = { class: "flex items-center justify-between" };
|
|
4
|
+
const _hoisted_3 = { class: "flex-1 grid grid-cols-2 gap-4 min-h-0" };
|
|
5
|
+
const _hoisted_4 = { class: "bg-deep-charcoal border-4 border-black rounded-xl shadow-hard overflow-hidden flex flex-col" };
|
|
6
|
+
const _hoisted_5 = { class: "bg-deep-charcoal border-4 border-black rounded-xl shadow-hard overflow-hidden flex flex-col" };
|
|
7
|
+
const _hoisted_6 = ["innerHTML"];
|
|
8
|
+
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
9
|
+
__name: "index",
|
|
10
|
+
setup(__props) {
|
|
11
|
+
const input = ref(`# Markdown 预览
|
|
12
|
+
|
|
13
|
+
这是一个 **Markdown** 实时预览工具。
|
|
14
|
+
|
|
15
|
+
## 功能
|
|
16
|
+
- 支持标题、列表、代码块
|
|
17
|
+
- 实时渲染预览
|
|
18
|
+
- 左右分栏布局
|
|
19
|
+
|
|
20
|
+
### 代码示例
|
|
21
|
+
\`\`\`javascript
|
|
22
|
+
const hello = "world"
|
|
23
|
+
console.log(hello)
|
|
24
|
+
\`\`\`
|
|
25
|
+
|
|
26
|
+
> 引用文本示例
|
|
27
|
+
|
|
28
|
+
| 表头1 | 表头2 |
|
|
29
|
+
|-------|-------|
|
|
30
|
+
| 内容1 | 内容2 |
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
[链接示例](https://example.com)
|
|
35
|
+
`);
|
|
36
|
+
const copyField = ref("");
|
|
37
|
+
function renderMarkdown(md) {
|
|
38
|
+
let html = md;
|
|
39
|
+
html = html.replace(/```(\w*)\n([\s\S]*?)```/g, '<pre class="md-code-block"><code>$2</code></pre>');
|
|
40
|
+
html = html.replace(/`([^`]+)`/g, '<code class="md-inline-code">$1</code>');
|
|
41
|
+
html = html.replace(/^\|(.+)\|\s*\n\|[-| :]+\|\s*\n((?:\|.+\|\s*\n?)*)/gm, (_, header, body) => {
|
|
42
|
+
const ths = header.split("|").map((h) => `<th>${h.trim()}</th>`).join("");
|
|
43
|
+
const rows = body.trim().split("\n").map((row) => {
|
|
44
|
+
const tds = row.replace(/^\||\|$/g, "").split("|").map((c) => `<td>${c.trim()}</td>`).join("");
|
|
45
|
+
return `<tr>${tds}</tr>`;
|
|
46
|
+
}).join("");
|
|
47
|
+
return `<table class="md-table"><thead><tr>${ths}</tr></thead><tbody>${rows}</tbody></table>`;
|
|
48
|
+
});
|
|
49
|
+
html = html.replace(/^### (.+)$/gm, "<h3>$1</h3>");
|
|
50
|
+
html = html.replace(/^## (.+)$/gm, "<h2>$1</h2>");
|
|
51
|
+
html = html.replace(/^# (.+)$/gm, "<h1>$1</h1>");
|
|
52
|
+
html = html.replace(/^---$/gm, "<hr/>");
|
|
53
|
+
html = html.replace(/^> (.+)$/gm, "<blockquote>$1</blockquote>");
|
|
54
|
+
html = html.replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>");
|
|
55
|
+
html = html.replace(/\*(.+?)\*/g, "<em>$1</em>");
|
|
56
|
+
html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" target="_blank">$1</a>');
|
|
57
|
+
html = html.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, '<img src="$2" alt="$1"/>');
|
|
58
|
+
html = html.replace(/^- (.+)$/gm, "<li>$1</li>");
|
|
59
|
+
html = html.replace(/(<li>.*<\/li>\n?)+/g, "<ul>$&</ul>");
|
|
60
|
+
html = html.replace(/^(?!<[a-z])((?!<\/)[^\n]+)$/gm, "<p>$1</p>");
|
|
61
|
+
return html;
|
|
62
|
+
}
|
|
63
|
+
const rendered = computed(() => renderMarkdown(input.value));
|
|
64
|
+
async function copy(text, field) {
|
|
65
|
+
await navigator.clipboard.writeText(text);
|
|
66
|
+
copyField.value = field;
|
|
67
|
+
setTimeout(() => {
|
|
68
|
+
copyField.value = "";
|
|
69
|
+
}, 1200);
|
|
70
|
+
}
|
|
71
|
+
return (_ctx, _cache) => {
|
|
72
|
+
return openBlock(), createElementBlock("div", _hoisted_1, [
|
|
73
|
+
createElementVNode("div", _hoisted_2, [
|
|
74
|
+
_cache[2] || (_cache[2] = createElementVNode(
|
|
75
|
+
"div",
|
|
76
|
+
{ class: "flex items-center gap-2" },
|
|
77
|
+
[
|
|
78
|
+
createElementVNode("span", { class: "material-icons text-primary text-lg" }, "article"),
|
|
79
|
+
createElementVNode("span", { class: "text-sm font-bold text-gray-400 uppercase tracking-wider" }, "Markdown 预览")
|
|
80
|
+
],
|
|
81
|
+
-1
|
|
82
|
+
/* CACHED */
|
|
83
|
+
)),
|
|
84
|
+
createElementVNode(
|
|
85
|
+
"button",
|
|
86
|
+
{
|
|
87
|
+
onClick: _cache[0] || (_cache[0] = ($event) => copy(rendered.value, "html")),
|
|
88
|
+
class: "h-8 px-3 bg-bg-dark text-gray-400 font-bold border-2 border-black rounded shadow-hard-sm hover:shadow-none hover:translate-x-0.5 hover:translate-y-0.5 transition-all text-xs"
|
|
89
|
+
},
|
|
90
|
+
toDisplayString(copyField.value === "html" ? "已复制 HTML" : "复制 HTML"),
|
|
91
|
+
1
|
|
92
|
+
/* TEXT */
|
|
93
|
+
)
|
|
94
|
+
]),
|
|
95
|
+
createElementVNode("div", _hoisted_3, [
|
|
96
|
+
createCommentVNode(" 编辑器 "),
|
|
97
|
+
createElementVNode("div", _hoisted_4, [
|
|
98
|
+
_cache[3] || (_cache[3] = createElementVNode(
|
|
99
|
+
"div",
|
|
100
|
+
{ class: "px-3 py-2 border-b-2 border-black text-xs font-bold text-gray-500 uppercase" },
|
|
101
|
+
"编辑",
|
|
102
|
+
-1
|
|
103
|
+
/* CACHED */
|
|
104
|
+
)),
|
|
105
|
+
withDirectives(createElementVNode(
|
|
106
|
+
"textarea",
|
|
107
|
+
{
|
|
108
|
+
"onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => input.value = $event),
|
|
109
|
+
class: "flex-1 w-full bg-transparent text-gray-100 px-4 py-3 font-mono text-sm outline-none resize-none placeholder-gray-600"
|
|
110
|
+
},
|
|
111
|
+
null,
|
|
112
|
+
512
|
|
113
|
+
/* NEED_PATCH */
|
|
114
|
+
), [
|
|
115
|
+
[vModelText, input.value]
|
|
116
|
+
])
|
|
117
|
+
]),
|
|
118
|
+
createCommentVNode(" 预览 "),
|
|
119
|
+
createElementVNode("div", _hoisted_5, [
|
|
120
|
+
_cache[4] || (_cache[4] = createElementVNode(
|
|
121
|
+
"div",
|
|
122
|
+
{ class: "px-3 py-2 border-b-2 border-black text-xs font-bold text-gray-500 uppercase" },
|
|
123
|
+
"预览",
|
|
124
|
+
-1
|
|
125
|
+
/* CACHED */
|
|
126
|
+
)),
|
|
127
|
+
createElementVNode("div", {
|
|
128
|
+
class: "flex-1 overflow-auto px-4 py-3 md-preview",
|
|
129
|
+
innerHTML: rendered.value
|
|
130
|
+
}, null, 8, _hoisted_6)
|
|
131
|
+
])
|
|
132
|
+
])
|
|
133
|
+
]);
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
const _export_sfc = (sfc, props) => {
|
|
138
|
+
const target = sfc.__vccOpts || sfc;
|
|
139
|
+
for (const [key, val] of props) {
|
|
140
|
+
target[key] = val;
|
|
141
|
+
}
|
|
142
|
+
return target;
|
|
143
|
+
};
|
|
144
|
+
const index = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-ff15d17d"]]);
|
|
145
|
+
export {
|
|
146
|
+
index as default
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
;(function(){var s=document.createElement("style");s.textContent=`
|
|
150
|
+
.md-preview[data-v-ff15d17d] h1 { font-size: 1.5rem; font-weight: 700; margin: 0.5rem 0; color: #f9b11f;
|
|
151
|
+
}
|
|
152
|
+
.md-preview[data-v-ff15d17d] h2 { font-size: 1.25rem; font-weight: 700; margin: 0.5rem 0; color: #f9b11f;
|
|
153
|
+
}
|
|
154
|
+
.md-preview[data-v-ff15d17d] h3 { font-size: 1.1rem; font-weight: 600; margin: 0.4rem 0; color: #e5a31b;
|
|
155
|
+
}
|
|
156
|
+
.md-preview[data-v-ff15d17d] p { margin: 0.3rem 0; color: #d1d5db; line-height: 1.6;
|
|
157
|
+
}
|
|
158
|
+
.md-preview[data-v-ff15d17d] strong { color: #fff;
|
|
159
|
+
}
|
|
160
|
+
.md-preview[data-v-ff15d17d] em { color: #a78bfa;
|
|
161
|
+
}
|
|
162
|
+
.md-preview[data-v-ff15d17d] a { color: #3b82f6; text-decoration: underline;
|
|
163
|
+
}
|
|
164
|
+
.md-preview[data-v-ff15d17d] blockquote { border-left: 3px solid #f9b11f; padding-left: 0.75rem; color: #9ca3af; margin: 0.5rem 0;
|
|
165
|
+
}
|
|
166
|
+
.md-preview[data-v-ff15d17d] ul { padding-left: 1.25rem; margin: 0.3rem 0;
|
|
167
|
+
}
|
|
168
|
+
.md-preview[data-v-ff15d17d] li { color: #d1d5db; margin: 0.15rem 0; list-style: disc;
|
|
169
|
+
}
|
|
170
|
+
.md-preview[data-v-ff15d17d] hr { border: none; border-top: 2px solid #333; margin: 0.75rem 0;
|
|
171
|
+
}
|
|
172
|
+
.md-preview[data-v-ff15d17d] .md-code-block { background: #1a1510; border: 2px solid #000; border-radius: 0.5rem; padding: 0.75rem; overflow-x: auto; margin: 0.5rem 0;
|
|
173
|
+
}
|
|
174
|
+
.md-preview[data-v-ff15d17d] .md-code-block code { color: #84cc16; font-size: 0.8rem;
|
|
175
|
+
}
|
|
176
|
+
.md-preview[data-v-ff15d17d] .md-inline-code { background: #1a1510; color: #f9b11f; padding: 0.1rem 0.3rem; border-radius: 0.25rem; font-size: 0.85rem;
|
|
177
|
+
}
|
|
178
|
+
.md-preview[data-v-ff15d17d] .md-table { width: 100%; border-collapse: collapse; margin: 0.5rem 0;
|
|
179
|
+
}
|
|
180
|
+
.md-preview[data-v-ff15d17d] .md-table th { background: #1a1510; border: 2px solid #000; padding: 0.4rem 0.6rem; text-align: left; color: #f9b11f; font-size: 0.8rem;
|
|
181
|
+
}
|
|
182
|
+
.md-preview[data-v-ff15d17d] .md-table td { border: 2px solid #000; padding: 0.4rem 0.6rem; color: #d1d5db; font-size: 0.8rem;
|
|
183
|
+
}
|
|
184
|
+
`;document.head.appendChild(s)})();
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import { defineComponent, ref, computed, openBlock, createElementBlock, createElementVNode, withDirectives, vModelText, toDisplayString, Fragment, renderList, createCommentVNode, normalizeStyle, normalizeClass } from "vue";
|
|
2
|
+
const _hoisted_1 = { class: "flex flex-col h-full gap-5" };
|
|
3
|
+
const _hoisted_2 = { class: "bg-deep-charcoal border-4 border-black rounded-xl p-4 shadow-hard" };
|
|
4
|
+
const _hoisted_3 = { class: "flex flex-wrap items-center gap-4 mb-3" };
|
|
5
|
+
const _hoisted_4 = { class: "flex items-center gap-2" };
|
|
6
|
+
const _hoisted_5 = { class: "font-mono text-sm text-gray-100 w-8 text-center" };
|
|
7
|
+
const _hoisted_6 = { class: "flex items-center gap-2" };
|
|
8
|
+
const _hoisted_7 = { class: "flex flex-wrap gap-3 mb-3" };
|
|
9
|
+
const _hoisted_8 = ["checked", "onChange"];
|
|
10
|
+
const _hoisted_9 = { class: "text-xs text-gray-400" };
|
|
11
|
+
const _hoisted_10 = { class: "flex items-center gap-3 mb-3" };
|
|
12
|
+
const _hoisted_11 = { class: "flex-1 h-2 bg-bg-dark border border-black rounded-full overflow-hidden" };
|
|
13
|
+
const _hoisted_12 = { class: "flex-1 overflow-auto bg-deep-charcoal border-4 border-black rounded-xl p-4 shadow-hard" };
|
|
14
|
+
const _hoisted_13 = ["onClick"];
|
|
15
|
+
const _hoisted_14 = { class: "font-mono text-sm text-gray-100 select-all break-all" };
|
|
16
|
+
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
17
|
+
__name: "index",
|
|
18
|
+
setup(__props) {
|
|
19
|
+
const length = ref(16);
|
|
20
|
+
const useLower = ref(true);
|
|
21
|
+
const useUpper = ref(true);
|
|
22
|
+
const useDigits = ref(true);
|
|
23
|
+
const useSymbols = ref(true);
|
|
24
|
+
const count = ref(5);
|
|
25
|
+
const passwords = ref([]);
|
|
26
|
+
const copyField = ref("");
|
|
27
|
+
const charsets = computed(() => {
|
|
28
|
+
let chars = "";
|
|
29
|
+
if (useLower.value) chars += "abcdefghijklmnopqrstuvwxyz";
|
|
30
|
+
if (useUpper.value) chars += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
31
|
+
if (useDigits.value) chars += "0123456789";
|
|
32
|
+
if (useSymbols.value) chars += "!@#$%^&*()_+-=[]{}|;:,.<>?";
|
|
33
|
+
return chars;
|
|
34
|
+
});
|
|
35
|
+
function generate() {
|
|
36
|
+
const chars = charsets.value;
|
|
37
|
+
if (!chars) return;
|
|
38
|
+
const arr = new Uint32Array(length.value * count.value);
|
|
39
|
+
crypto.getRandomValues(arr);
|
|
40
|
+
passwords.value = Array.from({ length: count.value }, (_, i) => {
|
|
41
|
+
return Array.from({ length: length.value }, (_2, j) => chars[arr[i * length.value + j] % chars.length]).join("");
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function toggleOption(key, checked) {
|
|
45
|
+
if (key === "lower") useLower.value = checked;
|
|
46
|
+
else if (key === "upper") useUpper.value = checked;
|
|
47
|
+
else if (key === "digits") useDigits.value = checked;
|
|
48
|
+
else useSymbols.value = checked;
|
|
49
|
+
}
|
|
50
|
+
const strength = computed(() => {
|
|
51
|
+
const poolSize = charsets.value.length;
|
|
52
|
+
if (!poolSize) return { label: "无", color: "text-gray-500", percent: 0 };
|
|
53
|
+
const entropy = length.value * Math.log2(poolSize);
|
|
54
|
+
if (entropy < 40) return { label: "弱", color: "text-coral-red", percent: 25 };
|
|
55
|
+
if (entropy < 60) return { label: "中等", color: "text-primary", percent: 50 };
|
|
56
|
+
if (entropy < 80) return { label: "强", color: "text-electric-blue", percent: 75 };
|
|
57
|
+
return { label: "极强", color: "text-neon-green", percent: 100 };
|
|
58
|
+
});
|
|
59
|
+
async function copy(text, field) {
|
|
60
|
+
await navigator.clipboard.writeText(text);
|
|
61
|
+
copyField.value = field;
|
|
62
|
+
setTimeout(() => {
|
|
63
|
+
copyField.value = "";
|
|
64
|
+
}, 1200);
|
|
65
|
+
}
|
|
66
|
+
generate();
|
|
67
|
+
return (_ctx, _cache) => {
|
|
68
|
+
return openBlock(), createElementBlock("div", _hoisted_1, [
|
|
69
|
+
createElementVNode("div", _hoisted_2, [
|
|
70
|
+
_cache[5] || (_cache[5] = createElementVNode(
|
|
71
|
+
"div",
|
|
72
|
+
{ class: "flex items-center gap-2 mb-3" },
|
|
73
|
+
[
|
|
74
|
+
createElementVNode("span", { class: "material-icons text-primary text-lg" }, "lock"),
|
|
75
|
+
createElementVNode("span", { class: "text-sm font-bold text-gray-400 uppercase tracking-wider" }, "密码生成器")
|
|
76
|
+
],
|
|
77
|
+
-1
|
|
78
|
+
/* CACHED */
|
|
79
|
+
)),
|
|
80
|
+
createElementVNode("div", _hoisted_3, [
|
|
81
|
+
createElementVNode("div", _hoisted_4, [
|
|
82
|
+
_cache[2] || (_cache[2] = createElementVNode(
|
|
83
|
+
"span",
|
|
84
|
+
{ class: "text-xs text-gray-500" },
|
|
85
|
+
"长度:",
|
|
86
|
+
-1
|
|
87
|
+
/* CACHED */
|
|
88
|
+
)),
|
|
89
|
+
withDirectives(createElementVNode(
|
|
90
|
+
"input",
|
|
91
|
+
{
|
|
92
|
+
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => length.value = $event),
|
|
93
|
+
type: "range",
|
|
94
|
+
min: "4",
|
|
95
|
+
max: "64",
|
|
96
|
+
class: "w-32 accent-primary"
|
|
97
|
+
},
|
|
98
|
+
null,
|
|
99
|
+
512
|
|
100
|
+
/* NEED_PATCH */
|
|
101
|
+
), [
|
|
102
|
+
[
|
|
103
|
+
vModelText,
|
|
104
|
+
length.value,
|
|
105
|
+
void 0,
|
|
106
|
+
{ number: true }
|
|
107
|
+
]
|
|
108
|
+
]),
|
|
109
|
+
createElementVNode(
|
|
110
|
+
"span",
|
|
111
|
+
_hoisted_5,
|
|
112
|
+
toDisplayString(length.value),
|
|
113
|
+
1
|
|
114
|
+
/* TEXT */
|
|
115
|
+
)
|
|
116
|
+
]),
|
|
117
|
+
createElementVNode("div", _hoisted_6, [
|
|
118
|
+
_cache[3] || (_cache[3] = createElementVNode(
|
|
119
|
+
"span",
|
|
120
|
+
{ class: "text-xs text-gray-500" },
|
|
121
|
+
"数量:",
|
|
122
|
+
-1
|
|
123
|
+
/* CACHED */
|
|
124
|
+
)),
|
|
125
|
+
withDirectives(createElementVNode(
|
|
126
|
+
"input",
|
|
127
|
+
{
|
|
128
|
+
"onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => count.value = $event),
|
|
129
|
+
type: "number",
|
|
130
|
+
min: "1",
|
|
131
|
+
max: "50",
|
|
132
|
+
class: "w-14 h-8 bg-bg-dark text-gray-100 border-2 border-black rounded px-2 font-mono text-sm text-center outline-none focus:border-primary"
|
|
133
|
+
},
|
|
134
|
+
null,
|
|
135
|
+
512
|
|
136
|
+
/* NEED_PATCH */
|
|
137
|
+
), [
|
|
138
|
+
[
|
|
139
|
+
vModelText,
|
|
140
|
+
count.value,
|
|
141
|
+
void 0,
|
|
142
|
+
{ number: true }
|
|
143
|
+
]
|
|
144
|
+
])
|
|
145
|
+
])
|
|
146
|
+
]),
|
|
147
|
+
createElementVNode("div", _hoisted_7, [
|
|
148
|
+
(openBlock(), createElementBlock(
|
|
149
|
+
Fragment,
|
|
150
|
+
null,
|
|
151
|
+
renderList([
|
|
152
|
+
{ label: "小写 a-z", key: "lower" },
|
|
153
|
+
{ label: "大写 A-Z", key: "upper" },
|
|
154
|
+
{ label: "数字 0-9", key: "digits" },
|
|
155
|
+
{ label: "符号 !@#", key: "symbols" }
|
|
156
|
+
], (opt) => {
|
|
157
|
+
return createElementVNode("label", {
|
|
158
|
+
key: opt.key,
|
|
159
|
+
class: "flex items-center gap-1.5 cursor-pointer"
|
|
160
|
+
}, [
|
|
161
|
+
createElementVNode("input", {
|
|
162
|
+
type: "checkbox",
|
|
163
|
+
checked: opt.key === "lower" ? useLower.value : opt.key === "upper" ? useUpper.value : opt.key === "digits" ? useDigits.value : useSymbols.value,
|
|
164
|
+
onChange: ($event) => toggleOption(opt.key, $event.target.checked),
|
|
165
|
+
class: "accent-primary w-4 h-4"
|
|
166
|
+
}, null, 40, _hoisted_8),
|
|
167
|
+
createElementVNode(
|
|
168
|
+
"span",
|
|
169
|
+
_hoisted_9,
|
|
170
|
+
toDisplayString(opt.label),
|
|
171
|
+
1
|
|
172
|
+
/* TEXT */
|
|
173
|
+
)
|
|
174
|
+
]);
|
|
175
|
+
}),
|
|
176
|
+
64
|
|
177
|
+
/* STABLE_FRAGMENT */
|
|
178
|
+
))
|
|
179
|
+
]),
|
|
180
|
+
createCommentVNode(" 强度指示 "),
|
|
181
|
+
createElementVNode("div", _hoisted_10, [
|
|
182
|
+
_cache[4] || (_cache[4] = createElementVNode(
|
|
183
|
+
"span",
|
|
184
|
+
{ class: "text-xs text-gray-500" },
|
|
185
|
+
"强度:",
|
|
186
|
+
-1
|
|
187
|
+
/* CACHED */
|
|
188
|
+
)),
|
|
189
|
+
createElementVNode("div", _hoisted_11, [
|
|
190
|
+
createElementVNode(
|
|
191
|
+
"div",
|
|
192
|
+
{
|
|
193
|
+
class: normalizeClass(["h-full transition-all duration-300 rounded-full", strength.value.color.replace("text-", "bg-")]),
|
|
194
|
+
style: normalizeStyle({ width: strength.value.percent + "%" })
|
|
195
|
+
},
|
|
196
|
+
null,
|
|
197
|
+
6
|
|
198
|
+
/* CLASS, STYLE */
|
|
199
|
+
)
|
|
200
|
+
]),
|
|
201
|
+
createElementVNode(
|
|
202
|
+
"span",
|
|
203
|
+
{
|
|
204
|
+
class: normalizeClass(["text-xs font-bold", strength.value.color])
|
|
205
|
+
},
|
|
206
|
+
toDisplayString(strength.value.label),
|
|
207
|
+
3
|
|
208
|
+
/* TEXT, CLASS */
|
|
209
|
+
)
|
|
210
|
+
]),
|
|
211
|
+
createElementVNode("button", {
|
|
212
|
+
onClick: generate,
|
|
213
|
+
class: "h-10 px-5 bg-primary text-black font-bold border-2 border-black rounded shadow-hard-sm hover:shadow-none hover:translate-x-0.5 hover:translate-y-0.5 transition-all text-sm"
|
|
214
|
+
}, " 生成 ")
|
|
215
|
+
]),
|
|
216
|
+
createElementVNode("div", _hoisted_12, [
|
|
217
|
+
(openBlock(true), createElementBlock(
|
|
218
|
+
Fragment,
|
|
219
|
+
null,
|
|
220
|
+
renderList(passwords.value, (pw, i) => {
|
|
221
|
+
return openBlock(), createElementBlock("div", {
|
|
222
|
+
key: i,
|
|
223
|
+
class: "flex items-center justify-between py-2 px-3 rounded hover:bg-white/5 cursor-pointer group",
|
|
224
|
+
onClick: ($event) => copy(pw, String(i))
|
|
225
|
+
}, [
|
|
226
|
+
createElementVNode(
|
|
227
|
+
"span",
|
|
228
|
+
_hoisted_14,
|
|
229
|
+
toDisplayString(pw),
|
|
230
|
+
1
|
|
231
|
+
/* TEXT */
|
|
232
|
+
),
|
|
233
|
+
createElementVNode(
|
|
234
|
+
"span",
|
|
235
|
+
{
|
|
236
|
+
class: normalizeClass(["material-icons text-sm opacity-0 group-hover:opacity-100 transition-opacity shrink-0 ml-2", copyField.value === String(i) ? "text-neon-green" : "text-gray-500"])
|
|
237
|
+
},
|
|
238
|
+
toDisplayString(copyField.value === String(i) ? "check" : "content_copy"),
|
|
239
|
+
3
|
|
240
|
+
/* TEXT, CLASS */
|
|
241
|
+
)
|
|
242
|
+
], 8, _hoisted_13);
|
|
243
|
+
}),
|
|
244
|
+
128
|
|
245
|
+
/* KEYED_FRAGMENT */
|
|
246
|
+
))
|
|
247
|
+
])
|
|
248
|
+
]);
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
export {
|
|
253
|
+
_sfc_main as default
|
|
254
|
+
};
|