@bytechain.cn/colamd-themes 0.3.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.
Files changed (108) hide show
  1. package/.claude/skills/colamd-themes-preview.skill.md +333 -0
  2. package/.claude/skills/colamd-themes.skill.md +155 -0
  3. package/.hermes/skills/tools/colamd-themes/SKILL.md +159 -0
  4. package/.openclaw/skills/colamd-themes/SKILL.md +166 -0
  5. package/.opencode/skills/colamd-themes/SKILL.md +162 -0
  6. package/.trae/rules/colamd-themes.md +150 -0
  7. package/CHANGELOG.md +102 -0
  8. package/README.md +373 -0
  9. package/README_CN.md +373 -0
  10. package/RELEASENOTE.md +177 -0
  11. package/dist/cli.d.ts +2 -0
  12. package/dist/cli.js +208 -0
  13. package/dist/cli.js.map +1 -0
  14. package/dist/color-systems.d.ts +17 -0
  15. package/dist/color-systems.js +251 -0
  16. package/dist/color-systems.js.map +1 -0
  17. package/dist/color-utils.d.ts +9 -0
  18. package/dist/color-utils.js +112 -0
  19. package/dist/color-utils.js.map +1 -0
  20. package/dist/contrast.d.ts +15 -0
  21. package/dist/contrast.js +63 -0
  22. package/dist/contrast.js.map +1 -0
  23. package/dist/docx-style-paradigm.d.ts +153 -0
  24. package/dist/docx-style-paradigm.js +640 -0
  25. package/dist/docx-style-paradigm.js.map +1 -0
  26. package/dist/export-cli.d.ts +10 -0
  27. package/dist/export-cli.js +266 -0
  28. package/dist/export-cli.js.map +1 -0
  29. package/dist/extractors/base.d.ts +6 -0
  30. package/dist/extractors/base.js +3 -0
  31. package/dist/extractors/base.js.map +1 -0
  32. package/dist/extractors/docx-extractor.d.ts +52 -0
  33. package/dist/extractors/docx-extractor.js +370 -0
  34. package/dist/extractors/docx-extractor.js.map +1 -0
  35. package/dist/extractors/pdf-extractor.d.ts +66 -0
  36. package/dist/extractors/pdf-extractor.js +430 -0
  37. package/dist/extractors/pdf-extractor.js.map +1 -0
  38. package/dist/extractors/url-extractor.d.ts +104 -0
  39. package/dist/extractors/url-extractor.js +761 -0
  40. package/dist/extractors/url-extractor.js.map +1 -0
  41. package/dist/generator.d.ts +4 -0
  42. package/dist/generator.js +71 -0
  43. package/dist/generator.js.map +1 -0
  44. package/dist/index.d.ts +10 -0
  45. package/dist/index.js +9 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/mermaid-presets.d.ts +14 -0
  48. package/dist/mermaid-presets.js +122 -0
  49. package/dist/mermaid-presets.js.map +1 -0
  50. package/dist/models.d.ts +106 -0
  51. package/dist/models.js +92 -0
  52. package/dist/models.js.map +1 -0
  53. package/dist/renderer.d.ts +70 -0
  54. package/dist/renderer.js +204 -0
  55. package/dist/renderer.js.map +1 -0
  56. package/dist/templates/template.css +498 -0
  57. package/dist/templates/theme-paradigm.md +658 -0
  58. package/dist/templates/theme-template.hbs +370 -0
  59. package/dist/theme-store.d.ts +37 -0
  60. package/dist/theme-store.js +90 -0
  61. package/dist/theme-store.js.map +1 -0
  62. package/dist/validators.d.ts +26 -0
  63. package/dist/validators.js +144 -0
  64. package/dist/validators.js.map +1 -0
  65. package/package.json +36 -0
  66. package/skills/build-skills.sh +166 -0
  67. package/skills/colamd-themes/SKILL.md +148 -0
  68. package/src/cli.ts +200 -0
  69. package/src/color-systems.ts +289 -0
  70. package/src/color-utils.ts +120 -0
  71. package/src/contrast.ts +66 -0
  72. package/src/docx-style-paradigm.ts +811 -0
  73. package/src/export-cli.ts +301 -0
  74. package/src/extractors/base.ts +8 -0
  75. package/src/extractors/docx-extractor.ts +417 -0
  76. package/src/extractors/pdf-extractor.ts +527 -0
  77. package/src/extractors/url-extractor.ts +927 -0
  78. package/src/generator.ts +88 -0
  79. package/src/index.ts +29 -0
  80. package/src/mermaid-presets.ts +142 -0
  81. package/src/models.ts +212 -0
  82. package/src/renderer.ts +277 -0
  83. package/src/templates/template.css +498 -0
  84. package/src/templates/theme-paradigm.md +658 -0
  85. package/src/templates/theme-template.hbs +370 -0
  86. package/src/theme-store.ts +112 -0
  87. package/src/types/pdf-parse.d.ts +12 -0
  88. package/src/validators.ts +176 -0
  89. package/themes/.gitkeep +0 -0
  90. package/themes/academic-paper-pt.css +1805 -0
  91. package/themes/academic-paper.css +1099 -0
  92. package/themes/academic-style.css +2430 -0
  93. package/themes/colly.css +370 -0
  94. package/themes/elegant.css +671 -0
  95. package/themes/forest-ink.css +664 -0
  96. package/themes/guizang.css +732 -0
  97. package/themes/meeting-minutes.css +370 -0
  98. package/themes/pixso-design.css +1261 -0
  99. package/themes/salvator-blog.css +370 -0
  100. package/themes/swiss-design copy.css +746 -0
  101. package/themes/swiss-design.css +746 -0
  102. package/themes/template.css +498 -0
  103. package/themes/trae-blue.css +737 -0
  104. package/themes-preview/colly-preview.html +623 -0
  105. package/themes-preview/demo-content.md +187 -0
  106. package/themes-preview/meeting-minutes-preview.html +625 -0
  107. package/themes-preview/salvator-blog-preview.html +623 -0
  108. package/tsconfig.json +18 -0
