dsh-structured 0.9.4 → 0.9.9

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/package.json CHANGED
@@ -1,99 +1,102 @@
1
- {
2
- "name": "dsh-structured",
3
- "version": "0.9.4",
4
- "description": "Structured output for DSH: no-label title card first, then tables/lists/steps; per-session switch and style.md override. 让 DSH 的每条实质回复默认结构化。",
5
- "type": "module",
6
- "main": "lib/index.js",
7
- "license": "MIT",
8
- "author": "MYCAIGC",
9
- "repository": {
10
- "type": "git",
11
- "url": "git+https://github.com/feigo313/dsh-structured.git"
12
- },
13
- "homepage": "https://github.com/feigo313/dsh-structured#readme",
14
- "bugs": {
15
- "url": "https://github.com/feigo313/dsh-structured/issues"
16
- },
17
- "publishConfig": {
18
- "access": "public",
19
- "registry": "https://registry.npmjs.org"
20
- },
21
- "keywords": [
22
- "deepseek",
23
- "harness",
24
- "dsh",
25
- "dsh-plugin",
26
- "output-style",
27
- "structured-output"
28
- ],
29
- "exports": {
30
- ".": "./lib/index.js",
31
- "./client": "./lib/client.js",
32
- "./locale/*.json": "./locale/*.json",
33
- "./icon": "./icon.svg",
34
- "./package.json": "./package.json"
35
- },
36
- "dsh": {
37
- "bundle": {
38
- "patch": "./cordis.patch.yml"
39
- },
40
- "client": {
41
- "platform": "web",
42
- "inject": [
43
- "@deepseek-ai/dsh-client-ui-settings"
44
- ],
45
- "immediately": true
46
- },
47
- "compatibility": {
48
- "dshReleases": {
49
- "0.1.7-rc.2": "compatible",
50
- "0.2.0-rc.2": "compatible",
51
- "0.2.1-rc.1": "compatible",
52
- "0.2.1-rc.2": "compatible",
53
- "0.2.1-rc.3": "compatible",
54
- "0.3.0-rc.1": "compatible"
55
- }
56
- }
57
- },
58
- "files": [
59
- "lib",
60
- "src",
61
- "scripts",
62
- "docs",
63
- "!docs/FULL-TEST-PROMPT.md",
64
- "!docs/FULL-TEST-REPORT.md",
65
- "!docs/RE-AUDIT-REPORT.md",
66
- "!docs/PUBLISH-READY.md",
67
- "!docs/RELEASE-NOTES-0.7.4.md",
68
- "!docs/MAINTENANCE*.md",
69
- "!docs/ACCEPTANCE-0.9.1.md",
70
- "assets/screenshots",
71
- "screenshots.json",
72
- "test",
73
- "cordis.patch.yml",
74
- "locale/*.json",
75
- "icon.svg",
76
- "README.md",
77
- "ACCEPTANCE.md",
78
- "CHANGELOG.md",
79
- "LICENSE"
80
- ],
81
- "scripts": {
82
- "build": "node scripts/build.mjs",
83
- "pretest": "node scripts/build.mjs",
84
- "test": "node --test test/*.test.mjs",
85
- "theme-contrast": "node scripts/theme-contrast.mjs",
86
- "prepack": "node scripts/build.mjs"
87
- },
88
- "engines": {
89
- "node": ">=22",
90
- "dsh": ">=0.1.7-rc.2 <0.4.0-0"
91
- },
92
- "peerDependencies": {
93
- "@deepseek-ai/schemastery": "^3.18.0"
94
- },
95
- "devDependencies": {
96
- "@deepseek-ai/schemastery": "^3.18.0",
97
- "linkedom": "0.18.14"
98
- }
99
- }
1
+ {
2
+ "name": "dsh-structured",
3
+ "version": "0.9.9",
4
+ "description": "Structured output for DSH: no-label title card first, then tables/lists/steps; per-session switch and style.md override. 让 DSH 的每条实质回复默认结构化。",
5
+ "type": "module",
6
+ "main": "lib/index.js",
7
+ "license": "MIT",
8
+ "author": "MYCAIGC",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/feigo313/dsh-structured.git"
12
+ },
13
+ "homepage": "https://github.com/feigo313/dsh-structured#readme",
14
+ "bugs": {
15
+ "url": "https://github.com/feigo313/dsh-structured/issues"
16
+ },
17
+ "publishConfig": {
18
+ "access": "public",
19
+ "registry": "https://registry.npmjs.org"
20
+ },
21
+ "keywords": [
22
+ "deepseek",
23
+ "harness",
24
+ "dsh",
25
+ "dsh-plugin",
26
+ "output-style",
27
+ "structured-output"
28
+ ],
29
+ "exports": {
30
+ ".": "./lib/index.js",
31
+ "./client": "./lib/client.js",
32
+ "./locale/*.json": "./locale/*.json",
33
+ "./icon": "./icon.svg",
34
+ "./package.json": "./package.json"
35
+ },
36
+ "dsh": {
37
+ "bundle": {
38
+ "patch": "./cordis.patch.yml"
39
+ },
40
+ "client": {
41
+ "platform": "web",
42
+ "inject": [
43
+ "@deepseek-ai/dsh-client-ui-settings"
44
+ ],
45
+ "immediately": true
46
+ },
47
+ "compatibility": {
48
+ "dshReleases": {
49
+ "0.1.7-rc.2": "compatible",
50
+ "0.2.0-rc.2": "compatible",
51
+ "0.2.1-rc.1": "compatible",
52
+ "0.2.1-rc.2": "compatible",
53
+ "0.2.1-rc.3": "compatible",
54
+ "0.3.0-rc.1": "compatible"
55
+ }
56
+ }
57
+ },
58
+ "files": [
59
+ "lib",
60
+ "src",
61
+ "scripts",
62
+ "docs",
63
+ "!docs/FULL-TEST-PROMPT.md",
64
+ "!docs/FULL-TEST-REPORT.md",
65
+ "!docs/RE-AUDIT-REPORT.md",
66
+ "!docs/PUBLISH-READY.md",
67
+ "!docs/RELEASE-NOTES-0.7.4.md",
68
+ "!docs/MAINTENANCE*.md",
69
+ "!docs/ACCEPTANCE-0.9.1.md",
70
+ "!docs/ACCEPTANCE-0.9.7.md",
71
+ "!docs/ACCEPTANCE-0.9.8.md",
72
+ "!docs/ACCEPTANCE-0.9.9.md",
73
+ "assets/screenshots",
74
+ "screenshots.json",
75
+ "test",
76
+ "cordis.patch.yml",
77
+ "locale/*.json",
78
+ "icon.svg",
79
+ "README.md",
80
+ "ACCEPTANCE.md",
81
+ "CHANGELOG.md",
82
+ "LICENSE"
83
+ ],
84
+ "scripts": {
85
+ "build": "node scripts/build.mjs",
86
+ "pretest": "node scripts/build.mjs",
87
+ "test": "node --test test/*.test.mjs",
88
+ "theme-contrast": "node scripts/theme-contrast.mjs",
89
+ "prepack": "node scripts/build.mjs"
90
+ },
91
+ "engines": {
92
+ "node": ">=22",
93
+ "dsh": ">=0.1.7-rc.2 <0.4.0-0"
94
+ },
95
+ "peerDependencies": {
96
+ "@deepseek-ai/schemastery": "^3.18.0"
97
+ },
98
+ "devDependencies": {
99
+ "@deepseek-ai/schemastery": "^3.18.0",
100
+ "linkedom": "0.18.14"
101
+ }
102
+ }
@@ -30,12 +30,12 @@ export const THEME_TOKENS = {
30
30
  anthropic: {
31
31
  light: {
32
32
  surface: '#FAF9F5', surface2: '#F5F1E8', text: '#141413', muted: '#6B6359',
33
- border: '#E5E0D5', accent: '#CC785C', accentText: '#A14A2E', success: '#266B4D', warn: '#92400E', error: '#8C1D18',
33
+ border: '#E5E0D5', accent: '#CC785C', accentText: '#A14A2E', success: '#266B4D', warn: '#806000', error: '#8C1D18',
34
34
  codeBg: '#F5F1E8', codeText: '#141413',
35
35
  },
36
36
  dark: {
37
37
  surface: '#1F1E1D', surface2: '#2A2825', text: '#F5F1E8', muted: '#A8A29A',
38
- border: '#3A3733', accent: '#E8A087', accentText: '#E8A087', success: '#6FBF9A', warn: '#E0A458', error: '#F28B82',
38
+ border: '#3A3733', accent: '#E8A087', accentText: '#E8A087', success: '#6FBF9A', warn: '#EAB308', error: '#F28B82',
39
39
  codeBg: '#171614', codeText: '#F5F1E8',
40
40
  },
41
41
  },
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env node
2
+ /** 0.9.8:品牌 accent 与语义 status 的 hue 分离检查(阈值 25°)。 */
3
+ import { pathToFileURL } from 'node:url'
4
+ import { THEME_TOKENS } from './theme-contrast.mjs'
5
+
6
+ export const HUE_THRESHOLD = 25
7
+
8
+ function rgb(hex) {
9
+ return [1, 3, 5].map((offset) => parseInt(hex.slice(offset, offset + 2), 16))
10
+ }
11
+
12
+ export function hue(hex) {
13
+ const [r, g, b] = rgb(hex).map((channel) => channel / 255)
14
+ const max = Math.max(r, g, b)
15
+ const min = Math.min(r, g, b)
16
+ const delta = max - min
17
+ if (delta === 0) return 0
18
+ let value
19
+ if (max === r) value = ((g - b) / delta) % 6
20
+ else if (max === g) value = (b - r) / delta + 2
21
+ else value = (r - g) / delta + 4
22
+ value *= 60
23
+ return value < 0 ? value + 360 : value
24
+ }
25
+
26
+ export function hueDistance(a, b) {
27
+ const diff = Math.abs(hue(a) - hue(b)) % 360
28
+ return diff > 180 ? 360 - diff : diff
29
+ }
30
+
31
+ export function checkHueSeparation() {
32
+ const results = []
33
+ const failures = []
34
+ for (const [theme, modes] of Object.entries(THEME_TOKENS)) {
35
+ for (const [mode, token] of Object.entries(modes)) {
36
+ for (const status of ['success', 'warn']) {
37
+ const distance = hueDistance(token.accent, token[status])
38
+ const row = { theme, mode, status, distance, threshold: HUE_THRESHOLD }
39
+ results.push(row)
40
+ if (distance < HUE_THRESHOLD) failures.push(row)
41
+ }
42
+ }
43
+ }
44
+ return { results, failures }
45
+ }
46
+
47
+ if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
48
+ const { results, failures } = checkHueSeparation()
49
+ for (const row of results) console.log(`${row.theme}/${row.mode} accent-${row.status}: ${row.distance.toFixed(1)}°`)
50
+ if (failures.length > 0) {
51
+ console.error(JSON.stringify(failures, null, 2))
52
+ process.exit(1)
53
+ }
54
+ console.log(`PASS ${results.length} hue checks`)
55
+ }
package/src/client.js CHANGED
@@ -129,12 +129,12 @@ body[data-ds-dark-theme][data-dsh-structured-theme="codex"] [class*="_markdown_"
129
129
  }
