@qzsy/dsh-command-palette 1.5.0 → 1.5.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/LICENSE +21 -21
- package/README.md +233 -230
- package/cordis.patch.yml +3 -3
- package/dist/client.js +1814 -1765
- package/icon.svg +12 -12
- package/locale/en.json +6 -6
- package/locale/zh.json +6 -6
- package/package.json +78 -78
- package/scripts/sync-vendor-engine.mjs +45 -45
- package/scripts/verify-status.mjs +62 -0
- package/vendor/text-search-engine.LICENSE +20 -20
- package/vendor/text-search-engine.min.js +1 -1
package/icon.svg
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64" role="img" aria-label="Command palette">
|
|
2
|
-
<defs>
|
|
3
|
-
<linearGradient id="cpbg" x1="8" y1="6" x2="56" y2="60" gradientUnits="userSpaceOnUse">
|
|
4
|
-
<stop offset="0" stop-color="#5B8CFF"/>
|
|
5
|
-
<stop offset="1" stop-color="#3466DB"/>
|
|
6
|
-
</linearGradient>
|
|
7
|
-
</defs>
|
|
8
|
-
<rect x="4" y="4" width="56" height="56" rx="16" fill="url(#cpbg)"/>
|
|
9
|
-
<circle cx="28" cy="27" r="10.5" fill="none" stroke="#FFFFFF" stroke-width="4"/>
|
|
10
|
-
<path d="M36 35.5 45 44.5" fill="none" stroke="#FFFFFF" stroke-width="4" stroke-linecap="round"/>
|
|
11
|
-
<path d="M23.5 27h9M28 22.5v9" fill="none" stroke="#FFFFFF" stroke-width="2.4" stroke-linecap="round" opacity="0.75"/>
|
|
12
|
-
</svg>
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64" role="img" aria-label="Command palette">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="cpbg" x1="8" y1="6" x2="56" y2="60" gradientUnits="userSpaceOnUse">
|
|
4
|
+
<stop offset="0" stop-color="#5B8CFF"/>
|
|
5
|
+
<stop offset="1" stop-color="#3466DB"/>
|
|
6
|
+
</linearGradient>
|
|
7
|
+
</defs>
|
|
8
|
+
<rect x="4" y="4" width="56" height="56" rx="16" fill="url(#cpbg)"/>
|
|
9
|
+
<circle cx="28" cy="27" r="10.5" fill="none" stroke="#FFFFFF" stroke-width="4"/>
|
|
10
|
+
<path d="M36 35.5 45 44.5" fill="none" stroke="#FFFFFF" stroke-width="4" stroke-linecap="round"/>
|
|
11
|
+
<path d="M23.5 27h9M28 22.5v9" fill="none" stroke="#FFFFFF" stroke-width="2.4" stroke-linecap="round" opacity="0.75"/>
|
|
12
|
+
</svg>
|
package/locale/en.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
{
|
|
2
|
-
"meta": {
|
|
3
|
-
"title": "Command Palette",
|
|
4
|
-
"description": "Command+K palette for sessions, workspaces, files, and actions with mixed Chinese/English pinyin search and live session status."
|
|
5
|
-
}
|
|
6
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"meta": {
|
|
3
|
+
"title": "Command Palette",
|
|
4
|
+
"description": "Command+K palette for sessions, workspaces, files, and actions with mixed Chinese/English pinyin search and live session status."
|
|
5
|
+
}
|
|
6
|
+
}
|
package/locale/zh.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
{
|
|
2
|
-
"meta": {
|
|
3
|
-
"title": "命令面板",
|
|
4
|
-
"description": "按 ⌘K 快速检索会话、工作区、文件与操作,支持拼音/中英文混拼,并显示会话实时状态(工作中、待处理等)。"
|
|
5
|
-
}
|
|
6
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"meta": {
|
|
3
|
+
"title": "命令面板",
|
|
4
|
+
"description": "按 ⌘K 快速检索会话、工作区、文件与操作,支持拼音/中英文混拼,并显示会话实时状态(工作中、待处理等)。"
|
|
5
|
+
}
|
|
6
|
+
}
|
package/package.json
CHANGED
|
@@ -1,78 +1,78 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@qzsy/dsh-command-palette",
|
|
3
|
-
"version": "1.5.
|
|
4
|
-
"description": "Command+K palette for recent sessions, workspaces, files, and actions with pinyin search and live session status.",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"license": "MIT",
|
|
7
|
-
"author": "qzsy",
|
|
8
|
-
"contributors": [
|
|
9
|
-
{
|
|
10
|
-
"name": "qzsy"
|
|
11
|
-
}
|
|
12
|
-
],
|
|
13
|
-
"keywords": [
|
|
14
|
-
"dsh",
|
|
15
|
-
"deepseek-harness",
|
|
16
|
-
"plugin",
|
|
17
|
-
"command-palette",
|
|
18
|
-
"pinyin"
|
|
19
|
-
],
|
|
20
|
-
"repository": {
|
|
21
|
-
"type": "git",
|
|
22
|
-
"url": "https://codeup.aliyun.com/qzsy/dshmarket/deepseek-harness-market",
|
|
23
|
-
"directory": "plugins/packages/dsh-command-palette"
|
|
24
|
-
},
|
|
25
|
-
"homepage": "https://codeup.aliyun.com/qzsy/dshmarket/deepseek-harness-market",
|
|
26
|
-
"bugs": {
|
|
27
|
-
"url": "https://codeup.aliyun.com/qzsy/dshmarket/deepseek-harness-market/issues"
|
|
28
|
-
},
|
|
29
|
-
"engines": {
|
|
30
|
-
"node": ">=20.9.0"
|
|
31
|
-
},
|
|
32
|
-
"files": [
|
|
33
|
-
"dist",
|
|
34
|
-
"cordis.patch.yml",
|
|
35
|
-
"README.md",
|
|
36
|
-
"LICENSE",
|
|
37
|
-
"locale/*.json",
|
|
38
|
-
"icon.svg",
|
|
39
|
-
"docs",
|
|
40
|
-
"vendor",
|
|
41
|
-
"scripts"
|
|
42
|
-
],
|
|
43
|
-
"publishConfig": {
|
|
44
|
-
"access": "public"
|
|
45
|
-
},
|
|
46
|
-
"dsh": {
|
|
47
|
-
"bundle": {
|
|
48
|
-
"patch": "./cordis.patch.yml"
|
|
49
|
-
},
|
|
50
|
-
"client": {
|
|
51
|
-
"platform": "web",
|
|
52
|
-
"immediately": true,
|
|
53
|
-
"inject": [
|
|
54
|
-
"@deepseek-ai/dsh-client-shortcuts",
|
|
55
|
-
"@deepseek-ai/dsh-client-ui-workspace",
|
|
56
|
-
"@deepseek-ai/dsh-client-ui-sidebar",
|
|
57
|
-
"@deepseek-ai/dsh-client-ui-reference"
|
|
58
|
-
]
|
|
59
|
-
}
|
|
60
|
-
},
|
|
61
|
-
"scripts": {
|
|
62
|
-
"build": "bun run ../../scripts/build-package.mjs .",
|
|
63
|
-
"typecheck": "bun exec tsc -p tsconfig.json --noEmit"
|
|
64
|
-
},
|
|
65
|
-
"dshBuild": {
|
|
66
|
-
"host": "src/index.ts",
|
|
67
|
-
"client": "runtime/client.js",
|
|
68
|
-
"copy": []
|
|
69
|
-
},
|
|
70
|
-
"main": "./dist/index.js",
|
|
71
|
-
"exports": {
|
|
72
|
-
".": "./dist/index.js",
|
|
73
|
-
"./client": "./dist/client.js",
|
|
74
|
-
"./locale/*.json": "./locale/*.json",
|
|
75
|
-
"./icon": "./icon.svg",
|
|
76
|
-
"./package.json": "./package.json"
|
|
77
|
-
}
|
|
78
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@qzsy/dsh-command-palette",
|
|
3
|
+
"version": "1.5.1",
|
|
4
|
+
"description": "Command+K palette for recent sessions, workspaces, files, and actions with pinyin search and live session status.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "qzsy",
|
|
8
|
+
"contributors": [
|
|
9
|
+
{
|
|
10
|
+
"name": "qzsy"
|
|
11
|
+
}
|
|
12
|
+
],
|
|
13
|
+
"keywords": [
|
|
14
|
+
"dsh",
|
|
15
|
+
"deepseek-harness",
|
|
16
|
+
"plugin",
|
|
17
|
+
"command-palette",
|
|
18
|
+
"pinyin"
|
|
19
|
+
],
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "https://codeup.aliyun.com/qzsy/dshmarket/deepseek-harness-market",
|
|
23
|
+
"directory": "plugins/packages/dsh-command-palette"
|
|
24
|
+
},
|
|
25
|
+
"homepage": "https://codeup.aliyun.com/qzsy/dshmarket/deepseek-harness-market",
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://codeup.aliyun.com/qzsy/dshmarket/deepseek-harness-market/issues"
|
|
28
|
+
},
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=20.9.0"
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"dist",
|
|
34
|
+
"cordis.patch.yml",
|
|
35
|
+
"README.md",
|
|
36
|
+
"LICENSE",
|
|
37
|
+
"locale/*.json",
|
|
38
|
+
"icon.svg",
|
|
39
|
+
"docs",
|
|
40
|
+
"vendor",
|
|
41
|
+
"scripts"
|
|
42
|
+
],
|
|
43
|
+
"publishConfig": {
|
|
44
|
+
"access": "public"
|
|
45
|
+
},
|
|
46
|
+
"dsh": {
|
|
47
|
+
"bundle": {
|
|
48
|
+
"patch": "./cordis.patch.yml"
|
|
49
|
+
},
|
|
50
|
+
"client": {
|
|
51
|
+
"platform": "web",
|
|
52
|
+
"immediately": true,
|
|
53
|
+
"inject": [
|
|
54
|
+
"@deepseek-ai/dsh-client-shortcuts",
|
|
55
|
+
"@deepseek-ai/dsh-client-ui-workspace",
|
|
56
|
+
"@deepseek-ai/dsh-client-ui-sidebar",
|
|
57
|
+
"@deepseek-ai/dsh-client-ui-reference"
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"scripts": {
|
|
62
|
+
"build": "bun run ../../scripts/build-package.mjs .",
|
|
63
|
+
"typecheck": "bun exec tsc -p tsconfig.json --noEmit"
|
|
64
|
+
},
|
|
65
|
+
"dshBuild": {
|
|
66
|
+
"host": "src/index.ts",
|
|
67
|
+
"client": "runtime/client.js",
|
|
68
|
+
"copy": []
|
|
69
|
+
},
|
|
70
|
+
"main": "./dist/index.js",
|
|
71
|
+
"exports": {
|
|
72
|
+
".": "./dist/index.js",
|
|
73
|
+
"./client": "./dist/client.js",
|
|
74
|
+
"./locale/*.json": "./locale/*.json",
|
|
75
|
+
"./icon": "./icon.svg",
|
|
76
|
+
"./package.json": "./package.json"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -1,45 +1,45 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Inject the vendored browser build of text-search-engine into client.js.
|
|
4
|
-
*
|
|
5
|
-
* The Harness browser module table resolves only its own platform modules and
|
|
6
|
-
* client-plugin rows, so a plain-JS plugin cannot `require('text-search-engine')`
|
|
7
|
-
* at runtime. The package's minified browser IIFE is therefore copied into the
|
|
8
|
-
* factory scope, where the generated `TextSearchEngine` const captures its
|
|
9
|
-
* exports. Re-run this script after updating vendor/text-search-engine.min.js.
|
|
10
|
-
*/
|
|
11
|
-
import { readFileSync, writeFileSync } from 'node:fs';
|
|
12
|
-
import { dirname, join } from 'node:path';
|
|
13
|
-
import { fileURLToPath } from 'node:url';
|
|
14
|
-
|
|
15
|
-
const root = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
16
|
-
const clientPath = join(root, 'client.js');
|
|
17
|
-
const enginePath = join(root, 'vendor', 'text-search-engine.min.js');
|
|
18
|
-
|
|
19
|
-
const begin = '\t\t//#region vendor:text-search-engine:begin';
|
|
20
|
-
const end = '\t\t//#endregion vendor:text-search-engine:end';
|
|
21
|
-
|
|
22
|
-
const engine = readFileSync(enginePath, 'utf8').replace(/\/\/# sourceMappingURL=.*\s*$/u, '').trim();
|
|
23
|
-
if (engine === '') throw new Error('vendor/text-search-engine.min.js is empty');
|
|
24
|
-
|
|
25
|
-
const block = [
|
|
26
|
-
begin,
|
|
27
|
-
'\t\t/**',
|
|
28
|
-
'\t\t * Vendored browser build of text-search-engine (MIT, cjinhuo); generated by',
|
|
29
|
-
'\t\t * scripts/sync-vendor-engine.mjs from vendor/text-search-engine.min.js.',
|
|
30
|
-
'\t\t * Do not edit this region by hand.',
|
|
31
|
-
'\t\t */',
|
|
32
|
-
'\t\tconst TextSearchEngine = (() => {',
|
|
33
|
-
`\t\t\t${engine}`,
|
|
34
|
-
'\t\t\treturn _TEXT_SEARCH_ENGINE_;',
|
|
35
|
-
'\t\t})();',
|
|
36
|
-
end
|
|
37
|
-
].join('\n');
|
|
38
|
-
|
|
39
|
-
const source = readFileSync(clientPath, 'utf8');
|
|
40
|
-
const start = source.indexOf(begin);
|
|
41
|
-
const stop = source.indexOf(end);
|
|
42
|
-
if (start < 0 || stop < 0 || stop < start) throw new Error('client.js is missing the vendored-engine markers');
|
|
43
|
-
const next = `${source.slice(0, start)}${block}${source.slice(stop + end.length)}`;
|
|
44
|
-
writeFileSync(clientPath, next);
|
|
45
|
-
console.log(`injected ${engine.length} bytes from ${enginePath}`);
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Inject the vendored browser build of text-search-engine into client.js.
|
|
4
|
+
*
|
|
5
|
+
* The Harness browser module table resolves only its own platform modules and
|
|
6
|
+
* client-plugin rows, so a plain-JS plugin cannot `require('text-search-engine')`
|
|
7
|
+
* at runtime. The package's minified browser IIFE is therefore copied into the
|
|
8
|
+
* factory scope, where the generated `TextSearchEngine` const captures its
|
|
9
|
+
* exports. Re-run this script after updating vendor/text-search-engine.min.js.
|
|
10
|
+
*/
|
|
11
|
+
import { readFileSync, writeFileSync } from 'node:fs';
|
|
12
|
+
import { dirname, join } from 'node:path';
|
|
13
|
+
import { fileURLToPath } from 'node:url';
|
|
14
|
+
|
|
15
|
+
const root = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
16
|
+
const clientPath = join(root, 'client.js');
|
|
17
|
+
const enginePath = join(root, 'vendor', 'text-search-engine.min.js');
|
|
18
|
+
|
|
19
|
+
const begin = '\t\t//#region vendor:text-search-engine:begin';
|
|
20
|
+
const end = '\t\t//#endregion vendor:text-search-engine:end';
|
|
21
|
+
|
|
22
|
+
const engine = readFileSync(enginePath, 'utf8').replace(/\/\/# sourceMappingURL=.*\s*$/u, '').trim();
|
|
23
|
+
if (engine === '') throw new Error('vendor/text-search-engine.min.js is empty');
|
|
24
|
+
|
|
25
|
+
const block = [
|
|
26
|
+
begin,
|
|
27
|
+
'\t\t/**',
|
|
28
|
+
'\t\t * Vendored browser build of text-search-engine (MIT, cjinhuo); generated by',
|
|
29
|
+
'\t\t * scripts/sync-vendor-engine.mjs from vendor/text-search-engine.min.js.',
|
|
30
|
+
'\t\t * Do not edit this region by hand.',
|
|
31
|
+
'\t\t */',
|
|
32
|
+
'\t\tconst TextSearchEngine = (() => {',
|
|
33
|
+
`\t\t\t${engine}`,
|
|
34
|
+
'\t\t\treturn _TEXT_SEARCH_ENGINE_;',
|
|
35
|
+
'\t\t})();',
|
|
36
|
+
end
|
|
37
|
+
].join('\n');
|
|
38
|
+
|
|
39
|
+
const source = readFileSync(clientPath, 'utf8');
|
|
40
|
+
const start = source.indexOf(begin);
|
|
41
|
+
const stop = source.indexOf(end);
|
|
42
|
+
if (start < 0 || stop < 0 || stop < start) throw new Error('client.js is missing the vendored-engine markers');
|
|
43
|
+
const next = `${source.slice(0, start)}${block}${source.slice(stop + end.length)}`;
|
|
44
|
+
writeFileSync(clientPath, next);
|
|
45
|
+
console.log(`injected ${engine.length} bytes from ${enginePath}`);
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* - failure message normalization (whitespace collapse + 180 char cap);
|
|
11
11
|
* - workspace aggregation priority/counts and subagent filtering;
|
|
12
12
|
* - session-group summary segments and session row wiring;
|
|
13
|
+
* - the phone drawer collapse guard and the overlay portal surface;
|
|
13
14
|
* - the production injection surface (inject/apply and hooks.sessionFailures).
|
|
14
15
|
*
|
|
15
16
|
* Usage (from the repository root):
|
|
@@ -185,6 +186,29 @@ function makeT() {
|
|
|
185
186
|
const t = makeT();
|
|
186
187
|
const at = (minutes) => NOW - minutes * MINUTE;
|
|
187
188
|
|
|
189
|
+
/** Frame/layout fixture for the phone drawer collapse check. */
|
|
190
|
+
function makeDrawerHarness(collapsed) {
|
|
191
|
+
const calls = [];
|
|
192
|
+
return {
|
|
193
|
+
calls,
|
|
194
|
+
frame: { hasAttribute: (name) => name === 'data-sidebar-collapsed' ? collapsed : false },
|
|
195
|
+
ctx: { get: (name) => name === 'layout' ? { toggleSidebar: () => calls.push('toggleSidebar') } : undefined }
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/** Run `run` with a stub `document` whose querySelector returns `queryResult`. */
|
|
200
|
+
function withFakeDocument(queryResult, run) {
|
|
201
|
+
const had = Object.prototype.hasOwnProperty.call(globalThis, 'document');
|
|
202
|
+
const previous = globalThis.document;
|
|
203
|
+
globalThis.document = { querySelector: () => queryResult };
|
|
204
|
+
try {
|
|
205
|
+
return run();
|
|
206
|
+
} finally {
|
|
207
|
+
if (had) globalThis.document = previous;
|
|
208
|
+
else delete globalThis.document;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
188
212
|
function createFakeRemote() {
|
|
189
213
|
const handlers = new Map();
|
|
190
214
|
const subscriptions = [];
|
|
@@ -245,6 +269,7 @@ function runChecks({ plugin, registration, source }) {
|
|
|
245
269
|
|
|
246
270
|
check('surface: __test exposes the documented helpers', () => {
|
|
247
271
|
const expected = [
|
|
272
|
+
'collapseDrawer',
|
|
248
273
|
'countUnreadCompletions',
|
|
249
274
|
'createFailureStore',
|
|
250
275
|
'installFailureFeed',
|
|
@@ -284,6 +309,43 @@ function runChecks({ plugin, registration, source }) {
|
|
|
284
309
|
);
|
|
285
310
|
});
|
|
286
311
|
|
|
312
|
+
// --- phone drawer collapse and overlay mounting -------------------------
|
|
313
|
+
|
|
314
|
+
check('drawer: collapses an open phone drawer through the layout face', () => {
|
|
315
|
+
const harness = makeDrawerHarness(false);
|
|
316
|
+
withFakeDocument(harness.frame, () => api.collapseDrawer(harness.ctx));
|
|
317
|
+
equal(harness.calls, ['toggleSidebar'], 'layout toggles');
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
check('drawer: leaves an already collapsed drawer untouched', () => {
|
|
321
|
+
const harness = makeDrawerHarness(true);
|
|
322
|
+
withFakeDocument(harness.frame, () => api.collapseDrawer(harness.ctx));
|
|
323
|
+
equal(harness.calls, [], 'layout toggles');
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
check('drawer: ignores frames that are not drawing a drawer', () => {
|
|
327
|
+
const harness = makeDrawerHarness(false);
|
|
328
|
+
withFakeDocument(null, () => api.collapseDrawer(harness.ctx));
|
|
329
|
+
equal(harness.calls, [], 'layout toggles');
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
check('drawer: tolerates a host without the layout face', () => {
|
|
333
|
+
const harness = makeDrawerHarness(false);
|
|
334
|
+
withFakeDocument(harness.frame, () => api.collapseDrawer({ get: () => undefined }));
|
|
335
|
+
equal(harness.calls, [], 'layout toggles');
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
check('source: the palette portals above the phone drawer', () => {
|
|
339
|
+
truthy(/return\s+mountOverlay\(h\(React\.Fragment/.test(source), 'PaletteDialog should mount through mountOverlay');
|
|
340
|
+
truthy(/createPortal\(node,\s*document\.body\)/.test(source), 'mountOverlay should portal to the document body');
|
|
341
|
+
truthy(/\.dshcp-layer\{[^}]*z-index:2147483000/.test(source), 'the layer should outrank the frame drawer');
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
check('source: opening the palette collapses the drawer first', () => {
|
|
345
|
+
truthy(/collapseSidebar:\s*\(\)\s*=>\s*collapseDrawer\(ctx\)/.test(source), 'actions should expose collapseSidebar');
|
|
346
|
+
truthy(/actions\.collapseSidebar\?\.\(\)/.test(source), 'PaletteDialog should collapse the drawer on mount');
|
|
347
|
+
});
|
|
348
|
+
|
|
287
349
|
// --- normalizeFailureMessage -------------------------------------------
|
|
288
350
|
|
|
289
351
|
check('normalize: collapses whitespace and trims', () => {
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025 cjinhuo@qq.com
|
|
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
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 cjinhuo@qq.com
|
|
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
21
|
SOFTWARE.
|