orz-markdown 1.2.2 → 1.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/README.md +20 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/plugins/chart.d.ts +2 -0
- package/dist/plugins/chart.d.ts.map +1 -0
- package/dist/plugins/chart.js +137 -0
- package/dist/plugins/chart.js.map +1 -0
- package/dist/preview-frame.d.ts +59 -0
- package/dist/preview-frame.d.ts.map +1 -0
- package/dist/preview-frame.js +88 -0
- package/dist/preview-frame.js.map +1 -0
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +69 -5
- package/dist/runtime.js.map +1 -1
- package/orz-markdown-skills/SKILL.md +10 -4
- package/orz-markdown-skills/assets/template.html +2 -2
- package/orz-markdown-skills/references/embedding.md +195 -0
- package/package.json +4 -1
- package/themes/README.md +43 -0
- package/themes/beige-decent-1.css +27 -2
- package/themes/beige-decent-2.css +23 -3
- package/themes/dark-elegant-1.css +11 -0
- package/themes/dark-elegant-2.css +17 -9
- package/themes/dark-elegant-3.css +297 -0
- package/themes/light-academic-1.css +49 -1
- package/themes/light-academic-2.css +25 -1
- package/themes/light-neat-1.css +23 -9
- package/themes/light-neat-2.css +8 -5
- package/themes/light-neat-3.css +383 -0
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# Embedding orz-markdown in a host app (custom stylesheet)
|
|
2
|
+
|
|
3
|
+
Read this when you call `md.render()` and supply **your own CSS and page shell**
|
|
4
|
+
instead of using a bundled theme — e.g. a slide engine, a doc viewer, an editor,
|
|
5
|
+
or any app that embeds rendered output. The bundled themes already do everything
|
|
6
|
+
below; this guide is the checklist for when you *don't* use them.
|
|
7
|
+
|
|
8
|
+
> The sibling `orz-slides` project hit a long tail of bugs (unstyled containers,
|
|
9
|
+
> bold that changed colour instead of weight, broken sub/sup, diagrams
|
|
10
|
+
> overflowing, copy losing `{{sp}}`/`:::` source) precisely because these points
|
|
11
|
+
> weren't gathered in one place. Follow this and you skip all of it.
|
|
12
|
+
|
|
13
|
+
There are **three** things to get right: CSS, JavaScript, and copy-as-Markdown.
|
|
14
|
+
|
|
15
|
+
> **Shortcut for iframe hosts — `getPreviewFrameAssets()`.** Most of the
|
|
16
|
+
> JavaScript below is the same everywhere, so it lives in one helper:
|
|
17
|
+
>
|
|
18
|
+
> ```js
|
|
19
|
+
> import { getPreviewFrameAssets } from 'orz-markdown/preview-frame';
|
|
20
|
+
> const pa = getPreviewFrameAssets();
|
|
21
|
+
> ```
|
|
22
|
+
>
|
|
23
|
+
> It returns the pinned CDN URLs (`pa.cdn`), the runtime (`pa.runtimeScript`), and
|
|
24
|
+
> ready-made strings: `pa.headLinks(scheme)` (KaTeX + highlight.js CSS, the hljs
|
|
25
|
+
> link carries `id="orz-hljs"`) for the iframe `<head>`, and `pa.bodyScripts()`
|
|
26
|
+
> (loads the libs + runtime and defines `window.__orzEnhance()`) for the `<body>`.
|
|
27
|
+
> After each render call `window.__orzEnhance()` — it highlights code, runs
|
|
28
|
+
> mermaid, draws SMILES (honoring `window.__orzSmilesTheme`) and charts, and
|
|
29
|
+
> re-inits the runtime (tabs + QR). On theme change swap
|
|
30
|
+
> `doc.getElementById('orz-hljs').href = pa.hljsCss(scheme)`. `__orzEnhance`
|
|
31
|
+
> scopes to `.markdown-body`, so it works whatever id/wrapper you use. The rest of
|
|
32
|
+
> this page is what that helper does under the hood — read it if you hand-roll the
|
|
33
|
+
> wiring or need to understand a failure.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 1. CSS
|
|
38
|
+
|
|
39
|
+
The parser emits plain HTML plus plugin/container classes. Two reference docs
|
|
40
|
+
have the full detail:
|
|
41
|
+
|
|
42
|
+
- `references/css-classes.md` — every class and element the parser emits.
|
|
43
|
+
- `references/themes.md` — the element checklist and design guidance.
|
|
44
|
+
|
|
45
|
+
When you bring your own stylesheet, the four things that bite hardest:
|
|
46
|
+
|
|
47
|
+
### 1a. Wrap output in `.markdown-body` and scope your rules to it
|
|
48
|
+
|
|
49
|
+
```html
|
|
50
|
+
<article class="markdown-body"> …md.render() output… </article>
|
|
51
|
+
```
|
|
52
|
+
Every theme rule is scoped under `.markdown-body`; copy-as-Markdown also keys off
|
|
53
|
+
this class (§3). For a region-based layout, each rendered region gets its own
|
|
54
|
+
`.markdown-body`.
|
|
55
|
+
|
|
56
|
+
### 1b. A host CSS *reset* will strip inline semantics — restore them
|
|
57
|
+
|
|
58
|
+
This is the #1 non-obvious failure. Many app/framework resets (notably
|
|
59
|
+
**reveal.js**'s `reset.css`) apply to `strong, b, em, i, sub, sup, small, …`:
|
|
60
|
+
|
|
61
|
+
```css
|
|
62
|
+
em, strong, sub, sup, b, i, small, … { font: inherit; font-size: 100%; vertical-align: baseline; }
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`font: inherit` wipes `font-weight`/`font-style`, and `vertical-align: baseline`
|
|
66
|
+
+ `font-size: 100%` flattens sub/sup. The result: **bold isn't bold, italic
|
|
67
|
+
isn't italic, H~2~O / x^2^ render flat.** (A theme that "fixed" bold with
|
|
68
|
+
`strong { color: accent }` then makes bold *vanish* wherever the accent equals
|
|
69
|
+
the background.) If your host has any such reset, restore the semantics
|
|
70
|
+
explicitly — **bold is weight, not colour**:
|
|
71
|
+
|
|
72
|
+
```css
|
|
73
|
+
.markdown-body strong, .markdown-body b { font-weight: 700; }
|
|
74
|
+
.markdown-body em, .markdown-body i { font-style: italic; }
|
|
75
|
+
.markdown-body s, .markdown-body del { text-decoration: line-through; }
|
|
76
|
+
.markdown-body ins,.markdown-body u { text-decoration: underline; }
|
|
77
|
+
.markdown-body sub, .markdown-body sup { font-size: 0.75em; line-height: 0; position: relative; vertical-align: baseline; }
|
|
78
|
+
.markdown-body sub { bottom: -0.3em; }
|
|
79
|
+
.markdown-body sup { top: -0.5em; }
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### 1c. Style **every** plugin/container class, or it renders unstyled
|
|
83
|
+
|
|
84
|
+
If you don't ship the bundled `common.css`/theme, these have **no** styling and
|
|
85
|
+
look broken. Minimum set (see `css-classes.md` for the exact selectors):
|
|
86
|
+
|
|
87
|
+
| Construct | Selectors to style |
|
|
88
|
+
|---|---|
|
|
89
|
+
| Admonitions | `div.info`, `div.success`, `div.warning`, `div.danger` |
|
|
90
|
+
| Spans — colour | `span.red`, `span.green`, `span.blue`, `span.yellow` (colour only) |
|
|
91
|
+
| Spans — badge | `span.success/info/warning/danger` — **need** `display:inline-flex; align-items:center; line-height:1; white-space:nowrap` + padding/radius (normally in `common.css`) |
|
|
92
|
+
| Columns | `.cols` (CSS grid), `.col` |
|
|
93
|
+
| Tabs | `.tabs`, `.tabs-bar`, `.tabs-bar-btn`(`.active`), `.tab`; **`.tabs:not([data-js]) .tab { display:block }`** (no-JS fallback) and `.tabs[data-js] .tab{display:none}` / `.tab.active{display:block}` |
|
|
94
|
+
| Spoiler | `details.spoil`, `summary` |
|
|
95
|
+
| Alignment | `div.left`, `div.center`, `div.right` (`text-align`) |
|
|
96
|
+
| QR | `span.qrcode` — **must** have `background:#fff; padding` (the SVG is black-on-transparent) |
|
|
97
|
+
| YouTube | `.youtube-embed` — the iframe has **no width/height**; make it a 16:9 responsive box or it defaults to 300×150 |
|
|
98
|
+
| Math | `.katex`, `.katex-display` (load `katex.min.css`) |
|
|
99
|
+
| Diagrams/chem | `.mermaid svg`, `.smiles-render canvas` / `canvas[data-smiles]` |
|
|
100
|
+
|
|
101
|
+
### 1d. Constrain generated graphics so they fit
|
|
102
|
+
|
|
103
|
+
Mermaid SVGs and smiles/chart canvases have intrinsic sizes and will overflow a
|
|
104
|
+
bounded container. At minimum cap the width; in a fixed-size layout (slides),
|
|
105
|
+
size them to the container in JS (measure the container, set explicit
|
|
106
|
+
width/height by the SVG's `viewBox` aspect; for Chart.js use `responsive:false`
|
|
107
|
+
+ explicit `resize(w,h)` because it can't read a definite height through a CSS
|
|
108
|
+
grid). Mermaid also sets an inline `max-width` you may need to override.
|
|
109
|
+
|
|
110
|
+
```css
|
|
111
|
+
.markdown-body .mermaid svg,
|
|
112
|
+
.markdown-body canvas[data-smiles],
|
|
113
|
+
.markdown-body canvas.orz-chart { max-width: 100%; height: auto; }
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## 2. JavaScript
|
|
119
|
+
|
|
120
|
+
Rendering is pure HTML, but several constructs need client-side JS **after mount**.
|
|
121
|
+
|
|
122
|
+
### 2a. Load the runtime — tabs, QR expand, and copy
|
|
123
|
+
|
|
124
|
+
```js
|
|
125
|
+
import { getBrowserRuntimeScript } from 'orz-markdown/runtime';
|
|
126
|
+
const s = document.createElement('script');
|
|
127
|
+
s.textContent = getBrowserRuntimeScript();
|
|
128
|
+
document.body.appendChild(s);
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
It auto-runs `OrzMarkdownRuntime.init(document)` **once** on `DOMContentLoaded`
|
|
132
|
+
and wires the global copy handler. It exposes
|
|
133
|
+
`OrzMarkdownRuntime.{ init, initTabs, initQrCodes, elementToMarkdown }`.
|
|
134
|
+
|
|
135
|
+
**If you render content dynamically** (after load, or re-render — e.g. an editor
|
|
136
|
+
or a slide engine), the one-time `init` won't see it. Call
|
|
137
|
+
`OrzMarkdownRuntime.init(newRoot)` (or `initTabs`/`initQrCodes`) on the new
|
|
138
|
+
content yourself. `initTabs` guards on `data-js="1"` — if you also have your own
|
|
139
|
+
tab init, use the **same** `data-js="1"` marker so the two don't both build a bar
|
|
140
|
+
(double tab bar bug).
|
|
141
|
+
|
|
142
|
+
### 2b. The runtime does **not** draw diagrams/charts — you do
|
|
143
|
+
|
|
144
|
+
mermaid, smiles, and chart canvases are placeholders. Load the libraries and draw
|
|
145
|
+
them (the bundled themes/`tests/example.html` show the calls):
|
|
146
|
+
|
|
147
|
+
| Construct | You must load | Then |
|
|
148
|
+
|---|---|---|
|
|
149
|
+
| `.mermaid` | mermaid.js | `mermaid.run({ querySelector: '.mermaid' })` |
|
|
150
|
+
| `canvas[data-smiles]` | smiles-drawer | `SmilesDrawer.parse(...)` → `drawer.draw(tree, canvas, scheme, false)` — pass `'dark'` on dark backgrounds so bonds are light |
|
|
151
|
+
| `canvas.orz-chart` | Chart.js | `new Chart(canvas, JSON.parse(canvas.dataset.chart))` |
|
|
152
|
+
| `$…$` / `$$…$$` | KaTeX **CSS** only | math is pre-rendered by `md.render()`; you just need `katex.min.css` |
|
|
153
|
+
|
|
154
|
+
Draw on first display and re-draw when the container resizes; canvases drawn
|
|
155
|
+
while their container is hidden (`display:none`) size to 0.
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## 3. Copy-as-Markdown
|
|
160
|
+
|
|
161
|
+
Selecting rendered content and copying yields **Markdown source** when (and only
|
|
162
|
+
when) all of this holds:
|
|
163
|
+
|
|
164
|
+
1. **The runtime is loaded** (§2a) — it installs the `copy` handler and the
|
|
165
|
+
DOM→Markdown walker (`elementToMarkdown`).
|
|
166
|
+
2. **Content is inside `.markdown-body`** (or an element with `data-orz-copy`).
|
|
167
|
+
The handler ignores selections elsewhere and inside inputs/textareas.
|
|
168
|
+
3. **`data-md` breadcrumbs are preserved.** Generated constructs whose source is
|
|
169
|
+
otherwise lost — `mermaid`, `smiles`, `qrcode`, `youtube`, `toc`, `chart`,
|
|
170
|
+
`{{sp}}` (and any plugin that adds one) — carry `data-md` with their original
|
|
171
|
+
directive. The walker emits it verbatim. **Never strip `data-md`** when you
|
|
172
|
+
post-process HTML.
|
|
173
|
+
4. **Plugin/container classes are preserved.** Constructs without a `data-md`
|
|
174
|
+
are recovered *by class*: `<span class="red">` → `{{sp[red] …}}`,
|
|
175
|
+
`<div class="center">` → `::: center … :::`, nested `cols`/`tabs` get the
|
|
176
|
+
right fence length. If you rewrite/strip these classes, copy loses the source.
|
|
177
|
+
|
|
178
|
+
Caveat: a container (`::: center`, `:::: cols`, spoiler, tabs) is recovered only
|
|
179
|
+
when the **selection includes the container element**, not just the text inside
|
|
180
|
+
it — select the whole block/region, not the inner words.
|
|
181
|
+
|
|
182
|
+
Convert a node directly: `OrzMarkdownRuntime.elementToMarkdown(node)`.
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Pre-flight checklist
|
|
187
|
+
|
|
188
|
+
- [ ] Output wrapped in `.markdown-body`; rules scoped under it.
|
|
189
|
+
- [ ] Inline semantics restored if a host reset touches `strong/em/sub/sup/…` (§1b).
|
|
190
|
+
- [ ] Every admonition / span / cols / tabs / spoil / align / qr / youtube / math / diagram class is styled (§1c, `css-classes.md`).
|
|
191
|
+
- [ ] Span badges have the inline-flex structural CSS; QR has a white plate; tabs have the no-JS fallback; YouTube is a 16:9 box.
|
|
192
|
+
- [ ] Graphics are width-capped (and size-fitted in fixed layouts) (§1d).
|
|
193
|
+
- [ ] Runtime loaded; `init` re-run on dynamically rendered content; tab `data-js="1"` aligned (§2a).
|
|
194
|
+
- [ ] mermaid / smiles-drawer / Chart.js loaded and drawn; KaTeX CSS loaded (§2b).
|
|
195
|
+
- [ ] `data-md` and plugin/container classes preserved end-to-end for copy (§3).
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "orz-markdown",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.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",
|
|
7
7
|
"exports": {
|
|
8
8
|
".": "./dist/index.js",
|
|
9
9
|
"./runtime": "./dist/runtime.js",
|
|
10
|
+
"./preview-frame": "./dist/preview-frame.js",
|
|
10
11
|
"./themes/*": "./themes/*"
|
|
11
12
|
},
|
|
12
13
|
"files": [
|
|
@@ -64,7 +65,9 @@
|
|
|
64
65
|
"@types/markdown-it-footnote": "^3.0.4",
|
|
65
66
|
"@types/node": "^25.3.5",
|
|
66
67
|
"@types/qrcode-svg": "^1.1.5",
|
|
68
|
+
"esbuild": "^0.21.5",
|
|
67
69
|
"happy-dom": "^15.11.0",
|
|
70
|
+
"path-browserify": "^1.0.1",
|
|
68
71
|
"tsx": "^4.21.0",
|
|
69
72
|
"typescript": "^5.9.3",
|
|
70
73
|
"vitest": "^4.0.18"
|
package/themes/README.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# orz-markdown themes
|
|
2
|
+
|
|
3
|
+
Twelve ready-to-use CSS themes for the parser's output. All rendered HTML lives
|
|
4
|
+
inside `<article class="markdown-body">`, so every theme is scoped to that class.
|
|
5
|
+
Each theme `@import`s the shared `common.css` (structural rules for tables,
|
|
6
|
+
images, KaTeX blocks, QR overlays, tabs/columns, and print), so you only ever
|
|
7
|
+
import a **single** theme file.
|
|
8
|
+
|
|
9
|
+
```js
|
|
10
|
+
// With a bundler:
|
|
11
|
+
import 'orz-markdown/themes/light-academic-1.css';
|
|
12
|
+
|
|
13
|
+
// Or over a CDN (jsDelivr):
|
|
14
|
+
// https://cdn.jsdelivr.net/npm/orz-markdown/themes/light-academic-1.css
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Bundled themes
|
|
18
|
+
|
|
19
|
+
| File | Style | Scheme |
|
|
20
|
+
|---|---|---|
|
|
21
|
+
| `light-neat-1.css` | Figtree · clean modern sans | Light |
|
|
22
|
+
| `light-neat-2.css` | Light neat variant | Light |
|
|
23
|
+
| `light-neat-3.css` | Bricolage · calm green — "Orchard" | Light |
|
|
24
|
+
| `light-academic-1.css` | Alegreya · justified scholarly prose | Light |
|
|
25
|
+
| `light-academic-2.css` | Light academic variant | Light |
|
|
26
|
+
| `beige-decent-1.css` | Warm beige · print-like prose | Light |
|
|
27
|
+
| `beige-decent-2.css` | Beige decent variant | Light |
|
|
28
|
+
| `light-playful-1.css` | Casual · personal blog | Light |
|
|
29
|
+
| `light-playful-2.css` | Light playful variant | Light |
|
|
30
|
+
| `dark-elegant-1.css` | Cinzel headings · scholarly serif | Dark |
|
|
31
|
+
| `dark-elegant-2.css` | Dark elegant variant | Dark |
|
|
32
|
+
| `dark-elegant-3.css` | Lora · VS Code-dark, colourful headings — "Nocturne" | Dark |
|
|
33
|
+
|
|
34
|
+
`common.css` is not a theme — it is imported automatically by each theme above.
|
|
35
|
+
|
|
36
|
+
## Theming your own output
|
|
37
|
+
|
|
38
|
+
If you supply your **own** stylesheet instead of a bundled theme, the
|
|
39
|
+
[embedding guide](../orz-markdown-skills/references/embedding.md) lists every CSS
|
|
40
|
+
class the parser emits (semantic containers, tabs/columns, spoilers, KaTeX
|
|
41
|
+
blocks, Mermaid/SMILES/chart canvases, clickable QR codes) and the JavaScript the
|
|
42
|
+
browser runtime needs. Start from `common.css` for the structural rules and layer
|
|
43
|
+
your visual design on top.
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
--line-height: 1.7;
|
|
28
28
|
|
|
29
29
|
--markdown-body-max-width: 800px;
|
|
30
|
-
--markdown-body-padding:
|
|
30
|
+
--markdown-body-padding: 2rem 2rem 4rem;
|
|
31
31
|
--markdown-body-border: none;
|
|
32
32
|
--markdown-body-radius: 0;
|
|
33
33
|
--markdown-body-shadow: none;
|
|
@@ -56,6 +56,8 @@ body {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
/* 2. Headings and body copy */
|
|
59
|
+
.markdown-body > :first-child { margin-top: 0; }
|
|
60
|
+
|
|
59
61
|
.markdown-body h1,
|
|
60
62
|
.markdown-body h2,
|
|
61
63
|
.markdown-body h3,
|
|
@@ -556,4 +558,27 @@ body {
|
|
|
556
558
|
box-shadow: none;
|
|
557
559
|
}
|
|
558
560
|
|
|
559
|
-
}
|
|
561
|
+
}
|
|
562
|
+
/* code block — warm paper panel */
|
|
563
|
+
.markdown-body pre { background: #f5f0e6; border: 1px solid #e7ddc9; border-radius: 8px; }
|
|
564
|
+
.markdown-body pre code, .markdown-body pre code.hljs { background: transparent; padding: 0; }
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
/* ============ modern decorative refresh ============ */
|
|
568
|
+
/* blockquote — warm card with a soft corner quote glyph (replaces the top/bottom rules) */
|
|
569
|
+
.markdown-body blockquote { position: relative; border: none; background: #f3ece0; border-radius: 12px;
|
|
570
|
+
padding: 1.1rem 1.4rem 1.1rem 1.6rem; margin: 1.9rem 0; font-style: italic; color: #5a4d42;
|
|
571
|
+
box-shadow: 0 2px 10px rgba(120, 90, 50, 0.06); }
|
|
572
|
+
.markdown-body blockquote::before { content: '“'; position: absolute; left: 0.55rem; top: -0.3rem;
|
|
573
|
+
font-family: Georgia, serif; font-size: 2.6em; line-height: 1; color: #c8a98a; opacity: 0.55; }
|
|
574
|
+
.markdown-body blockquote p { margin: 0 0 0.6em; } .markdown-body blockquote > :last-child { margin-bottom: 0; }
|
|
575
|
+
.markdown-body blockquote blockquote { background: rgba(255, 255, 255, 0.4); box-shadow: none; }
|
|
576
|
+
.markdown-body blockquote blockquote::before { display: none; }
|
|
577
|
+
/* callouts — rounder, softer */
|
|
578
|
+
.markdown-body .info, .markdown-body .success, .markdown-body .warning, .markdown-body .danger { border-radius: 10px; }
|
|
579
|
+
|
|
580
|
+
/* spoiler — add a chevron indicator */
|
|
581
|
+
.markdown-body details.spoil > summary { display: flex; align-items: center; gap: 0.55rem; list-style: none; }
|
|
582
|
+
.markdown-body details.spoil > summary::-webkit-details-marker { display: none; }
|
|
583
|
+
.markdown-body details.spoil > summary::before { content: '▸'; color: #b09a78; transition: transform 0.2s; }
|
|
584
|
+
.markdown-body details.spoil[open] > summary::before { transform: rotate(90deg); }
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
--line-height: 1.8;
|
|
32
32
|
|
|
33
33
|
--markdown-body-max-width: 760px;
|
|
34
|
-
--markdown-body-padding: 5rem 2rem;
|
|
34
|
+
--markdown-body-padding: 2.5rem 2rem 5rem;
|
|
35
35
|
--markdown-body-border: none;
|
|
36
36
|
--markdown-body-radius: 0;
|
|
37
37
|
--markdown-body-shadow: none;
|
|
@@ -59,6 +59,8 @@ body {
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
/* 2. Headings and body copy */
|
|
62
|
+
.markdown-body > :first-child { margin-top: 0; }
|
|
63
|
+
|
|
62
64
|
.markdown-body h1,
|
|
63
65
|
.markdown-body h2,
|
|
64
66
|
.markdown-body h3,
|
|
@@ -545,7 +547,6 @@ body {
|
|
|
545
547
|
@media (max-width: 640px) {
|
|
546
548
|
.markdown-body {
|
|
547
549
|
padding: 2.5rem 1.25rem;
|
|
548
|
-
font-size: 15px;
|
|
549
550
|
}
|
|
550
551
|
.markdown-body .left {
|
|
551
552
|
float: none;
|
|
@@ -575,4 +576,23 @@ body {
|
|
|
575
576
|
box-shadow: none;
|
|
576
577
|
}
|
|
577
578
|
|
|
578
|
-
}
|
|
579
|
+
}
|
|
580
|
+
/* code block — warm paper panel */
|
|
581
|
+
.markdown-body pre { background: #f6f1e7; border: 1px solid #e6dac3; border-radius: 8px; box-shadow: 0 1px 2px rgba(120,90,50,.06); }
|
|
582
|
+
.markdown-body pre code, .markdown-body pre code.hljs { background: transparent; padding: 0; color: inherit; }
|
|
583
|
+
|
|
584
|
+
|
|
585
|
+
/* ============ modern decorative refresh ============ */
|
|
586
|
+
/* blockquote — warm tint with a teal accent edge (pseudo-bar, not a heavy border) */
|
|
587
|
+
.markdown-body blockquote { position: relative; background: #efe7d8; border: none; border-radius: 0 10px 10px 0;
|
|
588
|
+
padding: 0.9rem 1.3rem; margin: 1.9rem 0; font-style: italic; color: var(--text-muted); overflow: hidden; }
|
|
589
|
+
.markdown-body blockquote::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 4px;
|
|
590
|
+
background: var(--link-color); }
|
|
591
|
+
.markdown-body blockquote p:last-child { margin-bottom: 0; }
|
|
592
|
+
.markdown-body blockquote blockquote { background: rgba(255, 255, 255, 0.35); }
|
|
593
|
+
|
|
594
|
+
/* spoiler — add a chevron indicator */
|
|
595
|
+
.markdown-body details.spoil > summary { display: flex; align-items: center; gap: 0.55rem; list-style: none; }
|
|
596
|
+
.markdown-body details.spoil > summary::-webkit-details-marker { display: none; }
|
|
597
|
+
.markdown-body details.spoil > summary::before { content: '▸'; color: #9c8a6f; transition: transform 0.2s; }
|
|
598
|
+
.markdown-body details.spoil[open] > summary::before { transform: rotate(90deg); }
|
|
@@ -727,3 +727,14 @@ details.spoil > summary:focus-visible {
|
|
|
727
727
|
page-break-inside: avoid;
|
|
728
728
|
}
|
|
729
729
|
}
|
|
730
|
+
|
|
731
|
+
/* code: uniform dark panel (no highlight.js inner box) */
|
|
732
|
+
.markdown-body pre code, .markdown-body pre code.hljs { background: transparent; padding: 0; }
|
|
733
|
+
|
|
734
|
+
|
|
735
|
+
/* ---- mermaid & charts: light panel for legibility on the dark background ---- */
|
|
736
|
+
.markdown-body div.mermaid { background: rgba(255, 255, 255, 0.88); border: 1px solid rgba(255, 255, 255, 0.1);
|
|
737
|
+
border-radius: 10px; padding: 1.1rem; box-shadow: 0 1px 8px rgba(0, 0, 0, 0.22); }
|
|
738
|
+
.markdown-body div.mermaid svg { max-width: 100%; height: auto; }
|
|
739
|
+
.markdown-body canvas.orz-chart { background: rgba(255, 255, 255, 0.88); border-radius: 10px; padding: 0.6rem;
|
|
740
|
+
box-shadow: 0 1px 8px rgba(0, 0, 0, 0.22); max-width: 100%; height: auto; }
|
|
@@ -118,10 +118,10 @@
|
|
|
118
118
|
/* markdown body container toggles */
|
|
119
119
|
--markdown-body-max-width: 920px;
|
|
120
120
|
--markdown-body-padding: clamp(1.5rem, 4vw, 3.5rem);
|
|
121
|
-
--markdown-body-border:
|
|
122
|
-
--markdown-body-radius:
|
|
123
|
-
--markdown-body-shadow:
|
|
124
|
-
--markdown-body-decorations-display:
|
|
121
|
+
--markdown-body-border: none;
|
|
122
|
+
--markdown-body-radius: 0;
|
|
123
|
+
--markdown-body-shadow: none;
|
|
124
|
+
--markdown-body-decorations-display: none;
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
/* --------------------------------------------------------------------------
|
|
@@ -187,10 +187,7 @@ body {
|
|
|
187
187
|
margin: 0;
|
|
188
188
|
min-height: 100vh;
|
|
189
189
|
padding: clamp(1.25rem, 3vw, 2.5rem);
|
|
190
|
-
background:
|
|
191
|
-
radial-gradient(circle at top left, rgba(224, 124, 74, 0.08), transparent 28%),
|
|
192
|
-
radial-gradient(circle at top right, rgba(176, 141, 207, 0.06), transparent 22%),
|
|
193
|
-
linear-gradient(180deg, var(--bg-ambient) 0%, var(--bg) 58%, #050b10 100%);
|
|
190
|
+
background: var(--bg);
|
|
194
191
|
color: var(--text);
|
|
195
192
|
font-family: var(--font-body);
|
|
196
193
|
font-size: var(--fs-100);
|
|
@@ -232,7 +229,7 @@ body {
|
|
|
232
229
|
max-width: var(--markdown-body-max-width);
|
|
233
230
|
margin: 0 auto;
|
|
234
231
|
padding: var(--markdown-body-padding);
|
|
235
|
-
background:
|
|
232
|
+
background: transparent;
|
|
236
233
|
border: var(--markdown-body-border);
|
|
237
234
|
border-radius: var(--markdown-body-radius);
|
|
238
235
|
box-shadow: var(--markdown-body-shadow);
|
|
@@ -1374,3 +1371,14 @@ details.spoil > summary:focus-visible {
|
|
|
1374
1371
|
page-break-inside: avoid;
|
|
1375
1372
|
}
|
|
1376
1373
|
}
|
|
1374
|
+
|
|
1375
|
+
/* code: uniform dark panel (no highlight.js inner box) */
|
|
1376
|
+
.markdown-body pre code, .markdown-body pre code.hljs { background: transparent; padding: 0; }
|
|
1377
|
+
|
|
1378
|
+
|
|
1379
|
+
/* ---- mermaid & charts: light panel for legibility on the dark background ---- */
|
|
1380
|
+
.markdown-body div.mermaid { background: rgba(255, 255, 255, 0.88); border: 1px solid rgba(255, 255, 255, 0.1);
|
|
1381
|
+
border-radius: 10px; padding: 1.1rem; box-shadow: 0 1px 8px rgba(0, 0, 0, 0.22); }
|
|
1382
|
+
.markdown-body div.mermaid svg { max-width: 100%; height: auto; }
|
|
1383
|
+
.markdown-body canvas.orz-chart { background: rgba(255, 255, 255, 0.88); border-radius: 10px; padding: 0.6rem;
|
|
1384
|
+
box-shadow: 0 1px 8px rgba(0, 0, 0, 0.22); max-width: 100%; height: auto; }
|