130
130
  body[data-dsh-structured-theme="anthropic"] [class*="_markdown_"]{
131
131
  --ds-surface:#FAF9F5;--ds-surface-2:#F5F1E8;--ds-text:#141413;--ds-muted:#6B6359;
132
- --ds-border:#E5E0D5;--ds-accent:#CC785C;--ds-accent-text:#A14A2E;--ds-success:#266B4D;--ds-warn:#92400E;--ds-error:#8C1D18;
132
+ --ds-border:#E5E0D5;--ds-accent:#CC785C;--ds-accent-text:#A14A2E;--ds-success:#266B4D;--ds-warn:#806000;--ds-error:#8C1D18;
133
133
  --ds-code-bg:#F5F1E8;--ds-code-text:#141413;
134
134
  }
135
135
  body[data-ds-dark-theme][data-dsh-structured-theme="anthropic"] [class*="_markdown_"]{
136
136
  --ds-surface:#1F1E1D;--ds-surface-2:#2A2825;--ds-text:#F5F1E8;--ds-muted:#A8A29A;
137
- --ds-border:#3A3733;--ds-accent:#E8A087;--ds-accent-text:#E8A087;--ds-success:#6FBF9A;--ds-warn:#E0A458;--ds-error:#F28B82;
137
+ --ds-border:#3A3733;--ds-accent:#E8A087;--ds-accent-text:#E8A087;--ds-success:#6FBF9A;--ds-warn:#EAB308;--ds-error:#F28B82;
138
138
  --ds-code-bg:#171614;--ds-code-text:#F5F1E8;
139
139
  }
