dsh-slash-command 0.0.0-stage → 0.1.0
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 -0
- package/README.md +56 -2
- package/cordis.patch.yml +4 -0
- package/lib/client.js +505 -0
- package/lib/client.js.map +7 -0
- package/lib/core.js +127 -0
- package/lib/core.js.map +7 -0
- package/lib/index.js +309 -0
- package/lib/index.js.map +7 -0
- package/lib/types/client/index.d.ts +27 -0
- package/lib/types/client/locales.d.ts +44 -0
- package/lib/types/client/panel.d.ts +8 -0
- package/lib/types/core.d.ts +58 -0
- package/lib/types/index.d.ts +8 -0
- package/package.json +76 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Cassius0924
|
|
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.
|
package/README.md
CHANGED
|
@@ -1,3 +1,57 @@
|
|
|
1
|
-
#
|
|
1
|
+
# dsh-slash-command
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/dsh-slash-command)
|
|
4
|
+
[](./LICENSE)
|
|
5
|
+
|
|
6
|
+
给 [DSH](https://github.com/deepseek-ai)(DeepSeek Harness)加自定义斜杠命令,对标 Hermes 的 `quick_commands`:
|
|
7
|
+
|
|
8
|
+
- **Prompt 型**:`/review 只看 src` → 把预设 prompt 发给模型,`$ARGUMENTS` 替换为命令后的参数。
|
|
9
|
+
- **Shell 型**:`/log 5` → 在本机直接执行,输出回显在命令卡片里,**不经过模型、不消耗 token**。
|
|
10
|
+
- **转发型(alias)**:`/c` → 转发到另一条斜杠命令(如 `/compact`),可带固定参数。
|
|
11
|
+
- 支持别名,在「设置 → 自定义命令」里增删改,保存即生效,无需重启。
|
|
12
|
+
|
|
13
|
+
## 安装
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
dsh plugin --profile web add dsh-slash-command
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
已验证宿主版本:`0.2.1-rc.3`。
|
|
20
|
+
|
|
21
|
+
## 配置
|
|
22
|
+
|
|
23
|
+
配置存放在 `$DSH_HOME/slash-commands.json`(默认 `~/.dsh/slash-commands.json`),设置页和手改文件都可以:
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{"commands":[
|
|
27
|
+
{"name":"review","aliases":["rv"],"description":"审查当前改动","type":"prompt",
|
|
28
|
+
"prompt":"审查 `git diff` 的全部改动。$ARGUMENTS"},
|
|
29
|
+
{"name":"branch","description":"当前分支","type":"exec",
|
|
30
|
+
"command":"git rev-parse --abbrev-ref HEAD","cwd":"workspace","timeoutMs":30000},
|
|
31
|
+
{"name":"log","description":"最近提交","type":"exec","command":"git log --oneline -n \"${1:-10}\""},
|
|
32
|
+
{"name":"c","description":"压缩上下文","type":"alias","target":"/compact"}
|
|
33
|
+
]}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`name`/别名需匹配 `^[a-z][a-z0-9_-]*$`;`cwd` 为 `workspace`(当前会话目录)或绝对路径;`timeoutMs` 默认 30000,上限 600000。
|
|
37
|
+
|
|
38
|
+
参数(命令名后面的文字):
|
|
39
|
+
|
|
40
|
+
- Prompt / 转发型:`$ARGUMENTS` 原位替换;没写时 Prompt 型以空行接在末尾,转发型以空格接在目标命令后。
|
|
41
|
+
- Shell 型:`$ARGUMENTS` 为完整参数,`$1 $2 …` / `"$@"` 为按空白拆分的参数。参数只以变量传入,不会拼进脚本,`/log 5; rm -rf ~` 里的 `; rm -rf ~` 只是普通字符串。输出合计截断到 16KB。
|
|
42
|
+
|
|
43
|
+
## 安全
|
|
44
|
+
|
|
45
|
+
Shell 命令以 dsh 进程权限运行,**没有审批确认**。能写配置文件或能登录 Web UI 的人就等于拥有这个权限,请只在可信环境使用。
|
|
46
|
+
|
|
47
|
+
## 开发
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
pnpm install && pnpm build && pnpm test
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
发版流程见 [RELEASING.md](./RELEASING.md)。
|
|
54
|
+
|
|
55
|
+
## License
|
|
56
|
+
|
|
57
|
+
MIT
|
package/cordis.patch.yml
ADDED
package/lib/client.js
ADDED
|
@@ -0,0 +1,505 @@
|
|
|
1
|
+
window.__ModuleLoader__.load({ id: "dsh-slash-command", factory: (require) => { var module = { exports: {} }; var exports = module.exports;
|
|
2
|
+
"use strict";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name2 in all)
|
|
9
|
+
__defProp(target, name2, { get: all[name2], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
|
|
21
|
+
// src/client/index.tsx
|
|
22
|
+
var index_exports = {};
|
|
23
|
+
__export(index_exports, {
|
|
24
|
+
apply: () => apply,
|
|
25
|
+
inject: () => inject,
|
|
26
|
+
name: () => name
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(index_exports);
|
|
29
|
+
|
|
30
|
+
// src/client/locales.ts
|
|
31
|
+
var NS = "dsh-slash-command";
|
|
32
|
+
var zh = {
|
|
33
|
+
"title": "\u81EA\u5B9A\u4E49\u547D\u4EE4",
|
|
34
|
+
"add": "\u65B0\u589E\u547D\u4EE4",
|
|
35
|
+
"edit": "\u7F16\u8F91",
|
|
36
|
+
"editOf": "\u7F16\u8F91 /{name}",
|
|
37
|
+
"delete": "\u5220\u9664",
|
|
38
|
+
"deleteOf": "\u5220\u9664 /{name}",
|
|
39
|
+
"deleteConfirm": "\u5220\u9664 /{name}\uFF1F\u7ACB\u5373\u751F\u6548\uFF0C\u65E0\u6CD5\u64A4\u9500\u3002",
|
|
40
|
+
"cancel": "\u53D6\u6D88",
|
|
41
|
+
"save": "\u4FDD\u5B58",
|
|
42
|
+
"saving": "\u4FDD\u5B58\u4E2D\u2026",
|
|
43
|
+
"saved": "\u5DF2\u4FDD\u5B58",
|
|
44
|
+
"retry": "\u91CD\u8BD5",
|
|
45
|
+
"loadFailed": "\u8BFB\u53D6\u5931\u8D25\uFF1A{detail}",
|
|
46
|
+
"saveFailed": "\u4FDD\u5B58\u5931\u8D25\uFF1A{detail}",
|
|
47
|
+
"help": "{field}\u8BF4\u660E",
|
|
48
|
+
"field.type": "\u7C7B\u578B",
|
|
49
|
+
"field.name": "\u540D\u79F0",
|
|
50
|
+
"field.aliases": "\u522B\u540D",
|
|
51
|
+
"field.description": "\u63CF\u8FF0",
|
|
52
|
+
"field.prompt": "Prompt",
|
|
53
|
+
"field.command": "\u547D\u4EE4",
|
|
54
|
+
"field.target": "\u76EE\u6807\u547D\u4EE4",
|
|
55
|
+
"field.cwd": "\u5DE5\u4F5C\u76EE\u5F55",
|
|
56
|
+
"field.timeoutMs": "\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09",
|
|
57
|
+
"type.prompt": "Prompt",
|
|
58
|
+
"type.exec": "Shell",
|
|
59
|
+
"type.alias": "\u8F6C\u53D1",
|
|
60
|
+
"tip.prompt": "$ARGUMENTS \u66FF\u6362\u4E3A\u547D\u4EE4\u540E\u7684\u53C2\u6570\uFF1B\u672A\u4F7F\u7528\u65F6\u53C2\u6570\u8FFD\u52A0\u5230\u672B\u5C3E\u3002",
|
|
61
|
+
"tip.command": "$ARGUMENTS \u4E3A\u5B8C\u6574\u53C2\u6570\uFF0C$1 $2\u2026 \u4E3A\u6309\u7A7A\u683C\u62C6\u5206\u7684\u53C2\u6570\uFF1B\u53C2\u6570\u53EA\u4F5C\u53D8\u91CF\u4F20\u5165\uFF0C\u4E0D\u4F1A\u88AB\u5F53\u4F5C\u547D\u4EE4\u6267\u884C\u3002",
|
|
62
|
+
"tip.target": "\u8F6C\u53D1\u5230\u53E6\u4E00\u6761\u659C\u6760\u547D\u4EE4\uFF0C\u53EF\u5E26\u56FA\u5B9A\u53C2\u6570\u3002$ARGUMENTS \u66FF\u6362\u4E3A\u53C2\u6570\uFF0C\u672A\u4F7F\u7528\u65F6\u53C2\u6570\u63A5\u5728\u672B\u5C3E\u3002",
|
|
63
|
+
"tip.cwd": "workspace \u4E3A\u5F53\u524D\u4F1A\u8BDD\u76EE\u5F55\uFF0C\u4E5F\u53EF\u586B\u7EDD\u5BF9\u8DEF\u5F84\u3002",
|
|
64
|
+
"execWarn": "\u4EE5 dsh \u8FDB\u7A0B\u6743\u9650\u76F4\u63A5\u8FD0\u884C\uFF0C\u4E0D\u7ECF\u5BA1\u6279\u3002",
|
|
65
|
+
"err.type": "\u7C7B\u578B\u4E0D\u5BF9",
|
|
66
|
+
"err.required": "\u5FC5\u586B",
|
|
67
|
+
"err.pattern": "\u5C0F\u5199\u5B57\u6BCD\u5F00\u5934\uFF0C\u4EC5\u542B a-z 0-9 - _",
|
|
68
|
+
"err.duplicate": "\u5DF2\u88AB\u5360\u7528\u6216\u6307\u5411\u81EA\u8EAB",
|
|
69
|
+
"err.enum": "\u586B workspace \u6216\u7EDD\u5BF9\u8DEF\u5F84",
|
|
70
|
+
"err.range": "1\u2013600000 \u4E4B\u95F4\u7684\u6574\u6570"
|
|
71
|
+
};
|
|
72
|
+
var en = {
|
|
73
|
+
"title": "Custom commands",
|
|
74
|
+
"add": "Add command",
|
|
75
|
+
"edit": "Edit",
|
|
76
|
+
"editOf": "Edit /{name}",
|
|
77
|
+
"delete": "Delete",
|
|
78
|
+
"deleteOf": "Delete /{name}",
|
|
79
|
+
"deleteConfirm": "Delete /{name}? Takes effect immediately and cannot be undone.",
|
|
80
|
+
"cancel": "Cancel",
|
|
81
|
+
"save": "Save",
|
|
82
|
+
"saving": "Saving\u2026",
|
|
83
|
+
"saved": "Saved",
|
|
84
|
+
"retry": "Retry",
|
|
85
|
+
"loadFailed": "Load failed: {detail}",
|
|
86
|
+
"saveFailed": "Save failed: {detail}",
|
|
87
|
+
"help": "About {field}",
|
|
88
|
+
"field.type": "Type",
|
|
89
|
+
"field.name": "Name",
|
|
90
|
+
"field.aliases": "Aliases",
|
|
91
|
+
"field.description": "Description",
|
|
92
|
+
"field.prompt": "Prompt",
|
|
93
|
+
"field.command": "Command",
|
|
94
|
+
"field.target": "Target command",
|
|
95
|
+
"field.cwd": "Working directory",
|
|
96
|
+
"field.timeoutMs": "Timeout (ms)",
|
|
97
|
+
"type.prompt": "Prompt",
|
|
98
|
+
"type.exec": "Shell",
|
|
99
|
+
"type.alias": "Alias",
|
|
100
|
+
"tip.prompt": "$ARGUMENTS is replaced with the text after the command; if absent, that text is appended.",
|
|
101
|
+
"tip.command": "$ARGUMENTS is the full argument text; $1 $2\u2026 are the space-separated words. Arguments are passed as variables, never run as code.",
|
|
102
|
+
"tip.target": "Forwards to another slash command, optionally with fixed arguments. $ARGUMENTS is replaced with the arguments; if absent they are appended.",
|
|
103
|
+
"tip.cwd": "workspace is the current session directory; an absolute path also works.",
|
|
104
|
+
"execWarn": "Runs directly with the dsh process\u2019s privileges, with no approval.",
|
|
105
|
+
"err.type": "Wrong type",
|
|
106
|
+
"err.required": "Required",
|
|
107
|
+
"err.pattern": "Start with a lowercase letter; only a-z 0-9 - _",
|
|
108
|
+
"err.duplicate": "Already used, or points to itself",
|
|
109
|
+
"err.enum": "Use workspace or an absolute path",
|
|
110
|
+
"err.range": "An integer from 1 to 600000"
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
// src/client/panel.tsx
|
|
114
|
+
var import_react = require("react");
|
|
115
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
116
|
+
var blank = () => ({ name: "", aliases: "", description: "", type: "prompt", prompt: "", target: "", command: "", cwd: "", timeoutMs: "" });
|
|
117
|
+
var toDraft = (c) => ({
|
|
118
|
+
name: String(c.name ?? ""),
|
|
119
|
+
aliases: Array.isArray(c.aliases) ? c.aliases.join(", ") : "",
|
|
120
|
+
description: String(c.description ?? ""),
|
|
121
|
+
type: c.type === "exec" || c.type === "alias" ? c.type : "prompt",
|
|
122
|
+
prompt: String(c.prompt ?? ""),
|
|
123
|
+
target: String(c.target ?? ""),
|
|
124
|
+
command: String(c.command ?? ""),
|
|
125
|
+
cwd: c.cwd === void 0 || c.cwd === "workspace" ? "" : String(c.cwd),
|
|
126
|
+
timeoutMs: c.timeoutMs === void 0 || c.timeoutMs === 3e4 ? "" : String(c.timeoutMs)
|
|
127
|
+
});
|
|
128
|
+
function toWire(d) {
|
|
129
|
+
const out = {
|
|
130
|
+
name: d.name.trim(),
|
|
131
|
+
aliases: d.aliases.split(",").map((s) => s.trim()).filter((s) => s !== ""),
|
|
132
|
+
description: d.description,
|
|
133
|
+
type: d.type
|
|
134
|
+
};
|
|
135
|
+
if (d.type === "prompt") out.prompt = d.prompt;
|
|
136
|
+
else if (d.type === "alias") out.target = d.target.trim();
|
|
137
|
+
else {
|
|
138
|
+
out.command = d.command;
|
|
139
|
+
if (d.cwd.trim() !== "") out.cwd = d.cwd.trim();
|
|
140
|
+
if (d.timeoutMs.trim() !== "") out.timeoutMs = Number(d.timeoutMs);
|
|
141
|
+
}
|
|
142
|
+
return out;
|
|
143
|
+
}
|
|
144
|
+
var aliasList = (d) => d.aliases.split(",").map((s) => s.trim()).filter((s) => s !== "");
|
|
145
|
+
async function saveAll(commands, t) {
|
|
146
|
+
try {
|
|
147
|
+
const res = await fetch("/api/dsh-slash-command/save", {
|
|
148
|
+
method: "POST",
|
|
149
|
+
headers: { "content-type": "application/json" },
|
|
150
|
+
body: JSON.stringify({ commands: commands.map(toWire) })
|
|
151
|
+
});
|
|
152
|
+
const body = await res.json();
|
|
153
|
+
if (res.ok && body.ok) return { ok: true };
|
|
154
|
+
if (res.status === 400) return { ok: false, errors: body.errors ?? [] };
|
|
155
|
+
return { ok: false, errors: [], text: t("saveFailed", { detail: `HTTP ${res.status}` }) };
|
|
156
|
+
} catch (e) {
|
|
157
|
+
return { ok: false, errors: [], text: t("saveFailed", { detail: e instanceof Error ? e.message : String(e) }) };
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
var TYPES = ["prompt", "exec", "alias"];
|
|
161
|
+
function SlashCommandSection({ t }) {
|
|
162
|
+
const [commands, setCommands] = (0, import_react.useState)(null);
|
|
163
|
+
const [loadError, setLoadError] = (0, import_react.useState)();
|
|
164
|
+
const [editing, setEditing] = (0, import_react.useState)();
|
|
165
|
+
const [deleting, setDeleting] = (0, import_react.useState)();
|
|
166
|
+
const [busy, setBusy] = (0, import_react.useState)(false);
|
|
167
|
+
const [errors, setErrors] = (0, import_react.useState)([]);
|
|
168
|
+
const [failure, setFailure] = (0, import_react.useState)();
|
|
169
|
+
const [announce, setAnnounce] = (0, import_react.useState)("");
|
|
170
|
+
const load = () => {
|
|
171
|
+
setLoadError(void 0);
|
|
172
|
+
fetch("/api/dsh-slash-command/read", { headers: { accept: "application/json" }, cache: "no-store" }).then(async (res) => {
|
|
173
|
+
const body = await res.json();
|
|
174
|
+
if (!res.ok || !body.ok) throw new Error(body.errors?.[0]?.message ?? `HTTP ${res.status}`);
|
|
175
|
+
setCommands((body.commands ?? []).map(toDraft));
|
|
176
|
+
}).catch((e) => {
|
|
177
|
+
setLoadError(t("loadFailed", { detail: e instanceof Error ? e.message : String(e) }));
|
|
178
|
+
});
|
|
179
|
+
};
|
|
180
|
+
(0, import_react.useEffect)(load, []);
|
|
181
|
+
const reset = () => {
|
|
182
|
+
setErrors([]);
|
|
183
|
+
setFailure(void 0);
|
|
184
|
+
setAnnounce("");
|
|
185
|
+
};
|
|
186
|
+
const openEditor = (next) => {
|
|
187
|
+
reset();
|
|
188
|
+
setDeleting(void 0);
|
|
189
|
+
setEditing(next);
|
|
190
|
+
};
|
|
191
|
+
const commit = async (next, target) => {
|
|
192
|
+
setBusy(true);
|
|
193
|
+
reset();
|
|
194
|
+
const result = await saveAll(next, t);
|
|
195
|
+
setBusy(false);
|
|
196
|
+
if (result.ok) {
|
|
197
|
+
setCommands(next);
|
|
198
|
+
setAnnounce(t("saved"));
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
setErrors(result.errors.filter((e) => e.index === target && e.field !== void 0));
|
|
202
|
+
const stray = result.errors.filter((e) => e.index !== target || e.field === void 0);
|
|
203
|
+
setFailure(result.text ?? (stray.length > 0 ? t("saveFailed", { detail: stray.map((e) => e.message).join("; ") }) : void 0));
|
|
204
|
+
return false;
|
|
205
|
+
};
|
|
206
|
+
const saveEditing = async () => {
|
|
207
|
+
if (commands === null || editing === void 0) return;
|
|
208
|
+
const index = editing.index ?? commands.length;
|
|
209
|
+
const next = editing.index === void 0 ? [...commands, editing.draft] : commands.map((c, i) => i === editing.index ? editing.draft : c);
|
|
210
|
+
if (await commit(next, index)) setEditing(void 0);
|
|
211
|
+
};
|
|
212
|
+
const confirmDelete = async (index) => {
|
|
213
|
+
if (commands === null) return;
|
|
214
|
+
if (await commit(commands.filter((_, i) => i !== index), -1)) setDeleting(void 0);
|
|
215
|
+
};
|
|
216
|
+
const editor = (key) => editing && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
217
|
+
Editor,
|
|
218
|
+
{
|
|
219
|
+
t,
|
|
220
|
+
draft: editing.draft,
|
|
221
|
+
errors,
|
|
222
|
+
failure,
|
|
223
|
+
busy,
|
|
224
|
+
onChange: (p) => {
|
|
225
|
+
setEditing({ ...editing, draft: { ...editing.draft, ...p } });
|
|
226
|
+
setErrors((es) => es.filter((e) => !(e.field in p)));
|
|
227
|
+
},
|
|
228
|
+
onCancel: () => openEditor(void 0),
|
|
229
|
+
onSave: () => {
|
|
230
|
+
void saveEditing();
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
key
|
|
234
|
+
);
|
|
235
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dsc-section", children: [
|
|
236
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: "dsc-title", children: t("title") }),
|
|
237
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dsc-sr", role: "status", children: announce }),
|
|
238
|
+
loadError !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dsc-notice", role: "alert", children: [
|
|
239
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: loadError }),
|
|
240
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "dsc-btn dsc-secondary dsc-compact", onClick: load, children: t("retry") })
|
|
241
|
+
] }),
|
|
242
|
+
commands !== null && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dsc-body", children: [
|
|
243
|
+
commands.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: "dsc-rows", children: commands.map((c, i) => {
|
|
244
|
+
const open = editing?.index === i;
|
|
245
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { className: "dsc-card", children: [
|
|
246
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dsc-head", children: [
|
|
247
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dsc-identity", children: [
|
|
248
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("code", { className: "dsc-name", children: [
|
|
249
|
+
"/",
|
|
250
|
+
c.name
|
|
251
|
+
] }),
|
|
252
|
+
aliasList(c).map((a) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("code", { className: "dsc-tag", children: [
|
|
253
|
+
"/",
|
|
254
|
+
a
|
|
255
|
+
] }, a)),
|
|
256
|
+
c.type === "exec" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dsc-tag", children: t("type.exec") }),
|
|
257
|
+
c.type === "alias" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("code", { className: "dsc-tag", children: [
|
|
258
|
+
"\u2192 ",
|
|
259
|
+
c.target.startsWith("/") ? c.target : `/${c.target}`
|
|
260
|
+
] })
|
|
261
|
+
] }),
|
|
262
|
+
!open && deleting !== i && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dsc-actions", children: [
|
|
263
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
264
|
+
"button",
|
|
265
|
+
{
|
|
266
|
+
type: "button",
|
|
267
|
+
className: "dsc-btn dsc-secondary dsc-compact",
|
|
268
|
+
"aria-label": t("editOf", { name: c.name }),
|
|
269
|
+
disabled: busy,
|
|
270
|
+
onClick: () => openEditor({ index: i, draft: c }),
|
|
271
|
+
children: t("edit")
|
|
272
|
+
}
|
|
273
|
+
),
|
|
274
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
275
|
+
"button",
|
|
276
|
+
{
|
|
277
|
+
type: "button",
|
|
278
|
+
className: "dsc-btn dsc-danger dsc-compact",
|
|
279
|
+
"aria-label": t("deleteOf", { name: c.name }),
|
|
280
|
+
disabled: busy,
|
|
281
|
+
onClick: () => {
|
|
282
|
+
openEditor(void 0);
|
|
283
|
+
setDeleting(i);
|
|
284
|
+
},
|
|
285
|
+
children: t("delete")
|
|
286
|
+
}
|
|
287
|
+
)
|
|
288
|
+
] })
|
|
289
|
+
] }),
|
|
290
|
+
!open && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "dsc-desc", children: c.description }),
|
|
291
|
+
deleting === i && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dsc-confirm", role: "alertdialog", "aria-label": t("deleteOf", { name: c.name }), children: [
|
|
292
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: t("deleteConfirm", { name: c.name }) }),
|
|
293
|
+
failure !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dsc-error", role: "alert", children: failure }),
|
|
294
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dsc-actions", children: [
|
|
295
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
296
|
+
"button",
|
|
297
|
+
{
|
|
298
|
+
type: "button",
|
|
299
|
+
className: "dsc-btn dsc-secondary dsc-compact",
|
|
300
|
+
disabled: busy,
|
|
301
|
+
autoFocus: true,
|
|
302
|
+
onClick: () => {
|
|
303
|
+
setDeleting(void 0);
|
|
304
|
+
reset();
|
|
305
|
+
},
|
|
306
|
+
children: t("cancel")
|
|
307
|
+
}
|
|
308
|
+
),
|
|
309
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
310
|
+
"button",
|
|
311
|
+
{
|
|
312
|
+
type: "button",
|
|
313
|
+
className: "dsc-btn dsc-danger-fill dsc-compact",
|
|
314
|
+
disabled: busy,
|
|
315
|
+
onClick: () => {
|
|
316
|
+
void confirmDelete(i);
|
|
317
|
+
},
|
|
318
|
+
children: busy ? t("saving") : t("delete")
|
|
319
|
+
}
|
|
320
|
+
)
|
|
321
|
+
] })
|
|
322
|
+
] }),
|
|
323
|
+
open && editor(`edit-${i}`)
|
|
324
|
+
] }, i);
|
|
325
|
+
}) }),
|
|
326
|
+
editing?.index === void 0 && editing !== void 0 ? editor("add") : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", className: "dsc-btn dsc-add", disabled: busy, onClick: () => openEditor({ index: void 0, draft: blank() }), children: [
|
|
327
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 14 14", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M7 2v10M2 7h10", stroke: "currentColor", strokeWidth: "1.4", strokeLinecap: "round" }) }),
|
|
328
|
+
t("add")
|
|
329
|
+
] })
|
|
330
|
+
] })
|
|
331
|
+
] });
|
|
332
|
+
}
|
|
333
|
+
function Editor({ t, draft, errors, failure, busy, onChange, onCancel, onSave }) {
|
|
334
|
+
const base = (0, import_react.useId)();
|
|
335
|
+
const errorOf = (field2) => errors.find((e) => e.field === field2);
|
|
336
|
+
const field = (key, control, tip) => {
|
|
337
|
+
const id = `${base}-${key}`;
|
|
338
|
+
const err = errorOf(key);
|
|
339
|
+
const label = t(`field.${key}`);
|
|
340
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dsc-field", children: [
|
|
341
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dsc-label", children: [
|
|
342
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { htmlFor: id, children: label }),
|
|
343
|
+
tip && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Help, { label: t("help", { field: label }), text: t(tip) })
|
|
344
|
+
] }),
|
|
345
|
+
control({ id, ...err ? { "aria-invalid": true, "aria-describedby": `${id}-err` } : {} }),
|
|
346
|
+
err && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { id: `${id}-err`, className: "dsc-error", children: t(`err.${err.code}`) })
|
|
347
|
+
] });
|
|
348
|
+
};
|
|
349
|
+
const text = (key, extra = {}) => (p) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
350
|
+
"input",
|
|
351
|
+
{
|
|
352
|
+
...p,
|
|
353
|
+
className: `dsc-input${extra.mono ? " dsc-mono" : ""}`,
|
|
354
|
+
value: draft[key],
|
|
355
|
+
placeholder: extra.placeholder,
|
|
356
|
+
inputMode: extra.inputMode,
|
|
357
|
+
spellCheck: false,
|
|
358
|
+
autoComplete: "off",
|
|
359
|
+
onChange: (e) => onChange({ [key]: e.target.value })
|
|
360
|
+
}
|
|
361
|
+
);
|
|
362
|
+
const area = (key, rows) => (p) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
363
|
+
"textarea",
|
|
364
|
+
{
|
|
365
|
+
...p,
|
|
366
|
+
className: `dsc-input dsc-area${key === "command" ? " dsc-mono" : ""}`,
|
|
367
|
+
rows,
|
|
368
|
+
value: draft[key],
|
|
369
|
+
spellCheck: false,
|
|
370
|
+
onChange: (e) => onChange({ [key]: e.target.value })
|
|
371
|
+
}
|
|
372
|
+
);
|
|
373
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: "dsc-editor", onSubmit: (e) => {
|
|
374
|
+
e.preventDefault();
|
|
375
|
+
onSave();
|
|
376
|
+
}, children: [
|
|
377
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dsc-segmented", role: "group", "aria-label": t("field.type"), style: { "--dsc-index": TYPES.indexOf(draft.type), "--dsc-count": TYPES.length }, children: [
|
|
378
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dsc-indicator", "aria-hidden": "true" }),
|
|
379
|
+
TYPES.map((v) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", "aria-pressed": draft.type === v, className: "dsc-segment", onClick: () => onChange({ type: v }), children: t(`type.${v}`) }, v))
|
|
380
|
+
] }),
|
|
381
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dsc-grid", children: [
|
|
382
|
+
field("name", (p) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dsc-affix", children: [
|
|
383
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { "aria-hidden": "true", children: "/" }),
|
|
384
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
385
|
+
"input",
|
|
386
|
+
{
|
|
387
|
+
...p,
|
|
388
|
+
className: "dsc-bare dsc-mono",
|
|
389
|
+
value: draft.name,
|
|
390
|
+
spellCheck: false,
|
|
391
|
+
autoComplete: "off",
|
|
392
|
+
autoFocus: true,
|
|
393
|
+
onChange: (e) => onChange({ name: e.target.value })
|
|
394
|
+
}
|
|
395
|
+
)
|
|
396
|
+
] })),
|
|
397
|
+
field("aliases", text("aliases", { placeholder: "rv, r", mono: true }))
|
|
398
|
+
] }),
|
|
399
|
+
field("description", text("description")),
|
|
400
|
+
draft.type === "prompt" && field("prompt", area("prompt", 5), "tip.prompt"),
|
|
401
|
+
draft.type === "alias" && field("target", text("target", { placeholder: "/compact", mono: true }), "tip.target"),
|
|
402
|
+
draft.type === "exec" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
403
|
+
field("command", area("command", 3), "tip.command"),
|
|
404
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dsc-grid", children: [
|
|
405
|
+
field("cwd", text("cwd", { placeholder: "workspace", mono: true }), "tip.cwd"),
|
|
406
|
+
field("timeoutMs", text("timeoutMs", { placeholder: "30000", inputMode: "numeric" }))
|
|
407
|
+
] }),
|
|
408
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "dsc-warn", children: t("execWarn") })
|
|
409
|
+
] }),
|
|
410
|
+
failure !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "dsc-error", role: "alert", children: failure }),
|
|
411
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dsc-editor-actions", children: [
|
|
412
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "dsc-btn dsc-secondary", disabled: busy, onClick: onCancel, children: t("cancel") }),
|
|
413
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "submit", className: "dsc-btn dsc-primary", disabled: busy || draft.name.trim() === "", children: busy ? t("saving") : t("save") })
|
|
414
|
+
] })
|
|
415
|
+
] });
|
|
416
|
+
}
|
|
417
|
+
function Help({ label, text }) {
|
|
418
|
+
const id = (0, import_react.useId)();
|
|
419
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dsc-help", children: [
|
|
420
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "dsc-help-btn", "aria-label": label, "aria-describedby": id, children: "?" }),
|
|
421
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { id, role: "tooltip", className: "dsc-tip", children: text })
|
|
422
|
+
] });
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// src/client/index.tsx
|
|
426
|
+
var name = "dsh-slash-command";
|
|
427
|
+
var inject = ["slots", "locale"];
|
|
428
|
+
var css = `
|
|
429
|
+
.dsc-section{display:flex;flex-direction:column;gap:12px;max-width:720px;color:var(--dsw-alias-label-primary)}
|
|
430
|
+
.dsc-title{margin:0;font-size:16px;line-height:24px;font-weight:500}
|
|
431
|
+
.dsc-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
|
|
432
|
+
.dsc-body{display:flex;flex-direction:column;gap:8px;margin-top:12px}
|
|
433
|
+
.dsc-rows{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}
|
|
434
|
+
.dsc-body>.dsc-editor{margin-top:0}
|
|
435
|
+
.dsc-card{border:.5px solid var(--dsw-alias-settings-card-stroke);background:var(--dsw-alias-settings-card-fill);border-radius:var(--dsw-radius-xl);padding:12px 14px;display:flex;flex-direction:column;gap:6px;}
|
|
436
|
+
.dsc-head{display:flex;align-items:center;gap:10px;min-height:28px}
|
|
437
|
+
.dsc-identity{display:inline-flex;align-items:center;flex-wrap:wrap;gap:6px;min-width:0}
|
|
438
|
+
.dsc-name{font-family:var(--ds-font-family-code);font-size:14px;line-height:22px;font-weight:500}
|
|
439
|
+
.dsc-tag{flex:none;padding:1px 6px;border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-xs);font-size:11px;line-height:16px;color:var(--dsw-alias-label-secondary)}
|
|
440
|
+
code.dsc-tag{font-family:var(--ds-font-family-code)}
|
|
441
|
+
.dsc-desc{margin:0;font-size:13px;line-height:20px;color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere}
|
|
442
|
+
.dsc-actions{display:inline-flex;align-items:center;gap:4px;margin-left:auto}
|
|
443
|
+
.dsc-btn{box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;gap:6px;height:36px;padding:0 14px;border:none;border-radius:var(--dsw-radius-md);background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:14px;line-height:22px;cursor:pointer}
|
|
444
|
+
.dsc-btn:disabled{opacity:.4;cursor:default}
|
|
445
|
+
.dsc-btn:focus-visible,.dsc-help-btn:focus-visible,.dsc-segment:focus-visible{outline:none;box-shadow:0 0 0 2px var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary))}
|
|
446
|
+
.dsc-compact{height:28px;padding:0 10px;border-radius:var(--dsw-radius-sm);font-size:12px;line-height:18px}
|
|
447
|
+
.dsc-primary{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground)}
|
|
448
|
+
.dsc-secondary{border:.5px solid var(--dsw-alias-border-l3)}
|
|
449
|
+
.dsc-danger{color:var(--dsw-alias-state-error-primary)}
|
|
450
|
+
.dsc-danger-fill{background:var(--dsw-alias-state-error-primary);color:#fff}
|
|
451
|
+
.dsc-add{width:100%;height:44px;border:1px dashed var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-lg)}
|
|
452
|
+
@media (hover:hover){
|
|
453
|
+
.dsc-primary:hover:not(:disabled){background:var(--dsw-alias-button-primary-hover)}
|
|
454
|
+
.dsc-secondary:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-solid)}
|
|
455
|
+
.dsc-add:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}
|
|
456
|
+
.dsc-danger:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger)}
|
|
457
|
+
.dsc-danger-fill:hover:not(:disabled){filter:brightness(.92)}
|
|
458
|
+
.dsc-segment:hover{color:var(--dsw-alias-label-primary)}
|
|
459
|
+
.dsc-help:hover .dsc-tip{display:block}
|
|
460
|
+
.dsc-help-btn:hover{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-tertiary)}
|
|
461
|
+
}
|
|
462
|
+
.dsc-confirm{display:flex;align-items:center;flex-wrap:wrap;gap:8px 12px;margin-top:4px;padding:10px 12px;border-radius:var(--dsw-radius-lg);background:var(--dsw-alias-bg-module-platform);font-size:13px;line-height:20px}
|
|
463
|
+
.dsc-editor{display:flex;flex-direction:column;gap:14px;margin-top:6px;padding:14px 16px;border-radius:var(--dsw-radius-lg);background:var(--dsw-alias-bg-module-platform)}
|
|
464
|
+
.dsc-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:14px}
|
|
465
|
+
.dsc-field{display:flex;flex-direction:column;gap:6px;min-width:0}
|
|
466
|
+
.dsc-label{display:inline-flex;align-items:center;gap:8px;font-size:12px;line-height:18px;font-weight:500;color:var(--dsw-alias-label-secondary)}
|
|
467
|
+
.dsc-input,.dsc-affix{box-sizing:border-box;width:100%;min-height:32px;padding:4px 8px;border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);font:inherit;font-size:14px;line-height:22px;outline:none}
|
|
468
|
+
.dsc-input:focus,.dsc-affix:focus-within{border-color:var(--dsw-alias-state-business-primary)}
|
|
469
|
+
.dsc-input[aria-invalid],.dsc-affix:has([aria-invalid]){border-color:var(--dsw-alias-state-error-primary)}
|
|
470
|
+
.dsc-input::placeholder{color:var(--dsw-alias-label-dimmed)}
|
|
471
|
+
.dsc-area{resize:vertical;min-height:72px}
|
|
472
|
+
.dsc-mono{font-family:var(--ds-font-family-code);font-size:13px}
|
|
473
|
+
.dsc-affix{display:flex;align-items:center;gap:2px;font-family:var(--ds-font-family-code);color:var(--dsw-alias-label-tertiary)}
|
|
474
|
+
.dsc-bare{flex:1;min-width:0;padding:0;border:none;outline:none;background:transparent;color:var(--dsw-alias-label-primary);font-size:14px;line-height:22px}
|
|
475
|
+
.dsc-segmented{position:relative;display:inline-grid;grid-auto-flow:column;grid-auto-columns:1fr;gap:2px;align-self:flex-start;padding:4px;border-radius:var(--dsw-radius-md);background:var(--dsw-alias-interactive-bg-hover)}
|
|
476
|
+
.dsc-indicator{position:absolute;top:4px;left:4px;width:calc((100% - 8px - 2px * (var(--dsc-count) - 1)) / var(--dsc-count));height:calc(100% - 8px);border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-bg-layer-1);box-shadow:var(--dsw-elevation-soft);transform:translateX(calc(var(--dsc-index) * (100% + 2px)));transition:transform 160ms ease;pointer-events:none}
|
|
477
|
+
.dsc-segment{position:relative;z-index:1;box-sizing:border-box;height:28px;padding:0 16px;border:0;border-radius:var(--dsw-radius-sm);background:transparent;color:var(--dsw-alias-label-secondary);font:inherit;font-size:13px;line-height:20px;font-weight:500;cursor:pointer}
|
|
478
|
+
.dsc-segment[aria-pressed=true]{color:var(--dsw-alias-label-primary)}
|
|
479
|
+
.dsc-help{position:relative;display:inline-flex}
|
|
480
|
+
.dsc-help-btn{box-sizing:border-box;width:16px;height:16px;padding:0;border:.5px solid var(--dsw-alias-border-l3);border-radius:50%;background:transparent;color:var(--dsw-alias-label-tertiary);font:inherit;font-size:11px;line-height:15px;text-align:center;cursor:help}
|
|
481
|
+
.dsc-tip{display:none;position:absolute;z-index:10;left:-4px;top:calc(100% + 6px);width:max-content;max-width:280px;padding:3px 7px;border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-tooltip-bg);color:var(--dsw-static-neutral-bluish-00,#fff);font-size:13px;line-height:20px;font-weight:400;pointer-events:none}
|
|
482
|
+
.dsc-help-btn:focus-visible+.dsc-tip{display:block}
|
|
483
|
+
.dsc-warn{margin:-4px 0 0;font-size:12px;line-height:18px;color:var(--dsw-alias-state-warn-label)}
|
|
484
|
+
.dsc-error{margin:0;font-size:12px;line-height:18px;color:var(--dsw-alias-state-error-primary)}
|
|
485
|
+
.dsc-notice{display:flex;align-items:center;gap:12px;font-size:13px;line-height:20px;color:var(--dsw-alias-state-error-primary)}
|
|
486
|
+
.dsc-editor-actions{display:flex;justify-content:flex-end;gap:8px}
|
|
487
|
+
@media (prefers-reduced-motion:reduce){.dsc-indicator{transition:none}}
|
|
488
|
+
`;
|
|
489
|
+
function apply(ctx) {
|
|
490
|
+
ctx.effect(() => ctx.locale.register(NS, { zh, en }), "dsh-slash-command: dictionaries");
|
|
491
|
+
const t = ctx.locale.bind(NS);
|
|
492
|
+
if (typeof document !== "undefined") {
|
|
493
|
+
document.querySelectorAll('style[data-plugin="dsh-slash-command"]').forEach((node) => node.remove());
|
|
494
|
+
const tag = document.createElement("style");
|
|
495
|
+
tag.dataset.plugin = "dsh-slash-command";
|
|
496
|
+
tag.textContent = css;
|
|
497
|
+
document.head.appendChild(tag);
|
|
498
|
+
}
|
|
499
|
+
ctx.slots.inject("settings.section", () => ctx.slots.register(
|
|
500
|
+
{ name: "settings.section", id: "slash-commands", order: 25, locale: NS, label: () => t("title") },
|
|
501
|
+
SlashCommandSection
|
|
502
|
+
));
|
|
503
|
+
}
|
|
504
|
+
return module.exports; } });
|
|
505
|
+
//# sourceMappingURL=client.js.map
|