orz-markdown 1.0.0 → 1.2.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/README.md +28 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/plugins/attrs.d.ts.map +1 -1
- package/dist/plugins/attrs.js +10 -0
- package/dist/plugins/attrs.js.map +1 -1
- package/dist/plugins/mermaid.js +14 -1
- package/dist/plugins/mermaid.js.map +1 -1
- package/dist/plugins/qrcode.js +11 -1
- package/dist/plugins/qrcode.js.map +1 -1
- package/dist/plugins/smiles.js +4 -1
- package/dist/plugins/smiles.js.map +1 -1
- package/dist/plugins/youtube.js +9 -1
- package/dist/plugins/youtube.js.map +1 -1
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +283 -0
- package/dist/runtime.js.map +1 -1
- package/orz-markdown-skills/SKILL.md +179 -0
- package/orz-markdown-skills/assets/minimal.css +658 -0
- package/orz-markdown-skills/assets/template.html +505 -0
- package/orz-markdown-skills/references/block-ids.md +51 -0
- package/orz-markdown-skills/references/css-classes.md +218 -0
- package/orz-markdown-skills/references/syntax.md +439 -0
- package/orz-markdown-skills/references/themes.md +302 -0
- package/package.json +4 -2
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
# Custom Theme Guide — orz-markdown
|
|
2
|
+
|
|
3
|
+
How to write a CSS theme for the parser. A theme is a single CSS file that imports `common.css` for structural rules and then styles every element the parser emits.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Starting Point
|
|
8
|
+
|
|
9
|
+
Option A — start from scratch with shared infrastructure:
|
|
10
|
+
```css
|
|
11
|
+
@import 'orz-markdown/themes/common.css';
|
|
12
|
+
/* or relative path when living alongside the bundled themes: */
|
|
13
|
+
@import './common.css';
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Option B — start from `assets/minimal.css` (all structural rules already included, only visual layer needed). Copy it and add your visual styles on top.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Design Token Pattern
|
|
21
|
+
|
|
22
|
+
All bundled themes use CSS custom properties for maintainability. Define them on `:root`:
|
|
23
|
+
|
|
24
|
+
```css
|
|
25
|
+
:root {
|
|
26
|
+
/* Surface colors */
|
|
27
|
+
--bg: #ffffff;
|
|
28
|
+
--bg-surface: #f8f8f8;
|
|
29
|
+
--surface: #ffffff;
|
|
30
|
+
--border: #e0e0e0;
|
|
31
|
+
--border-soft: #eeeeee;
|
|
32
|
+
|
|
33
|
+
/* Text colors */
|
|
34
|
+
--text: #222222;
|
|
35
|
+
--text-soft: #555555;
|
|
36
|
+
--text-muted: #888888;
|
|
37
|
+
--heading: #111111;
|
|
38
|
+
|
|
39
|
+
/* Accent / link */
|
|
40
|
+
--accent: #0060cc;
|
|
41
|
+
--link: #0060cc;
|
|
42
|
+
--link-visited: #5050aa;
|
|
43
|
+
|
|
44
|
+
/* Code */
|
|
45
|
+
--code-bg: #f5f5f5;
|
|
46
|
+
--code-border: #dddddd;
|
|
47
|
+
--code-text: #333333;
|
|
48
|
+
|
|
49
|
+
/* Semantic callout colors (4 required sets) */
|
|
50
|
+
--success-bg: #efffed; --success-border: #5ab85a; --success-text: #1a5e2a;
|
|
51
|
+
--info-bg: #e8f4fd; --info-border: #5a9fd4; --info-text: #1a4a70;
|
|
52
|
+
--warning-bg: #fff8e1; --warning-border: #e0a820; --warning-text: #7a5c00;
|
|
53
|
+
--danger-bg: #fff0f0; --danger-border: #d45a5a; --danger-text: #7a1a1a;
|
|
54
|
+
|
|
55
|
+
/* Inline span colors */
|
|
56
|
+
--span-red: #c0392b;
|
|
57
|
+
--span-yellow: #9a7615;
|
|
58
|
+
--span-green: #218763;
|
|
59
|
+
--span-blue: #1d6db0;
|
|
60
|
+
|
|
61
|
+
/* Typography */
|
|
62
|
+
--font-body: system-ui, sans-serif;
|
|
63
|
+
--font-heading: system-ui, sans-serif;
|
|
64
|
+
--font-code: monospace;
|
|
65
|
+
--base-size: 1rem;
|
|
66
|
+
--line-height: 1.7;
|
|
67
|
+
|
|
68
|
+
/* Markdown body container */
|
|
69
|
+
--markdown-body-max-width: 860px;
|
|
70
|
+
--markdown-body-padding: clamp(1.5rem, 5vw, 3rem);
|
|
71
|
+
--markdown-body-border: 1px solid var(--border);
|
|
72
|
+
--markdown-body-shadow: none;
|
|
73
|
+
--markdown-body-radius: 0px;
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
For dark themes add `color-scheme: dark` so browser chrome adapts:
|
|
78
|
+
```css
|
|
79
|
+
:root { color-scheme: dark; }
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Recommended File Structure
|
|
85
|
+
|
|
86
|
+
Follow this section order in every theme file for consistency:
|
|
87
|
+
|
|
88
|
+
1. `@import './common.css'` and metadata comments
|
|
89
|
+
2. `:root` theme tokens
|
|
90
|
+
3. Optional modifier classes (`.font-*`, `.size-*`) if implemented
|
|
91
|
+
4. Reset and document shell (`html`, `body`, `*`)
|
|
92
|
+
5. `.markdown-body` container: max-width, padding, surface
|
|
93
|
+
6. Headings `h1`–`h6` and `.header-anchor`
|
|
94
|
+
7. Body copy: `p`, `strong`, `em`, `s`, `mark`, `ins`, `sub`, `sup`
|
|
95
|
+
8. Links: `a`, `a:hover`, `a:visited`
|
|
96
|
+
9. Lists and task lists: `ul`, `ol`, `li`, `.task-list-item`
|
|
97
|
+
10. Code and math: `code`, `pre`, `.katex`, `.katex-display`
|
|
98
|
+
11. Structural blocks: `blockquote`, `table`, `img`, `hr`
|
|
99
|
+
12. Semantic containers: `.success`, `.info`, `.warning`, `.danger`
|
|
100
|
+
13. Layout utilities: `.left`, `.right`, `.center`
|
|
101
|
+
14. Spoiler, tabs, and columns: `details.spoil`, `.tabs`, `.cols`
|
|
102
|
+
15. TOC and footnotes: `nav.toc`, `.footnotes`
|
|
103
|
+
16. Plugin output: `.youtube-embed`, `.mermaid`, `.smiles-render`, `.qrcode`, span color/badge classes
|
|
104
|
+
17. Decorative pseudo-elements and theme-only flourishes
|
|
105
|
+
18. Responsive rules (`@media`)
|
|
106
|
+
19. Print rules (`@media print`)
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## Optional Modifier Classes
|
|
111
|
+
|
|
112
|
+
Some bundled themes expose utility classes for runtime font and size switching. If you implement them, follow the same class names for interoperability:
|
|
113
|
+
|
|
114
|
+
```css
|
|
115
|
+
/* Font family modifiers — applied to body or .markdown-body */
|
|
116
|
+
.font-serif { font-family: var(--font-body-serif, Georgia, serif); }
|
|
117
|
+
.font-sans { font-family: var(--font-body-sans, system-ui, sans-serif); }
|
|
118
|
+
.font-handwritten { font-family: var(--font-body-handwritten, cursive); }
|
|
119
|
+
.font-typewrite { font-family: var(--font-body-mono, monospace); }
|
|
120
|
+
|
|
121
|
+
/* Size modifiers */
|
|
122
|
+
.size-xs { font-size: 0.8rem; }
|
|
123
|
+
.size-sm { font-size: 0.9rem; }
|
|
124
|
+
.size-lg { font-size: 1.15rem; }
|
|
125
|
+
.size-xl { font-size: 1.3rem; }
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
These are not required by `common.css` — they are opt-in per theme.
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Element Checklist
|
|
133
|
+
|
|
134
|
+
Every theme must have CSS rules for all of the following. See `references/css-classes.md` for the exact selectors.
|
|
135
|
+
|
|
136
|
+
### Container & page
|
|
137
|
+
- [ ] `body` — page background, base font, line-height
|
|
138
|
+
- [ ] `.markdown-body` — outer container: max-width, padding, background, border
|
|
139
|
+
|
|
140
|
+
### Headings and anchors
|
|
141
|
+
- [ ] `h1` `h2` `h3` `h4` `h5` `h6` — font size, color, margin, font-family
|
|
142
|
+
- [ ] `.header-anchor` — hidden by default, visible on heading hover
|
|
143
|
+
|
|
144
|
+
### Inline text
|
|
145
|
+
- [ ] `p` `a` `a:visited` `a:hover`
|
|
146
|
+
- [ ] `strong` `em` `s` / `del` `mark` `ins` `sub` `sup`
|
|
147
|
+
- [ ] `code` (inline) — background, border, border-radius, font
|
|
148
|
+
- [ ] `pre` — block container: background, border, overflow
|
|
149
|
+
- [ ] `pre > code` — reset border/background, set font-size and line-height
|
|
150
|
+
|
|
151
|
+
### Structural blocks
|
|
152
|
+
- [ ] `blockquote` — left border or background, text color
|
|
153
|
+
- [ ] `ul` `ol` `li` — padding, list markers
|
|
154
|
+
- [ ] `.task-list-item` `.task-list-item-checkbox`
|
|
155
|
+
- [ ] `table` `thead` `tbody` `th` `td` — borders, header background, row striping
|
|
156
|
+
- [ ] `hr` — height, color, margin
|
|
157
|
+
- [ ] `img` — margin, optional border/radius
|
|
158
|
+
|
|
159
|
+
### Plugins and containers
|
|
160
|
+
- [ ] `.footnote-ref` `.footnote-ref a` `.footnotes` `.footnotes-sep` `.footnote-backref`
|
|
161
|
+
- [ ] `.katex` `.katex-display` `.katex-error`
|
|
162
|
+
- [ ] `div.success` `div.info` `div.warning` `div.danger` — background, border, text color
|
|
163
|
+
- [ ] `.left` `.right` `.center` — float/alignment, optional box styling
|
|
164
|
+
- [ ] `details.spoil` `details.spoil > summary` — border, summary background, open/closed marker
|
|
165
|
+
- [ ] `.tabs` `.tabs-bar` `.tabs-bar-btn` `.tabs-bar-btn.active` `.tab` `.tab.active`
|
|
166
|
+
- [ ] `.tabs:not([data-js]) .tab` — no-JS fallback: show all panels
|
|
167
|
+
- [ ] `.cols` `.col`
|
|
168
|
+
- [ ] `nav.toc` `.toc-list` — list reset, link styles
|
|
169
|
+
- [ ] `span.red` `span.yellow` `span.green` `span.blue`
|
|
170
|
+
- [ ] `span.success` `span.info` `span.warning` `span.danger` — inline badge variant
|
|
171
|
+
- [ ] `div.youtube-embed` `div.youtube-embed iframe` — 16:9 responsive wrapper (structural)
|
|
172
|
+
- [ ] `div.mermaid` `div.mermaid svg`
|
|
173
|
+
- [ ] `div.smiles-render` `canvas[data-smiles]`
|
|
174
|
+
- [ ] `span.qrcode` — **must have `background: #fff`** (SVG is always black-on-white)
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Design Guidelines
|
|
179
|
+
|
|
180
|
+
### 1. Scope under `.markdown-body`
|
|
181
|
+
|
|
182
|
+
Prefix all element rules with `.markdown-body` to avoid polluting global page styles. Exception: `body`, `html`, and `::selection` are acceptable at page scope.
|
|
183
|
+
|
|
184
|
+
```css
|
|
185
|
+
/* Good */
|
|
186
|
+
.markdown-body h2 { ... }
|
|
187
|
+
.markdown-body blockquote { ... }
|
|
188
|
+
|
|
189
|
+
/* Page-scoped (OK) */
|
|
190
|
+
body { background: var(--bg); font-family: var(--font-body); }
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### 2. Semantic callouts must be visibly distinct
|
|
194
|
+
|
|
195
|
+
`div.success/info/warning/danger` must clearly differ from regular content even in neutral palettes. The four semantic meanings (green/blue/amber/red) must be preserved — do not swap, remove, or use identical styles for multiple variants.
|
|
196
|
+
|
|
197
|
+
### 3. QR codes always need white background
|
|
198
|
+
|
|
199
|
+
The SVG emitted inside `.qrcode` is black-on-transparent. Set an explicit white background on both the inline widget and the overlay so it reads correctly on dark themes:
|
|
200
|
+
|
|
201
|
+
```css
|
|
202
|
+
span.qrcode { background: #fff; padding: 4px; }
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### 4. Tabs functional CSS is non-negotiable
|
|
206
|
+
|
|
207
|
+
The tabs show/hide behavior depends on these rules being present. They are functional, not decorative:
|
|
208
|
+
|
|
209
|
+
```css
|
|
210
|
+
.tab { display: none; }
|
|
211
|
+
.tab.active { display: block; }
|
|
212
|
+
.tabs:not([data-js]) .tab { display: block; } /* no-JS fallback */
|
|
213
|
+
.tabs:not([data-js]) .tab + .tab { border-top: 1px solid ...; } /* visual separator */
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### 5. Spoiler open/close marker is functional
|
|
217
|
+
|
|
218
|
+
The `summary::before` pseudo-element communicating open/closed state must be present. Use `+`/`–`, `▶`/`▼`, or any clear pair:
|
|
219
|
+
|
|
220
|
+
```css
|
|
221
|
+
details.spoil > summary::before { content: '+'; }
|
|
222
|
+
details.spoil[open] > summary::before { content: '–'; }
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### 6. YouTube embed needs the 16:9 hack
|
|
226
|
+
|
|
227
|
+
The responsive iframe technique is structural — do not change the core ratio or remove it:
|
|
228
|
+
|
|
229
|
+
```css
|
|
230
|
+
div.youtube-embed { position: relative; height: 0; padding-bottom: 56.25%; overflow: hidden; }
|
|
231
|
+
div.youtube-embed iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### 7. Float `.left` needs a mobile breakpoint
|
|
235
|
+
|
|
236
|
+
Without this the float causes overflow on narrow screens:
|
|
237
|
+
|
|
238
|
+
```css
|
|
239
|
+
@media (max-width: 600px) {
|
|
240
|
+
.left { float: none; max-width: 100%; margin-right: 0; }
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### 8. Dark themes: code block foreground vs syntax highlighting
|
|
245
|
+
|
|
246
|
+
Highlight.js injects its own colors into `<code>` tokens. Set `pre code { color: inherit; }` and choose a matching Highlight.js theme (e.g., `atom-one-dark.min.css`) rather than fighting it with heavy specificity.
|
|
247
|
+
|
|
248
|
+
### 9. Keep the palette small and purposeful
|
|
249
|
+
|
|
250
|
+
Avoid "AI tells": no gradients on every element, no excessive border-radius, no layout that relies on 15+ custom properties for a single component. Two to four accent colors with consistent usage throughout is more human than a rainbow.
|
|
251
|
+
|
|
252
|
+
### 10. Test with `tests/example.html`
|
|
253
|
+
|
|
254
|
+
After writing your theme, run `npm run render` from the project root to regenerate the example page and visually verify every element type. The example page includes all containers, all custom plugins, math, chemistry, mermaid, code blocks, tables, and footnotes.
|
|
255
|
+
|
|
256
|
+
### 11. CJK font stacks
|
|
257
|
+
|
|
258
|
+
Include CJK fallback fonts in your font stacks for proper Chinese/Japanese/Korean glyph rendering:
|
|
259
|
+
|
|
260
|
+
- **Serif themes**: include `Noto Serif TC`, `Noto Serif SC` in the serif stack
|
|
261
|
+
- **Sans-serif themes**: include `Noto Sans TC`, `Noto Sans SC` in the sans stack
|
|
262
|
+
- **Handwritten themes**: prefer `Hanzi Pen TC`, `Hanzi Pen SC`
|
|
263
|
+
|
|
264
|
+
```css
|
|
265
|
+
--font-body: 'Your Primary Font', 'Noto Sans TC', 'Noto Sans SC', system-ui, sans-serif;
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### 12. SMILES rendering: match the page color scheme
|
|
269
|
+
|
|
270
|
+
SmilesDrawer's `draw()` call accepts a theme argument (`'light'` or `'dark'`). Dark-background themes need `'dark'` so bonds and atoms render white instead of black. This is set in the page initialization script (see `assets/template.html`), not in CSS — but coordinate with it:
|
|
271
|
+
|
|
272
|
+
```js
|
|
273
|
+
// Light themes:
|
|
274
|
+
drawer.draw(tree, canvas, 'light', false);
|
|
275
|
+
// Dark themes:
|
|
276
|
+
drawer.draw(tree, canvas, 'dark', false);
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
## Theme Compliance Checklist
|
|
282
|
+
|
|
283
|
+
Use this when auditing an existing theme or reviewing a new one:
|
|
284
|
+
|
|
285
|
+
- [ ] Section order follows the 19-section structure above
|
|
286
|
+
- [ ] `@import './common.css'` is the first line
|
|
287
|
+
- [ ] Base font size and line-height are declared as `:root` tokens near the top
|
|
288
|
+
- [ ] `.markdown-body` max-width, padding, border, and shadow are easy to override
|
|
289
|
+
- [ ] All heading levels `h1`–`h6` are styled distinctly
|
|
290
|
+
- [ ] Ordered lists use decimal counters (`1, 2, 3`) — never `01, 02, 03`
|
|
291
|
+
- [ ] Narrow tables shrink to content width instead of always stretching to full width
|
|
292
|
+
- [ ] All four semantic containers (`success/info/warning/danger`) are visually distinct
|
|
293
|
+
- [ ] Badge spans (`span.success/info/warning/danger`) stay single-line — no pseudo-label text injected
|
|
294
|
+
- [ ] QR code: `span.qrcode` has explicit `background: #fff` (SVG is always black-on-white)
|
|
295
|
+
- [ ] `.left` float has a mobile breakpoint (`float: none` below ~600px)
|
|
296
|
+
- [ ] Tabs show/hide CSS is functional (`display: none` default, `block` when `.active`)
|
|
297
|
+
- [ ] `.tabs:not([data-js]) .tab` fallback shows all panels when JS is absent
|
|
298
|
+
- [ ] Spoiler open/close marker (`summary::before`) communicates state clearly
|
|
299
|
+
- [ ] YouTube embed uses the 16:9 padding-bottom trick
|
|
300
|
+
- [ ] SMILES container is visually neutral — no decorative box styling
|
|
301
|
+
- [ ] Print rules strip outer body framing, fit paper width, and repeat `thead` across pages
|
|
302
|
+
- [ ] CJK font fallbacks are present in serif/sans/handwritten font stacks
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "orz-markdown",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Customized markdown-it parser with official and custom plugins",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
},
|
|
12
12
|
"files": [
|
|
13
13
|
"dist",
|
|
14
|
-
"themes"
|
|
14
|
+
"themes",
|
|
15
|
+
"orz-markdown-skills"
|
|
15
16
|
],
|
|
16
17
|
"scripts": {
|
|
17
18
|
"build": "tsc",
|
|
@@ -63,6 +64,7 @@
|
|
|
63
64
|
"@types/markdown-it-footnote": "^3.0.4",
|
|
64
65
|
"@types/node": "^25.3.5",
|
|
65
66
|
"@types/qrcode-svg": "^1.1.5",
|
|
67
|
+
"happy-dom": "^15.11.0",
|
|
66
68
|
"tsx": "^4.21.0",
|
|
67
69
|
"typescript": "^5.9.3",
|
|
68
70
|
"vitest": "^4.0.18"
|