140
140
  [class*="_markdown_"] p{margin:.72em 0}
@@ -145,13 +145,15 @@ body[data-ds-dark-theme][data-dsh-structured-theme="anthropic"] [class*="_markdo
145
145
  [class*="_markdown_"] h1{font-size:26px;font-weight:700;margin:32px 0 12px;padding-bottom:8px;border-bottom:1px solid var(--ds-border)}
146
146
  [class*="_markdown_"] h2{font-size:21px;font-weight:700;margin:28px 0 10px;padding-left:12px;border-left:3px solid var(--ds-accent)}
147
147
  [class*="_markdown_"] h3{font-size:17px;font-weight:650;margin:22px 0 8px}
148
+ [class*="_markdown_"] h2[${ICON_ATTR}]{padding-left:42px;text-indent:-30px}
149
+ [class*="_markdown_"] h3[${ICON_ATTR}]{padding-left:30px;text-indent:-30px}
148
150
  [class*="_markdown_"] h4{font-size:15px;font-weight:650;margin:16px 0 6px}
149
151
  [class*="_markdown_"] h5,[class*="_markdown_"] h6{font-size:13px;font-weight:700;margin:14px 0 6px;color:var(--ds-muted);text-transform:uppercase;letter-spacing:.06em}
150
152
  [class*="_markdown_"] h2[${ICON_ATTR}]::before,
151
153
  [class*="_markdown_"] h3[${ICON_ATTR}]::before{
152
154
  content:attr(${ICON_ATTR});
153
155
  display:inline-flex;align-items:center;justify-content:center;
154
- width:22px;height:22px;margin-right:8px;border-radius:6px;
156
+ width:22px;height:22px;margin-right:8px;text-indent:0;border-radius:6px;
155
157
  background:color-mix(in srgb,var(--ds-accent) 12%,transparent);
156
158
  color:var(--ds-accent-text);font-size:12px;font-weight:700;vertical-align:2px;
157
159
  }
@@ -163,18 +165,19 @@ body[data-ds-dark-theme][data-dsh-structured-theme="anthropic"] [class*="_markdo
163
165
  [class*="_markdown_"] li::marker{color:var(--ds-accent-text)}
164
166
  [class*="_markdown_"] hr{height:1px;border:0;margin:28px 0;background:linear-gradient(90deg,transparent,var(--ds-border),transparent)}
165
167
  [class*="_markdown_"] table:not([${SKIP_ATTR}]){
166
- width:100%;margin:18px 0;border-collapse:separate;border-spacing:0;
167
- border:1px solid var(--ds-border);border-radius:12px;overflow:hidden;font-size:13.5px;
168
+ width:100%;margin:16px 0;border-collapse:separate;border-spacing:0;
169
+ border:1px solid var(--ds-border);border-radius:12px;overflow:hidden;font-size:12.5px;
168
170
  box-shadow:0 1px 2px rgba(0,0,0,.03);
169
171
  }
170
172
  [class*="_markdown_"] table:not([${SKIP_ATTR}]) thead th{
171
- background:var(--ds-surface-2);
172
- font-size:11px!important;letter-spacing:.07em!important;color:var(--ds-muted);
173
- font-weight:700!important;text-align:left;padding:12px 18px!important;
173
+ height:38px;background:var(--ds-surface-2);
174
+ font-size:13px!important;letter-spacing:0!important;
175
+ color:color-mix(in srgb,var(--ds-text) 78%,var(--ds-muted));
176
+ font-weight:700!important;text-align:left;padding:0 18px!important;vertical-align:middle;
174
177
  border-bottom:1px solid var(--ds-border);
175
178
  }
176
179
  [class*="_markdown_"] table:not([${SKIP_ATTR}]) tbody td{
177
- padding:13px 18px!important;line-height:1.55;vertical-align:middle;border-left:0;border-right:0;
180
+ padding:12px 18px!important;line-height:1.55;vertical-align:middle;border-left:0;border-right:0;
178
181
  border-bottom:1px solid color-mix(in srgb,var(--ds-border) 55%,transparent);
179
182
  word-break:break-word;
180
183
  }
@@ -189,17 +192,17 @@ body[data-ds-dark-theme][data-dsh-structured-theme="anthropic"] [class*="_markdo
189
192
  [class*="_markdown_"] table:not([${SKIP_ATTR}]):not([${STATUS_TABLE_ATTR}]):has(thead th:nth-child(3):last-child) td:nth-child(2){width:22%}
190
193
  [class*="_markdown_"] table:not([${SKIP_ATTR}])[${STATUS_TABLE_ATTR}] th:first-child,
191
194
  [class*="_markdown_"] table:not([${SKIP_ATTR}])[${STATUS_TABLE_ATTR}] td:first-child{
192
- width:68px;text-align:center;padding:7px 8px!important;font-size:11px;font-weight:700;
193
- white-space:nowrap;vertical-align:middle;border-radius:7px;
195
+ width:68px;text-align:center;padding:4px 8px!important;font-size:10px;font-weight:700;
196
+ white-space:nowrap;vertical-align:middle;border-radius:6px;
194
197
  }
195
198
  [class*="_markdown_"] table:not([${SKIP_ATTR}])[${STATUS_TABLE_ATTR}] tbody tr[${ROW_ATTR}="success"] td:first-child{background:color-mix(in srgb,var(--ds-success) 12%,transparent);color:var(--ds-success)}
196
199
  [class*="_markdown_"] table:not([${SKIP_ATTR}])[${STATUS_TABLE_ATTR}] tbody tr[${ROW_ATTR}="warn"] td:first-child{background:color-mix(in srgb,var(--ds-warn) 12%,transparent);color:var(--ds-warn)}
197
200
  [class*="_markdown_"] table:not([${SKIP_ATTR}])[${STATUS_TABLE_ATTR}] tbody tr[${ROW_ATTR}="error"] td:first-child{background:color-mix(in srgb,var(--ds-error) 12%,transparent);color:var(--ds-error)}
198
201
  [class*="_markdown_"] p[${LEAD_ATTR}="table"]{
199
- border-left:2px solid var(--ds-accent);padding-left:10px;margin:10px 0 8px;
200
- font-size:14px;color:var(--ds-text);
202
+ border:0;padding:0;margin:12px 0 8px;
203
+ font-size:13px;color:var(--ds-text);
201
204
  }
202
- [class*="_markdown_"] p[${LEAD_ATTR}="table"] strong{color:var(--ds-accent-text)}
205
+ [class*="_markdown_"] p[${LEAD_ATTR}="table"] strong{font-size:14px;font-weight:700;color:var(--ds-text)}
203
206
  [class*="_markdown_"] h2+table,[class*="_markdown_"] h2+p,[class*="_markdown_"] h3+table,[class*="_markdown_"] h3+p{margin-top:8px}
204
207
  [class*="_markdown_"] :not(pre)>code{
205
208
  background:var(--ds-surface-2);border:1px solid var(--ds-border);border-radius:6px;
@@ -250,65 +253,49 @@ body[data-ds-dark-theme][data-dsh-structured-theme="anthropic"] [class*="_markdo
250
253
  [class*="_markdown_"] blockquote[${TONE_ATTR}="warn"]{--ds-accent:var(--ds-warn);--ds-accent-text:var(--ds-warn)}
251
254
  [class*="_markdown_"] blockquote[${TONE_ATTR}="success"]{--ds-accent:var(--ds-success);--ds-accent-text:var(--ds-success)}
252
255
  [class*="_markdown_"] blockquote[${CARD_ATTR}="1"]{
253
- border:1px solid color-mix(in srgb,var(--ds-accent) 16%,var(--ds-border));
256
+ border:1px solid color-mix(in srgb,var(--ds-accent) 18%,var(--ds-border));
254
257
  border-left:3px solid var(--ds-accent);
255
- border-radius:12px;padding:14px 16px 15px;
256
- background:linear-gradient(135deg,color-mix(in srgb,var(--ds-accent) 6%,var(--ds-surface)),var(--ds-surface) 60%);
257
- box-shadow:0 1px 2px rgba(0,0,0,.04),0 12px 32px -24px color-mix(in srgb,var(--ds-accent) 32%,transparent);
258
+ border-radius:12px;padding:18px;
259
+ background:linear-gradient(135deg,color-mix(in srgb,var(--ds-accent) 5%,var(--ds-surface)),var(--ds-surface) 62%);
260
+ box-shadow:0 1px 2px rgba(0,0,0,.04);
258
261
  }
259
262
  [class*="_markdown_"] blockquote[${CARD_ATTR}="1"]>p:first-child>strong:first-child{
260
- display:flex;align-items:center;gap:9px;position:relative;
261
- font-size:13px;line-height:1.1;letter-spacing:.06em;text-transform:uppercase;
262
- color:var(--ds-accent-text);margin-bottom:8px;
263
+ display:block;position:static;
264
+ font-size:14px;line-height:1.3;letter-spacing:0;text-transform:none;
265
+ color:var(--ds-accent-text);margin-bottom:6px;
263
266
  }
264
- [class*="_markdown_"] blockquote[${CARD_ATTR}="1"]>p:first-child>strong:first-child::before{
265
- content:"";display:inline-flex;flex:none;
266
- width:26px;height:26px;border-radius:7px;
267
- background:color-mix(in srgb,var(--ds-accent) 12%,transparent);
268
- }
269
- [class*="_markdown_"] blockquote[${CARD_ATTR}="1"]>p:first-child>strong:first-child::after{
270
- content:"";position:absolute;left:5.5px;top:5.5px;width:15px;height:15px;
271
- background-color:var(--ds-accent);
272
- -webkit-mask:var(--ds-card-icon) center/contain no-repeat;
273
- mask:var(--ds-card-icon) center/contain no-repeat;
274
- }
275
- [class*="_markdown_"] blockquote[${CARD_ATTR}="1"]>p:nth-child(2)>strong:first-child{
276
- display:block;font-size:16px;font-weight:700;line-height:1.45;
277
- letter-spacing:-.01em;color:var(--ds-text);margin-bottom:4px;
278
- }
279
- [class*="_markdown_"] blockquote[${CARD_ATTR}="1"]>p{font-size:15.5px;line-height:1.7;font-weight:450;color:var(--ds-text)}
267
+ [class*="_markdown_"] blockquote[${CARD_ATTR}="1"]>p{font-size:13px;line-height:1.6;font-weight:400;color:var(--ds-text)}
280
268
  [class*="_markdown_"] blockquote[${CARD_ATTR}="1"]>p strong{font-weight:700;color:var(--ds-text)}
281
269
  [class*="_markdown_"] blockquote[${TONE_ATTR}]>p:first-child>strong:first-child{color:var(--ds-accent-text)}
282
- [class*="_markdown_"] blockquote[${CARD_TYPE_ATTR}="conclusion"]{
283
- --ds-card-icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 3l9 9-9 9-9-9 9-9z' fill='none' stroke='black' stroke-width='1.8' stroke-linejoin='round'/%3E%3C/svg%3E");
284
- }
285
- [class*="_markdown_"] blockquote[${CARD_TYPE_ATTR}="decision"]{
286
- --ds-card-icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M4 7h6l4 10h6M4 17h6l4-10h6' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
287
- }
288
- [class*="_markdown_"] blockquote[${CARD_TYPE_ATTR}="metric"]{
289
- --ds-card-icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M5 20V10M12 20V4M19 20v-7' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E");
270
+ [class*="_markdown_"] blockquote[${CARD_TYPE_ATTR}="risk"]{--ds-accent:var(--ds-warn);--ds-accent-text:var(--ds-warn)}
271
+ [class*="_markdown_"] blockquote[${CARD_TYPE_ATTR}="accept"]{--ds-accent:var(--ds-success);--ds-accent-text:var(--ds-success)}
272
+ [class*="_markdown_"] blockquote[${CARD_TYPE_ATTR}="statement"]>p:first-child>strong:first-child{
273
+ font-size:24px;line-height:1.25;letter-spacing:-.02em;text-transform:none;
274
+ color:var(--ds-text);margin-bottom:0;
290
275
  }
291
- [class*="_markdown_"] blockquote[${CARD_TYPE_ATTR}="risk"]{
292
- --ds-accent:var(--ds-warn);--ds-accent-text:var(--ds-warn);
293
- --ds-card-icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 4l9 16H3L12 4z' fill='none' stroke='black' stroke-width='1.8' stroke-linejoin='round'/%3E%3Cpath d='M12 10v4M12 17v.5' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E");
276
+ [class*="_markdown_"] blockquote[${CARD_TYPE_ATTR}="statement"]>p:first-child>strong:first-child::after{
277
+ content:"";display:block;height:1px;margin:12px 0;
278
+ background:var(--ds-border);
294
279
  }
280
+ [class*="_markdown_"] blockquote[${CARD_TYPE_ATTR}="statement"]>p{font-size:13.5px;line-height:1.6;font-weight:400}
281
+ [class*="_markdown_"] blockquote[${CARD_TYPE_ATTR}="statement"]>p:first-child{margin-bottom:0}
295
282
  [class*="_markdown_"] blockquote[${CARD_TYPE_ATTR}="next"]{
296
- --ds-card-icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M5 12h14M13 6l6 6-6 6' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
297
- }
298
- [class*="_markdown_"] blockquote[${CARD_TYPE_ATTR}="accept"]{
299
- --ds-accent:var(--ds-success);--ds-accent-text:var(--ds-success);
300
- --ds-card-icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M4 12.5l5 5L20 6.5' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
301
- }
302
- [class*="_markdown_"] blockquote[${CARD_TYPE_ATTR}="key"]{
303
- --ds-card-icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 3l2.6 6.2 6.7.5-5.1 4.4 1.6 6.5L12 17.3 6.2 20.6l1.6-6.5L2.7 9.7l6.7-.5L12 3z' fill='none' stroke='black' stroke-width='1.6' stroke-linejoin='round'/%3E%3C/svg%3E");
304
- }
305
- [class*="_markdown_"] blockquote[${CARD_TYPE_ATTR}="statement"]{
306
- --ds-card-icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 3l9 9-9 9-9-9 9-9z' fill='none' stroke='black' stroke-width='1.8' stroke-linejoin='round'/%3E%3C/svg%3E");
307
- }
308
- [class*="_markdown_"] blockquote[${CARD_TYPE_ATTR}="statement"]>p:first-child>strong:first-child{
309
- font-size:16px;line-height:1.45;letter-spacing:-.01em;text-transform:none;
310
- color:var(--ds-text);margin-bottom:4px;
311
- }
283
+ background:none;border:0;border-top:1px solid var(--ds-border);border-radius:0;
284
+ box-shadow:none;padding:14px 0 0 14px;margin:18px 0;position:relative;
285
+ }
286
+ [class*="_markdown_"] blockquote[${CARD_TYPE_ATTR}="next"]::before{
287
+ content:"";position:absolute;left:0;top:17px;width:0;height:0;
288
+ border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:9px solid #C2410C;
289
+ }
290
+ [class*="_markdown_"] blockquote[${CARD_TYPE_ATTR}="next"]>p:first-child>strong:first-child{
291
+ font-size:16px;line-height:1.3;color:var(--ds-text);margin-bottom:8px;
292
+ }
293
+ [class*="_markdown_"] blockquote[${CARD_TYPE_ATTR}="next"]>p,
294
+ [class*="_markdown_"] blockquote[${CARD_TYPE_ATTR}="next"] li{font-size:13px;line-height:1.6}
295
+ [class*="_markdown_"] blockquote[${CARD_TYPE_ATTR}="next"] ol,
296
+ [class*="_markdown_"] blockquote[${CARD_TYPE_ATTR}="next"] ul{padding-left:0;margin:.4em 0 0;list-style-position:inside}
297
+ [class*="_markdown_"] blockquote[${CARD_TYPE_ATTR}="next"] li{padding-left:0}
298
+ body[data-ds-dark-theme] [class*="_markdown_"] blockquote[${CARD_TYPE_ATTR}="next"]::before{border-left-color:#FB923C}
312
299
  [class*="_markdown_"] blockquote[${CARD_ATTR}="1"]>p:first-child{margin-top:0}
313
300
  [class*="_markdown_"] blockquote[${CARD_ATTR}="1"]>p:last-child{margin-bottom:0}
314
301
  [class*="_markdown_"] p[${STATUS_ATTR}],[class*="_markdown_"] li[${STATUS_ATTR}]{
@@ -662,11 +649,36 @@ body[data-ds-dark-theme][data-dsh-structured-theme="anthropic"] [class*="_markdo
662
649
  let disposed = false
663
650
  let scheduled = false
664
651
  let pending = null
652
+ let pendingRoots = null
653
+
654
+ // 增量扫描:mutation 只重扫它所在的 markdown 容器(或新增子树),
655
+ // 避免长会话里每帧对整页做一次全量 querySelectorAll(O(N²))。
656
+ const markRoot = (node) => {
657
+ if (!node) return
658
+ const element = node.nodeType === 1 ? node : node.parentElement
659
+ if (!element) return
660
+ const markdown = element.closest?.('[class*="_markdown_"]')
661
+ const root = markdown ?? element
662
+ if (pendingRoots === null) pendingRoots = new Set()
663
+ pendingRoots.add(root)
664
+ }
665
665
  const run = () => {
666
666
  if (disposed) return
667
667
  scheduled = false
668
668
  pending = null
669
- decorate(document)
669
+ const roots = pendingRoots
670
+ pendingRoots = null
671
+ if (roots === null) {
672
+ decorate(document)
673
+ return
674
+ }
675
+ const list = [...roots]
676
+ for (const root of list) {
677
+ if (root?.isConnected === false) continue
678
+ // 被另一个待扫根包含时跳过,避免重复工作。
679
+ if (list.some((other) => other !== root && other.contains?.(root))) continue
680
+ decorate(root)
681
+ }
670
682
  }
671
683
  const schedule = () => {
672
684
  if (disposed || scheduled) return
@@ -674,7 +686,22 @@ body[data-ds-dark-theme][data-dsh-structured-theme="anthropic"] [class*="_markdo
674
686
  if (typeof requestAnimationFrame === 'function') pending = requestAnimationFrame(run)
675
687
  else pending = setTimeout(run, 16)
676
688
  }
677
- const observer = new MutationObserver(schedule)
689
+ const observer = new MutationObserver((records) => {
690
+ try {
691
+ for (const record of records) {
692
+ if (record.type === 'childList') {
693
+ for (const node of record.addedNodes) markRoot(node)
694
+ if (record.addedNodes.length === 0) markRoot(record.target)
695
+ } else {
696
+ markRoot(record.target)
697
+ }
698
+ }
699
+ } catch {
700
+ // 记录结构异常时退回整页扫描,保证装饰不丢。
701
+ pendingRoots = null
702
+ }
703
+ schedule()
704
+ })
678
705
  observer.observe(document.body, { childList: true, subtree: true, characterData: true })
679
706
  run()
680
707