@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.
- package/.claude/skills/colamd-themes-preview.skill.md +333 -0
- package/.claude/skills/colamd-themes.skill.md +155 -0
- package/.hermes/skills/tools/colamd-themes/SKILL.md +159 -0
- package/.openclaw/skills/colamd-themes/SKILL.md +166 -0
- package/.opencode/skills/colamd-themes/SKILL.md +162 -0
- package/.trae/rules/colamd-themes.md +150 -0
- package/CHANGELOG.md +102 -0
- package/README.md +373 -0
- package/README_CN.md +373 -0
- package/RELEASENOTE.md +177 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +208 -0
- package/dist/cli.js.map +1 -0
- package/dist/color-systems.d.ts +17 -0
- package/dist/color-systems.js +251 -0
- package/dist/color-systems.js.map +1 -0
- package/dist/color-utils.d.ts +9 -0
- package/dist/color-utils.js +112 -0
- package/dist/color-utils.js.map +1 -0
- package/dist/contrast.d.ts +15 -0
- package/dist/contrast.js +63 -0
- package/dist/contrast.js.map +1 -0
- package/dist/docx-style-paradigm.d.ts +153 -0
- package/dist/docx-style-paradigm.js +640 -0
- package/dist/docx-style-paradigm.js.map +1 -0
- package/dist/export-cli.d.ts +10 -0
- package/dist/export-cli.js +266 -0
- package/dist/export-cli.js.map +1 -0
- package/dist/extractors/base.d.ts +6 -0
- package/dist/extractors/base.js +3 -0
- package/dist/extractors/base.js.map +1 -0
- package/dist/extractors/docx-extractor.d.ts +52 -0
- package/dist/extractors/docx-extractor.js +370 -0
- package/dist/extractors/docx-extractor.js.map +1 -0
- package/dist/extractors/pdf-extractor.d.ts +66 -0
- package/dist/extractors/pdf-extractor.js +430 -0
- package/dist/extractors/pdf-extractor.js.map +1 -0
- package/dist/extractors/url-extractor.d.ts +104 -0
- package/dist/extractors/url-extractor.js +761 -0
- package/dist/extractors/url-extractor.js.map +1 -0
- package/dist/generator.d.ts +4 -0
- package/dist/generator.js +71 -0
- package/dist/generator.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/mermaid-presets.d.ts +14 -0
- package/dist/mermaid-presets.js +122 -0
- package/dist/mermaid-presets.js.map +1 -0
- package/dist/models.d.ts +106 -0
- package/dist/models.js +92 -0
- package/dist/models.js.map +1 -0
- package/dist/renderer.d.ts +70 -0
- package/dist/renderer.js +204 -0
- package/dist/renderer.js.map +1 -0
- package/dist/templates/template.css +498 -0
- package/dist/templates/theme-paradigm.md +658 -0
- package/dist/templates/theme-template.hbs +370 -0
- package/dist/theme-store.d.ts +37 -0
- package/dist/theme-store.js +90 -0
- package/dist/theme-store.js.map +1 -0
- package/dist/validators.d.ts +26 -0
- package/dist/validators.js +144 -0
- package/dist/validators.js.map +1 -0
- package/package.json +36 -0
- package/skills/build-skills.sh +166 -0
- package/skills/colamd-themes/SKILL.md +148 -0
- package/src/cli.ts +200 -0
- package/src/color-systems.ts +289 -0
- package/src/color-utils.ts +120 -0
- package/src/contrast.ts +66 -0
- package/src/docx-style-paradigm.ts +811 -0
- package/src/export-cli.ts +301 -0
- package/src/extractors/base.ts +8 -0
- package/src/extractors/docx-extractor.ts +417 -0
- package/src/extractors/pdf-extractor.ts +527 -0
- package/src/extractors/url-extractor.ts +927 -0
- package/src/generator.ts +88 -0
- package/src/index.ts +29 -0
- package/src/mermaid-presets.ts +142 -0
- package/src/models.ts +212 -0
- package/src/renderer.ts +277 -0
- package/src/templates/template.css +498 -0
- package/src/templates/theme-paradigm.md +658 -0
- package/src/templates/theme-template.hbs +370 -0
- package/src/theme-store.ts +112 -0
- package/src/types/pdf-parse.d.ts +12 -0
- package/src/validators.ts +176 -0
- package/themes/.gitkeep +0 -0
- package/themes/academic-paper-pt.css +1805 -0
- package/themes/academic-paper.css +1099 -0
- package/themes/academic-style.css +2430 -0
- package/themes/colly.css +370 -0
- package/themes/elegant.css +671 -0
- package/themes/forest-ink.css +664 -0
- package/themes/guizang.css +732 -0
- package/themes/meeting-minutes.css +370 -0
- package/themes/pixso-design.css +1261 -0
- package/themes/salvator-blog.css +370 -0
- package/themes/swiss-design copy.css +746 -0
- package/themes/swiss-design.css +746 -0
- package/themes/template.css +498 -0
- package/themes/trae-blue.css +737 -0
- package/themes-preview/colly-preview.html +623 -0
- package/themes-preview/demo-content.md +187 -0
- package/themes-preview/meeting-minutes-preview.html +625 -0
- package/themes-preview/salvator-blog-preview.html +623 -0
- package/tsconfig.json +18 -0
package/src/generator.ts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/** CSS theme file generator — v3.0 seed palette pipeline. */
|
|
2
|
+
|
|
3
|
+
import Handlebars from "handlebars";
|
|
4
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync } from "node:fs";
|
|
5
|
+
import { join, dirname, isAbsolute } from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
import type { ThemeStyle } from "./models.js";
|
|
8
|
+
import { paletteToSeed } from "./models.js";
|
|
9
|
+
import { toRgba, normalizeThemeStyle } from "./color-utils.js";
|
|
10
|
+
import { matchColorSystem } from "./color-systems.js";
|
|
11
|
+
import { selectMermaidPreset } from "./mermaid-presets.js";
|
|
12
|
+
import { validateSeedPalette, summarizeIssues } from "./validators.js";
|
|
13
|
+
|
|
14
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
15
|
+
const templatePath = join(__dirname, "templates", "theme-template.hbs");
|
|
16
|
+
|
|
17
|
+
// ── Handlebars helpers ──
|
|
18
|
+
|
|
19
|
+
Handlebars.registerHelper("rgba", (hex: unknown, alpha: unknown) => {
|
|
20
|
+
return toRgba(String(hex), Number(alpha));
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
let compiledTemplate: HandlebarsTemplateDelegate<ThemeStyle> | null = null;
|
|
24
|
+
|
|
25
|
+
function getTemplate(): HandlebarsTemplateDelegate<ThemeStyle> {
|
|
26
|
+
if (!compiledTemplate) {
|
|
27
|
+
const source = readFileSync(templatePath, "utf-8");
|
|
28
|
+
compiledTemplate = Handlebars.compile(source, { noEscape: true });
|
|
29
|
+
}
|
|
30
|
+
return compiledTemplate;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// ── Pipeline ──
|
|
34
|
+
|
|
35
|
+
export function generateCss(style: ThemeStyle): string {
|
|
36
|
+
// 1. Map legacy palette → seed palette if seed is still default
|
|
37
|
+
if (style.seed.accent === "#6366f1") {
|
|
38
|
+
style.seed = paletteToSeed(style.palette);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// 2. Normalize from legacy extractor path
|
|
42
|
+
normalizeThemeStyle(style);
|
|
43
|
+
|
|
44
|
+
// 3. Match color system
|
|
45
|
+
if (!style.colorSystemId) {
|
|
46
|
+
const cs = matchColorSystem(style.seed.accent, style.seed.surface);
|
|
47
|
+
style.colorSystemId = cs.id;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// 4. Select Mermaid preset
|
|
51
|
+
if (!style.mermaidPresetId) {
|
|
52
|
+
const mp = selectMermaidPreset(style.seed.surface, style.seed.accent);
|
|
53
|
+
style.mermaidPresetId = mp.id;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// 5. Validate against paradigm
|
|
57
|
+
const issues = validateSeedPalette(style.seed);
|
|
58
|
+
if (issues.filter((i) => i.level === "MUST" || i.level === "MUST_NOT").length > 0) {
|
|
59
|
+
console.warn("Paradigm validation issues:", summarizeIssues(issues));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// 6. Render
|
|
63
|
+
const template = getTemplate();
|
|
64
|
+
return template(style);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function writeThemeFile(
|
|
68
|
+
style: ThemeStyle,
|
|
69
|
+
target: string = "themes"
|
|
70
|
+
): string {
|
|
71
|
+
const css = generateCss(style);
|
|
72
|
+
const safeName = style.name.replace(/[^a-zA-Z0-9_-]/g, "-").replace(/-+/g, "-");
|
|
73
|
+
|
|
74
|
+
let filePath: string;
|
|
75
|
+
if (target.endsWith(".css")) {
|
|
76
|
+
filePath = isAbsolute(target) ? target : join(process.cwd(), target);
|
|
77
|
+
} else {
|
|
78
|
+
const dirPath = isAbsolute(target) ? target : join(process.cwd(), target);
|
|
79
|
+
if (!existsSync(dirPath)) mkdirSync(dirPath, { recursive: true });
|
|
80
|
+
filePath = join(dirPath, `${safeName}.css`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const parent = dirname(filePath);
|
|
84
|
+
if (!existsSync(parent)) mkdirSync(parent, { recursive: true });
|
|
85
|
+
|
|
86
|
+
writeFileSync(filePath, css, "utf-8");
|
|
87
|
+
return filePath;
|
|
88
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** ColaMD Theme Development Tool. */
|
|
2
|
+
|
|
3
|
+
export * from "./models.js";
|
|
4
|
+
export * from "./color-utils.js";
|
|
5
|
+
export * from "./generator.js";
|
|
6
|
+
export { UrlExtractor } from "./extractors/url-extractor.js";
|
|
7
|
+
export { DocxExtractor } from "./extractors/docx-extractor.js";
|
|
8
|
+
export { PdfExtractor } from "./extractors/pdf-extractor.js";
|
|
9
|
+
export type { Extractor } from "./extractors/base.js";
|
|
10
|
+
|
|
11
|
+
export {
|
|
12
|
+
ACADEMIC_PAPER_DEFAULTS,
|
|
13
|
+
BUSINESS_REPORT_DEFAULTS,
|
|
14
|
+
TECHNICAL_DOC_DEFAULTS,
|
|
15
|
+
generatePrintFriendlyGrayscale,
|
|
16
|
+
generateMorandiPrintPalette,
|
|
17
|
+
validateDocumentStyle,
|
|
18
|
+
normalizeForPrinting,
|
|
19
|
+
getRecommendedPreset,
|
|
20
|
+
DOCUMENT_STYLE_PRESETS,
|
|
21
|
+
} from "./docx-style-paradigm.js";
|
|
22
|
+
|
|
23
|
+
export type {
|
|
24
|
+
DocumentStyleParadigm,
|
|
25
|
+
FontStyleDefinition,
|
|
26
|
+
TableCellStyle,
|
|
27
|
+
PrintOptimization,
|
|
28
|
+
StyleValidationIssue,
|
|
29
|
+
} from "./docx-style-paradigm.js";
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mermaid 20-variable presets for light, dark, and elegant theme modes.
|
|
3
|
+
* Based on ColaMD-extend reference themes (elegant.css, forest-ink.css, guizang.css).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { isLightMode, hslHue } from "./contrast.js";
|
|
7
|
+
|
|
8
|
+
export interface MermaidPreset {
|
|
9
|
+
id: string;
|
|
10
|
+
name: string;
|
|
11
|
+
description: string;
|
|
12
|
+
variables: Record<string, string>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// ═══════════════════════════════════════════════════════════
|
|
16
|
+
// Light Preset — warm paper tone (from elegant.css style)
|
|
17
|
+
// ═══════════════════════════════════════════════════════════
|
|
18
|
+
|
|
19
|
+
const lightPreset: MermaidPreset = {
|
|
20
|
+
id: "light",
|
|
21
|
+
name: "Light",
|
|
22
|
+
description: "亮色主题 Mermaid 预设 — 暖色调,节点用浅色填充、accent 描边",
|
|
23
|
+
variables: {
|
|
24
|
+
"mermaid-background": "var(--seed-panel)",
|
|
25
|
+
"mermaid-border-color": "var(--seed-border)",
|
|
26
|
+
"mermaid-border-radius": "var(--radius-md)",
|
|
27
|
+
"mermaid-padding": "20px",
|
|
28
|
+
"mermaid-font-family": "var(--font-mermaid)",
|
|
29
|
+
"mermaid-font-size": "var(--font-size-mermaid)",
|
|
30
|
+
"mermaid-node-fill": "var(--seed-panel)",
|
|
31
|
+
"mermaid-node-stroke": "var(--seed-accent)",
|
|
32
|
+
"mermaid-node-stroke-width": "1.5px",
|
|
33
|
+
"mermaid-node-text": "var(--seed-ink)",
|
|
34
|
+
"mermaid-edge-stroke": "var(--seed-ink-muted)",
|
|
35
|
+
"mermaid-edge-stroke-width": "1.5px",
|
|
36
|
+
"mermaid-cluster-fill": "rgba accent 0.06",
|
|
37
|
+
"mermaid-cluster-stroke": "var(--seed-accent)",
|
|
38
|
+
"mermaid-label-text": "var(--seed-ink)",
|
|
39
|
+
"mermaid-edge-label-text": "var(--seed-ink-muted)",
|
|
40
|
+
"mermaid-edge-label-bg": "var(--seed-surface)",
|
|
41
|
+
"mermaid-title-text": "var(--seed-ink)",
|
|
42
|
+
"mermaid-axis-text": "var(--seed-ink-muted)",
|
|
43
|
+
"mermaid-highlight": "var(--seed-accent)",
|
|
44
|
+
"mermaid-person-stroke": "var(--seed-ink)",
|
|
45
|
+
"mermaid-person-fill": "var(--seed-panel)",
|
|
46
|
+
"mermaid-label-offset-y": "0px",
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// ═══════════════════════════════════════════════════════════
|
|
51
|
+
// Dark Preset — dark background (for dark themes)
|
|
52
|
+
// ═══════════════════════════════════════════════════════════
|
|
53
|
+
|
|
54
|
+
const darkPreset: MermaidPreset = {
|
|
55
|
+
id: "dark",
|
|
56
|
+
name: "Dark",
|
|
57
|
+
description: "暗色主题 Mermaid 预设 — 深色背景,亮色节点",
|
|
58
|
+
variables: {
|
|
59
|
+
"mermaid-background": "var(--seed-panel-alt)",
|
|
60
|
+
"mermaid-border-color": "var(--seed-border-strong)",
|
|
61
|
+
"mermaid-border-radius": "var(--radius-md)",
|
|
62
|
+
"mermaid-padding": "20px",
|
|
63
|
+
"mermaid-font-family": "var(--font-mermaid)",
|
|
64
|
+
"mermaid-font-size": "var(--font-size-mermaid)",
|
|
65
|
+
"mermaid-node-fill": "var(--seed-panel)",
|
|
66
|
+
"mermaid-node-stroke": "var(--seed-accent-light)",
|
|
67
|
+
"mermaid-node-stroke-width": "1.5px",
|
|
68
|
+
"mermaid-node-text": "var(--seed-ink)",
|
|
69
|
+
"mermaid-edge-stroke": "var(--seed-ink-muted)",
|
|
70
|
+
"mermaid-edge-stroke-width": "1.5px",
|
|
71
|
+
"mermaid-cluster-fill": "rgba accent 0.08",
|
|
72
|
+
"mermaid-cluster-stroke": "var(--seed-border-strong)",
|
|
73
|
+
"mermaid-label-text": "var(--seed-ink)",
|
|
74
|
+
"mermaid-edge-label-text": "var(--seed-ink-muted)",
|
|
75
|
+
"mermaid-edge-label-bg": "var(--seed-surface)",
|
|
76
|
+
"mermaid-title-text": "var(--seed-ink)",
|
|
77
|
+
"mermaid-axis-text": "var(--seed-ink-muted)",
|
|
78
|
+
"mermaid-highlight": "var(--seed-accent)",
|
|
79
|
+
"mermaid-person-stroke": "var(--seed-ink)",
|
|
80
|
+
"mermaid-person-fill": "var(--seed-panel)",
|
|
81
|
+
"mermaid-label-offset-y": "0px",
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// ═══════════════════════════════════════════════════════════
|
|
86
|
+
// Elegant Preset — warm toned (for warm ink/paper themes)
|
|
87
|
+
// ═══════════════════════════════════════════════════════════
|
|
88
|
+
|
|
89
|
+
const elegantPreset: MermaidPreset = {
|
|
90
|
+
id: "elegant",
|
|
91
|
+
name: "Elegant",
|
|
92
|
+
description: "典雅暖调 Mermaid 预设 — 米色底 + 暖棕点缀",
|
|
93
|
+
variables: {
|
|
94
|
+
"mermaid-background": "var(--seed-panel)",
|
|
95
|
+
"mermaid-border-color": "var(--seed-border)",
|
|
96
|
+
"mermaid-border-radius": "var(--radius-md)",
|
|
97
|
+
"mermaid-padding": "20px",
|
|
98
|
+
"mermaid-font-family": "var(--font-mermaid)",
|
|
99
|
+
"mermaid-font-size": "var(--font-size-mermaid)",
|
|
100
|
+
"mermaid-node-fill": "var(--seed-panel)",
|
|
101
|
+
"mermaid-node-stroke": "var(--seed-accent)",
|
|
102
|
+
"mermaid-node-stroke-width": "1.5px",
|
|
103
|
+
"mermaid-node-text": "var(--seed-ink)",
|
|
104
|
+
"mermaid-edge-stroke": "var(--seed-ink-muted)",
|
|
105
|
+
"mermaid-edge-stroke-width": "1.5px",
|
|
106
|
+
"mermaid-cluster-fill": "rgba accent 0.04",
|
|
107
|
+
"mermaid-cluster-stroke": "var(--seed-accent)",
|
|
108
|
+
"mermaid-label-text": "var(--seed-ink)",
|
|
109
|
+
"mermaid-edge-label-text": "var(--seed-ink-muted)",
|
|
110
|
+
"mermaid-edge-label-bg": "var(--seed-surface)",
|
|
111
|
+
"mermaid-title-text": "var(--seed-ink)",
|
|
112
|
+
"mermaid-axis-text": "var(--seed-ink-muted)",
|
|
113
|
+
"mermaid-highlight": "var(--seed-accent)",
|
|
114
|
+
"mermaid-person-stroke": "var(--seed-ink)",
|
|
115
|
+
"mermaid-person-fill": "var(--seed-panel)",
|
|
116
|
+
"mermaid-label-offset-y": "0px",
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
// ── Registry ──
|
|
121
|
+
|
|
122
|
+
export const MERMAID_PRESETS: MermaidPreset[] = [lightPreset, darkPreset, elegantPreset];
|
|
123
|
+
|
|
124
|
+
export function getMermaidPreset(id: string): MermaidPreset | undefined {
|
|
125
|
+
return MERMAID_PRESETS.find((p) => p.id === id);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** Auto-select Mermaid preset based on background luminance. */
|
|
129
|
+
export function selectMermaidPreset(
|
|
130
|
+
bgHex: string,
|
|
131
|
+
accentHex: string
|
|
132
|
+
): MermaidPreset {
|
|
133
|
+
const light = isLightMode(bgHex);
|
|
134
|
+
if (!light) return darkPreset;
|
|
135
|
+
|
|
136
|
+
// For light themes: check accent warmth — warm accent → elegant, cool → light
|
|
137
|
+
const hue = hslHue(accentHex);
|
|
138
|
+
// Warm hues: red (0-30), orange (30-50), brown is low sat orange
|
|
139
|
+
if (hue >= 0 && hue <= 50) return elegantPreset;
|
|
140
|
+
|
|
141
|
+
return lightPreset;
|
|
142
|
+
}
|
package/src/models.ts
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/** Theme style data models — v3.0 Seed Palette paradigm. */
|
|
2
|
+
|
|
3
|
+
// ═══════════════════════════════════════════════════════════
|
|
4
|
+
// Legacy model (kept for extractor compatibility)
|
|
5
|
+
// ═══════════════════════════════════════════════════════════
|
|
6
|
+
|
|
7
|
+
export interface ColorPalette {
|
|
8
|
+
bgColor: string;
|
|
9
|
+
textColor: string;
|
|
10
|
+
headingColor: string;
|
|
11
|
+
borderColor: string;
|
|
12
|
+
accentColor: string;
|
|
13
|
+
codeBg: string;
|
|
14
|
+
codeColor: string;
|
|
15
|
+
codeBlockBg: string;
|
|
16
|
+
codeBlockText: string;
|
|
17
|
+
blockquoteBg: string;
|
|
18
|
+
blockquoteBorder: string;
|
|
19
|
+
tableHeaderBg: string;
|
|
20
|
+
selectionBg: string;
|
|
21
|
+
textMuted: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface Typography {
|
|
25
|
+
bodyFontFamily: string;
|
|
26
|
+
headingFontFamily: string;
|
|
27
|
+
codeFontFamily: string;
|
|
28
|
+
baseFontSize: string;
|
|
29
|
+
baseLineHeight: number;
|
|
30
|
+
headingWeight: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface Spacing {
|
|
34
|
+
contentMaxWidth: string;
|
|
35
|
+
contentPadding: string;
|
|
36
|
+
paragraphMargin: string;
|
|
37
|
+
headingMarginTop: string;
|
|
38
|
+
headingMarginBottom: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface SyntaxHighlighting {
|
|
42
|
+
comment: string;
|
|
43
|
+
punctuation: string;
|
|
44
|
+
keyword: string;
|
|
45
|
+
booleanBuiltinTag: string;
|
|
46
|
+
string: string;
|
|
47
|
+
number: string;
|
|
48
|
+
functionClass: string;
|
|
49
|
+
operator: string;
|
|
50
|
+
variable: string;
|
|
51
|
+
regex: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// ═══════════════════════════════════════════════════════════
|
|
55
|
+
// v3.0 Seed Palette model
|
|
56
|
+
// ═══════════════════════════════════════════════════════════
|
|
57
|
+
|
|
58
|
+
export interface SeedPalette {
|
|
59
|
+
accent: string;
|
|
60
|
+
accentLight: string;
|
|
61
|
+
accentDark: string;
|
|
62
|
+
surface: string;
|
|
63
|
+
panel: string;
|
|
64
|
+
panelAlt: string;
|
|
65
|
+
ink: string;
|
|
66
|
+
inkMuted: string;
|
|
67
|
+
inkDim: string;
|
|
68
|
+
border: string;
|
|
69
|
+
borderStrong: string;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface SeedTypography {
|
|
73
|
+
fontBody: string;
|
|
74
|
+
fontHeading: string;
|
|
75
|
+
fontCode: string;
|
|
76
|
+
fontMermaid: string;
|
|
77
|
+
fontSizeRoot: string; // e.g. "16px"
|
|
78
|
+
fontScaleH1: number;
|
|
79
|
+
fontScaleH2: number;
|
|
80
|
+
fontScaleH3: number;
|
|
81
|
+
fontScaleH4: number;
|
|
82
|
+
fontScaleH5: number;
|
|
83
|
+
fontScaleH6: number;
|
|
84
|
+
fontSizeMermaid: string;
|
|
85
|
+
lineHeightBody: number;
|
|
86
|
+
lineHeightHeading: number;
|
|
87
|
+
lineHeightCode: number;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export interface ThemeStyle {
|
|
91
|
+
name: string;
|
|
92
|
+
description: string;
|
|
93
|
+
/** Legacy — populated by extractors, then mapped to seed */
|
|
94
|
+
palette: ColorPalette;
|
|
95
|
+
typography: Typography;
|
|
96
|
+
spacing: Spacing;
|
|
97
|
+
syntax: SyntaxHighlighting;
|
|
98
|
+
/** v3.0 seed palette */
|
|
99
|
+
seed: SeedPalette;
|
|
100
|
+
seedTypography: SeedTypography;
|
|
101
|
+
/** Selected presets */
|
|
102
|
+
colorSystemId: string;
|
|
103
|
+
mermaidPresetId: string;
|
|
104
|
+
/** Metadata */
|
|
105
|
+
sourceUrl: string;
|
|
106
|
+
sourceType: string;
|
|
107
|
+
/** Computed radius and width */
|
|
108
|
+
radiusSm: string;
|
|
109
|
+
radiusMd: string;
|
|
110
|
+
radiusLg: string;
|
|
111
|
+
contentWidth: string;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// ═══════════════════════════════════════════════════════════
|
|
115
|
+
// Defaults
|
|
116
|
+
// ═══════════════════════════════════════════════════════════
|
|
117
|
+
|
|
118
|
+
export function defaultPalette(): ColorPalette {
|
|
119
|
+
return {
|
|
120
|
+
bgColor: "#ffffff", textColor: "#000000", headingColor: "",
|
|
121
|
+
borderColor: "#cccccc", accentColor: "#0000ff", codeBg: "#f5f5f5",
|
|
122
|
+
codeColor: "", codeBlockBg: "#1e1e1e", codeBlockText: "#d4d4d4",
|
|
123
|
+
blockquoteBg: "#f9f9f9", blockquoteBorder: "",
|
|
124
|
+
tableHeaderBg: "#f0f0f0", selectionBg: "", textMuted: "#666666",
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function defaultTypography(): Typography {
|
|
129
|
+
return {
|
|
130
|
+
bodyFontFamily: "Georgia, serif", headingFontFamily: "",
|
|
131
|
+
codeFontFamily: "'JetBrains Mono', 'Fira Code', monospace",
|
|
132
|
+
baseFontSize: "16px", baseLineHeight: 1.9, headingWeight: 700,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function defaultSpacing(): Spacing {
|
|
137
|
+
return {
|
|
138
|
+
contentMaxWidth: "820px", contentPadding: "30px 60px 100px",
|
|
139
|
+
paragraphMargin: "0.8em 0", headingMarginTop: "1.8em",
|
|
140
|
+
headingMarginBottom: "0.6em",
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function defaultSyntax(): SyntaxHighlighting {
|
|
145
|
+
return { comment: "", punctuation: "", keyword: "", booleanBuiltinTag: "",
|
|
146
|
+
string: "", number: "", functionClass: "", operator: "", variable: "", regex: "" };
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export function defaultSeedPalette(): SeedPalette {
|
|
150
|
+
return {
|
|
151
|
+
accent: "#6366f1", accentLight: "#eef2ff", accentDark: "#4f46e5",
|
|
152
|
+
surface: "#ffffff", panel: "#f8f9fb", panelAlt: "#f1f3f5",
|
|
153
|
+
ink: "#1a1d26", inkMuted: "#6b7280", inkDim: "#9ca3af",
|
|
154
|
+
border: "#e5e7eb", borderStrong: "#d1d5db",
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export function defaultSeedTypography(): SeedTypography {
|
|
159
|
+
return {
|
|
160
|
+
fontBody: `"Inter", "SF Pro Text", -apple-system, "Noto Serif SC", "Source Han Serif SC", Georgia, serif`,
|
|
161
|
+
fontHeading: `"Inter", "SF Pro Display", -apple-system, "Noto Sans SC", "PingFang SC", sans-serif`,
|
|
162
|
+
fontCode: `"JetBrains Mono", "SF Mono", "Fira Code", Menlo, Consolas, monospace`,
|
|
163
|
+
fontMermaid: `var(--font-heading)`,
|
|
164
|
+
fontSizeRoot: "16px",
|
|
165
|
+
fontScaleH1: 2.0, fontScaleH2: 1.5, fontScaleH3: 1.25,
|
|
166
|
+
fontScaleH4: 1.1, fontScaleH5: 1.0, fontScaleH6: 0.95,
|
|
167
|
+
fontSizeMermaid: "13px",
|
|
168
|
+
lineHeightBody: 1.75, lineHeightHeading: 1.35, lineHeightCode: 1.6,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// ═══════════════════════════════════════════════════════════
|
|
173
|
+
// Factory
|
|
174
|
+
// ═══════════════════════════════════════════════════════════
|
|
175
|
+
|
|
176
|
+
export function makeThemeStyle(name: string, sourceType: string, sourceUrl: string): ThemeStyle {
|
|
177
|
+
return {
|
|
178
|
+
name,
|
|
179
|
+
description: `Theme extracted from ${sourceType}`,
|
|
180
|
+
palette: defaultPalette(),
|
|
181
|
+
typography: defaultTypography(),
|
|
182
|
+
spacing: defaultSpacing(),
|
|
183
|
+
syntax: defaultSyntax(),
|
|
184
|
+
seed: defaultSeedPalette(),
|
|
185
|
+
seedTypography: defaultSeedTypography(),
|
|
186
|
+
colorSystemId: "",
|
|
187
|
+
mermaidPresetId: "",
|
|
188
|
+
sourceUrl,
|
|
189
|
+
sourceType,
|
|
190
|
+
radiusSm: "3px",
|
|
191
|
+
radiusMd: "6px",
|
|
192
|
+
radiusLg: "10px",
|
|
193
|
+
contentWidth: "820px",
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/** Map legacy ColorPalette to SeedPalette. */
|
|
198
|
+
export function paletteToSeed(palette: ColorPalette): SeedPalette {
|
|
199
|
+
return {
|
|
200
|
+
accent: palette.accentColor,
|
|
201
|
+
accentLight: palette.selectionBg || palette.accentColor,
|
|
202
|
+
accentDark: palette.accentColor,
|
|
203
|
+
surface: palette.bgColor,
|
|
204
|
+
panel: palette.codeBg,
|
|
205
|
+
panelAlt: palette.codeBlockBg,
|
|
206
|
+
ink: palette.textColor,
|
|
207
|
+
inkMuted: palette.textMuted,
|
|
208
|
+
inkDim: palette.textMuted,
|
|
209
|
+
border: palette.borderColor,
|
|
210
|
+
borderStrong: palette.borderColor,
|
|
211
|
+
};
|
|
212
|
+
}
|