dsh-claude-design 0.0.0-stage → 2.4.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 +40 -2
- package/cordis.patch.yml +7 -0
- package/docs/DETAIL.md +26 -0
- package/docs/DETAIL.zh.md +16 -0
- package/icon.svg +11 -0
- package/lib/client.js +241 -0
- package/lib/index.js +342 -0
- package/locale/en.json +7 -0
- package/locale/zh.json +7 -0
- package/package.json +59 -4
- package/skills/claude-design/SKILL.md +168 -0
- package/skills/claude-design/artifact-type/reference/brand-colors.md +51 -0
- package/skills/claude-design/artifact-type/reference/brand-typography.md +36 -0
- package/skills/claude-design/artifact-type/reference/craft.md +296 -0
- package/skills/claude-design/artifact-type/reference/design-system-components.md +171 -0
- package/skills/claude-design/artifact-type/reference/diagrams.md +46 -0
- package/skills/claude-design/artifact-type/reference/format.md +205 -0
- package/skills/claude-design/artifact-type/reference/google-fonts-families.json +1 -0
- package/skills/claude-design/artifact-type/reference/google-fonts-notices.json +1 -0
- package/skills/claude-design/artifact-type/reference/google-fonts-reserved.json +1 -0
- package/skills/claude-design/artifact-type/reference/make-from-this.md +5 -0
- package/skills/claude-design/artifact-type/reference/print.md +93 -0
- package/skills/claude-design/artifact-type/reference/questions.md +74 -0
- package/skills/claude-design/artifact-type/reference/view-state.md +139 -0
- package/skills/claude-design/scripts/artifact.mjs +3061 -0
- package/skills/claude-design/scripts/editor/artifact-type/babel.min.js +4 -0
- package/skills/claude-design/scripts/editor/artifact-type/dc-runtime.js +25916 -0
- package/skills/claude-design/scripts/editor/artifact-type/fast-edit-worker.js +73125 -0
- package/skills/claude-design/scripts/editor/artifact-type/reference/google-fonts-families.json +1 -0
- package/skills/claude-design/scripts/editor/artifact-type/reference/google-fonts-notices.json +1 -0
- package/skills/claude-design/scripts/editor/artifact-type/reference/google-fonts-reserved.json +1 -0
- package/skills/claude-design/scripts/editor/assets/anthropicons-fizzy-lake-c1fxtHDl.woff2 +0 -0
- package/skills/claude-design/scripts/editor/assets/index-DqKyhcn7.js +28775 -0
- package/skills/claude-design/scripts/editor/assets/index-oDSQuawR.css +1 -0
- package/skills/claude-design/scripts/editor/index.html +23 -0
- package/skills/claude-design/scripts/editor/third-party-licenses.txt +977 -0
- package/skills/claude-design/scripts/server.mjs +1716 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jim Liu 宝玉
|
|
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,41 @@
|
|
|
1
|
-
#
|
|
1
|
+
# dsh-claude-design
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) plugin that adds the **claude-design** skill from
|
|
4
|
+
[baoyu-design](https://github.com/JimLiu/baoyu-design): the agent writes editable design canvases (artboards side by
|
|
5
|
+
side) as files in your workspace and opens them in a local canvas editor, where you can retype copy and adjust each
|
|
6
|
+
artboard's tweaks.
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
In the DeepSeek Harness desktop app: **Plugins** → **Add plugin** → enter `dsh-claude-design` in **Package name or
|
|
11
|
+
address** → **Install**, and turn the plugin on. From the command line, for a CLI profile such as `web`:
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
dsh plugin --profile web add dsh-claude-design
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Then quit and reopen the app, start a new session, and ask for a design, or type `/claude-design`. A workspace that has
|
|
18
|
+
its own `claude-design` skill (in `.agents/skills/` or `.dsh/skills/`) uses that copy instead of this plugin's.
|
|
19
|
+
|
|
20
|
+
To update, uninstall the plugin, install it again, and quit and reopen the app. For a day after a release the app's
|
|
21
|
+
package manager (pnpm) still picks the previous version; to get the new one sooner, enter the name with the version,
|
|
22
|
+
such as `dsh-claude-design@2.4.0`.
|
|
23
|
+
|
|
24
|
+
## What is inside
|
|
25
|
+
|
|
26
|
+
- `skills/claude-design/`: the skill as baoyu-design publishes it (`SKILL.md`, `artifact-type/reference/`, and the
|
|
27
|
+
prebuilt `scripts/`: the editor page, `artifact.mjs`, and its server).
|
|
28
|
+
- `lib/index.js`: the plugin. It registers the skill with the Harness skill registry and, when the skill loads, tells
|
|
29
|
+
the agent which Node executable runs `scripts/artifact.mjs`: the Host's own Node, the Node runtime the desktop app
|
|
30
|
+
ships, or `node` on PATH. Set `node` in the `claude-design` row's config to choose another. Whenever the agent opens
|
|
31
|
+
the editor, the plugin also waits for comments, so a comment's **Send to agent** box is there: send one and the agent
|
|
32
|
+
wakes up, changes the artboard, and replies in the comment.
|
|
33
|
+
- `lib/client.js`: the part that runs in the app's window. It shows a comment sent to the agent as a card in the chat;
|
|
34
|
+
**View thread** on the card opens it in the editor.
|
|
35
|
+
- `cordis.patch.yml`: the bundle layer that mounts the plugin row.
|
|
36
|
+
|
|
37
|
+
The editor server listens on 127.0.0.1 only and reads and writes only the canvas's folder.
|
|
38
|
+
|
|
39
|
+
## License
|
|
40
|
+
|
|
41
|
+
MIT. The editor's third-party licenses are in `skills/claude-design/scripts/editor/third-party-licenses.txt`.
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# dsh-claude-design bundle patch: installing the package (the Plugins page, or
|
|
2
|
+
# `dsh plugin --profile <name> add <spec>`) adds it to the profile's bundles,
|
|
3
|
+
# and this layer mounts its one plugin row, which registers the claude-design
|
|
4
|
+
# skill with the profile's skill registry.
|
|
5
|
+
- insert:
|
|
6
|
+
- id: claude-design
|
|
7
|
+
name: dsh-claude-design
|
package/docs/DETAIL.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Claude Design
|
|
2
|
+
|
|
3
|
+
Adds the **claude-design** skill to DeepSeek Harness. Ask for a design ("three landing-page directions for our app")
|
|
4
|
+
and the agent writes it as files in your workspace: a folder with `project/canvas.json` and one `.dc.html` file per
|
|
5
|
+
artboard. It then starts a local canvas editor and gives you its link.
|
|
6
|
+
|
|
7
|
+
## Using it
|
|
8
|
+
|
|
9
|
+
- Ask for a design in plain words, or type `/claude-design` to call the skill by name.
|
|
10
|
+
- Open the link the agent gives you. In the desktop app it opens in the right sidebar's Browser, beside the
|
|
11
|
+
conversation (Settings → General → Open chat links in: **In-App Sidebar**, the default).
|
|
12
|
+
- In the editor you see the artboards side by side, retype copy and adjust each artboard's tweaks. Your edits are
|
|
13
|
+
saved back into the same files, and the agent's changes show up in the page as it writes them.
|
|
14
|
+
- Comment on anything on an artboard (Comment, or C). Tick **Send to agent** and the agent picks it up at once, even
|
|
15
|
+
when the conversation is idle: it changes the artboard and replies in the comment. The comment also shows in the chat
|
|
16
|
+
as a card; **View thread** on the card opens it in the editor. The box is there while comments can reach the agent,
|
|
17
|
+
which starts each time it gives you the link. After restarting the app, ask the agent to open the design again to
|
|
18
|
+
bring it back.
|
|
19
|
+
- To change a design later, ask the agent to revise the folder that holds its `project/canvas.json`.
|
|
20
|
+
- A workspace that has its own `claude-design` skill (in `.agents/skills/` or `.dsh/skills/`) uses that copy instead
|
|
21
|
+
of this plugin's.
|
|
22
|
+
|
|
23
|
+
## What runs where
|
|
24
|
+
|
|
25
|
+
The editor is a small server on 127.0.0.1 that the skill's script starts in the background, one per design. It reads
|
|
26
|
+
and writes only that design's folder. The desktop app's own Node runtime runs it; nothing else is installed.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Claude 设计稿
|
|
2
|
+
|
|
3
|
+
给 DeepSeek Harness 加上 **claude-design** 技能。让 Agent 做一份设计("给我们的 App 出三个落地页方向"),它会在工作区里把设计写成文件:一个文件夹,里面是 `project/canvas.json` 和每个画板一个 `.dc.html` 文件。写完它会启动本地画布编辑器,把链接给你。
|
|
4
|
+
|
|
5
|
+
## 怎么用
|
|
6
|
+
|
|
7
|
+
- 直接用自然语言要设计稿,或者输入 `/claude-design` 点名调用这个技能。
|
|
8
|
+
- 打开 Agent 给的链接。桌面版里它会在右侧栏的浏览器里打开,和对话并排(设置 → 通用 → 聊天链接打开方式:**应用内侧栏**,默认就是这个)。
|
|
9
|
+
- 编辑器里各个画板并排摆着,可以改文字、调每个画板的可调参数。你的修改会存回同一批文件;Agent 写的改动也会实时出现在页面上。
|
|
10
|
+
- 在画板上可以给任何元素加评论(点评论按钮或按 C)。勾上 **Send to agent** 发出去,Agent 会马上接手,对话空闲时也一样:它改好那个画板,再在评论里回复你。评论也会以卡片的形式出现在对话里,点卡片上的 **View thread**(中文界面是「查看评论」)会在编辑器里打开这条评论。这个勾选框只在评论能发给 Agent 时出现;Agent 每次给你编辑器链接时都会开始等评论。重启应用后,让 Agent 再打开一次这份设计稿就能恢复。
|
|
11
|
+
- 以后要改,让 Agent 修改那个装着 `project/canvas.json` 的文件夹即可。
|
|
12
|
+
- 如果工作区自己带了 `claude-design` 技能(在 `.agents/skills/` 或 `.dsh/skills/` 里),这个工作区会用它自己那份,而不是插件里的。
|
|
13
|
+
|
|
14
|
+
## 运行方式
|
|
15
|
+
|
|
16
|
+
编辑器是技能脚本在后台启动的一个本地服务(127.0.0.1),一份设计稿一个,只读写这份设计稿自己的文件夹。用的是桌面版自带的 Node,不需要另外安装任何东西。
|
package/icon.svg
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64">
|
|
2
|
+
<rect width="64" height="64" rx="14" fill="#D97757"/>
|
|
3
|
+
<rect x="9" y="17" width="20" height="30" rx="3" fill="#FFF7F2"/>
|
|
4
|
+
<rect x="35" y="17" width="20" height="30" rx="3" fill="#FFF7F2"/>
|
|
5
|
+
<rect x="13" y="22" width="12" height="9" rx="1.5" fill="#E9B8A3"/>
|
|
6
|
+
<rect x="13" y="35" width="10" height="2.5" rx="1.25" fill="#D97757"/>
|
|
7
|
+
<rect x="13" y="40" width="7" height="2.5" rx="1.25" fill="#E9B8A3"/>
|
|
8
|
+
<rect x="39" y="22" width="12" height="2.5" rx="1.25" fill="#D97757"/>
|
|
9
|
+
<rect x="39" y="27" width="9" height="2.5" rx="1.25" fill="#E9B8A3"/>
|
|
10
|
+
<rect x="39" y="34" width="12" height="9" rx="1.5" fill="#E9B8A3"/>
|
|
11
|
+
</svg>
|
package/lib/client.js
ADDED
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
// dsh-claude-design 2.4.0: built from baoyu-design.
|
|
2
|
+
window.__ModuleLoader__.load({
|
|
3
|
+
id: "dsh-claude-design",
|
|
4
|
+
factory: (require) => {
|
|
5
|
+
var module = { exports: {} };
|
|
6
|
+
var exports = module.exports;
|
|
7
|
+
"use strict";
|
|
8
|
+
var __defProp = Object.defineProperty;
|
|
9
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
10
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
11
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
12
|
+
var __export = (target, all) => {
|
|
13
|
+
for (var name in all)
|
|
14
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
15
|
+
};
|
|
16
|
+
var __copyProps = (to, from, except, desc) => {
|
|
17
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
18
|
+
for (let key of __getOwnPropNames(from))
|
|
19
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
20
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
21
|
+
}
|
|
22
|
+
return to;
|
|
23
|
+
};
|
|
24
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
25
|
+
|
|
26
|
+
var client_exports = {};
|
|
27
|
+
__export(client_exports, {
|
|
28
|
+
apply: () => apply,
|
|
29
|
+
inject: () => inject
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(client_exports);
|
|
32
|
+
|
|
33
|
+
var define_CLIENT_default = { plugin: "dsh-claude-design", key: "dsh-claude-design", simple: false };
|
|
34
|
+
|
|
35
|
+
var import_react = require("react");
|
|
36
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
37
|
+
var CLIENT = define_CLIENT_default;
|
|
38
|
+
var COMMENT_SOURCE = "baoyu-design-comment";
|
|
39
|
+
var KIND = `${CLIENT.key}:comment`;
|
|
40
|
+
var NS = CLIENT.key;
|
|
41
|
+
var zh = {
|
|
42
|
+
"card.title": "已将对“{title}”的评论发给 Agent",
|
|
43
|
+
"card.request": "已将“{title}”上的 {label} 发给 Agent",
|
|
44
|
+
"card.view": "查看评论",
|
|
45
|
+
"card.more": "显示位置",
|
|
46
|
+
"card.less": "收起位置"
|
|
47
|
+
};
|
|
48
|
+
var en = {
|
|
49
|
+
"card.title": "Comment on “{title}” sent to agent",
|
|
50
|
+
"card.request": "{label} on “{title}” sent to agent",
|
|
51
|
+
"card.view": "View thread",
|
|
52
|
+
"card.more": "Show where",
|
|
53
|
+
"card.less": "Hide where"
|
|
54
|
+
};
|
|
55
|
+
var str = (value) => typeof value === "string" ? value : "";
|
|
56
|
+
function ours(event) {
|
|
57
|
+
if (event.type !== "user/message" || event.surfaceOp !== "append") return false;
|
|
58
|
+
const source = event.data?.source;
|
|
59
|
+
return source?.kind === COMMENT_SOURCE && source.plugin === CLIENT.plugin;
|
|
60
|
+
}
|
|
61
|
+
function cardData(event) {
|
|
62
|
+
const source = event.data?.source ?? {};
|
|
63
|
+
const threads = Array.isArray(source.threads) ? source.threads : [];
|
|
64
|
+
const requests = Array.isArray(source.requests) ? source.requests : [];
|
|
65
|
+
return {
|
|
66
|
+
title: str(source.title),
|
|
67
|
+
url: str(source.url),
|
|
68
|
+
threads: threads.map((t) => ({ id: str(t.id), where: str(t.where), text: str(t.text) })).filter((t) => t.id),
|
|
69
|
+
requests: requests.map((r) => ({ id: str(r.id), label: str(r.label), text: str(r.text) })).filter((r) => r.id && r.text),
|
|
70
|
+
seq: event.seq
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
var definition = {
|
|
74
|
+
kind: KIND,
|
|
75
|
+
target: "chat",
|
|
76
|
+
match: (event) => (
|
|
77
|
+
// Claimed: the built-in input-message Definition would draw it as a context row.
|
|
78
|
+
ours(event) ? { id: String(event.data?.id), role: "start", exclusive: true } : null
|
|
79
|
+
),
|
|
80
|
+
start: (_context, match) => cardData(match.event),
|
|
81
|
+
update: (context) => context.state,
|
|
82
|
+
buildViewNode: (context) => {
|
|
83
|
+
if (context.state === void 0) return null;
|
|
84
|
+
return {
|
|
85
|
+
key: context.key,
|
|
86
|
+
kind: KIND,
|
|
87
|
+
id: context.id,
|
|
88
|
+
target: "chat",
|
|
89
|
+
anchorSeq: context.state.seq,
|
|
90
|
+
location: context.start?.location ?? context.matches[0]?.location ?? { kind: "unresolved" },
|
|
91
|
+
visibility: "visible",
|
|
92
|
+
// A person's input, as a user message: it opens the agent's reply below it.
|
|
93
|
+
groupTree: "input",
|
|
94
|
+
data: context.state
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
var CSS = `
|
|
99
|
+
.bdc-row{display:flex;flex-direction:column;align-items:flex-end;gap:8px;width:100%}
|
|
100
|
+
.bdc-card{box-sizing:border-box;max-width:min(calc(var(--dsh-chat-content-width, 748px) * 0.702), 82%);min-width:min(320px, 82%);
|
|
101
|
+
border:0.5px solid var(--dsw-alias-border-l1);border-radius:var(--dsw-radius-xl, 12px);background:var(--dsw-alias-markdown-code-block);
|
|
102
|
+
color:var(--dsw-alias-label-primary);padding:10px 14px 12px;display:flex;flex-direction:column;gap:6px}
|
|
103
|
+
.bdc-head{display:flex;align-items:center;gap:6px;color:var(--dsw-alias-label-tertiary);font:var(--dsw-font-xxs-12, 12px/18px sans-serif)}
|
|
104
|
+
.bdc-head svg{flex:none}
|
|
105
|
+
.bdc-head-text{flex:1;min-width:0;display:flex;white-space:nowrap;overflow:hidden}
|
|
106
|
+
.bdc-head-text>span{flex:none}
|
|
107
|
+
.bdc-head-text>.bdc-head-title{flex:0 1 auto;min-width:1.5em;overflow:hidden;text-overflow:ellipsis}
|
|
108
|
+
.bdc-toggle{flex:none;display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;margin:-2px -4px -2px 0;
|
|
109
|
+
border:0;border-radius:var(--dsw-radius-sm, 6px);background:none;color:inherit;cursor:pointer;padding:0}
|
|
110
|
+
.bdc-toggle:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary)}
|
|
111
|
+
.bdc-toggle svg{transition:transform .15s}
|
|
112
|
+
.bdc-toggle[aria-expanded=false] svg{transform:rotate(-90deg)}
|
|
113
|
+
.bdc-body{font-size:var(--dsh-content-font-size, 14px);line-height:1.6;white-space:pre-wrap;overflow-wrap:anywhere}
|
|
114
|
+
.bdc-meta{display:flex;flex-direction:column;gap:6px;padding-top:6px;border-top:0.5px solid var(--dsw-alias-border-l1)}
|
|
115
|
+
.bdc-where{color:var(--dsw-alias-label-tertiary);font:var(--dsw-font-xxs-12, 12px/18px sans-serif);overflow-wrap:anywhere}
|
|
116
|
+
.bdc-view{align-self:flex-start;display:inline-flex;align-items:center;gap:2px;height:24px;margin-left:-6px;padding:0 6px;border:0;
|
|
117
|
+
border-radius:var(--dsw-radius-sm, 6px);background:none;color:var(--dsw-alias-label-secondary);font:var(--dsw-font-xxs-12, 12px/18px sans-serif);cursor:pointer}
|
|
118
|
+
.bdc-view:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}
|
|
119
|
+
.bdc-view:focus-visible,.bdc-toggle:focus-visible{outline:var(--dsw-focus-ring-width, 2px) solid var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary));outline-offset:1px}
|
|
120
|
+
@media (prefers-reduced-motion:reduce){.bdc-toggle svg{transition:none}}
|
|
121
|
+
`;
|
|
122
|
+
var iconStyle = { display: "block" };
|
|
123
|
+
var TITLE_MARK = "";
|
|
124
|
+
function CommentIcon() {
|
|
125
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", style: iconStyle, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
126
|
+
"path",
|
|
127
|
+
{
|
|
128
|
+
d: "M3 3.5h10a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1H8.2L5.4 13.8a.3.3 0 0 1-.5-.23V11.5H3a1 1 0 0 1-1-1v-6a1 1 0 0 1 1-1Z",
|
|
129
|
+
stroke: "currentColor",
|
|
130
|
+
strokeWidth: "1.2",
|
|
131
|
+
strokeLinejoin: "round"
|
|
132
|
+
}
|
|
133
|
+
) });
|
|
134
|
+
}
|
|
135
|
+
function RequestIcon() {
|
|
136
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", style: iconStyle, children: [
|
|
137
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "2", y: "4", width: "12", height: "7", rx: "2", stroke: "currentColor", strokeWidth: "1.2" }),
|
|
138
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M8.5 8.5 11 14l.9-2.1L14 11l-5.5-2.5Z", fill: "currentColor", stroke: "var(--dsw-alias-markdown-code-block, #fff)", strokeWidth: "0.8", strokeLinejoin: "round" })
|
|
139
|
+
] });
|
|
140
|
+
}
|
|
141
|
+
function ChevronDown() {
|
|
142
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", "aria-hidden": "true", style: iconStyle, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 4.5 6 7.5l3-3", stroke: "currentColor", strokeWidth: "1.3", strokeLinecap: "round", strokeLinejoin: "round" }) });
|
|
143
|
+
}
|
|
144
|
+
function ChevronRight() {
|
|
145
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", "aria-hidden": "true", style: iconStyle, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M4.5 3 7.5 6l-3 3", stroke: "currentColor", strokeWidth: "1.3", strokeLinecap: "round", strokeLinejoin: "round" }) });
|
|
146
|
+
}
|
|
147
|
+
function Card({ title, thread, url, t, openThread }) {
|
|
148
|
+
const [open, setOpen] = (0, import_react.useState)(true);
|
|
149
|
+
const heading = t("card.title", { title });
|
|
150
|
+
const meta = !CLIENT.simple && (thread.where || url);
|
|
151
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bdc-card", "data-comment-id": thread.id, children: [
|
|
152
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bdc-head", children: [
|
|
153
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommentIcon, {}),
|
|
154
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { text: heading, title, parts: t("card.title", { title: TITLE_MARK }).split(TITLE_MARK) }),
|
|
155
|
+
meta && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "bdc-toggle", "aria-expanded": open, "aria-label": t(open ? "card.less" : "card.more"), onClick: () => setOpen(!open), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronDown, {}) })
|
|
156
|
+
] }),
|
|
157
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "bdc-body", children: thread.text }),
|
|
158
|
+
meta && open && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bdc-meta", children: [
|
|
159
|
+
thread.where && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "bdc-where", children: thread.where }),
|
|
160
|
+
url && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", className: "bdc-view", onClick: () => openThread(url, thread.id), children: [
|
|
161
|
+
t("card.view"),
|
|
162
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronRight, {})
|
|
163
|
+
] })
|
|
164
|
+
] })
|
|
165
|
+
] });
|
|
166
|
+
}
|
|
167
|
+
function Heading({ text, title, parts }) {
|
|
168
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "bdc-head-text", title: text, children: parts.length === 2 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
169
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: parts[0] }),
|
|
170
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "bdc-head-title", children: title }),
|
|
171
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: parts[1] })
|
|
172
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "bdc-head-title", children: text }) });
|
|
173
|
+
}
|
|
174
|
+
function RequestCardView({ title, request, t }) {
|
|
175
|
+
const label = request.label || "Request";
|
|
176
|
+
const heading = t("card.request", { title, label });
|
|
177
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bdc-card", "data-request-id": request.id, children: [
|
|
178
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bdc-head", children: [
|
|
179
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(RequestIcon, {}),
|
|
180
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { text: heading, title, parts: t("card.request", { title: TITLE_MARK, label }).split(TITLE_MARK) })
|
|
181
|
+
] }),
|
|
182
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "bdc-body", children: request.text })
|
|
183
|
+
] });
|
|
184
|
+
}
|
|
185
|
+
function CommentCards({ node, t, openThread }) {
|
|
186
|
+
const { title, url, threads, requests } = node.data;
|
|
187
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bdc-row", children: [
|
|
188
|
+
threads.map((thread) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, { title, thread, url, t, openThread }, thread.id)),
|
|
189
|
+
(requests ?? []).map((request) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RequestCardView, { title, request, t }, request.id))
|
|
190
|
+
] });
|
|
191
|
+
}
|
|
192
|
+
var inject = ["slots", "locale", "uiConversation"];
|
|
193
|
+
function threadUrl(url, id) {
|
|
194
|
+
try {
|
|
195
|
+
const at = new URL(url);
|
|
196
|
+
at.searchParams.set("comment", id);
|
|
197
|
+
return at.href;
|
|
198
|
+
} catch {
|
|
199
|
+
return url;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
function apply(ctx) {
|
|
203
|
+
ctx.effect(() => {
|
|
204
|
+
if (typeof document === "undefined") return () => {
|
|
205
|
+
};
|
|
206
|
+
const id = `${CLIENT.plugin}/comment-card.css`;
|
|
207
|
+
if (document.querySelector(`style[data-plugin-css=${JSON.stringify(id)}]`)) return () => {
|
|
208
|
+
};
|
|
209
|
+
const tag = document.createElement("style");
|
|
210
|
+
tag.dataset.plugin = CLIENT.plugin;
|
|
211
|
+
tag.dataset.pluginCss = id;
|
|
212
|
+
tag.textContent = CSS;
|
|
213
|
+
document.head.appendChild(tag);
|
|
214
|
+
return () => tag.remove();
|
|
215
|
+
}, `${CLIENT.plugin}: comment card styles`);
|
|
216
|
+
ctx.effect(() => ctx.locale.register(NS, { zh, en }), `${CLIENT.plugin}: dictionaries`);
|
|
217
|
+
ctx.uiConversation.events.register(definition);
|
|
218
|
+
ctx.slots.inject(
|
|
219
|
+
"conversation.chat.node",
|
|
220
|
+
() => ctx.slots.register(
|
|
221
|
+
{
|
|
222
|
+
name: "conversation.chat.node",
|
|
223
|
+
key: KIND,
|
|
224
|
+
locale: NS,
|
|
225
|
+
inject: (sessionId) => ({
|
|
226
|
+
openThread: (url, threadId) => {
|
|
227
|
+
const target = threadUrl(url, threadId);
|
|
228
|
+
const sidebar = ctx.get("sidebarRight");
|
|
229
|
+
const tabs = ctx.get("sidebarRightTabs");
|
|
230
|
+
if (sidebar && tabs?.get("browser") !== void 0) sidebar.openTabIn(sessionId, "browser", { params: { url: target } });
|
|
231
|
+
else window.open(target, "_blank", "noopener,noreferrer");
|
|
232
|
+
}
|
|
233
|
+
})
|
|
234
|
+
},
|
|
235
|
+
CommentCards
|
|
236
|
+
)
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
return module.exports;
|
|
240
|
+
}
|
|
241
|
+
});
|