@@ -0,0 +1,370 @@
1
+ /*
2
+ * ColaMD Theme: {{ name }}
3
+ * {{ description }}
4
+ * Generated by colamd-themes ({{ sourceType }}: {{ sourceUrl }})
5
+ *
6
+ * ═══════════════════════════════════════════════════════════
7
+ * SECTION 1 — Design Tokens
8
+ * Modify the 5 seed colors + 3 font stacks to change the theme
9
+ * ═══════════════════════════════════════════════════════════ */
10
+
11
+ body.theme-custom {
12
+
13
+ /* ── 1.1 Seed Palette ── */
14
+ --seed-accent: {{ seed.accent }};
15
+ --seed-accent-light: {{ seed.accentLight }};
16
+ --seed-accent-dark: {{ seed.accentDark }};
17
+ --seed-surface: {{ seed.surface }};
18
+ --seed-panel: {{ seed.panel }};
19
+ --seed-panel-alt: {{ seed.panelAlt }};
20
+ --seed-ink: {{ seed.ink }};
21
+ --seed-ink-muted: {{ seed.inkMuted }};
22
+ --seed-ink-dim: {{ seed.inkDim }};
23
+ --seed-border: {{ seed.border }};
24
+ --seed-border-strong: {{ seed.borderStrong }};
25
+
26
+ /* ── 1.2 Typography ── */
27
+ --font-body: {{{ seedTypography.fontBody }}};
28
+ --font-heading: {{{ seedTypography.fontHeading }}};
29
+ --font-code: {{{ seedTypography.fontCode }}};
30
+ --font-mermaid: {{ seedTypography.fontMermaid }};
31
+
32
+ /* ── 1.3 Font Sizing ── */
33
+ --font-size-root: {{ seedTypography.fontSizeRoot }};
34
+ --font-scale-h1: {{ seedTypography.fontScaleH1 }};
35
+ --font-scale-h2: {{ seedTypography.fontScaleH2 }};
36
+ --font-scale-h3: {{ seedTypography.fontScaleH3 }};
37
+ --font-scale-h4: {{ seedTypography.fontScaleH4 }};
38
+ --font-scale-h5: {{ seedTypography.fontScaleH5 }};
39
+ --font-scale-h6: {{ seedTypography.fontScaleH6 }};
40
+ --font-size-mermaid: {{ seedTypography.fontSizeMermaid }};
41
+ --line-height-body: {{ seedTypography.lineHeightBody }};
42
+ --line-height-heading: {{ seedTypography.lineHeightHeading }};
43
+ --line-height-code: {{ seedTypography.lineHeightCode }};
44
+
45
+ /* ── 1.4 Radii & Spacing ── */
46
+ --radius-sm: {{ radiusSm }};
47
+ --radius-md: {{ radiusMd }};
48
+ --radius-lg: {{ radiusLg }};
49
+ --content-width: {{ contentWidth }};
50
+
51
+ /* ═══════════════════════════════════════════════════════════
52
+ SECTION 2 — Semantic Mapping
53
+ Auto-maps seed tokens → ColaMD built-in variables
54
+ ═══════════════════════════════════════════════════════════ */
55
+
56
+ /* ── 2.1 Surface ── */
57
+ --bg-color: var(--seed-surface);
58
+ --surface-color: var(--seed-panel);
59
+ --surface-alt: var(--seed-panel-alt);
60
+
61
+ /* ── 2.2 Text ── */
62
+ --text-color: var(--seed-ink);
63
+ --heading-color: var(--seed-ink);
64
+ --text-muted: var(--seed-ink-muted);
65
+ --text-dim: var(--seed-ink-dim);
66
+
67
+ /* ── 2.3 Links & Accent ── */
68
+ --link-color: var(--seed-accent);
69
+ --accent-color: var(--seed-accent);
70
+ --accent-dark: var(--seed-accent-dark);
71
+ --accent-light: var(--seed-accent-light);
72
+ --selection-bg: {{rgba seed.accent 0.15}};
73
+
74
+ /* ── 2.4 Borders ── */
75
+ --border-color: var(--seed-border);
76
+ --blockquote-border: var(--seed-accent);
77
+ --hr-color: var(--seed-border);
78
+
79
+ /* ── 2.5 Inline Code ── */
80
+ --code-bg: var(--seed-panel);
81
+ --code-color: var(--seed-accent-dark);
82
+
83
+ /* ── 2.6 Code Blocks ── */
84
+ --code-block-bg: var(--seed-panel-alt);
85
+ --code-block-text: var(--seed-ink);
86
+ --code-block-color: var(--seed-ink);
87
+
88
+ /* ── 2.7 Blockquote ── */
89
+ --blockquote-bg: var(--seed-panel);
90
+
91
+ /* ── 2.8 Tables ── */
92
+ --table-header-bg: var(--seed-panel);
93
+ --table-border: var(--seed-border);
94
+
95
+ /* ── 2.9 Scrollbar ── */
96
+ --scrollbar-thumb: var(--seed-border-strong);
97
+ --scrollbar-thumb-hover: var(--seed-ink-muted);
98
+
99
+ /* ═══════════════════════════════════════════════════════════
100
+ SECTION 3 — Mermaid 20 Core Variables
101
+ Auto-consumed by built-in variables.css for 22 diagram types
102
+ ═══════════════════════════════════════════════════════════ */
103
+
104
+ /* ── 3.1 Container ── */
105
+ --mermaid-background: var(--seed-panel);
106
+ --mermaid-border-color: var(--seed-border);
107
+ --mermaid-border-radius: var(--radius-md);
108
+ --mermaid-padding: 20px;
109
+
110
+ /* ── 3.2 Font ── */
111
+ --mermaid-font-family: var(--font-mermaid);
112
+ --mermaid-font-size: var(--font-size-mermaid);
113
+
114
+ /* ── 3.3 Nodes ── */
115
+ --mermaid-node-fill: var(--seed-panel);
116
+ --mermaid-node-stroke: var(--seed-accent);
117
+ --mermaid-node-stroke-width: 1.5px;
118
+ --mermaid-node-text: var(--seed-ink);
119
+
120
+ /* ── 3.4 Edges ── */
121
+ --mermaid-edge-stroke: var(--seed-ink-muted);
122
+ --mermaid-edge-stroke-width: 1.5px;
123
+
124
+ /* ── 3.5 Clusters ── */
125
+ --mermaid-cluster-fill: {{rgba seed.accent 0.06}};
126
+ --mermaid-cluster-stroke: var(--seed-accent);
127
+
128
+ /* ── 3.6 Labels ── */
129
+ --mermaid-label-text: var(--seed-ink);
130
+ --mermaid-edge-label-text: var(--seed-ink-muted);
131
+ --mermaid-edge-label-bg: var(--seed-surface);
132
+
133
+ /* ── 3.7 Titles & Axes ── */
134
+ --mermaid-title-text: var(--seed-ink);
135
+ --mermaid-axis-text: var(--seed-ink-muted);
136
+ --mermaid-highlight: var(--seed-accent);
137
+
138
+ /* ── 3.8 Person Nodes ── */
139
+ --mermaid-person-stroke: var(--seed-ink);
140
+ --mermaid-person-fill: var(--seed-panel);
141
+
142
+ /* ── 3.9 Label Offset ── */
143
+ --mermaid-label-offset-y: 0px;
144
+
145
+ /* ── 4. Fine Tuning ── */
146
+ --line-height-base: var(--line-height-body);
147
+ }
148
+
149
+ /* ═══════════════════════════════════════════════════════════
150
+ SECTION 5 — Selector-Level Micro Adjustments
151
+ Only where base.css doesn't cover. All values via var(--*).
152
+ ═══════════════════════════════════════════════════════════ */
153
+
154
+ html { font-size: var(--font-size-root); }
155
+ body.theme-custom, html, body {
156
+ background-color: var(--bg-color);
157
+ color: var(--text-color);
158
+ font-family: var(--font-body);
159
+ line-height: var(--line-height-body);
160
+ }
161
+
162
+ #write {
163
+ max-width: var(--content-width);
164
+ margin: 0 auto;
165
+ padding: 30px 60px 100px;
166
+ }
167
+
168
+ body.theme-custom h1, body.theme-custom h2, body.theme-custom h3,
169
+ body.theme-custom h4, body.theme-custom h5, body.theme-custom h6 {
170
+ font-family: var(--font-heading);
171
+ color: var(--heading-color);
172
+ font-weight: 700;
173
+ line-height: var(--line-height-heading);
174
+ }
175
+
176
+ body.theme-custom h1 { font-size: calc(var(--font-size-root) * var(--font-scale-h1)); }
177
+ body.theme-custom h2 { font-size: calc(var(--font-size-root) * var(--font-scale-h2)); }
178
+ body.theme-custom h3 { font-size: calc(var(--font-size-root) * var(--font-scale-h3)); }
179
+ body.theme-custom h4 { font-size: calc(var(--font-size-root) * var(--font-scale-h4)); }
180
+ body.theme-custom h5 { font-size: calc(var(--font-size-root) * var(--font-scale-h5)); }
181
+ body.theme-custom h6 { font-size: calc(var(--font-size-root) * var(--font-scale-h6)); }
182
+
183
+ body.theme-custom strong { color: var(--accent-color); }
184
+ body.theme-custom code {
185
+ font-family: var(--font-code);
186
+ background: var(--code-bg);
187
+ color: var(--code-color);
188
+ }
189
+
190
+ body.theme-custom pre {
191
+ background: var(--code-block-bg);
192
+ font-family: var(--font-code);
193
+ line-height: var(--line-height-code);
194
+ }
195
+ body.theme-custom pre code { color: var(--code-block-text); background: transparent; }
196
+
197
+ body.theme-custom blockquote {
198
+ background: var(--blockquote-bg);
199
+ border-left: 4px solid var(--blockquote-border);
200
+ }
201
+
202
+ body.theme-custom table th {
203
+ background: var(--table-header-bg);
204
+ font-weight: 700;
205
+ border-bottom: 2px solid var(--accent-color);
206
+ }
207
+
208
+ body.theme-custom hr {
209
+ border: none;
210
+ border-top: 1px solid var(--hr-color);
211
+ }
212
+
213
+ body.theme-custom img { max-width: 100%; }
214
+
215
+ /* ── 5.11 Mermaid caption ── */
216
+ body.theme-custom .mermaid-block + p {
217
+ text-align: center;
218
+ font-family: var(--font-heading);
219
+ font-size: calc(var(--font-size-mermaid) + 2px);
220
+ color: var(--text-muted);
221
+ }
222
+
223
+ /* ── 5.12 Responsive ── */
224
+ @media only screen and (max-width: 768px) {
225
+ #write { padding: 20px; }
226
+ body.theme-custom .mermaid-block { padding: 12px; }
227
+ }
228
+
229
+ /* ═══════════════════════════════════════════════════════════
230
+ SECTION 6 — Print / Export
231
+ Screen mirror: every screen property restated with !important.
232
+ ═══════════════════════════════════════════════════════════ */
233
+ @media print {
234
+ @page { margin: 20mm; }
235
+
236
+ /* ── 6.0 Variable re-declaration (Chromium strips CSS variables in print) ── */
237
+ body.theme-custom {
238
+ --seed-accent: {{ seed.accent }};
239
+ --seed-accent-dark: {{ seed.accentDark }};
240
+ --seed-surface: {{ seed.surface }};
241
+ --seed-ink: {{ seed.ink }};
242
+ --seed-ink-muted: {{ seed.inkMuted }};
243
+ --seed-panel: {{ seed.panel }};
244
+ --seed-panel-alt: {{ seed.panelAlt }};
245
+ --seed-border: {{ seed.border }};
246
+ --font-size-root: {{ seedTypography.fontSizeRoot }};
247
+ --line-height-body: {{ seedTypography.lineHeightBody }};
248
+ --line-height-heading: {{ seedTypography.lineHeightHeading }};
249
+ --line-height-code: {{ seedTypography.lineHeightCode }};
250
+ --font-scale-h1: {{ seedTypography.fontScaleH1 }};
251
+ --font-scale-h2: {{ seedTypography.fontScaleH2 }};
252
+ --font-scale-h3: {{ seedTypography.fontScaleH3 }};
253
+ --font-scale-h4: {{ seedTypography.fontScaleH4 }};
254
+ --font-scale-h5: {{ seedTypography.fontScaleH5 }};
255
+ --font-scale-h6: {{ seedTypography.fontScaleH6 }};
256
+ --content-width: {{ contentWidth }};
257
+ --font-size-mermaid: {{ seedTypography.fontSizeMermaid }};
258
+ --accent-color: var(--seed-accent);
259
+ --accent-dark: var(--seed-accent-dark);
260
+ --code-bg: var(--seed-panel);
261
+ --code-color: var(--seed-accent-dark);
262
+ --code-block-bg: var(--seed-panel-alt);
263
+ --code-block-text: var(--seed-ink);
264
+ --blockquote-bg: var(--seed-panel);
265
+ --table-header-bg: var(--seed-panel);
266
+ --border-color: var(--seed-border);
267
+ --hr-color: var(--seed-border);
268
+ }
269
+
270
+ html, body, body.theme-custom {
271
+ background: var(--seed-surface) !important;
272
+ color: var(--seed-ink) !important;
273
+ font-family: var(--font-body) !important;
274
+ line-height: var(--line-height-body) !important;
275
+ -webkit-print-color-adjust: exact !important;
276
+ print-color-adjust: exact !important;
277
+ }
278
+
279
+ #write {
280
+ max-width: var(--content-width) !important;
281
+ margin: 0 auto !important;
282
+ padding: 30px 60px 100px !important;
283
+ }
284
+
285
+ body.theme-custom h1, body.theme-custom h2, body.theme-custom h3,
286
+ body.theme-custom h4, body.theme-custom h5, body.theme-custom h6 {
287
+ font-family: var(--font-heading) !important;
288
+ color: var(--seed-ink) !important;
289
+ font-weight: 700 !important;
290
+ line-height: var(--line-height-heading) !important;
291
+ -webkit-print-color-adjust: exact !important;
292
+ print-color-adjust: exact !important;
293
+ }
294
+ body.theme-custom h1 { font-size: calc(var(--font-size-root) * var(--font-scale-h1)) !important; }
295
+ body.theme-custom h2 { font-size: calc(var(--font-size-root) * var(--font-scale-h2)) !important; }
296
+ body.theme-custom h3 { font-size: calc(var(--font-size-root) * var(--font-scale-h3)) !important; }
297
+ body.theme-custom h4 { font-size: calc(var(--font-size-root) * var(--font-scale-h4)) !important; }
298
+ body.theme-custom h5 { font-size: calc(var(--font-size-root) * var(--font-scale-h5)) !important; }
299
+ body.theme-custom h6 { font-size: calc(var(--font-size-root) * var(--font-scale-h6)) !important; }
300
+
301
+ body.theme-custom strong {
302
+ color: var(--accent-color) !important;
303
+ -webkit-print-color-adjust: exact !important;
304
+ print-color-adjust: exact !important;
305
+ }
306
+
307
+ body.theme-custom code {
308
+ font-family: var(--font-code) !important;
309
+ background: var(--code-bg) !important;
310
+ color: var(--code-color) !important;
311
+ -webkit-print-color-adjust: exact !important;
312
+ print-color-adjust: exact !important;
313
+ }
314
+
315
+ body.theme-custom pre {
316
+ background: var(--code-block-bg) !important;
317
+ font-family: var(--font-code) !important;
318
+ line-height: var(--line-height-code) !important;
319
+ -webkit-print-color-adjust: exact !important;
320
+ print-color-adjust: exact !important;
321
+ }
322
+ body.theme-custom pre code { color: var(--code-block-text) !important; background: transparent !important; }
323
+
324
+ body.theme-custom blockquote {
325
+ background: var(--blockquote-bg) !important;
326
+ border-left: 4px solid var(--seed-accent) !important;
327
+ -webkit-print-color-adjust: exact !important;
328
+ print-color-adjust: exact !important;
329
+ }
330
+
331
+ body.theme-custom table th {
332
+ background: var(--table-header-bg) !important;
333
+ color: var(--seed-ink) !important;
334
+ font-weight: 700 !important;
335
+ border-bottom: 2px solid var(--accent-color) !important;
336
+ -webkit-print-color-adjust: exact !important;
337
+ print-color-adjust: exact !important;
338
+ }
339
+
340
+ body.theme-custom a {
341
+ color: var(--seed-accent) !important;
342
+ -webkit-print-color-adjust: exact !important;
343
+ print-color-adjust: exact !important;
344
+ }
345
+
346
+ body.theme-custom hr {
347
+ border: none !important;
348
+ border-top: 1px solid var(--hr-color) !important;
349
+ }
350
+
351
+ body.theme-custom img { max-width: 100% !important; }
352
+
353
+ body.theme-custom .mermaid-block {
354
+ background: var(--seed-surface) !important;
355
+ border-color: var(--seed-border) !important;
356
+ -webkit-print-color-adjust: exact !important;
357
+ print-color-adjust: exact !important;
358
+ }
359
+ body.theme-custom .mermaid-preview svg * {
360
+ -webkit-print-color-adjust: exact !important;
361
+ print-color-adjust: exact !important;
362
+ }
363
+
364
+ body.theme-custom .mermaid-block + p {
365
+ color: var(--seed-ink-muted) !important;
366
+ text-align: center !important;
367
+ font-family: var(--font-heading) !important;
368
+ font-size: calc(var(--font-size-mermaid) + 2px) !important;
369
+ }
370
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Theme configuration persistence.
3
+ *
4
+ * Stores default theme and registered custom themes in ~/.colamd-themes/config.json
5
+ */
6
+ /** Built-in themes provided by @bytechain.cn/colamd */
7
+ export declare const BUILTIN_THEMES: readonly ["light", "dark", "elegant", "newsprint"];
8
+ export type BuiltinTheme = (typeof BUILTIN_THEMES)[number];
9
+ export interface ThemeConfig {
10
+ /** Default theme name (built-in or custom) */
11
+ defaultTheme: string;
12
+ /** Registered custom themes: name → CSS file path */
13
+ themes: Record<string, string>;
14
+ }
15
+ /** Get the full config. */
16
+ export declare function getConfig(): ThemeConfig;
17
+ /** Set the default theme (built-in name or registered custom name). */
18
+ export declare function setDefaultTheme(name: string): void;
19
+ /**
20
+ * Register a custom theme.
21
+ * @param name Unique name (will be prefixed with "custom:" when applied)
22
+ * @param cssPath Absolute path to the CSS file
23
+ */
24
+ export declare function registerTheme(name: string, cssPath: string): void;
25
+ /** Remove a registered custom theme. */
26
+ export declare function unregisterTheme(name: string): boolean;
27
+ /**
28
+ * Resolve a theme name to the arguments needed by the ColaMD renderer.
29
+ *
30
+ * @param name Theme name. If omitted, uses the configured default.
31
+ * @returns { themeName, customCSS? } — themeName is either a built-in name
32
+ * or "custom:<name>"; customCSS is the CSS content for custom themes.
33
+ */
34
+ export declare function resolveTheme(name?: string): {
35
+ themeName: string;
36
+ customCSS?: string;
37
+ };
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Theme configuration persistence.
3
+ *
4
+ * Stores default theme and registered custom themes in ~/.colamd-themes/config.json
5
+ */
6
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
7
+ import { join } from "node:path";
8
+ import { homedir } from "node:os";
9
+ const CONFIG_DIR = join(homedir(), ".colamd-themes");
10
+ const CONFIG_FILE = join(CONFIG_DIR, "config.json");
11
+ /** Built-in themes provided by @bytechain.cn/colamd */
12
+ export const BUILTIN_THEMES = ["light", "dark", "elegant", "newsprint"];
13
+ function readConfig() {
14
+ if (!existsSync(CONFIG_FILE))
15
+ return { defaultTheme: "elegant", themes: {} };
16
+ try {
17
+ return JSON.parse(readFileSync(CONFIG_FILE, "utf-8"));
18
+ }
19
+ catch {
20
+ return { defaultTheme: "elegant", themes: {} };
21
+ }
22
+ }
23
+ function writeConfig(config) {
24
+ if (!existsSync(CONFIG_DIR))
25
+ mkdirSync(CONFIG_DIR, { recursive: true });
26
+ writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), "utf-8");
27
+ }
28
+ /** Get the full config. */
29
+ export function getConfig() {
30
+ return readConfig();
31
+ }
32
+ /** Set the default theme (built-in name or registered custom name). */
33
+ export function setDefaultTheme(name) {
34
+ const config = readConfig();
35
+ config.defaultTheme = name;
36
+ writeConfig(config);
37
+ }
38
+ /**
39
+ * Register a custom theme.
40
+ * @param name Unique name (will be prefixed with "custom:" when applied)
41
+ * @param cssPath Absolute path to the CSS file
42
+ */
43
+ export function registerTheme(name, cssPath) {
44
+ const config = readConfig();
45
+ config.themes[name] = cssPath;
46
+ writeConfig(config);
47
+ }
48
+ /** Remove a registered custom theme. */
49
+ export function unregisterTheme(name) {
50
+ const config = readConfig();
51
+ if (!(name in config.themes))
52
+ return false;
53
+ delete config.themes[name];
54
+ writeConfig(config);
55
+ return true;
56
+ }
57
+ /**
58
+ * Resolve a theme name to the arguments needed by the ColaMD renderer.
59
+ *
60
+ * @param name Theme name. If omitted, uses the configured default.
61
+ * @returns { themeName, customCSS? } — themeName is either a built-in name
62
+ * or "custom:<name>"; customCSS is the CSS content for custom themes.
63
+ */
64
+ export function resolveTheme(name) {
65
+ const config = readConfig();
66
+ const resolved = name ?? config.defaultTheme;
67
+ // Check if it's a registered custom theme
68
+ if (config.themes[resolved]) {
69
+ const cssPath = config.themes[resolved];
70
+ if (!existsSync(cssPath)) {
71
+ throw new Error(`Custom theme CSS file not found: ${cssPath}`);
72
+ }
73
+ return { themeName: `custom:${resolved}`, customCSS: readFileSync(cssPath, "utf-8") };
74
+ }
75
+ // Check if it's a built-in theme
76
+ if (BUILTIN_THEMES.includes(resolved)) {
77
+ return { themeName: resolved };
78
+ }
79
+ // Treat as a direct CSS file path
80
+ if (existsSync(resolved)) {
81
+ const nameFromPath = resolved.replace(/\.css$/i, "").split("/").pop() ?? "custom";
82
+ return {
83
+ themeName: `custom:${nameFromPath}`,
84
+ customCSS: readFileSync(resolved, "utf-8"),
85
+ };
86
+ }
87
+ throw new Error(`Unknown theme: "${resolved}". Use a built-in theme (${BUILTIN_THEMES.join(", ")}), ` +
88
+ `a registered custom theme, or a path to a .css file.`);
89
+ }
90
+ //# sourceMappingURL=theme-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-store.js","sourceRoot":"","sources":["../src/theme-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Paradigm validation engine — checks SeedPalette against v3.0 design constraints.
3
+ * Based on theme-paradigm.md Section 2.
4
+ */
5
+ export interface ValidationIssue {
6
+ ruleId: string;
7
+ level: "MUST" | "MUST_NOT" | "SHOULD" | "SHOULD_NOT";
8
+ message: string;
9
+ fix?: string;
10
+ }
11
+ export interface SeedPalette {
12
+ accent: string;
13
+ accentLight: string;
14
+ accentDark: string;
15
+ surface: string;
16
+ panel: string;
17
+ panelAlt: string;
18
+ ink: string;
19
+ inkMuted: string;
20
+ inkDim: string;
21
+ border: string;
22
+ borderStrong: string;
23
+ }
24
+ export declare function validateSeedPalette(palette: SeedPalette): ValidationIssue[];
25
+ /** Summarize validation results. */
26
+ export declare function summarizeIssues(issues: ValidationIssue[]): string;
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Paradigm validation engine — checks SeedPalette against v3.0 design constraints.
3
+ * Based on theme-paradigm.md Section 2.
4
+ */
5
+ import { contrastRatio, hslSaturation, hslLightness, sameHueAxis, isLightMode } from "./contrast.js";
6
+ export function validateSeedPalette(palette) {
7
+ const issues = [];
8
+ const light = isLightMode(palette.surface);
9
+ // CR-01: ink vs surface ≥ 7:1
10
+ const crInk = contrastRatio(palette.ink, palette.surface);
11
+ if (crInk < 7.0) {
12
+ issues.push({
13
+ ruleId: "CR-01",
14
+ level: "MUST",
15
+ message: `正文-底色对比度 ${crInk.toFixed(1)}:1 < 7:1 (WCAG AAA)`,
16
+ fix: `建议加深 ink 或调浅 surface`,
17
+ });
18
+ }
19
+ // CR-02: inkMuted vs surface ≥ 4.5:1
20
+ const crMuted = contrastRatio(palette.inkMuted, palette.surface);
21
+ if (crMuted < 4.5) {
22
+ issues.push({
23
+ ruleId: "CR-02",
24
+ level: "MUST",
25
+ message: `次要文字-底色对比度 ${crMuted.toFixed(1)}:1 < 4.5:1 (WCAG AA)`,
26
+ });
27
+ }
28
+ // CR-04: accent vs surface ≥ 4.5:1
29
+ const crAccent = contrastRatio(palette.accent, palette.surface);
30
+ if (crAccent < 4.5) {
31
+ issues.push({
32
+ ruleId: "CR-04",
33
+ level: "MUST",
34
+ message: `点缀色-底色对比度 ${crAccent.toFixed(1)}:1 < 4.5:1`,
35
+ });
36
+ }
37
+ // SL-01: surface saturation ≤ 0.05
38
+ const sSurface = hslSaturation(palette.surface);
39
+ if (sSurface > 0.05) {
40
+ issues.push({
41
+ ruleId: "SL-01",
42
+ level: "MUST",
43
+ message: `底色饱和度 ${(sSurface * 100).toFixed(1)}% > 5%,页面会偏色`,
44
+ });
45
+ }
46
+ // SL-02: panel/panelAlt saturation ≤ 0.10
47
+ for (const [name, hex] of [["panel", palette.panel], ["panelAlt", palette.panelAlt]]) {
48
+ const s = hslSaturation(hex);
49
+ if (s > 0.10) {
50
+ issues.push({
51
+ ruleId: "SL-02",
52
+ level: "MUST_NOT",
53
+ message: `表面色 ${name} 饱和度 ${(s * 100).toFixed(1)}% > 10%`,
54
+ });
55
+ }
56
+ }
57
+ // SL-03: surface/panel/panelAlt same hue axis
58
+ if (!sameHueAxis(palette.surface, palette.panel, 5) || !sameHueAxis(palette.surface, palette.panelAlt, 5)) {
59
+ issues.push({
60
+ ruleId: "SL-03",
61
+ level: "SHOULD",
62
+ message: "三层表面色应保持相同色相轴(H 偏差 ≤ 5°)",
63
+ });
64
+ }
65
+ // SL-04: L(surface) > L(panel) > L(panelAlt) for light
66
+ const lSurface = hslLightness(palette.surface);
67
+ const lPanel = hslLightness(palette.panel);
68
+ const lPanelAlt = hslLightness(palette.panelAlt);
69
+ if (light) {
70
+ if (!(lSurface > lPanel && lPanel > lPanelAlt)) {
71
+ issues.push({
72
+ ruleId: "SL-04",
73
+ level: "MUST",
74
+ message: `浅色主题要求 L(surface) > L(panel) > L(panelAlt)`,
75
+ });
76
+ }
77
+ }
78
+ else {
79
+ if (!(lSurface < lPanel && lPanel < lPanelAlt)) {
80
+ issues.push({
81
+ ruleId: "SL-04",
82
+ level: "MUST",
83
+ message: `深色主题要求 L(surface) < L(panel) < L(panelAlt)`,
84
+ });
85
+ }
86
+ }
87
+ // NT-01: ink/inkMuted/inkDim same hue axis
88
+ if (!sameHueAxis(palette.ink, palette.inkMuted, 3) || !sameHueAxis(palette.ink, palette.inkDim, 3)) {
89
+ issues.push({
90
+ ruleId: "NT-01",
91
+ level: "MUST",
92
+ message: "文字色必须位于同一色相轴(H 偏差 ≤ 3°)",
93
+ });
94
+ }
95
+ // NT-02: border vs panel lightness diff ≥ 0.08
96
+ const lBorder = hslLightness(palette.border);
97
+ if (Math.abs(lBorder - lPanel) < 0.08) {
98
+ issues.push({
99
+ ruleId: "NT-02",
100
+ level: "MUST",
101
+ message: `边框色与 panel 明度差 ${Math.abs(lBorder - lPanel).toFixed(3)} < 0.08,边框不可见`,
102
+ });
103
+ }
104
+ // NT-03: border should be neutral gray
105
+ const sBorder = hslSaturation(palette.border);
106
+ if (sBorder > 0.05) {
107
+ issues.push({
108
+ ruleId: "NT-03",
109
+ level: "SHOULD",
110
+ message: `边框色饱和度 ${(sBorder * 100).toFixed(1)}% > 5%,应使用中性灰`,
111
+ });
112
+ }
113
+ // HR-01: accent saturation ≥ 0.30 for light themes
114
+ const sAccent = hslSaturation(palette.accent);
115
+ if (light && sAccent < 0.30) {
116
+ issues.push({
117
+ ruleId: "HR-01",
118
+ level: "SHOULD",
119
+ message: `点缀色饱和度 ${(sAccent * 100).toFixed(1)}% < 30%,建议选暖色或冷色`,
120
+ });
121
+ }
122
+ return issues;
123
+ }
124
+ /** Summarize validation results. */
125
+ export function summarizeIssues(issues) {
126
+ const errors = issues.filter((i) => i.level === "MUST" || i.level === "MUST_NOT");
127
+ const warnings = issues.filter((i) => i.level === "SHOULD" || i.level === "SHOULD_NOT");
128
+ const lines = [];
129
+ if (errors.length > 0) {
130
+ lines.push(`ERRORS (${errors.length}):`);
131
+ for (const e of errors)
132
+ lines.push(` [${e.ruleId}] ${e.message}`);
133
+ }
134
+ if (warnings.length > 0) {
135
+ lines.push(`WARNINGS (${warnings.length}):`);
136
+ for (const w of warnings)
137
+ lines.push(` [${w.ruleId}] ${w.message}`);
138
+ }
139
+ if (errors.length === 0 && warnings.length === 0) {
140
+ lines.push("All validations passed.");
141
+ }
142
+ return lines.join("\n");
143
+ }
144
+ //# sourceMappingURL=validators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.js","sourceRoot":"","sources":["../src/validators.ts"],"names":[],"mappings":"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"}