@stylewx/theme 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/dist/compiler.d.ts +25 -0
- package/dist/compiler.d.ts.map +1 -0
- package/dist/compiler.js +64 -0
- package/dist/compiler.js.map +1 -0
- package/dist/css-whitelist.d.ts +73 -0
- package/dist/css-whitelist.d.ts.map +1 -0
- package/dist/css-whitelist.js +269 -0
- package/dist/css-whitelist.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/presets.d.ts +10 -0
- package/dist/presets.d.ts.map +1 -0
- package/dist/presets.js +280 -0
- package/dist/presets.js.map +1 -0
- package/dist/schema.d.ts +75 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +93 -0
- package/dist/schema.js.map +1 -0
- package/dist/theme.test.d.ts +2 -0
- package/dist/theme.test.d.ts.map +1 -0
- package/dist/theme.test.js +163 -0
- package/dist/theme.test.js.map +1 -0
- package/dist/tokens.d.ts +20 -0
- package/dist/tokens.d.ts.map +1 -0
- package/dist/tokens.js +46 -0
- package/dist/tokens.js.map +1 -0
- package/dist/validate.d.ts +16 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +17 -0
- package/dist/validate.js.map +1 -0
- package/dist/wemd-presets.d.ts +8 -0
- package/dist/wemd-presets.d.ts.map +1 -0
- package/dist/wemd-presets.js +2369 -0
- package/dist/wemd-presets.js.map +1 -0
- package/package.json +31 -0
package/dist/presets.js
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 预置主题。
|
|
3
|
+
* 每个主题通过 tokens 定义配色/字体/间距,blocks 尽量使用 `{{token}}` 引用以保持一致性。
|
|
4
|
+
* description 面向「选主题的 Agent」,务必写清楚风格与适用场景。
|
|
5
|
+
*/
|
|
6
|
+
import { WEMD_THEMES } from './wemd-presets.js';
|
|
7
|
+
/** 生成一组默认 block,可传入覆盖项做定制。 */
|
|
8
|
+
function defaultBlocks(p, overrides) {
|
|
9
|
+
const base = {
|
|
10
|
+
h1: {
|
|
11
|
+
color: '{{primaryColor}}',
|
|
12
|
+
'font-size': '1.6em',
|
|
13
|
+
'font-weight': '600',
|
|
14
|
+
'line-height': '1.35',
|
|
15
|
+
'margin': `0 0 {{spacing.block}}`,
|
|
16
|
+
},
|
|
17
|
+
h2: {
|
|
18
|
+
color: '{{primaryColor}}',
|
|
19
|
+
'font-size': '1.35em',
|
|
20
|
+
'font-weight': '600',
|
|
21
|
+
'line-height': '1.4',
|
|
22
|
+
'margin': `0 0 {{spacing.block}}`,
|
|
23
|
+
},
|
|
24
|
+
h3: {
|
|
25
|
+
color: '{{primaryColor}}',
|
|
26
|
+
'font-size': '1.15em',
|
|
27
|
+
'font-weight': '600',
|
|
28
|
+
'line-height': '1.4',
|
|
29
|
+
'margin': `0 0 {{spacing.block}}`,
|
|
30
|
+
},
|
|
31
|
+
p: {
|
|
32
|
+
color: '{{textColor}}',
|
|
33
|
+
'font-size': '{{fontSize}}',
|
|
34
|
+
'line-height': '{{lineHeight}}',
|
|
35
|
+
'margin': `0 0 {{spacing.block}}`,
|
|
36
|
+
},
|
|
37
|
+
blockquote: {
|
|
38
|
+
'border-left': `4px solid {{primaryColor}}`,
|
|
39
|
+
'background-color': p.blockquoteBg,
|
|
40
|
+
color: p.blockquoteColor,
|
|
41
|
+
padding: '12px 16px',
|
|
42
|
+
margin: `0 0 {{spacing.block}}`,
|
|
43
|
+
'border-radius': '4px',
|
|
44
|
+
},
|
|
45
|
+
ul: {
|
|
46
|
+
'padding-left': '1.4em',
|
|
47
|
+
margin: `0 0 {{spacing.block}}`,
|
|
48
|
+
'list-style': 'disc',
|
|
49
|
+
},
|
|
50
|
+
ol: {
|
|
51
|
+
'padding-left': '1.4em',
|
|
52
|
+
margin: `0 0 {{spacing.block}}`,
|
|
53
|
+
},
|
|
54
|
+
li: {
|
|
55
|
+
'line-height': '{{lineHeight}}',
|
|
56
|
+
margin: '0 0 6px',
|
|
57
|
+
},
|
|
58
|
+
code: {
|
|
59
|
+
'font-family': 'Menlo, Consolas, "Courier New", monospace',
|
|
60
|
+
'font-size': '0.9em',
|
|
61
|
+
'background-color': p.codeBg,
|
|
62
|
+
color: p.codeColor,
|
|
63
|
+
padding: '2px 5px',
|
|
64
|
+
'border-radius': '4px',
|
|
65
|
+
},
|
|
66
|
+
pre: {
|
|
67
|
+
'background-color': p.codeBg,
|
|
68
|
+
padding: '16px',
|
|
69
|
+
'border-radius': '6px',
|
|
70
|
+
'overflow-x': 'auto',
|
|
71
|
+
'font-size': '0.88em',
|
|
72
|
+
'line-height': '1.6',
|
|
73
|
+
'font-family': 'Menlo, Consolas, "Courier New", monospace',
|
|
74
|
+
color: p.codeColor,
|
|
75
|
+
margin: `0 0 {{spacing.block}}`,
|
|
76
|
+
},
|
|
77
|
+
img: {
|
|
78
|
+
'max-width': '100%',
|
|
79
|
+
height: 'auto',
|
|
80
|
+
display: 'block',
|
|
81
|
+
'border-radius': '4px',
|
|
82
|
+
margin: `0 auto {{spacing.block}}`,
|
|
83
|
+
},
|
|
84
|
+
figcaption: {
|
|
85
|
+
'font-size': '0.85em',
|
|
86
|
+
color: p.weakText,
|
|
87
|
+
'text-align': 'center',
|
|
88
|
+
'margin-top': '8px',
|
|
89
|
+
},
|
|
90
|
+
hr: {
|
|
91
|
+
border: 'none',
|
|
92
|
+
'border-top': `1px solid ${p.borderColor}`,
|
|
93
|
+
margin: '24px 0',
|
|
94
|
+
},
|
|
95
|
+
a: {
|
|
96
|
+
color: '{{primaryColor}}',
|
|
97
|
+
'text-decoration': 'none',
|
|
98
|
+
'border-bottom': `1px solid {{primaryColor}}`,
|
|
99
|
+
},
|
|
100
|
+
strong: {
|
|
101
|
+
color: '{{primaryColor}}',
|
|
102
|
+
'font-weight': '600',
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
return mergeBlocks(base, overrides);
|
|
106
|
+
}
|
|
107
|
+
function mergeBlocks(base, overrides) {
|
|
108
|
+
const result = { ...base };
|
|
109
|
+
if (!overrides)
|
|
110
|
+
return result;
|
|
111
|
+
for (const [key, value] of Object.entries(overrides)) {
|
|
112
|
+
if (!value)
|
|
113
|
+
continue;
|
|
114
|
+
const k = key;
|
|
115
|
+
result[k] = { ...(result[k] ?? {}), ...value };
|
|
116
|
+
}
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
119
|
+
function build(name, description, p, tokens, blockOverrides) {
|
|
120
|
+
return {
|
|
121
|
+
name,
|
|
122
|
+
description,
|
|
123
|
+
tokens,
|
|
124
|
+
blocks: defaultBlocks(p, blockOverrides),
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
const safeFont = '-apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif';
|
|
128
|
+
/** 科技极简 —— 冷冽的蓝/青主色,留白多,适合技术、效率、产品类文章。 */
|
|
129
|
+
const techMinimal = build('tech-minimal', '科技极简:以冷峻的青蓝色为主,大量留白、细线条与克制的高对比,强调「清晰易读」。适合技术博客、效率工具、SaaS 产品介绍、测试与工程类文章。', {
|
|
130
|
+
primaryColor: '#0b6bff',
|
|
131
|
+
textColor: '#1f2329',
|
|
132
|
+
codeBg: '#f0f4ff',
|
|
133
|
+
codeColor: '#3b5b9a',
|
|
134
|
+
blockquoteBg: '#f5f9ff',
|
|
135
|
+
blockquoteColor: '#3a4a5a',
|
|
136
|
+
weakText: '#8a94a6',
|
|
137
|
+
borderColor: '#e2e8f0',
|
|
138
|
+
}, {
|
|
139
|
+
primaryColor: '#0b6bff',
|
|
140
|
+
textColor: '#1f2329',
|
|
141
|
+
fontSize: '15px',
|
|
142
|
+
lineHeight: 1.75,
|
|
143
|
+
fontFamily: safeFont,
|
|
144
|
+
spacing: { block: '16px' },
|
|
145
|
+
}, {
|
|
146
|
+
h1: { 'border-left': '5px solid #0b6bff', 'padding-left': '12px' },
|
|
147
|
+
h2: { 'border-left': '3px solid #0b6bff', 'padding-left': '10px' },
|
|
148
|
+
});
|
|
149
|
+
/** 商务 —— 稳重藏蓝 + 金色点缀,适合企业、财经、公司动态。 */
|
|
150
|
+
const business = build('business', '商务稳重:以藏蓝为主色、金色作点缀,字重稍高、行距适中,传达专业与信任感。适合企业宣传、行业报告、财经分析、公司动态类内容。', {
|
|
151
|
+
primaryColor: '#1f3864',
|
|
152
|
+
textColor: '#2b2b2b',
|
|
153
|
+
codeBg: '#f2f4f8',
|
|
154
|
+
codeColor: '#3f4a63',
|
|
155
|
+
blockquoteBg: '#f4f6fa',
|
|
156
|
+
blockquoteColor: '#59627a',
|
|
157
|
+
weakText: '#8a8f99',
|
|
158
|
+
borderColor: '#d9dee8',
|
|
159
|
+
}, {
|
|
160
|
+
primaryColor: '#1f3864',
|
|
161
|
+
textColor: '#2b2b2b',
|
|
162
|
+
fontSize: '15px',
|
|
163
|
+
lineHeight: 1.8,
|
|
164
|
+
fontFamily: safeFont,
|
|
165
|
+
spacing: { block: '16px' },
|
|
166
|
+
}, {
|
|
167
|
+
h1: { 'background-color': '#1f3864', color: '#ffffff', padding: '10px 14px', 'border-radius': '4px' },
|
|
168
|
+
h2: { 'border-bottom': '2px solid #1f3864', 'padding-bottom': '8px' },
|
|
169
|
+
});
|
|
170
|
+
/** 文艺杂志 —— 衬线感字体、暖棕/玫红,适合文学、生活、人文。 */
|
|
171
|
+
const magazine = build('magazine', '文艺杂志:暖棕与玫红调、衬线字体、宽松行距,如同杂志内页。适合文学、散文、生活感悟、文化评论、旅行笔记类内容。', {
|
|
172
|
+
primaryColor: '#b4546a',
|
|
173
|
+
textColor: '#3a3232',
|
|
174
|
+
codeBg: '#f6f0ee',
|
|
175
|
+
codeColor: '#7a5a5f',
|
|
176
|
+
blockquoteBg: '#faf3f1',
|
|
177
|
+
blockquoteColor: '#7d6a6a',
|
|
178
|
+
weakText: '#a89a9a',
|
|
179
|
+
borderColor: '#e8dbd7',
|
|
180
|
+
}, {
|
|
181
|
+
primaryColor: '#b4546a',
|
|
182
|
+
textColor: '#3a3232',
|
|
183
|
+
fontSize: '16px',
|
|
184
|
+
lineHeight: 2,
|
|
185
|
+
fontFamily: 'Georgia, "STZhongsong", "Songti SC", "SimSun", serif',
|
|
186
|
+
spacing: { block: '18px' },
|
|
187
|
+
}, {
|
|
188
|
+
h1: { 'text-align': 'center', 'letter-spacing': '2px' },
|
|
189
|
+
h2: { 'text-align': 'center', 'font-style': 'normal' },
|
|
190
|
+
p: { 'text-align': 'justify', 'text-indent': '2em' },
|
|
191
|
+
blockquote: { 'font-style': 'italic' },
|
|
192
|
+
});
|
|
193
|
+
/** 政务红 —— 正式、庄重的中国红,适合政务、党建、官方通知。 */
|
|
194
|
+
const govRed = build('gov-red', '政务庄重:以中国红为主色,字重较重、结构清晰,传递正式与权威感。适合政务发布、党建文章、官方通知、政策解读。', {
|
|
195
|
+
primaryColor: '#c8142c',
|
|
196
|
+
textColor: '#2e2e2e',
|
|
197
|
+
codeBg: '#f7f0f0',
|
|
198
|
+
codeColor: '#8a3a3a',
|
|
199
|
+
blockquoteBg: '#fdf2f3',
|
|
200
|
+
blockquoteColor: '#8a4a4a',
|
|
201
|
+
weakText: '#9a8a8a',
|
|
202
|
+
borderColor: '#e7d2d4',
|
|
203
|
+
}, {
|
|
204
|
+
primaryColor: '#c8142c',
|
|
205
|
+
textColor: '#2e2e2e',
|
|
206
|
+
fontSize: '16px',
|
|
207
|
+
lineHeight: 1.9,
|
|
208
|
+
fontFamily: safeFont,
|
|
209
|
+
spacing: { block: '16px' },
|
|
210
|
+
}, {
|
|
211
|
+
h1: { 'text-align': 'center', 'font-weight': '700' },
|
|
212
|
+
h2: { 'border-left': '5px solid #c8142c', 'padding-left': '12px' },
|
|
213
|
+
p: { 'text-indent': '2em' },
|
|
214
|
+
});
|
|
215
|
+
/** 学术 —— 中性、克制、多注释的论文风。 */
|
|
216
|
+
const academic = build('academic', '学术严谨:中性灰黑、极小装饰、高可读性,适合论文导读、研究报告、技术文档、方法论类内容。', {
|
|
217
|
+
primaryColor: '#005a8c',
|
|
218
|
+
textColor: '#1c1c1c',
|
|
219
|
+
codeBg: '#f4f4f4',
|
|
220
|
+
codeColor: '#333333',
|
|
221
|
+
blockquoteBg: '#f2f5f7',
|
|
222
|
+
blockquoteColor: '#4a5a63',
|
|
223
|
+
weakText: '#888888',
|
|
224
|
+
borderColor: '#d8d8d8',
|
|
225
|
+
}, {
|
|
226
|
+
primaryColor: '#005a8c',
|
|
227
|
+
textColor: '#1c1c1c',
|
|
228
|
+
fontSize: '14px',
|
|
229
|
+
lineHeight: 1.85,
|
|
230
|
+
fontFamily: 'Georgia, "Times New Roman", "Songti SC", serif',
|
|
231
|
+
spacing: { block: '14px' },
|
|
232
|
+
}, {
|
|
233
|
+
h1: { 'font-weight': '700', 'border-bottom': '2px solid #005a8c', 'padding-bottom': '8px' },
|
|
234
|
+
h2: { 'font-weight': '700', 'border-bottom': '1px solid #cccccc', 'padding-bottom': '6px' },
|
|
235
|
+
p: { 'text-align': 'justify' },
|
|
236
|
+
blockquote: { 'font-style': 'italic' },
|
|
237
|
+
});
|
|
238
|
+
/** 深色代码风 —— 深色底 + 高亮语法色,适合代码示例、极客向内容。 */
|
|
239
|
+
const darkCode = build('dark-code', '深色代码风:深色底、荧光高亮、等宽字体,沉浸感强,适合技术教程、代码赏析、极客与开发者向内容。注意:微信内不支持动态高亮,颜色为静态内联。', {
|
|
240
|
+
primaryColor: '#3ee0a4',
|
|
241
|
+
textColor: '#e7e7e7',
|
|
242
|
+
codeBg: '#1e1e1e',
|
|
243
|
+
codeColor: '#c9d1d9',
|
|
244
|
+
blockquoteBg: '#26262a',
|
|
245
|
+
blockquoteColor: '#b7b7c0',
|
|
246
|
+
weakText: '#9a9aa3',
|
|
247
|
+
borderColor: '#3a3a40',
|
|
248
|
+
}, {
|
|
249
|
+
primaryColor: '#3ee0a4',
|
|
250
|
+
textColor: '#e7e7e7',
|
|
251
|
+
fontSize: '15px',
|
|
252
|
+
lineHeight: 1.7,
|
|
253
|
+
fontFamily: safeFont,
|
|
254
|
+
spacing: { block: '16px' },
|
|
255
|
+
}, {
|
|
256
|
+
h1: { color: '#3ee0a4', 'border-bottom': '1px solid #2a2a30', 'padding-bottom': '8px' },
|
|
257
|
+
h2: { color: '#7cd1ff', 'border-bottom': '1px solid #2a2a30', 'padding-bottom': '6px' },
|
|
258
|
+
p: { color: '#e7e7e7' },
|
|
259
|
+
blockquote: { color: '#b7b7c0', 'border-left': '4px solid #3ee0a4' },
|
|
260
|
+
code: { color: '#f4b25b', 'background-color': '#2d2d33' },
|
|
261
|
+
pre: { color: '#c9d1d9', 'background-color': '#1e1e1e' },
|
|
262
|
+
a: { color: '#7cd1ff' },
|
|
263
|
+
strong: { color: '#3ee0a4' },
|
|
264
|
+
hr: { 'border-top': '1px solid #3a3a40' },
|
|
265
|
+
img: { 'border-radius': '6px' },
|
|
266
|
+
});
|
|
267
|
+
export const PRESET_THEMES = [
|
|
268
|
+
techMinimal,
|
|
269
|
+
business,
|
|
270
|
+
magazine,
|
|
271
|
+
govRed,
|
|
272
|
+
academic,
|
|
273
|
+
darkCode,
|
|
274
|
+
...WEMD_THEMES,
|
|
275
|
+
];
|
|
276
|
+
/** 按名字查找预置主题。 */
|
|
277
|
+
export function getPresetTheme(name) {
|
|
278
|
+
return PRESET_THEMES.find((t) => t.name === name);
|
|
279
|
+
}
|
|
280
|
+
//# sourceMappingURL=presets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.js","sourceRoot":"","sources":["../src/presets.ts"],"names":[],"mappings":"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"}
|
package/dist/schema.d.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/** 主题 block 允许出现的元素名(Markdown/rehype 输出中对应的标签)。 */
|
|
3
|
+
export declare const BLOCK_NAMES: readonly ["h1", "h2", "h3", "p", "blockquote", "ul", "ol", "li", "code", "pre", "img", "figcaption", "hr", "a", "strong"];
|
|
4
|
+
export type BlockName = (typeof BLOCK_NAMES)[number];
|
|
5
|
+
export declare const colorSchema: z.ZodString;
|
|
6
|
+
export declare const lengthSchema: z.ZodString;
|
|
7
|
+
export declare const themeBlocksSchema: z.ZodObject<{
|
|
8
|
+
h1: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
9
|
+
h2: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
10
|
+
h3: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
11
|
+
p: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
12
|
+
blockquote: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
13
|
+
ul: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
14
|
+
ol: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
15
|
+
li: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
16
|
+
code: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
17
|
+
pre: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
18
|
+
img: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
19
|
+
figcaption: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
20
|
+
hr: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
21
|
+
a: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
22
|
+
strong: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
23
|
+
}, z.core.$strip>;
|
|
24
|
+
/** 主题 tokens —— 全局可复用的「设计变量」,block 声明里可用 `{{tokenName}}` 引用。 */
|
|
25
|
+
export declare const themeTokensSchema: z.ZodObject<{
|
|
26
|
+
primaryColor: z.ZodString;
|
|
27
|
+
textColor: z.ZodString;
|
|
28
|
+
fontSize: z.ZodString;
|
|
29
|
+
lineHeight: z.ZodNumber;
|
|
30
|
+
fontFamily: z.ZodString;
|
|
31
|
+
spacing: z.ZodObject<{
|
|
32
|
+
block: z.ZodString;
|
|
33
|
+
}, z.core.$strip>;
|
|
34
|
+
}, z.core.$strip>;
|
|
35
|
+
/**
|
|
36
|
+
* 主题 Schema。
|
|
37
|
+
* blocks 内每个声明键(CSS 属性)必须落在微信白名单内;值可通过 `{{token}}` 引用 tokens。
|
|
38
|
+
*/
|
|
39
|
+
export declare const themeSchema: z.ZodObject<{
|
|
40
|
+
name: z.ZodString;
|
|
41
|
+
description: z.ZodString;
|
|
42
|
+
tokens: z.ZodObject<{
|
|
43
|
+
primaryColor: z.ZodString;
|
|
44
|
+
textColor: z.ZodString;
|
|
45
|
+
fontSize: z.ZodString;
|
|
46
|
+
lineHeight: z.ZodNumber;
|
|
47
|
+
fontFamily: z.ZodString;
|
|
48
|
+
spacing: z.ZodObject<{
|
|
49
|
+
block: z.ZodString;
|
|
50
|
+
}, z.core.$strip>;
|
|
51
|
+
}, z.core.$strip>;
|
|
52
|
+
blocks: z.ZodObject<{
|
|
53
|
+
h1: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
54
|
+
h2: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
55
|
+
h3: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
56
|
+
p: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
57
|
+
blockquote: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
58
|
+
ul: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
59
|
+
ol: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
60
|
+
li: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
61
|
+
code: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
62
|
+
pre: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
63
|
+
img: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
64
|
+
figcaption: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
65
|
+
hr: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
66
|
+
a: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
67
|
+
strong: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
68
|
+
}, z.core.$strip>;
|
|
69
|
+
}, z.core.$strip>;
|
|
70
|
+
export type Theme = z.infer<typeof themeSchema>;
|
|
71
|
+
export type ThemeTokens = z.infer<typeof themeTokensSchema>;
|
|
72
|
+
export type ThemeBlock = Record<string, string>;
|
|
73
|
+
/** 导出 JSON Schema(供 LLM 结构化输出约束 / MCP tool 描述使用)。 */
|
|
74
|
+
export declare function themeToJsonSchema(): Record<string, unknown>;
|
|
75
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,mDAAmD;AACnD,eAAO,MAAM,WAAW,2HAgBd,CAAA;AACV,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAA;AAEpD,eAAO,MAAM,WAAW,aASrB,CAAA;AAEH,eAAO,MAAM,YAAY,aAE4C,CAAA;AAYrE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;iBAA2B,CAAA;AAEzD,gEAAgE;AAChE,eAAO,MAAM,iBAAiB;;;;;;;;;iBAS5B,CAAA;AAEF;;;GAGG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAkCpB,CAAA;AAEJ,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAA;AAC/C,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAA;AAC3D,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAE/C,qDAAqD;AACrD,wBAAgB,iBAAiB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE3D"}
|
package/dist/schema.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { isCssPropertyAllowed } from './css-whitelist.js';
|
|
3
|
+
import { resolveTokenReferences } from './tokens.js';
|
|
4
|
+
/** 主题 block 允许出现的元素名(Markdown/rehype 输出中对应的标签)。 */
|
|
5
|
+
export const BLOCK_NAMES = [
|
|
6
|
+
'h1',
|
|
7
|
+
'h2',
|
|
8
|
+
'h3',
|
|
9
|
+
'p',
|
|
10
|
+
'blockquote',
|
|
11
|
+
'ul',
|
|
12
|
+
'ol',
|
|
13
|
+
'li',
|
|
14
|
+
'code',
|
|
15
|
+
'pre',
|
|
16
|
+
'img',
|
|
17
|
+
'figcaption',
|
|
18
|
+
'hr',
|
|
19
|
+
'a',
|
|
20
|
+
'strong',
|
|
21
|
+
];
|
|
22
|
+
export const colorSchema = z
|
|
23
|
+
.string()
|
|
24
|
+
.refine((v) => /^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(v) ||
|
|
25
|
+
/^rgba?\([^)]+\)$/.test(v) ||
|
|
26
|
+
/^hsla?\([^)]+\)$/.test(v) ||
|
|
27
|
+
/^oklch\([^)]+\)$/.test(v), { message: '颜色值必须是十六进制、rgb/rgba、hsl/hsla 或 oklch 格式。' });
|
|
28
|
+
export const lengthSchema = z
|
|
29
|
+
.string()
|
|
30
|
+
.regex(/^\d+(\.\d+)?(px|em|rem|pt|%)$/, '尺寸必须带合法单位,例如 16px、1.5em。');
|
|
31
|
+
/** 各 block 的「声明值」必须是字符串字面量,或 `{{token}}` 引用。 */
|
|
32
|
+
const declarationValueSchema = z.string().min(1);
|
|
33
|
+
const blockSchema = z.record(declarationValueSchema, declarationValueSchema);
|
|
34
|
+
function buildBlockObjectSchema() {
|
|
35
|
+
const record = {};
|
|
36
|
+
for (const name of BLOCK_NAMES)
|
|
37
|
+
record[name] = blockSchema;
|
|
38
|
+
return z.object(record);
|
|
39
|
+
}
|
|
40
|
+
export const themeBlocksSchema = buildBlockObjectSchema();
|
|
41
|
+
/** 主题 tokens —— 全局可复用的「设计变量」,block 声明里可用 `{{tokenName}}` 引用。 */
|
|
42
|
+
export const themeTokensSchema = z.object({
|
|
43
|
+
primaryColor: colorSchema,
|
|
44
|
+
textColor: colorSchema,
|
|
45
|
+
fontSize: lengthSchema,
|
|
46
|
+
lineHeight: z.number().min(0.8).max(4),
|
|
47
|
+
fontFamily: z.string().min(1).max(200),
|
|
48
|
+
spacing: z.object({
|
|
49
|
+
block: lengthSchema,
|
|
50
|
+
}),
|
|
51
|
+
});
|
|
52
|
+
/**
|
|
53
|
+
* 主题 Schema。
|
|
54
|
+
* blocks 内每个声明键(CSS 属性)必须落在微信白名单内;值可通过 `{{token}}` 引用 tokens。
|
|
55
|
+
*/
|
|
56
|
+
export const themeSchema = z
|
|
57
|
+
.object({
|
|
58
|
+
name: z.string().min(1).max(60),
|
|
59
|
+
description: z.string().min(1).max(500),
|
|
60
|
+
tokens: themeTokensSchema,
|
|
61
|
+
blocks: themeBlocksSchema,
|
|
62
|
+
})
|
|
63
|
+
.superRefine((theme, ctx) => {
|
|
64
|
+
for (const blockName of BLOCK_NAMES) {
|
|
65
|
+
const block = theme.blocks[blockName];
|
|
66
|
+
for (const [property, rawValue] of Object.entries(block)) {
|
|
67
|
+
const propPath = `blocks.${blockName}.${property}`;
|
|
68
|
+
// 仅对「微信真实会过滤」的属性硬禁止(position/filter 等);transform/animation/float
|
|
69
|
+
// 等为灰色属性(微信草稿 API 实测保留),不在主题层面判非法,交由 validator 提示。
|
|
70
|
+
if (!isCssPropertyAllowed(property)) {
|
|
71
|
+
ctx.addIssue({
|
|
72
|
+
code: 'custom',
|
|
73
|
+
path: [propPath],
|
|
74
|
+
message: `CSS 属性「${property}」已被真实微信实测会过滤(如 position / filter 等),请移除或改用微信保留的属性。`,
|
|
75
|
+
});
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
const resolved = resolveTokenReferences(rawValue, theme.tokens);
|
|
79
|
+
if (resolved.trim() === '') {
|
|
80
|
+
ctx.addIssue({
|
|
81
|
+
code: 'custom',
|
|
82
|
+
path: [propPath],
|
|
83
|
+
message: `属性「${property}」的值经过 token 引用解析后为空,请检查是否引用了非法 token。`,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
/** 导出 JSON Schema(供 LLM 结构化输出约束 / MCP tool 描述使用)。 */
|
|
90
|
+
export function themeToJsonSchema() {
|
|
91
|
+
return z.toJSONSchema(themeSchema);
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme.test.d.ts","sourceRoot":"","sources":["../src/theme.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { compileThemeToCss, compileRootBaseStyle, getPresetTheme, PRESET_THEMES, resolveTokenReferences, validateTheme, themeToJsonSchema, themeSchema, isCssPropertyAllowed, classifyCssProperty, findUnsafeCssValue, hasTokenReferences, } from './index.js';
|
|
3
|
+
const validTheme = {
|
|
4
|
+
name: 'test-theme',
|
|
5
|
+
description: '用于测试的主题',
|
|
6
|
+
tokens: {
|
|
7
|
+
primaryColor: '#0b6bff',
|
|
8
|
+
textColor: '#1f2329',
|
|
9
|
+
fontSize: '15px',
|
|
10
|
+
lineHeight: 1.75,
|
|
11
|
+
fontFamily: 'sans-serif',
|
|
12
|
+
spacing: { block: '16px' },
|
|
13
|
+
},
|
|
14
|
+
blocks: {
|
|
15
|
+
h1: { color: '{{primaryColor}}', 'font-size': '1.6em', margin: '0 0 {{spacing.block}}' },
|
|
16
|
+
h2: {},
|
|
17
|
+
h3: {},
|
|
18
|
+
p: { color: '{{textColor}}', 'font-size': '{{fontSize}}', 'line-height': '{{lineHeight}}' },
|
|
19
|
+
blockquote: { 'border-left': '4px solid {{primaryColor}}' },
|
|
20
|
+
ul: {},
|
|
21
|
+
ol: {},
|
|
22
|
+
li: {},
|
|
23
|
+
code: { 'background-color': '#f2f2f2' },
|
|
24
|
+
pre: { 'background-color': '#f6f8fa' },
|
|
25
|
+
img: { 'max-width': '100%' },
|
|
26
|
+
figcaption: {},
|
|
27
|
+
hr: { 'border-top': '1px solid #ccc' },
|
|
28
|
+
a: { color: '{{primaryColor}}' },
|
|
29
|
+
strong: { 'font-weight': '600' },
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
describe('preset themes', () => {
|
|
33
|
+
it('至少提供 6 套预置主题,且每套都通过 schema 校验', () => {
|
|
34
|
+
expect(PRESET_THEMES.length).toBeGreaterThanOrEqual(6);
|
|
35
|
+
for (const theme of PRESET_THEMES) {
|
|
36
|
+
const result = validateTheme(theme);
|
|
37
|
+
expect(result.ok, `主题 ${theme.name} 应通过校验:${JSON.stringify(result.issues)}`).toBe(true);
|
|
38
|
+
expect(theme.description.length).toBeGreaterThan(10);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
it('每套主题应包含全部 16 个 block', () => {
|
|
42
|
+
const names = [
|
|
43
|
+
'h1', 'h2', 'h3', 'p', 'blockquote', 'ul', 'ol', 'li',
|
|
44
|
+
'code', 'pre', 'img', 'figcaption', 'hr', 'a', 'strong',
|
|
45
|
+
];
|
|
46
|
+
for (const theme of PRESET_THEMES) {
|
|
47
|
+
for (const n of names)
|
|
48
|
+
expect(theme.blocks[n], `${theme.name} 缺 block ${n}`).toBeDefined();
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
it('可通过名字查找预置主题', () => {
|
|
52
|
+
expect(getPresetTheme('tech-minimal')?.name).toBe('tech-minimal');
|
|
53
|
+
expect(getPresetTheme('not-exist')).toBeUndefined();
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
describe('validateTheme', () => {
|
|
57
|
+
it('合法主题通过', () => {
|
|
58
|
+
const r = validateTheme(validTheme);
|
|
59
|
+
expect(r.ok).toBe(true);
|
|
60
|
+
expect(r.issues).toEqual([]);
|
|
61
|
+
});
|
|
62
|
+
it('包含真实微信会过滤的属性(position)时失败并给出可读提示', () => {
|
|
63
|
+
const bad = structuredClone(validTheme);
|
|
64
|
+
bad.blocks.p['position'] = 'absolute';
|
|
65
|
+
const r = validateTheme(bad);
|
|
66
|
+
expect(r.ok).toBe(false);
|
|
67
|
+
const issue = r.issues.find((i) => i.path.includes('position'));
|
|
68
|
+
expect(issue).toBeDefined();
|
|
69
|
+
expect(issue?.message).toContain('过滤');
|
|
70
|
+
});
|
|
71
|
+
it('灰色属性(transform)不判主题非法,但归类为 gray', () => {
|
|
72
|
+
const ok = structuredClone(validTheme);
|
|
73
|
+
ok.blocks.h1['transform'] = 'rotate(3deg)';
|
|
74
|
+
const r = validateTheme(ok);
|
|
75
|
+
expect(r.ok).toBe(true); // 不再硬禁止
|
|
76
|
+
expect(classifyCssProperty('transform')).toBe('gray');
|
|
77
|
+
});
|
|
78
|
+
it('!important 不再让主题非法(降级为 validator 层 warning)', () => {
|
|
79
|
+
const bad = structuredClone(validTheme);
|
|
80
|
+
bad.blocks.h1['color'] = '{{primaryColor}} !important';
|
|
81
|
+
const r = validateTheme(bad);
|
|
82
|
+
expect(r.ok).toBe(true);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
describe('themeToJsonSchema', () => {
|
|
86
|
+
it('导出合法 JSON Schema,包含 name/description/tokens/blocks', () => {
|
|
87
|
+
const schema = themeToJsonSchema();
|
|
88
|
+
expect(schema.type).toBe('object');
|
|
89
|
+
const props = schema.properties;
|
|
90
|
+
expect(props).toHaveProperty('name');
|
|
91
|
+
expect(props).toHaveProperty('description');
|
|
92
|
+
expect(props).toHaveProperty('tokens');
|
|
93
|
+
expect(props).toHaveProperty('blocks');
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
describe('compileThemeToCss', () => {
|
|
97
|
+
it('能解析 token 引用,输出中不残留 {{ }}', () => {
|
|
98
|
+
const css = compileThemeToCss(validTheme);
|
|
99
|
+
expect(css).not.toContain('{{');
|
|
100
|
+
expect(css).toContain('h1');
|
|
101
|
+
expect(css).toContain('#0b6bff');
|
|
102
|
+
expect(css).toContain('line-height: 1.75');
|
|
103
|
+
});
|
|
104
|
+
it('root base style 包含继承默认值', () => {
|
|
105
|
+
const base = compileRootBaseStyle(validTheme);
|
|
106
|
+
expect(base).toContain('font-family: sans-serif');
|
|
107
|
+
expect(base).toContain('font-size: 15px');
|
|
108
|
+
expect(base).toContain('color: #1f2329');
|
|
109
|
+
expect(base).toContain('line-height: 1.75');
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
describe('token 系统', () => {
|
|
113
|
+
it('解析 token 引用', () => {
|
|
114
|
+
expect(resolveTokenReferences('0 0 {{spacing.block}}', validTheme.tokens)).toBe('0 0 16px');
|
|
115
|
+
expect(resolveTokenReferences('{{rowColor}}', validTheme.tokens)).toBe('');
|
|
116
|
+
});
|
|
117
|
+
it('检测 token 引用存在', () => {
|
|
118
|
+
expect(hasTokenReferences('{{primaryColor}}')).toBe(true);
|
|
119
|
+
expect(hasTokenReferences('#0b6bff')).toBe(false);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
describe('CSS 白名单', () => {
|
|
123
|
+
it('白名单允许安全属性', () => {
|
|
124
|
+
expect(isCssPropertyAllowed('color')).toBe(true);
|
|
125
|
+
expect(isCssPropertyAllowed('font-size')).toBe(true);
|
|
126
|
+
expect(isCssPropertyAllowed('margin')).toBe(true);
|
|
127
|
+
expect(isCssPropertyAllowed('border-radius')).toBe(true);
|
|
128
|
+
});
|
|
129
|
+
it('真实微信会过滤的属性(banned)被拒绝', () => {
|
|
130
|
+
for (const prop of ['position', 'filter', 'backdrop-filter']) {
|
|
131
|
+
expect(isCssPropertyAllowed(prop), `${prop} 应被禁止`).toBe(false);
|
|
132
|
+
expect(classifyCssProperty(prop)).toBe('banned');
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
it('灰色属性(allow + warning)被放行', () => {
|
|
136
|
+
for (const prop of ['transform', 'animation', 'float', 'box-shadow', 'transition', 'opacity', 'top', 'z-index']) {
|
|
137
|
+
expect(isCssPropertyAllowed(prop), `${prop} 应可放行`).toBe(true);
|
|
138
|
+
expect(classifyCssProperty(prop)).toBe('gray');
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
it('拒绝通配符与 CSS 变量定义', () => {
|
|
142
|
+
expect(isCssPropertyAllowed('*')).toBe(false);
|
|
143
|
+
expect(isCssPropertyAllowed('--bg')).toBe(false);
|
|
144
|
+
});
|
|
145
|
+
it('findUnsafeCssValue 识别外部 url()', () => {
|
|
146
|
+
expect(findUnsafeCssValue('url(https://evil.com/a.png)')).not.toBeNull();
|
|
147
|
+
expect(findUnsafeCssValue('url(data:image/png;base64,xxx)')).toBeNull();
|
|
148
|
+
expect(findUnsafeCssValue('red')).toBeNull();
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
describe('themeSchema 类型解析', () => {
|
|
152
|
+
it('lineHeight 越界被拒绝', () => {
|
|
153
|
+
const bad = structuredClone(validTheme);
|
|
154
|
+
bad.tokens.lineHeight = 5;
|
|
155
|
+
expect(themeSchema.safeParse(bad).success).toBe(false);
|
|
156
|
+
});
|
|
157
|
+
it('无效颜色被拒绝', () => {
|
|
158
|
+
const bad = structuredClone(validTheme);
|
|
159
|
+
bad.tokens.primaryColor = 'not-a-color';
|
|
160
|
+
expect(themeSchema.safeParse(bad).success).toBe(false);
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
//# sourceMappingURL=theme.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme.test.js","sourceRoot":"","sources":["../src/theme.test.ts"],"names":[],"mappings":"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"}
|