@lynn123411/dsh-maple-theme 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/DETAILS.md +137 -0
- package/README.md +28 -2
- package/assets/icon.svg +5 -0
- package/cordis.patch.yml +11 -0
- package/lib/client.js +560 -0
- package/lib/client.js.map +7 -0
- package/lib/index.js +36 -0
- package/lib/index.js.map +7 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +94 -4
- package/src/client/binding.ts +69 -0
- package/src/client/card-css.ts +20 -0
- package/src/client/card.tsx +179 -0
- package/src/client/css.d.ts +5 -0
- package/src/client/index.ts +149 -0
- package/src/client/locales.ts +60 -0
- package/src/client/settings.ts +171 -0
- package/src/client/styles/markdown.css +266 -0
- package/src/client/styles/shell.css +83 -0
- package/src/client/styles/tokens.css +119 -0
- package/src/client/tokens.ts +78 -0
- package/src/index.ts +69 -0
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
/* Maple 正文层:对话流里的 markdown 排版与装饰。
|
|
2
|
+
*
|
|
3
|
+
* 作用范围只有一处:助手回答的正文(`[data-chat-flow-kind='assistant-step']`)。
|
|
4
|
+
* 推理块用的是同一个 kind,但它自己带 `data-chat-group-part='reasoning'`,被排除在外——
|
|
5
|
+
* 推理行要保持宿主的小字号与紧凑行距,跟着正文一起放大就糊成一片。
|
|
6
|
+
* 工具行也排除:它的 flow kind 是 `tool-call`,宿主本来就不在里面放 markdown 元素。
|
|
7
|
+
*
|
|
8
|
+
* 选择器一律「宿主的数据属性 + 元素名」两层:宿主正文的类名是 CSS Modules 的哈希串,
|
|
9
|
+
* 换一次构建就变,不能当锚点。典型一条是
|
|
10
|
+
* `html[data-maple-theme][data-maple-heading][data-chat-flow-kind]:not([data-chat-group-part]) body :where(h2)`,
|
|
11
|
+
* 属性三个(`html` 与 `body` 两个元素不计在内)压过宿主 module 样式表里的
|
|
12
|
+
* `.markdown h2` 那一个类,所以不需要 !important。
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
html[data-maple-theme='on'] {
|
|
16
|
+
--maple-p-gap: 10px;
|
|
17
|
+
--maple-underline-offset: 2px;
|
|
18
|
+
--maple-inline-code: hsl(0 45% 48%);
|
|
19
|
+
--maple-quote-bar: hsl(var(--maple-hue-light, 35) 26% 38% / 45%);
|
|
20
|
+
--maple-quote-fill: hsl(var(--maple-hue-light, 35) 20% 95%);
|
|
21
|
+
--maple-table-head: hsl(var(--maple-hue-light, 35) 30% 91%);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
html[data-maple-theme='on'] body[data-ds-dark-theme] {
|
|
25
|
+
--maple-inline-code: hsl(0 44% 68%);
|
|
26
|
+
--maple-quote-bar: hsl(var(--maple-hue-dark, 207) 30% 72% / 40%);
|
|
27
|
+
--maple-quote-fill: hsl(var(--maple-hue-dark, 207) 10% 14%);
|
|
28
|
+
--maple-table-head: hsl(var(--maple-hue-dark, 207) 12% 17%);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/* 段距:宿主的正文容器是纵向 flex,块与块之间的空隙由容器的 `gap: 16px` 给,
|
|
32
|
+
* 段落自己的 margin 被归零。所以要改的是容器那一个 gap,不是 p 的 margin。
|
|
33
|
+
* 容器是包住 markdown 根节点的那个 div,用 :has() 从根节点往上认。 */
|
|
34
|
+
html[data-maple-theme='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) {
|
|
35
|
+
--maple-gap: var(--maple-p-gap, 10px);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
html[data-maple-theme='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :has(> [class*='markdown']) {
|
|
39
|
+
gap: var(--maple-p-gap, 10px);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* 列表项里的段落仍按块级 margin 走:宿主的列表没有 gap,段落间距归零会挤成一坨。 */
|
|
43
|
+
html[data-maple-theme='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(li > p) {
|
|
44
|
+
margin: 4px 0;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
html[data-maple-theme='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(strong) {
|
|
48
|
+
font-weight: 600;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/* 行内代码:Maple 用暖红一色区分,不再是「加了底的正文」。 */
|
|
52
|
+
html[data-maple-theme='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :not(pre) > code {
|
|
53
|
+
color: var(--maple-inline-code);
|
|
54
|
+
background-color: color-mix(in srgb, var(--maple-inline-code) 8%, transparent);
|
|
55
|
+
border-color: color-mix(in srgb, var(--maple-inline-code) 18%, transparent);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/* 链接下划线的抬升量:Maple 的 --setting-underline-offset 默认 2px。 */
|
|
59
|
+
html[data-maple-theme='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(a) {
|
|
60
|
+
text-underline-offset: var(--maple-underline-offset);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/* 标题:字号与字重来自 tokens.css 的复合令牌,这里只补颜色、间距与 h5/h6。 */
|
|
64
|
+
html[data-maple-theme='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(h1, h2, h3, h4, h5, h6) {
|
|
65
|
+
position: relative;
|
|
66
|
+
margin: 28px 0 12px;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
html[data-maple-theme='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(h5) {
|
|
70
|
+
font-size: calc(var(--dsh-content-font-size, 14px) * 1.05);
|
|
71
|
+
font-weight: 600;
|
|
72
|
+
line-height: 1.5;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
html[data-maple-theme='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(h6) {
|
|
76
|
+
font-size: var(--dsh-content-font-size, 14px);
|
|
77
|
+
font-weight: 600;
|
|
78
|
+
line-height: 1.6;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
html[data-maple-theme='on'][data-maple-heading='colorful'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(h1) { color: var(--maple-h1); }
|
|
82
|
+
html[data-maple-theme='on'][data-maple-heading='colorful'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(h2) { color: var(--maple-h2); }
|
|
83
|
+
html[data-maple-theme='on'][data-maple-heading='colorful'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(h3) { color: var(--maple-h3); }
|
|
84
|
+
html[data-maple-theme='on'][data-maple-heading='colorful'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(h4) { color: var(--maple-h4); }
|
|
85
|
+
html[data-maple-theme='on'][data-maple-heading='colorful'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(h5) { color: var(--maple-h5); }
|
|
86
|
+
html[data-maple-theme='on'][data-maple-heading='colorful'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(h6) { color: var(--maple-h6); }
|
|
87
|
+
|
|
88
|
+
/* 另两种标题配色:六级统一取一个色,不再逐级换。
|
|
89
|
+
* 令牌层给了 --maple-heading-color,这里按元素逐级挂上——宿主用的是元素选择器,
|
|
90
|
+
* 一次 :where(h1, h2, …) 的优先级与它相同,分不开。 */
|
|
91
|
+
html[data-maple-theme='on'][data-maple-heading='accent'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(h1),
|
|
92
|
+
html[data-maple-theme='on'][data-maple-heading='accent'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(h2),
|
|
93
|
+
html[data-maple-theme='on'][data-maple-heading='accent'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(h3),
|
|
94
|
+
html[data-maple-theme='on'][data-maple-heading='accent'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(h4),
|
|
95
|
+
html[data-maple-theme='on'][data-maple-heading='accent'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(h5),
|
|
96
|
+
html[data-maple-theme='on'][data-maple-heading='accent'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(h6) { color: var(--maple-heading-color); }
|
|
97
|
+
|
|
98
|
+
html[data-maple-theme='on'][data-maple-heading='text'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(h1),
|
|
99
|
+
html[data-maple-theme='on'][data-maple-heading='text'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(h2),
|
|
100
|
+
html[data-maple-theme='on'][data-maple-heading='text'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(h3),
|
|
101
|
+
html[data-maple-theme='on'][data-maple-heading='text'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(h4),
|
|
102
|
+
html[data-maple-theme='on'][data-maple-heading='text'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(h5),
|
|
103
|
+
html[data-maple-theme='on'][data-maple-heading='text'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(h6) { color: var(--maple-heading-color); }
|
|
104
|
+
|
|
105
|
+
/* 标题等级标记:Maple 的 heading-indicator-auto——平时看不见,悬停时在左侧淡入 H1…H6。 */
|
|
106
|
+
html[data-maple-theme='on'][data-maple-indicator='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(h1, h2, h3, h4, h5, h6)::before {
|
|
107
|
+
position: absolute;
|
|
108
|
+
inset-inline-start: -1.9rem;
|
|
109
|
+
top: 0.15em;
|
|
110
|
+
font-size: calc(var(--dsh-content-font-size, 14px) * 0.7);
|
|
111
|
+
font-weight: 500;
|
|
112
|
+
line-height: 1;
|
|
113
|
+
color: var(--dsw-alias-label-caption);
|
|
114
|
+
opacity: 0;
|
|
115
|
+
transition: opacity var(--ds-transition-duration-fast) var(--ds-ease-in-out);
|
|
116
|
+
pointer-events: none;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
html[data-maple-theme='on'][data-maple-indicator='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(h1, h2, h3, h4, h5, h6):hover::before {
|
|
120
|
+
opacity: 1;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
html[data-maple-theme='on'][data-maple-indicator='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(h1)::before { content: 'H1'; }
|
|
124
|
+
html[data-maple-theme='on'][data-maple-indicator='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(h2)::before { content: 'H2'; }
|
|
125
|
+
html[data-maple-theme='on'][data-maple-indicator='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(h3)::before { content: 'H3'; }
|
|
126
|
+
html[data-maple-theme='on'][data-maple-indicator='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(h4)::before { content: 'H4'; }
|
|
127
|
+
html[data-maple-theme='on'][data-maple-indicator='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(h5)::before { content: 'H5'; }
|
|
128
|
+
html[data-maple-theme='on'][data-maple-indicator='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(h6)::before { content: 'H6'; }
|
|
129
|
+
|
|
130
|
+
/* 引用:Maple 是浅底 + 左侧一条色带,不是宿主的单边竖线。 */
|
|
131
|
+
html[data-maple-theme='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(blockquote) {
|
|
132
|
+
position: relative;
|
|
133
|
+
margin: 14px 0;
|
|
134
|
+
padding: 8px 14px 8px 18px;
|
|
135
|
+
border: 0;
|
|
136
|
+
border-radius: var(--dsw-radius-sm);
|
|
137
|
+
background: var(--maple-quote-fill);
|
|
138
|
+
color: var(--dsw-alias-label-secondary);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
html[data-maple-theme='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(blockquote)::before {
|
|
142
|
+
content: '';
|
|
143
|
+
position: absolute;
|
|
144
|
+
inset-block: 8px;
|
|
145
|
+
inset-inline-start: 7px;
|
|
146
|
+
width: 3px;
|
|
147
|
+
border-radius: var(--dsw-radius-xs);
|
|
148
|
+
background: var(--maple-quote-bar);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
html[data-maple-theme='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(blockquote blockquote) {
|
|
152
|
+
margin-inline-end: 0;
|
|
153
|
+
background: color-mix(in srgb, var(--maple-quote-fill) 70%, var(--dsw-alias-bg-base));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/* 列表:Maple 的标记用等宽字体,并按层级换形状(实心圆 → 空心圆 → 方块)。 */
|
|
157
|
+
html[data-maple-theme='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(ul, ol) {
|
|
158
|
+
margin: var(--maple-p-gap) 0;
|
|
159
|
+
padding-inline-start: 1.35em;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
html[data-maple-theme='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(li)::marker {
|
|
163
|
+
font-family: var(--ds-font-family-code);
|
|
164
|
+
color: var(--dsw-alias-state-business-primary);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
html[data-maple-theme='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(ul) > :where(li)::marker {
|
|
168
|
+
font-size: 0.85em;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
html[data-maple-theme='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(ul ul, ul ul ul ul, ul ul ul ul ul ul) {
|
|
172
|
+
list-style-type: circle;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
html[data-maple-theme='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(ul ul ul, ul ul ul ul ul) {
|
|
176
|
+
list-style-type: square;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
html[data-maple-theme='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(li) {
|
|
180
|
+
margin: 3px 0;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
html[data-maple-theme='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(input[type='checkbox']) {
|
|
184
|
+
accent-color: var(--dsw-alias-state-business-primary);
|
|
185
|
+
margin-inline-end: 8px;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/* 表格:Maple 的表头填一层浅底、外边圆角、横线只在行之间。
|
|
189
|
+
* 宿主用 border-collapse: collapse,圆角会被裁掉,所以改成 separate + 零间距,
|
|
190
|
+
* 只给四角的单元格上圆角。 */
|
|
191
|
+
html[data-maple-theme='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(table) {
|
|
192
|
+
border-collapse: separate;
|
|
193
|
+
border-spacing: 0;
|
|
194
|
+
font-size: calc(var(--dsh-content-font-size, 14px) - 1px);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
html[data-maple-theme='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(th) {
|
|
198
|
+
background: var(--maple-table-head);
|
|
199
|
+
font-weight: 600;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
html[data-maple-theme='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(thead > tr > th:first-child) {
|
|
203
|
+
border-start-start-radius: var(--dsw-radius-sm);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
html[data-maple-theme='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(thead > tr > th:last-child) {
|
|
207
|
+
border-start-end-radius: var(--dsw-radius-sm);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
html[data-maple-theme='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(tbody > tr:last-child > td:first-child) {
|
|
211
|
+
border-end-start-radius: var(--dsw-radius-sm);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
html[data-maple-theme='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(tbody > tr:last-child > td:last-child) {
|
|
215
|
+
border-end-end-radius: var(--dsw-radius-sm);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/* 分隔线:Maple 是一条两端淡出的渐变,不是一根等宽实线,上下留白也更大。 */
|
|
219
|
+
html[data-maple-theme='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(hr) {
|
|
220
|
+
height: 1px;
|
|
221
|
+
margin: 28px 0;
|
|
222
|
+
border: 0;
|
|
223
|
+
background: linear-gradient(
|
|
224
|
+
to right,
|
|
225
|
+
transparent 0%,
|
|
226
|
+
var(--dsw-alias-border-l3) 22%,
|
|
227
|
+
var(--dsw-alias-border-l4) 50%,
|
|
228
|
+
var(--dsw-alias-border-l3) 78%,
|
|
229
|
+
transparent 100%
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/* 代码块:Maple 给它一圈发丝边框、比宿主小一档的圆角,标题条用比正文深一档的底。
|
|
234
|
+
* 宿主把圆角收在一个局部变量里(--dsl-code-block-border-radius,默认 radius-lg),
|
|
235
|
+
* 所以换圆角只要换那个变量,不必去写各角的 border-radius。 */
|
|
236
|
+
html[data-maple-theme='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(.md-code-block) {
|
|
237
|
+
border: 0.5px solid var(--dsw-alias-border-l2);
|
|
238
|
+
--dsl-code-block-border-radius: var(--dsw-radius-md);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/* 标题条:Maple 的 code-language 用等宽字体、行内代码那个暖色,字号小一号。 */
|
|
242
|
+
html[data-maple-theme='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where([data-code-block-banner]) {
|
|
243
|
+
border-bottom: 0.5px solid var(--dsw-alias-border-l1);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
html[data-maple-theme='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where([data-code-block-banner]) :where(div:first-child) {
|
|
247
|
+
font-family: var(--ds-font-family-code);
|
|
248
|
+
letter-spacing: 0.02em;
|
|
249
|
+
color: var(--maple-inline-code);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/* 行号栏:Maple 的行号比宿主的再淡一档,让代码本身更突出。
|
|
253
|
+
* 宿主把行号画在 `.line::before` 上并直接取 --dsw-alias-label-tertiary,所以在行号容器里
|
|
254
|
+
* 把那个变量换成 caption 一档;`--dsl-*` 是组件自己的局部变量,不在这里改。 */
|
|
255
|
+
html[data-maple-theme='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where([data-line-numbers]) {
|
|
256
|
+
--dsw-alias-label-tertiary: var(--dsw-alias-label-caption);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/* 选中文字:Maple 用强调色的低透明度,不是浏览器的默认蓝。 */
|
|
260
|
+
html[data-maple-theme='on'] [data-chat-flow-kind='assistant-step'] ::selection {
|
|
261
|
+
background: hsl(35 60% 62% / 28%);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
html[data-maple-theme='on'] [data-chat-flow-kind='assistant-step']:not([data-chat-group-part='reasoning']) :where(h1, h2, h3, h4, h5, h6):first-child {
|
|
265
|
+
margin-top: 0;
|
|
266
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/* Maple 外壳层:侧栏、会话头部、输入区与标签条的观感。
|
|
2
|
+
*
|
|
3
|
+
* 锚点只有一样是稳的:`data-slot`。宿主的外壳类名全是 CSS Modules 的哈希串
|
|
4
|
+
* (`pI_x6G_sidebarCol`、`wSkVaW_tabActive`),换一次构建就变;而 `data-slot` 是座位注册时
|
|
5
|
+
* 写死的名字,属于跨包契约——插件的座位就是靠它认的。需要选中「装座位的那个壳」时用
|
|
6
|
+
* `:has(> [data-slot='…'])`:壳没有名字,但它的孩子有。行与标签另有具体属性:
|
|
7
|
+
* `[data-row-key^='session:']`、`[data-conversation-tabs] [aria-selected]`。
|
|
8
|
+
*
|
|
9
|
+
* 这一层只改**观感**:底色、分隔线、圆角、留白。唯独中央列那一圈内边距算是尺寸——
|
|
10
|
+
* 它是 Maple 卡片式布局的外沿,值固定在 6px,不参与宿主的任何计算。
|
|
11
|
+
* 不动 grid 轨道、不动滚动归属,所以折叠、拖宽、响应式都照旧。
|
|
12
|
+
*
|
|
13
|
+
* 整层受 `data-maple-shell` 开关控制,配置页上可以整个关掉回到宿主原样。
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/* 中央列:Maple 的 app-layout-card 把编辑区当成一张浮在侧栏底色上的卡片,
|
|
17
|
+
* 四周留一条窄缝(它的 --app-layout-spacing 默认在 6~8px)。这里照同样思路,
|
|
18
|
+
* 但只给内边距,不动 grid 轨道——轨道由宿主按拖宽实时写行内样式。 */
|
|
19
|
+
html[data-maple-theme='on'][data-maple-shell='on'] body :has(> [data-slot='main']) {
|
|
20
|
+
padding: 6px 6px 0;
|
|
21
|
+
box-sizing: border-box;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/* 侧栏与中央卡片之间:宿主的 0.5px 冷灰分隔线,Maple 用留白分层,不要这条线。
|
|
25
|
+
* 两侧都要撤——非 darwin 画在侧栏的右边框上,darwin 画在中央列的左边框上。
|
|
26
|
+
* 侧栏底色已由 tokens.css 的 --dsw-specific-sidebar-fill 给出(Maple 的暖灰)。 */
|
|
27
|
+
html[data-maple-theme='on'][data-maple-shell='on'] body :has(> [data-slot='sidebar']) {
|
|
28
|
+
border-right: 0;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
html[data-maple-theme='on'][data-maple-shell='on'] body :has(> [data-slot='main']) {
|
|
32
|
+
border-left: 0;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* 会话头部:Maple 的标题区没有那条贯穿的分隔线。
|
|
36
|
+
* 座位锚点自己是 display: contents,边框画在它包着的真 <header> 上,
|
|
37
|
+
* 所以这里往下一层找;改成 transparent 而不是 none,避免高度跳 0.5px。 */
|
|
38
|
+
html[data-maple-theme='on'][data-maple-shell='on'] body [data-slot='conversation.header'] header {
|
|
39
|
+
border-bottom-color: transparent;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* 标签条:Maple 的 tab-float 把活动标签做成一枚浮起的圆角块,底下不带指示条。
|
|
43
|
+
* 宿主的活动指示是 `::after` 的一条 2px 线,这里撤掉它、改用同宽的圆角底。
|
|
44
|
+
* 圆角与 corner-shape 必须写在同一组声明里,否则宿主的 superellipse 会把
|
|
45
|
+
* 这个直角圆角揉成方圆形。 */
|
|
46
|
+
html[data-maple-theme='on'][data-maple-shell='on'] body [data-conversation-tabs] [aria-selected='true'] {
|
|
47
|
+
border-radius: var(--dsw-radius-sm);
|
|
48
|
+
corner-shape: round;
|
|
49
|
+
background: var(--dsw-alias-interactive-bg-hover-solid);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
html[data-maple-theme='on'][data-maple-shell='on'] body [data-conversation-tabs] [aria-selected='true']::after {
|
|
53
|
+
opacity: 0;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/* 输入区:Maple 的输入卡是「比正文浅一档的纸」,圆角取面板级。
|
|
57
|
+
* 宿主的 composer 已经是 border: 0 + elevation-soft(投影层只换填充与圆角,不碰阴影)。 */
|
|
58
|
+
html[data-maple-theme='on'][data-maple-shell='on'] body [data-composer-card] {
|
|
59
|
+
background: var(--dsw-specific-input-major);
|
|
60
|
+
border-radius: var(--dsw-radius-panel);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/* 侧栏的导航行与工作区行:Maple 的列表项带圆角,悬停与选中都是圆角块。 */
|
|
64
|
+
html[data-maple-theme='on'][data-maple-shell='on'] body [data-row-key^='session:'],
|
|
65
|
+
html[data-maple-theme='on'][data-maple-shell='on'] body [data-row-key^='workspace:'] {
|
|
66
|
+
border-radius: var(--dsw-radius-sm);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/* 侧栏底部工具栏:宿主的冷灰浮层,换成 Maple 的纸色。
|
|
70
|
+
* 座位锚点是 display: contents,涂在它不会见效,得涂装它的那个壳。 */
|
|
71
|
+
html[data-maple-theme='on'][data-maple-shell='on'] body :has(> [data-slot='shell.bottom']) {
|
|
72
|
+
background: var(--dsw-specific-tip);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/* 会话头部的图标按钮:Maple 的图标按钮是紧凑控件级圆角。 */
|
|
76
|
+
html[data-maple-theme='on'][data-maple-shell='on'] body [data-slot='conversation.session.header.actions'] button {
|
|
77
|
+
border-radius: var(--dsw-radius-sm);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/* 滚动条:Maple 的滑块宽 12px、圆头,颜色取它的暖灰(tokens.css 已换)。 */
|
|
81
|
+
html[data-maple-theme='on'][data-maple-shell='on'] body {
|
|
82
|
+
--dsh-scrollbar-width: 12px;
|
|
83
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/* Maple 装饰层:标题配色、代码语法色、正文排版。
|
|
2
|
+
*
|
|
3
|
+
* 配色令牌本身不在这里——它们走宿主的主题通道(src/client/tokens.ts +
|
|
4
|
+
* ctx.theme.overrideTokens),由宿主写到 body 的行内样式上。这里只剩三类:
|
|
5
|
+
* 按开关切换的标题配色、shiki 语法色、以及正文排版的复合令牌。
|
|
6
|
+
*
|
|
7
|
+
* 每一条都挂在 `html[data-maple-theme='on']` 与它自己的开关属性下面:
|
|
8
|
+
* 关掉时整段不匹配,不必跟宿主争优先级。
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/* 标题六色:Maple 默认的 colorful,逐级换色。浅色那一列按 4.5:1 调过明度,
|
|
12
|
+
* 深色用它自己那套提亮色。 */
|
|
13
|
+
html[data-maple-theme='on'][data-maple-heading='colorful'] {
|
|
14
|
+
--maple-h1: hsl(0 45% 52.5%);
|
|
15
|
+
--maple-h2: hsl(32 70% 37%);
|
|
16
|
+
--maple-h3: hsl(95 75% 29%);
|
|
17
|
+
--maple-h4: hsl(193 94% 31.5%);
|
|
18
|
+
--maple-h5: hsl(260 20% 48%);
|
|
19
|
+
--maple-h6: hsl(156 75% 28%);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
html[data-maple-theme='on'][data-maple-heading='colorful'] body[data-ds-dark-theme] {
|
|
23
|
+
--maple-h1: hsl(0 44% 68%);
|
|
24
|
+
--maple-h2: hsl(20 40% 68%);
|
|
25
|
+
--maple-h3: hsl(130 32% 68%);
|
|
26
|
+
--maple-h4: hsl(210 80% 72%);
|
|
27
|
+
--maple-h5: hsl(247 65% 82%);
|
|
28
|
+
--maple-h6: hsl(178 40% 64%);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/* 强调色一档:六级标题统一用主题的强调色,不分级换色。
|
|
32
|
+
* 这是 Maple 的「标题颜色 = 强调色」分支,与本主题既有的强调色取同一个值。 */
|
|
33
|
+
html[data-maple-theme='on'][data-maple-heading='accent'] {
|
|
34
|
+
--maple-heading-color: hsl(35 26% 38%);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/* 正文色一档:标题只靠字号与字重区分,颜色跟正文一致。 */
|
|
38
|
+
html[data-maple-theme='on'][data-maple-heading='text'] {
|
|
39
|
+
--maple-heading-color: hsl(var(--maple-hue-light, 35) 10% 18%);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
html[data-maple-theme='on'][data-maple-heading='accent'] body[data-ds-dark-theme] {
|
|
43
|
+
--maple-heading-color: hsl(207 26% 72%);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
html[data-maple-theme='on'][data-maple-heading='text'] body[data-ds-dark-theme] {
|
|
47
|
+
--maple-heading-color: hsl(var(--maple-hue-dark, 207) 24% 88%);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* 代码语法色:Maple 的 prism 调色板落到宿主的 shiki 变量上。
|
|
51
|
+
* 宿主 CodeBlock 只认 --shiki-token-*,换这一组就整体换配色。 */
|
|
52
|
+
html[data-maple-theme='on'][data-maple-code='on'] {
|
|
53
|
+
--shiki-token-keyword: hsl(260 20% 48%);
|
|
54
|
+
--shiki-token-string: hsl(95 75% 29%);
|
|
55
|
+
--shiki-token-string-expression: hsl(95 75% 29%);
|
|
56
|
+
--shiki-token-function: hsl(193 94% 31.5%);
|
|
57
|
+
--shiki-token-constant: hsl(156 75% 28%);
|
|
58
|
+
--shiki-token-parameter: hsl(32 70% 37%);
|
|
59
|
+
--shiki-token-comment: hsl(35 6% 58%);
|
|
60
|
+
--shiki-token-punctuation: hsl(35 7% 46%);
|
|
61
|
+
--shiki-token-link: hsl(162 76% 29%);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
html[data-maple-theme='on'][data-maple-code='on'] body[data-ds-dark-theme] {
|
|
65
|
+
--shiki-token-keyword: hsl(247 65% 82%);
|
|
66
|
+
--shiki-token-string: hsl(130 32% 68%);
|
|
67
|
+
--shiki-token-string-expression: hsl(130 32% 68%);
|
|
68
|
+
--shiki-token-function: hsl(210 80% 72%);
|
|
69
|
+
--shiki-token-constant: hsl(178 40% 64%);
|
|
70
|
+
--shiki-token-parameter: hsl(20 40% 68%);
|
|
71
|
+
--shiki-token-comment: hsl(207 10% 46%);
|
|
72
|
+
--shiki-token-punctuation: hsl(207 12% 58%);
|
|
73
|
+
--shiki-token-link: hsl(178 30% 62%);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/* 正文排版:MarkdownText 用 `font: var(--dsw-font-markdown-*)` 一次取字号、行高与字族,
|
|
77
|
+
* 所以改这几条就够,不必碰 CSS Modules 的哈希类名。
|
|
78
|
+
*
|
|
79
|
+
* 行高从宿主的字号轴推,不写死像素:宿主把正文行高写成「24px + 字号增量」,
|
|
80
|
+
* 这里改成「字号 × 配置的行高倍数」——两个轴同时生效,用户调大字号时行高跟着长。
|
|
81
|
+
*
|
|
82
|
+
* h5 / h6 宿主归并进 base-strong,没有独立令牌,由 markdown.css 用元素选择器补。 */
|
|
83
|
+
html[data-maple-theme='on'] body {
|
|
84
|
+
--dsw-font-markdown-base:
|
|
85
|
+
var(--dsh-content-font-size, 14px) / calc(var(--dsh-content-font-size, 14px) * var(--maple-line-height, 1.75))
|
|
86
|
+
var(--dsw-font-family);
|
|
87
|
+
--dsw-font-markdown-base-font-size: var(--dsh-content-font-size, 14px);
|
|
88
|
+
--dsw-font-markdown-base-line-height: calc(var(--dsh-content-font-size, 14px) * var(--maple-line-height, 1.75));
|
|
89
|
+
|
|
90
|
+
--dsw-font-markdown-base-strong:
|
|
91
|
+
600 var(--dsh-content-font-size, 14px) / calc(var(--dsh-content-font-size, 14px) * var(--maple-line-height, 1.75))
|
|
92
|
+
var(--dsw-font-family);
|
|
93
|
+
--dsw-font-markdown-base-strong-font-size: var(--dsh-content-font-size, 14px);
|
|
94
|
+
--dsw-font-markdown-base-strong-line-height: calc(var(--dsh-content-font-size, 14px) * var(--maple-line-height, 1.75));
|
|
95
|
+
|
|
96
|
+
--dsw-font-markdown-h1:
|
|
97
|
+
700 calc(var(--dsh-content-font-size, 14px) * 1.6) / 1.3 var(--dsw-font-family);
|
|
98
|
+
--dsw-font-markdown-h1-font-size: calc(var(--dsh-content-font-size, 14px) * 1.6);
|
|
99
|
+
--dsw-font-markdown-h1-font-weight: 700;
|
|
100
|
+
--dsw-font-markdown-h1-line-height: 1.3;
|
|
101
|
+
|
|
102
|
+
--dsw-font-markdown-h2:
|
|
103
|
+
700 calc(var(--dsh-content-font-size, 14px) * 1.5) / 1.3 var(--dsw-font-family);
|
|
104
|
+
--dsw-font-markdown-h2-font-size: calc(var(--dsh-content-font-size, 14px) * 1.5);
|
|
105
|
+
--dsw-font-markdown-h2-font-weight: 700;
|
|
106
|
+
--dsw-font-markdown-h2-line-height: 1.3;
|
|
107
|
+
|
|
108
|
+
--dsw-font-markdown-h3:
|
|
109
|
+
600 calc(var(--dsh-content-font-size, 14px) * 1.35) / 1.35 var(--dsw-font-family);
|
|
110
|
+
--dsw-font-markdown-h3-font-size: calc(var(--dsh-content-font-size, 14px) * 1.35);
|
|
111
|
+
--dsw-font-markdown-h3-font-weight: 600;
|
|
112
|
+
--dsw-font-markdown-h3-line-height: 1.35;
|
|
113
|
+
|
|
114
|
+
--dsw-font-markdown-h4:
|
|
115
|
+
600 calc(var(--dsh-content-font-size, 14px) * 1.15) / 1.4 var(--dsw-font-family);
|
|
116
|
+
--dsw-font-markdown-h4-font-size: calc(var(--dsh-content-font-size, 14px) * 1.15);
|
|
117
|
+
--dsw-font-markdown-h4-font-weight: 600;
|
|
118
|
+
--dsw-font-markdown-h4-line-height: 1.4;
|
|
119
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maple 两套调色板的令牌表:`--dsw-*` 名字 → 浅色 / 深色各一个值。
|
|
3
|
+
*
|
|
4
|
+
* 值里允许出现 `var(--maple-hue-light, 35)` 这类引用:宿主把这份表写到 `body` 的
|
|
5
|
+
* 行内样式上,色相变量写在 `<html>` 上,行内样式按继承链解析得到,所以整套色板
|
|
6
|
+
* 仍然由一个数字转动,而令牌本身走宿主的主题通道(不是另立一份全局主题)。
|
|
7
|
+
*
|
|
8
|
+
* 与 Maple 原版的偏差都在 `DETAILS.md`「与 Maple 原版的偏差」里写明;
|
|
9
|
+
* 对比度由 scripts/test-tokens.mjs 读这份表自己算。
|
|
10
|
+
*/
|
|
11
|
+
/** 一条令牌在浅色与深色下各一个值;与宿主 `ThemeTokenOverrides` 的结构一致。 */
|
|
12
|
+
export type ThemeTokenOverrides = Record<string, { light: string; dark: string }>;
|
|
13
|
+
|
|
14
|
+
/** 本插件在主题通道里的来源名,与包名一致,便于在宿主里认出是谁改的。 */
|
|
15
|
+
export const THEME_SOURCE = '@lynn123411/dsh-maple-theme';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* 两套色板。浅色取 Maple 的暖白(基础色相 35°)、深色取冷灰(207°)。
|
|
19
|
+
* 令牌名与宿主 `design-platform.css` 一致,换的是值,不是名字。
|
|
20
|
+
*/
|
|
21
|
+
export const MAPLE_TOKENS = {
|
|
22
|
+
'--dsw-alias-bg-base': { light: 'hsl(var(--maple-hue-light, 35) 12% 97%)', dark: 'hsl(var(--maple-hue-dark, 207) 6% 11%)' },
|
|
23
|
+
'--dsw-alias-bg-layer-1': { light: 'hsl(var(--maple-hue-light, 35) 10% 95%)', dark: 'hsl(var(--maple-hue-dark, 207) 10% 13%)' },
|
|
24
|
+
'--dsw-alias-bg-layer-2': { light: 'hsl(calc(var(--maple-hue-light, 35) - 18) 8% 93%)', dark: 'hsl(calc(var(--maple-hue-dark, 207) - 8) 6% 12%)' },
|
|
25
|
+
'--dsw-alias-bg-overlay': { light: 'hsl(var(--maple-hue-light, 35) 10% 94%)', dark: 'hsl(var(--maple-hue-dark, 207) 8% 14%)' },
|
|
26
|
+
'--dsw-alias-bg-module-platform': { light: 'hsl(var(--maple-hue-light, 35) 13.2% 90.6%)', dark: 'hsl(var(--maple-hue-dark, 207) 12% 12.4%)' },
|
|
27
|
+
'--dsw-alias-label-primary': { light: 'hsl(var(--maple-hue-light, 35) 10% 18%)', dark: 'hsl(var(--maple-hue-dark, 207) 24% 88%)' },
|
|
28
|
+
'--dsw-alias-label-secondary': { light: 'hsl(var(--maple-hue-light, 35) 8% 35%)', dark: 'hsl(var(--maple-hue-dark, 207) 16% 72%)' },
|
|
29
|
+
'--dsw-alias-label-tertiary': { light: 'hsl(var(--maple-hue-light, 35) 7% 42%)', dark: 'hsl(var(--maple-hue-dark, 207) 12% 58%)' },
|
|
30
|
+
'--dsw-alias-label-caption': { light: 'hsl(var(--maple-hue-light, 35) 6% 50%)', dark: 'hsl(var(--maple-hue-dark, 207) 10% 46%)' },
|
|
31
|
+
'--dsw-alias-label-dimmed': { light: 'hsl(var(--maple-hue-light, 35) 8% 82%)', dark: 'hsl(var(--maple-hue-dark, 207) 8% 26%)' },
|
|
32
|
+
'--dsw-alias-label-primary-dimmed': { light: 'hsl(var(--maple-hue-light, 35) 9% 27%)', dark: 'hsl(var(--maple-hue-dark, 207) 18% 80%)' },
|
|
33
|
+
'--dsw-alias-label-primary-bluish': { light: 'hsl(var(--maple-hue-light, 35) 26% 38%)', dark: 'hsl(var(--maple-hue-dark, 207) 26% 72%)' },
|
|
34
|
+
'--dsw-alias-label-primary-foreground': { light: 'hsl(var(--maple-hue-light, 35) 40% 96%)', dark: 'hsl(var(--maple-hue-dark, 207) 10% 9%)' },
|
|
35
|
+
'--dsw-alias-label-primary-inverted': { light: 'hsl(var(--maple-hue-light, 35) 40% 96%)', dark: 'hsl(var(--maple-hue-dark, 207) 10% 13%)' },
|
|
36
|
+
'--dsw-alias-label-shimmer': { light: 'hsl(var(--maple-hue-light, 35) 10% 18% / 30%)', dark: 'hsl(0 0% 100% / 45%)' },
|
|
37
|
+
'--dsw-alias-link': { light: 'hsl(162 76% 29%)', dark: 'hsl(178 30% 62%)' },
|
|
38
|
+
'--dsw-alias-brand-primary': { light: 'hsl(var(--maple-hue-light, 35) 26% 38%)', dark: 'hsl(var(--maple-hue-dark, 207) 26% 72%)' },
|
|
39
|
+
'--dsw-alias-brand-text': { light: 'hsl(var(--maple-hue-light, 35) 10% 18%)', dark: 'hsl(var(--maple-hue-dark, 207) 24% 88%)' },
|
|
40
|
+
'--dsw-alias-state-business-primary': { light: 'hsl(var(--maple-hue-light, 35) 26% 38%)', dark: 'hsl(var(--maple-hue-dark, 207) 26% 72%)' },
|
|
41
|
+
'--dsw-alias-state-business-tertiary': { light: 'hsl(var(--maple-hue-light, 35) 40% 88%)', dark: 'hsl(var(--maple-hue-dark, 207) 18% 22%)' },
|
|
42
|
+
'--dsw-alias-state-error-primary': { light: 'hsl(0 45% 48%)', dark: 'hsl(0 44% 68%)' },
|
|
43
|
+
'--dsw-alias-state-warn-primary': { light: 'hsl(32 70% 37%)', dark: 'hsl(20 40% 68%)' },
|
|
44
|
+
'--dsw-alias-state-success-primary': { light: 'hsl(95 75% 29%)', dark: 'hsl(130 32% 68%)' },
|
|
45
|
+
'--dsw-alias-border-l1': { light: 'hsl(var(--maple-hue-light, 35) 26% 38% / 10%)', dark: 'hsl(var(--maple-hue-dark, 207) 24% 88% / 7%)' },
|
|
46
|
+
'--dsw-alias-border-l2': { light: 'hsl(var(--maple-hue-light, 35) 26% 38% / 16%)', dark: 'hsl(var(--maple-hue-dark, 207) 24% 88% / 13%)' },
|
|
47
|
+
'--dsw-alias-border-l3': { light: 'hsl(var(--maple-hue-light, 35) 26% 38% / 20%)', dark: 'hsl(var(--maple-hue-dark, 207) 24% 88% / 17%)' },
|
|
48
|
+
'--dsw-alias-border-l4': { light: 'hsl(var(--maple-hue-light, 35) 26% 38% / 26%)', dark: 'hsl(var(--maple-hue-dark, 207) 24% 88% / 22%)' },
|
|
49
|
+
'--dsw-alias-separator-primary': { light: 'hsl(var(--maple-hue-light, 35) 26% 38% / 16%)', dark: 'hsl(var(--maple-hue-dark, 207) 24% 88% / 13%)' },
|
|
50
|
+
'--dsw-alias-interactive-bg-hover': { light: 'hsl(var(--maple-hue-light, 35) 26% 38% / 7%)', dark: 'hsl(var(--maple-hue-dark, 207) 24% 88% / 8%)' },
|
|
51
|
+
'--dsw-alias-interactive-bg-active': { light: 'hsl(var(--maple-hue-light, 35) 26% 38% / 12%)', dark: 'hsl(var(--maple-hue-dark, 207) 24% 88% / 14%)' },
|
|
52
|
+
'--dsw-alias-interactive-bg-hover-solid': { light: 'hsl(var(--maple-hue-light, 35) 12% 93%)', dark: 'hsl(var(--maple-hue-dark, 207) 14% 16%)' },
|
|
53
|
+
'--dsw-alias-button-info-fill': { light: 'hsl(162 62% 30%)', dark: 'hsl(178 34% 34%)' },
|
|
54
|
+
'--dsw-alias-button-info-hover': { light: 'hsl(162 62% 24%)', dark: 'hsl(178 34% 42%)' },
|
|
55
|
+
'--dsw-alias-brand-primary-new-colorprimary-new-color': { light: 'hsl(var(--maple-hue-light, 35) 30% 42%)', dark: 'hsl(var(--maple-hue-dark, 207) 30% 66%)' },
|
|
56
|
+
'--dsw-alias-button-primary-fill': { light: 'hsl(var(--maple-hue-light, 35) 30% 42%)', dark: 'hsl(var(--maple-hue-dark, 207) 30% 66%)' },
|
|
57
|
+
'--dsw-alias-button-primary-hover': { light: 'hsl(var(--maple-hue-light, 35) 32% 34%)', dark: 'hsl(var(--maple-hue-dark, 207) 32% 76%)' },
|
|
58
|
+
'--dsw-alias-button-floating-fill': { light: 'hsl(var(--maple-hue-light, 35) 14% 98.5%)', dark: 'hsl(var(--maple-hue-dark, 207) 8% 15%)' },
|
|
59
|
+
'--dsw-alias-button-floating-hover': { light: 'hsl(var(--maple-hue-light, 35) 10% 95%)', dark: 'hsl(var(--maple-hue-dark, 207) 14% 19%)' },
|
|
60
|
+
'--dsw-alias-markdown-code-block': { light: 'hsl(var(--maple-hue-light, 35) 10% 95%)', dark: 'hsl(var(--maple-hue-dark, 207) 10% 13%)' },
|
|
61
|
+
'--dsw-alias-markdown-code-block-banner': { light: 'hsl(var(--maple-hue-light, 35) 13.2% 90.6%)', dark: 'hsl(var(--maple-hue-dark, 207) 8% 15%)' },
|
|
62
|
+
'--dsw-alias-markdown-inline-code': { light: 'hsl(var(--maple-hue-light, 35) 14% 94%)', dark: 'hsl(var(--maple-hue-dark, 207) 8% 15%)' },
|
|
63
|
+
'--dsw-alias-markdown-tag': { light: 'hsl(var(--maple-hue-light, 35) 40% 88%)', dark: 'hsl(var(--maple-hue-dark, 207) 14% 20%)' },
|
|
64
|
+
'--dsw-alias-markdown-citation': { light: 'hsl(var(--maple-hue-light, 35) 10% 94%)', dark: 'hsl(var(--maple-hue-dark, 207) 8% 14%)' },
|
|
65
|
+
'--dsw-alias-scrollbar-bg-l1': { light: 'hsl(var(--maple-hue-light, 35) 14% 84%)', dark: 'hsl(var(--maple-hue-dark, 207) 10% 25%)' },
|
|
66
|
+
'--dsw-alias-scrollbar-bg-l2': { light: 'hsl(var(--maple-hue-light, 35) 20% 78%)', dark: 'hsl(var(--maple-hue-dark, 207) 12% 32%)' },
|
|
67
|
+
'--dsw-alias-scrollbar-hover-l2': { light: 'hsl(var(--maple-hue-light, 35) 18% 71%)', dark: 'hsl(var(--maple-hue-dark, 207) 10% 39%)' },
|
|
68
|
+
'--dsw-alias-menu-icon': { light: 'hsl(var(--maple-hue-light, 35) 8% 35%)', dark: 'hsl(var(--maple-hue-dark, 207) 18% 80%)' },
|
|
69
|
+
'--dsw-specific-sidebar-fill': { light: 'hsl(calc(var(--maple-hue-light, 35) - 18) 8% 93%)', dark: 'hsl(calc(var(--maple-hue-dark, 207) - 8) 6% 12%)' },
|
|
70
|
+
'--dsw-specific-sidebar-nav-item-active': { light: 'hsl(var(--maple-hue-light, 35) 26% 88%)', dark: 'hsl(var(--maple-hue-dark, 207) 14% 19%)' },
|
|
71
|
+
'--dsw-specific-sidebar-nav-item-hover': { light: 'hsl(var(--maple-hue-light, 35) 26% 38% / 8%)', dark: 'hsl(var(--maple-hue-dark, 207) 24% 88% / 8%)' },
|
|
72
|
+
'--dsw-specific-sidebar-nav-item-active-accent': { light: 'hsl(var(--maple-hue-light, 35) 40% 84%)', dark: 'hsl(var(--maple-hue-dark, 207) 18% 24%)' },
|
|
73
|
+
'--dsw-specific-tip': { light: 'hsl(var(--maple-hue-light, 35) 18% 90%)', dark: 'hsl(var(--maple-hue-dark, 207) 12% 18%)' },
|
|
74
|
+
'--dsw-specific-bubble': { light: 'hsl(var(--maple-hue-light, 35) 24% 93%)', dark: 'hsl(var(--maple-hue-dark, 207) 14% 19%)' },
|
|
75
|
+
'--dsw-specific-bubble-highlight': { light: 'hsl(var(--maple-hue-light, 35) 30% 87%)', dark: 'hsl(var(--maple-hue-dark, 207) 16% 24%)' },
|
|
76
|
+
'--dsw-specific-input-major': { light: 'hsl(var(--maple-hue-light, 35) 14% 98.5%)', dark: 'hsl(var(--maple-hue-dark, 207) 8% 15%)' },
|
|
77
|
+
'--dsw-specific-selector': { light: 'hsl(var(--maple-hue-light, 35) 14% 94%)', dark: 'hsl(var(--maple-hue-dark, 207) 14% 19%)' },
|
|
78
|
+
} satisfies ThemeTokenOverrides;
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import z from '@deepseek-ai/schemastery';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* `@lynn123411/dsh-maple-theme` —— 把 Maple 的配色与聊天正文排版带进 DSH。
|
|
5
|
+
*
|
|
6
|
+
* 宿主半边只声明这份配置的形状:界面全部由浏览器半边画(注入样式表 + 插件页上的配置卡片),
|
|
7
|
+
* 这里不碰任何界面,也不注册工具。配置项落进本插件那一行的 config,浏览器半边经
|
|
8
|
+
* `ctx.configForms.get('dsh-maple-theme')` 读写同一份值。
|
|
9
|
+
*
|
|
10
|
+
* 每个字段都标 `volatile()`:改一个开关不该重挂整条 loader entry,浏览器半边收到通知后
|
|
11
|
+
* 自己改 <html> 上的属性与变量,样式表不重建。
|
|
12
|
+
*/
|
|
13
|
+
export const name = 'dsh-maple-theme';
|
|
14
|
+
|
|
15
|
+
/** 只需要 settings 服务:它承载这一行的配置,也是「不自动生成设置页」那条策略的入口。 */
|
|
16
|
+
export const inject = ['settings'];
|
|
17
|
+
|
|
18
|
+
/** 标题配色的三种取材方式。 */
|
|
19
|
+
export const HEADING_MODES = ['colorful', 'accent', 'text'] as const;
|
|
20
|
+
|
|
21
|
+
/** 标题配色:六色依次换 / 全用强调色 / 全用正文色。 */
|
|
22
|
+
export type HeadingMode = typeof HEADING_MODES[number];
|
|
23
|
+
|
|
24
|
+
/** 本插件在 profile 里的 loader 行 id,同时是设置的命名空间。 */
|
|
25
|
+
export const SETTINGS_NAMESPACE = name;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 配置的形状与默认值。色相取 Maple 自己的出厂值(浅色 35、深色 207)。
|
|
29
|
+
* 行高与段落间距比 Maple 的 1.8 / 8px 松一档:对话正文的行宽比笔记窄,
|
|
30
|
+
* 按笔记的行距排会显得稀,所以这里收紧行距、放大段距。
|
|
31
|
+
*/
|
|
32
|
+
export const Config = z.object({
|
|
33
|
+
/** 浅色基础色相(度):整套浅色从它推导。 */
|
|
34
|
+
hueLight: z.number().step(1).min(0).max(360).default(35).volatile(),
|
|
35
|
+
/** 深色基础色相(度)。 */
|
|
36
|
+
hueDark: z.number().step(1).min(0).max(360).default(207).volatile(),
|
|
37
|
+
/** 正文行高倍数(Maple 的出厂值是 1.8,对话正文取 1.75)。 */
|
|
38
|
+
lineHeight: z.number().step(0.05).min(1.4).max(2).default(1.75).volatile(),
|
|
39
|
+
/** 段落间距(px;Maple 的出厂值是 8,对话正文取 10)。 */
|
|
40
|
+
paragraphGap: z.number().step(1).min(4).max(24).default(10).volatile(),
|
|
41
|
+
/** 标题配色方式。 */
|
|
42
|
+
headingColor: z.union([...HEADING_MODES]).default('colorful').volatile(),
|
|
43
|
+
/** 悬停时在标题左侧显示 H1…H6 等级标记。 */
|
|
44
|
+
headingIndicator: z.boolean().default(true).volatile(),
|
|
45
|
+
/** 代码块使用 Maple 的语法配色。 */
|
|
46
|
+
codePalette: z.boolean().default(true).volatile(),
|
|
47
|
+
/** 外壳装饰:侧栏与标签条的圆角、输入卡填充、去掉会话头部那条分隔线。 */
|
|
48
|
+
shellSkin: z.boolean().default(true).volatile(),
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
/** 宿主上下文里本插件用到的那两个成员。 */
|
|
52
|
+
interface HostContext {
|
|
53
|
+
fiber: unknown;
|
|
54
|
+
settings: {
|
|
55
|
+
/** 登记这一行在设置页上的自动生成策略;`auto: false` 表示不生成。 */
|
|
56
|
+
configure(presentation: { auto?: boolean }, owner?: unknown): () => void;
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* 插件本体:声明本行的设置页策略。
|
|
62
|
+
*
|
|
63
|
+
* 配置界面在宿主「插件」页上(浏览器半边注册 `plugins.bundle.config`),
|
|
64
|
+
* 所以这里要显式关掉内核按 Config schema 自动生成的设置页,否则同一批字段会出现两次。
|
|
65
|
+
* @param ctx - 宿主插件上下文。
|
|
66
|
+
*/
|
|
67
|
+
export function apply(ctx: HostContext): void {
|
|
68
|
+
ctx.settings.configure({ auto: false }, ctx.fiber);
|
|
69
|
+
}
|