gutterpress 0.11.22 → 0.11.23-alpha.2
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 +23 -24
- package/dist/{README-3nj919rm.md → README-8ef336pp.md} +1 -1
- package/dist/api/index.d.ts +4 -4
- package/dist/api/index.js +16 -22
- package/dist/{build-53bw14h7.js → build-encgnv0c.js} +9 -10
- package/dist/{chapter-01-rkpyvjna.md → chapter-01-gsbjt584.md} +1 -1
- package/dist/chapter-01-s71xrf5q.md +69 -0
- package/dist/{chapter-01-7jwqg1ct.md → chapter-01-wgjfz4w6.md} +1 -1
- package/dist/checks/source/character-table.d.ts +12 -6
- package/dist/{cli-habkc5ng.js → cli-a35w7wzg.js} +5 -4
- package/dist/{cli-kx4hbnx2.js → cli-aqh6brew.js} +1 -1
- package/dist/{cli-1hxxwbaq.js → cli-evg8sbht.js} +1 -1
- package/dist/{cli-cjftezxr.js → cli-kh8v4vvw.js} +2 -1
- package/dist/{cli-ntwqmdnw.js → cli-pwwfxdgb.js} +846 -13
- package/dist/{cli-8kg0wjdt.js → cli-pz4bn98t.js} +185 -9
- package/dist/{cli-zj5xaepv.js → cli-sdmv4bba.js} +57 -117
- package/dist/{cli-ke86zsz6.js → cli-xq6djqbj.js} +51 -54
- package/dist/{index-r7jcsk6h.js → cli-y28j019d.js} +19 -10
- package/dist/cli.js +12 -12
- package/dist/{doctor-xka1frnx.js → doctor-5gtpgpd1.js} +3 -3
- package/dist/{engine-p93f06gj.js → engine-mc5br8g8.js} +1 -2
- package/dist/{engine-0ndvy8vj.js → engine-tn13gk0b.js} +3 -3
- package/dist/{ext-dwfqyy1j.js → ext-wn2a5afq.js} +18 -33
- package/dist/{extension-restore-ct1wk344.js → extension-restore-g8jnmmzq.js} +5 -6
- package/dist/{extension-restore-7vp3vh77.js → extension-restore-s3x1618g.js} +4 -4
- package/dist/{index-apc8w9w8.js → index-0skhjx3e.js} +180 -1
- package/dist/{index-4v7e621e.js → index-2bjcghze.js} +847 -13
- package/dist/index-46ycxe6r.js +18 -0
- package/dist/{index-53nrm5j1.js → index-4x6y8krm.js} +2 -4
- package/dist/{cli-h3phdstf.js → index-5x42amh8.js} +19 -10
- package/dist/{index-93pqkvty.js → index-h6yk5tjx.js} +5 -4
- package/dist/{index-kh7fayjv.js → index-j5z86r4a.js} +57 -54
- package/dist/{index-6cmn2wpd.js → index-x3ema2w3.js} +69 -128
- package/dist/index.js +17 -23
- package/dist/lib/build-runner.d.ts +1 -1
- package/dist/lib/extension-manager.d.ts +16 -43
- package/dist/lib/extension-scaffold.d.ts +3 -3
- package/dist/lib/extension-specifier.d.ts +23 -6
- package/dist/lib/markdown/assemble.d.ts +7 -1
- package/dist/lib/markdown/gutterpress-css.d.ts +1 -1
- package/dist/lib/markdown/index.d.ts +4 -0
- package/dist/lib/markdown/math.d.ts +43 -0
- package/dist/lib/markdown/renderer.d.ts +11 -8
- package/dist/lib/markdown/table.d.ts +46 -0
- package/dist/lib/markdown/typography.d.ts +12 -0
- package/dist/lib/npm-plugin-installer.d.ts +1 -1
- package/dist/lib/plugin-vendor.d.ts +11 -3
- package/dist/lib/presets.d.ts +1 -1
- package/dist/lib/project-gitignore.d.ts +2 -2
- package/dist/lib/project-scaffold.d.ts +6 -8
- package/dist/lib/project-templates.d.ts +6 -1
- package/dist/lib/snippets.d.ts +2 -1
- package/dist/lib/style-resolver.d.ts +1 -2
- package/dist/manifest-eagfhba6.yaml +19 -0
- package/dist/{manifest.schema-399bx3vc.json → manifest.schema-t7nx2stg.json} +12 -5
- package/dist/{new-1pawj2qf.js → new-mhs46pw3.js} +22 -21
- package/dist/{plugins-fr4fnzhb.js → plugins-1sxe0dkz.js} +4 -4
- package/dist/{plugins-g4dgw7mn.js → plugins-2cek4mz1.js} +2 -2
- package/dist/{preflight-ept9q57t.js → preflight-3k2b1x8e.js} +9 -10
- package/dist/preview/file-watcher.d.ts +1 -0
- package/dist/{preview-fxpnjv7k.js → preview-6p9v6rht.js} +9 -10
- package/dist/{publish-zhqqsgmr.js → publish-qgsngy8s.js} +9 -10
- package/dist/render.js +470 -11
- package/dist/schema/manifest.types.d.ts +8 -0
- package/dist/{source-provider-qbfknhyy.js → source-provider-98k5deda.js} +2 -2
- package/dist/{source-provider-2r74a7wp.js → source-provider-knmcam50.js} +2 -2
- package/dist/{validate-t68gvckq.js → validate-0v7xw6wa.js} +9 -10
- package/package.json +2 -1
- package/dist/cli-1ngqzg8s.js +0 -196
- package/dist/index-vay3ff1f.js +0 -213
- package/dist/package-97gm31sg.json +0 -10
- package/dist/package-gag6ykwn.json +0 -10
- package/dist/package-nrhkwf2m.json +0 -10
- package/dist/theme-h5recz6c.css +0 -61
- package/dist/theme-j2bagrfx.css +0 -59
- package/dist/theme-nn6d53zy.css +0 -71
|
@@ -2,11 +2,12 @@ import {
|
|
|
2
2
|
isExactNpmVersion,
|
|
3
3
|
isValidNpmPackageName,
|
|
4
4
|
packageResolutionTargets,
|
|
5
|
+
parseNpmPluginSpec,
|
|
5
6
|
resolvePackageEntry,
|
|
6
7
|
resolveVendoredPluginInstallRoot,
|
|
7
8
|
safePackageTarget,
|
|
8
9
|
vendoredNpmPluginPackageDir
|
|
9
|
-
} from "./index-
|
|
10
|
+
} from "./index-5x42amh8.js";
|
|
10
11
|
|
|
11
12
|
// src/lib/markdown/plugins.ts
|
|
12
13
|
import { existsSync as existsSync2, readFileSync, statSync, unlinkSync } from "node:fs";
|
|
@@ -15,6 +16,374 @@ import { isBuiltin } from "node:module";
|
|
|
15
16
|
import { resolve as resolve2, join, dirname, basename, extname, isAbsolute, relative, sep } from "node:path";
|
|
16
17
|
import { pathToFileURL } from "node:url";
|
|
17
18
|
|
|
19
|
+
// src/assets/themes/clean-book/theme.css
|
|
20
|
+
var theme_default = `/* =============================================================================
|
|
21
|
+
Clean Book — gutterpress built-in theme (theme.css)
|
|
22
|
+
A calm, classic long-form book look. Change the :root tokens from the book's own stylesheet.
|
|
23
|
+
============================================================================= */
|
|
24
|
+
|
|
25
|
+
:root {
|
|
26
|
+
--color-ink: #1a1a1a; /* body text */
|
|
27
|
+
--color-ink-muted: #555555; /* captions, secondary text */
|
|
28
|
+
--color-accent: #2b4c7e; /* headings, links */
|
|
29
|
+
--color-paper: #ffffff; /* page background */
|
|
30
|
+
--color-rule: #d9d9d9; /* borders, rules */
|
|
31
|
+
|
|
32
|
+
--font-body: "Georgia", "Times New Roman", serif;
|
|
33
|
+
--font-display: "Georgia", "Times New Roman", serif;
|
|
34
|
+
--font-mono: "Menlo", "Consolas", monospace;
|
|
35
|
+
|
|
36
|
+
--fs-body: 11pt;
|
|
37
|
+
--fs-h1: 2.1rem;
|
|
38
|
+
--fs-h2: 1.5rem;
|
|
39
|
+
--fs-h3: 1.2rem;
|
|
40
|
+
--leading: 1.55;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@page {
|
|
44
|
+
size: 6in 9in;
|
|
45
|
+
margin: 0.85in 0.75in;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
body {
|
|
49
|
+
color: var(--color-ink);
|
|
50
|
+
background: var(--color-paper);
|
|
51
|
+
font-family: var(--font-body);
|
|
52
|
+
line-height: var(--leading);
|
|
53
|
+
font-size: var(--fs-body);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
h1, h2, h3 {
|
|
57
|
+
font-family: var(--font-display);
|
|
58
|
+
color: var(--color-accent);
|
|
59
|
+
line-height: 1.2;
|
|
60
|
+
font-weight: 600;
|
|
61
|
+
}
|
|
62
|
+
h1 { font-size: var(--fs-h1); margin: 0 0 0.6em; }
|
|
63
|
+
h2 { font-size: var(--fs-h2); margin: 1.4em 0 0.4em; }
|
|
64
|
+
h3 { font-size: var(--fs-h3); margin: 1.2em 0 0.3em; }
|
|
65
|
+
|
|
66
|
+
p { margin: 0 0 0.8em; text-align: justify; hyphens: auto; }
|
|
67
|
+
|
|
68
|
+
a { color: var(--color-accent); text-decoration: none; }
|
|
69
|
+
|
|
70
|
+
blockquote {
|
|
71
|
+
margin: 1em 0; padding: 0.2em 0 0.2em 1em;
|
|
72
|
+
border-left: 3px solid var(--color-rule);
|
|
73
|
+
color: var(--color-ink-muted); font-style: italic;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
code, pre { font-family: var(--font-mono); font-size: 0.9em; }
|
|
77
|
+
|
|
78
|
+
hr { border: 0; border-top: 1px solid var(--color-rule); margin: 1.5em 0; }
|
|
79
|
+
`;
|
|
80
|
+
|
|
81
|
+
// src/assets/themes/zine/theme.css
|
|
82
|
+
var theme_default2 = `/* =============================================================================
|
|
83
|
+
Zine — gutterpress built-in theme (theme.css)
|
|
84
|
+
High-contrast, punchy, photocopier-friendly. Change the :root tokens from the book's own stylesheet.
|
|
85
|
+
============================================================================= */
|
|
86
|
+
|
|
87
|
+
:root {
|
|
88
|
+
--color-ink: #000000; /* body text */
|
|
89
|
+
--color-ink-muted: #333333; /* secondary text */
|
|
90
|
+
--color-accent: #000000; /* headings (mono, high ink) */
|
|
91
|
+
--color-paper: #ffffff; /* page background */
|
|
92
|
+
--color-rule: #000000; /* heavy borders, rules */
|
|
93
|
+
|
|
94
|
+
--font-body: "Helvetica Neue", "Arial", sans-serif;
|
|
95
|
+
--font-display: "Impact", "Haettenschweiler", "Arial Black", sans-serif;
|
|
96
|
+
--font-mono: "Courier New", monospace;
|
|
97
|
+
|
|
98
|
+
--fs-body: 10pt;
|
|
99
|
+
--fs-h1: 2.8rem;
|
|
100
|
+
--fs-h2: 1.8rem;
|
|
101
|
+
--fs-h3: 1.3rem;
|
|
102
|
+
--leading: 1.4;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
@page {
|
|
106
|
+
size: 5.5in 8.5in;
|
|
107
|
+
margin: 0.4in;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
body {
|
|
111
|
+
color: var(--color-ink);
|
|
112
|
+
background: var(--color-paper);
|
|
113
|
+
font-family: var(--font-body);
|
|
114
|
+
line-height: var(--leading);
|
|
115
|
+
font-size: var(--fs-body);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
h1, h2, h3 {
|
|
119
|
+
font-family: var(--font-display);
|
|
120
|
+
color: var(--color-accent);
|
|
121
|
+
text-transform: uppercase;
|
|
122
|
+
letter-spacing: -0.01em;
|
|
123
|
+
line-height: 0.95;
|
|
124
|
+
font-weight: 900;
|
|
125
|
+
}
|
|
126
|
+
h1 { font-size: var(--fs-h1); margin: 0 0 0.4em; }
|
|
127
|
+
h2 { font-size: var(--fs-h2); margin: 1.1em 0 0.3em; }
|
|
128
|
+
h3 { font-size: var(--fs-h3); margin: 1em 0 0.25em; }
|
|
129
|
+
|
|
130
|
+
p { margin: 0 0 0.6em; }
|
|
131
|
+
|
|
132
|
+
a { color: var(--color-accent); text-decoration: underline; font-weight: 700; }
|
|
133
|
+
|
|
134
|
+
blockquote {
|
|
135
|
+
margin: 1em 0; padding: 0.5em 0.8em;
|
|
136
|
+
border: 2px solid var(--color-rule);
|
|
137
|
+
font-weight: 700;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
hr { border: 0; border-top: 3px solid var(--color-rule); margin: 1em 0; }
|
|
141
|
+
|
|
142
|
+
code, pre { font-family: var(--font-mono); font-size: 0.95em; }
|
|
143
|
+
`;
|
|
144
|
+
|
|
145
|
+
// src/assets/themes/technical-doc/theme.css
|
|
146
|
+
var theme_default3 = `/* =============================================================================
|
|
147
|
+
Technical Document — gutterpress built-in theme (theme.css)
|
|
148
|
+
Clean sans-serif manual look with clear hierarchy. Change the :root tokens from the book's own stylesheet.
|
|
149
|
+
============================================================================= */
|
|
150
|
+
|
|
151
|
+
:root {
|
|
152
|
+
--color-ink: #1c1e21; /* body text */
|
|
153
|
+
--color-ink-muted: #5a5f66; /* captions, secondary text */
|
|
154
|
+
--color-accent: #0b5fff; /* headings, links */
|
|
155
|
+
--color-paper: #ffffff; /* page background */
|
|
156
|
+
--color-tint: #f3f5f9; /* code / note fill */
|
|
157
|
+
--color-rule: #d6dae0; /* borders, rules */
|
|
158
|
+
|
|
159
|
+
--font-body: "Helvetica Neue", "Segoe UI", Arial, sans-serif;
|
|
160
|
+
--font-display: "Helvetica Neue", "Segoe UI", Arial, sans-serif;
|
|
161
|
+
--font-mono: "SFMono-Regular", "Consolas", "Menlo", monospace;
|
|
162
|
+
|
|
163
|
+
--fs-body: 10.5pt;
|
|
164
|
+
--fs-h1: 2.0rem;
|
|
165
|
+
--fs-h2: 1.45rem;
|
|
166
|
+
--fs-h3: 1.15rem;
|
|
167
|
+
--leading: 1.5;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
@page {
|
|
171
|
+
size: 8.5in 11in;
|
|
172
|
+
margin: 0.9in 1in;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
body {
|
|
176
|
+
color: var(--color-ink);
|
|
177
|
+
background: var(--color-paper);
|
|
178
|
+
font-family: var(--font-body);
|
|
179
|
+
line-height: var(--leading);
|
|
180
|
+
font-size: var(--fs-body);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
h1, h2, h3 {
|
|
184
|
+
font-family: var(--font-display);
|
|
185
|
+
color: var(--color-ink);
|
|
186
|
+
font-weight: 600;
|
|
187
|
+
line-height: 1.25;
|
|
188
|
+
}
|
|
189
|
+
h1 { font-size: var(--fs-h1); margin: 0 0 0.5em; color: var(--color-accent); }
|
|
190
|
+
h2 { font-size: var(--fs-h2); margin: 1.4em 0 0.4em; border-bottom: 1px solid var(--color-rule); padding-bottom: 0.15em; }
|
|
191
|
+
h3 { font-size: var(--fs-h3); margin: 1.2em 0 0.3em; }
|
|
192
|
+
|
|
193
|
+
p { margin: 0 0 0.7em; }
|
|
194
|
+
|
|
195
|
+
a { color: var(--color-accent); text-decoration: none; }
|
|
196
|
+
|
|
197
|
+
code {
|
|
198
|
+
font-family: var(--font-mono); font-size: 0.88em;
|
|
199
|
+
background: var(--color-tint); padding: 0.1em 0.35em; border-radius: 3px;
|
|
200
|
+
}
|
|
201
|
+
pre {
|
|
202
|
+
font-family: var(--font-mono); font-size: 0.85em;
|
|
203
|
+
background: var(--color-tint); border: 1px solid var(--color-rule);
|
|
204
|
+
border-radius: 4px; padding: 0.7em 0.9em; overflow: auto;
|
|
205
|
+
}
|
|
206
|
+
pre code { background: none; padding: 0; }
|
|
207
|
+
|
|
208
|
+
table { width: 100%; border-collapse: collapse; margin: 1em 0; font-size: 0.95em; }
|
|
209
|
+
th, td { border: 1px solid var(--color-rule); padding: 0.4em 0.6em; text-align: left; }
|
|
210
|
+
th { background: var(--color-tint); font-weight: 600; }
|
|
211
|
+
|
|
212
|
+
blockquote {
|
|
213
|
+
margin: 1em 0; padding: 0.5em 0.9em;
|
|
214
|
+
background: var(--color-tint); border-left: 3px solid var(--color-accent);
|
|
215
|
+
color: var(--color-ink-muted);
|
|
216
|
+
}
|
|
217
|
+
`;
|
|
218
|
+
|
|
219
|
+
// src/assets/themes/academic/theme.css
|
|
220
|
+
var theme_default4 = `/* =============================================================================
|
|
221
|
+
Academic — gutterpress built-in theme (theme.css)
|
|
222
|
+
A journal-article look in the spirit of LaTeX's \`article\` class: a serif
|
|
223
|
+
text face, justified and hyphenated text, 1in margins, a centred page
|
|
224
|
+
number, and the parts of a paper styled by the @section they sit in.
|
|
225
|
+
Change the :root tokens from the book's own stylesheet. The page SIZE comes from the manifest
|
|
226
|
+
(\`page:\` — US Letter or A4), so it is deliberately not set here.
|
|
227
|
+
============================================================================= */
|
|
228
|
+
|
|
229
|
+
:root {
|
|
230
|
+
--color-ink: #111111; /* body text */
|
|
231
|
+
--color-ink-muted: #555555; /* captions, secondary text */
|
|
232
|
+
--color-accent: #111111; /* headings, links */
|
|
233
|
+
--color-paper: #ffffff; /* page background */
|
|
234
|
+
--color-rule: #111111; /* table rules */
|
|
235
|
+
|
|
236
|
+
--font-body: "Latin Modern Roman", "CMU Serif", "STIX Two Text", "Times New Roman", "Liberation Serif", serif;
|
|
237
|
+
--font-display: "Latin Modern Roman", "CMU Serif", "STIX Two Text", "Times New Roman", "Liberation Serif", serif;
|
|
238
|
+
--font-mono: "Latin Modern Mono", "Menlo", "Consolas", monospace;
|
|
239
|
+
|
|
240
|
+
--fs-body: 10.5pt;
|
|
241
|
+
--fs-h1: 1.65em;
|
|
242
|
+
--fs-h2: 1.2em;
|
|
243
|
+
--fs-h3: 1em;
|
|
244
|
+
--leading: 1.38;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
@page {
|
|
248
|
+
margin: 1in;
|
|
249
|
+
@bottom-center { content: counter(page); font-family: var(--font-body); font-size: 9pt; }
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
body {
|
|
253
|
+
color: var(--color-ink);
|
|
254
|
+
background: var(--color-paper);
|
|
255
|
+
font-family: var(--font-body);
|
|
256
|
+
line-height: var(--leading);
|
|
257
|
+
font-size: var(--fs-body);
|
|
258
|
+
text-align: justify;
|
|
259
|
+
hyphens: auto;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
h1, h2, h3 {
|
|
263
|
+
font-family: var(--font-display);
|
|
264
|
+
color: var(--color-accent);
|
|
265
|
+
line-height: 1.2;
|
|
266
|
+
font-weight: bold;
|
|
267
|
+
}
|
|
268
|
+
h1 { font-size: var(--fs-h1); margin: 0 0 0.7em; }
|
|
269
|
+
h2 { font-size: var(--fs-h2); margin: 1.4em 0 0.5em; }
|
|
270
|
+
h3 { font-size: var(--fs-h3); margin: 1.2em 0 0.4em; }
|
|
271
|
+
|
|
272
|
+
a { color: var(--color-accent); text-decoration: none; }
|
|
273
|
+
|
|
274
|
+
code, pre { font-family: var(--font-mono); }
|
|
275
|
+
pre { font-size: 0.8em; line-height: 1.3; }
|
|
276
|
+
|
|
277
|
+
/* @section .title — the title, authors, affiliations and date */
|
|
278
|
+
.title { text-align: center; hyphens: manual; margin-bottom: 2em; }
|
|
279
|
+
|
|
280
|
+
/* @section .abstract — the abstract, keywords and subject classes */
|
|
281
|
+
.abstract { font-size: 0.9em; margin: 0 2.5em 2em; }
|
|
282
|
+
|
|
283
|
+
/* @section .figure — a figure, table or listing kept on one page with its caption */
|
|
284
|
+
.figure { break-inside: avoid; margin: 1.4em 0; }
|
|
285
|
+
.caption { font-size: 0.9em; color: var(--color-ink-muted); }
|
|
286
|
+
|
|
287
|
+
/* Tables ruled above, below and under the header row, as journals set them */
|
|
288
|
+
table { border-collapse: collapse; margin: 0.6em auto; border-top: 1pt solid var(--color-rule); border-bottom: 1pt solid var(--color-rule); }
|
|
289
|
+
thead th { border-bottom: 0.5pt solid var(--color-rule); }
|
|
290
|
+
th, td { padding: 0.2em 0.8em; }
|
|
291
|
+
|
|
292
|
+
/* Notes (from [^1] footnotes) and @section .references, a size smaller than the text */
|
|
293
|
+
.footnotes, .references { font-size: 0.85em; }
|
|
294
|
+
.footnotes-sep { border: 0; border-top: 0.5pt solid var(--color-rule); width: 30%; margin: 1.5em 0 0.5em; }
|
|
295
|
+
.footnote-backref { display: none; }
|
|
296
|
+
`;
|
|
297
|
+
|
|
298
|
+
// src/lib/extension-specifier.ts
|
|
299
|
+
var BUNDLED_EXTENSIONS = [
|
|
300
|
+
{
|
|
301
|
+
name: "markdown-it-mark",
|
|
302
|
+
label: "Highlight",
|
|
303
|
+
description: "Highlight text by wrapping it in `==double equals==`."
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
name: "markdown-it-sub",
|
|
307
|
+
label: "Subscript",
|
|
308
|
+
description: "Lower text below the line, like the 2 in `H~2~O`."
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
name: "markdown-it-sup",
|
|
312
|
+
label: "Superscript",
|
|
313
|
+
description: "Raise text above the line, like the th in `29^th^`."
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
name: "markdown-it-abbr",
|
|
317
|
+
label: "Abbreviations",
|
|
318
|
+
description: "Explain an abbreviation when readers hover over it. Define it once, like `*[GPS]: Global Positioning System`."
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
name: "gutterpress-gfm-alerts",
|
|
322
|
+
label: "Callouts",
|
|
323
|
+
description: "Turn a quote into a boxed note: start it with `> [!NOTE]` (or `TIP`, `IMPORTANT`, `WARNING`, `CAUTION`)."
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
name: "gutterpress-math",
|
|
327
|
+
label: "Math",
|
|
328
|
+
description: "Write LaTeX math between dollar signs: `$E = mc^2$` in a line, or `$$` … `$$` on lines of their own."
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
name: "clean-book",
|
|
332
|
+
label: "Clean book",
|
|
333
|
+
description: "A calm, classic book look: serif body, generous margins, restrained accents.",
|
|
334
|
+
css: theme_default
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
name: "zine",
|
|
338
|
+
label: "Zine",
|
|
339
|
+
description: "High-contrast, punchy sans-serif look for short photocopier-friendly zines.",
|
|
340
|
+
css: theme_default2
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
name: "technical-doc",
|
|
344
|
+
label: "Technical doc",
|
|
345
|
+
description: "Clean sans-serif manual look with clear hierarchy, code styling, and tidy tables.",
|
|
346
|
+
css: theme_default3
|
|
347
|
+
},
|
|
348
|
+
{
|
|
349
|
+
name: "academic",
|
|
350
|
+
label: "Academic",
|
|
351
|
+
description: "A journal-article look: serif text, justified and hyphenated, ruled tables, notes and references set smaller.",
|
|
352
|
+
css: theme_default4
|
|
353
|
+
}
|
|
354
|
+
];
|
|
355
|
+
function bundledExtension(name) {
|
|
356
|
+
return BUNDLED_EXTENSIONS.find((e) => e.name === name);
|
|
357
|
+
}
|
|
358
|
+
function isBundledExtension(name) {
|
|
359
|
+
return bundledExtension(name) !== undefined;
|
|
360
|
+
}
|
|
361
|
+
function isPathSpecifier(use) {
|
|
362
|
+
return use.startsWith("./") || use.startsWith("../") || use.startsWith("/") || /^[a-zA-Z]:[\\/]/.test(use);
|
|
363
|
+
}
|
|
364
|
+
function parseExtensionSpecifier(use) {
|
|
365
|
+
const spec = use.trim();
|
|
366
|
+
if (!spec) {
|
|
367
|
+
throw new Error("An extension specifier is required — an npm package name, or a ./ path.");
|
|
368
|
+
}
|
|
369
|
+
if (isPathSpecifier(spec))
|
|
370
|
+
return { kind: "path", path: spec };
|
|
371
|
+
if (/\.(m?js|cjs)$/i.test(spec) || !spec.startsWith("@") && spec.includes("/")) {
|
|
372
|
+
throw new Error(`"${spec}" looks like a path; write it as "./${spec}". A specifier that does not ` + "start with ./, ../ or / is an npm package name.");
|
|
373
|
+
}
|
|
374
|
+
const parsed = parseNpmPluginSpec(spec);
|
|
375
|
+
if (isBundledExtension(parsed.name)) {
|
|
376
|
+
if (parsed.selector !== undefined) {
|
|
377
|
+
throw new Error(`"${parsed.name}" is bundled with Gutterpress and always resolves to the bundled copy — ` + `drop "@${parsed.selector}".`);
|
|
378
|
+
}
|
|
379
|
+
return { kind: "bundled", name: parsed.name };
|
|
380
|
+
}
|
|
381
|
+
return parsed.selector === undefined ? { kind: "npm", name: parsed.name } : { kind: "npm", name: parsed.name, version: parsed.selector };
|
|
382
|
+
}
|
|
383
|
+
function pinnedNpmSpecifier(name, version) {
|
|
384
|
+
return `${name}@${version}`;
|
|
385
|
+
}
|
|
386
|
+
|
|
18
387
|
// src/lib/style-declarations.ts
|
|
19
388
|
import { existsSync } from "node:fs";
|
|
20
389
|
import { resolve } from "node:path";
|
|
@@ -37,7 +406,7 @@ import { satisfies, validRange } from "semver";
|
|
|
37
406
|
// package.json
|
|
38
407
|
var package_default = {
|
|
39
408
|
name: "gutterpress",
|
|
40
|
-
version: "0.11.
|
|
409
|
+
version: "0.11.23-alpha.2",
|
|
41
410
|
description: "Markdown-to-PDF converter for professional print layout using a native Chromium print engine and Ghostscript.",
|
|
42
411
|
author: "itlackey",
|
|
43
412
|
license: "MPL-2.0",
|
|
@@ -115,6 +484,7 @@ var package_default = {
|
|
|
115
484
|
"markdown-it-sub": "^2.0.0",
|
|
116
485
|
"markdown-it-sup": "^2.0.0",
|
|
117
486
|
markdownlint: "^0.40.0",
|
|
487
|
+
"mathjax-full": "^3.2.2",
|
|
118
488
|
"pdf-lib": "^1.17.1",
|
|
119
489
|
postcss: "^8.5.18",
|
|
120
490
|
"resolve.exports": "2.0.3",
|
|
@@ -1760,6 +2130,38 @@ img.gp-shape {
|
|
|
1760
2130
|
:where(.gp-alert-important) { --gp-alert-color: var(--gp-alert-important-color); }
|
|
1761
2131
|
:where(.gp-alert-warning) { --gp-alert-color: var(--gp-alert-warning-color); }
|
|
1762
2132
|
:where(.gp-alert-caution) { --gp-alert-color: var(--gp-alert-caution-color); }
|
|
2133
|
+
|
|
2134
|
+
/* Math (the bundled gutterpress-math feature, math.ts): MathJax's own rules
|
|
2135
|
+
for the <mjx-container> SVG output it emits, from its SVG output jax's
|
|
2136
|
+
stylesheet, less the ones for its interactive menu and tooltips. Inert in
|
|
2137
|
+
a book without formulas. */
|
|
2138
|
+
mjx-container[jax="SVG"] { direction: ltr; }
|
|
2139
|
+
mjx-container[jax="SVG"] > svg { overflow: visible; min-height: 1px; min-width: 1px; }
|
|
2140
|
+
mjx-container[jax="SVG"] > svg a { fill: blue; stroke: blue; }
|
|
2141
|
+
mjx-container[jax="SVG"][display="true"] { display: block; text-align: center; margin: 1em 0; }
|
|
2142
|
+
mjx-container[jax="SVG"][display="true"][width="full"] { display: flex; }
|
|
2143
|
+
mjx-container[jax="SVG"][justify="left"] { text-align: left; }
|
|
2144
|
+
mjx-container[jax="SVG"][justify="right"] { text-align: right; }
|
|
2145
|
+
mjx-container[jax="SVG"] path[data-c], mjx-container[jax="SVG"] use[data-c] { stroke-width: 3; }
|
|
2146
|
+
mjx-assistive-mml {
|
|
2147
|
+
position: absolute !important;
|
|
2148
|
+
top: 0px; left: 0px;
|
|
2149
|
+
clip: rect(1px, 1px, 1px, 1px);
|
|
2150
|
+
padding: 1px 0px 0px 0px !important;
|
|
2151
|
+
border: 0px !important;
|
|
2152
|
+
display: block !important;
|
|
2153
|
+
width: auto !important;
|
|
2154
|
+
overflow: hidden !important;
|
|
2155
|
+
user-select: none;
|
|
2156
|
+
}
|
|
2157
|
+
mjx-assistive-mml[display="block"] { width: 100% !important; }
|
|
2158
|
+
g[data-mml-node="merror"] > g { fill: red; stroke: red; }
|
|
2159
|
+
g[data-mml-node="merror"] > rect[data-background] { fill: yellow; stroke: none; }
|
|
2160
|
+
g[data-mml-node="mtable"] > line[data-line], svg[data-table] > g > line[data-line] { stroke-width: 70px; fill: none; }
|
|
2161
|
+
g[data-mml-node="mtable"] > rect[data-frame], svg[data-table] > g > rect[data-frame] { stroke-width: 70px; fill: none; }
|
|
2162
|
+
g[data-mml-node="mtable"] > .mjx-dashed, svg[data-table] > g > .mjx-dashed { stroke-dasharray: 140; }
|
|
2163
|
+
g[data-mml-node="mtable"] > .mjx-dotted, svg[data-table] > g > .mjx-dotted { stroke-linecap: round; stroke-dasharray: 0,140; }
|
|
2164
|
+
g[data-mml-node="mtable"] > g > svg { overflow: visible; }
|
|
1763
2165
|
`;
|
|
1764
2166
|
var GP_CLASSES = new Set([
|
|
1765
2167
|
"gp-left",
|
|
@@ -2074,6 +2476,224 @@ function gpBlockNames(md) {
|
|
|
2074
2476
|
md.core.ruler.push("gp_block_names", (state) => nameBlocksAndHeadings(state.tokens));
|
|
2075
2477
|
}
|
|
2076
2478
|
|
|
2479
|
+
// src/lib/markdown/table.ts
|
|
2480
|
+
import { isSpace } from "markdown-it/lib/common/utils.mjs";
|
|
2481
|
+
var scanCodeSpan = (src, start, max) => {
|
|
2482
|
+
let open = start;
|
|
2483
|
+
while (open < max && src.charCodeAt(open) === 96)
|
|
2484
|
+
open++;
|
|
2485
|
+
const length = open - start;
|
|
2486
|
+
let pos = open;
|
|
2487
|
+
while (pos < max) {
|
|
2488
|
+
if (src.charCodeAt(pos) !== 96) {
|
|
2489
|
+
pos++;
|
|
2490
|
+
continue;
|
|
2491
|
+
}
|
|
2492
|
+
let run = pos;
|
|
2493
|
+
while (run < max && src.charCodeAt(run) === 96)
|
|
2494
|
+
run++;
|
|
2495
|
+
if (run - pos === length)
|
|
2496
|
+
return run;
|
|
2497
|
+
pos = run;
|
|
2498
|
+
}
|
|
2499
|
+
return open;
|
|
2500
|
+
};
|
|
2501
|
+
var DEFAULT_SPANS = { 96: scanCodeSpan };
|
|
2502
|
+
function splitCells(str2, spans) {
|
|
2503
|
+
const result = [];
|
|
2504
|
+
const max = str2.length;
|
|
2505
|
+
let pos = 0;
|
|
2506
|
+
let lastPos = 0;
|
|
2507
|
+
let current = "";
|
|
2508
|
+
let isEscaped = false;
|
|
2509
|
+
while (pos < max) {
|
|
2510
|
+
const ch = str2.charCodeAt(pos);
|
|
2511
|
+
if (ch === 124) {
|
|
2512
|
+
if (!isEscaped) {
|
|
2513
|
+
result.push(current + str2.substring(lastPos, pos));
|
|
2514
|
+
current = "";
|
|
2515
|
+
lastPos = pos + 1;
|
|
2516
|
+
} else {
|
|
2517
|
+
current += str2.substring(lastPos, pos - 1);
|
|
2518
|
+
lastPos = pos;
|
|
2519
|
+
}
|
|
2520
|
+
} else if (!isEscaped && spans[ch]) {
|
|
2521
|
+
pos = spans[ch](str2, pos, max);
|
|
2522
|
+
continue;
|
|
2523
|
+
}
|
|
2524
|
+
isEscaped = ch === 92;
|
|
2525
|
+
pos++;
|
|
2526
|
+
}
|
|
2527
|
+
result.push(current + str2.substring(lastPos));
|
|
2528
|
+
return result;
|
|
2529
|
+
}
|
|
2530
|
+
function getLine(state, line) {
|
|
2531
|
+
const pos = state.bMarks[line] + state.tShift[line];
|
|
2532
|
+
const max = state.eMarks[line];
|
|
2533
|
+
return state.src.slice(pos, max);
|
|
2534
|
+
}
|
|
2535
|
+
var MAX_AUTOCOMPLETED_CELLS = 65536;
|
|
2536
|
+
function warnExtraCells(env, line, cells, columns) {
|
|
2537
|
+
if (!env.layoutWarnings)
|
|
2538
|
+
env.layoutWarnings = [];
|
|
2539
|
+
const extra = cells - columns;
|
|
2540
|
+
env.layoutWarnings.push({
|
|
2541
|
+
line: line + 1,
|
|
2542
|
+
type: "table_extra_cells",
|
|
2543
|
+
message: `This row has ${cells} cells but the table has ${columns} columns, so its last ` + `${extra === 1 ? "cell is" : `${extra} cells are`} left out. ` + "A | inside a cell splits it: write \\| for a literal one."
|
|
2544
|
+
});
|
|
2545
|
+
}
|
|
2546
|
+
function tableRule(spans) {
|
|
2547
|
+
return function table(state, startLine, endLine, silent) {
|
|
2548
|
+
if (startLine + 2 > endLine)
|
|
2549
|
+
return false;
|
|
2550
|
+
let nextLine = startLine + 1;
|
|
2551
|
+
if (state.sCount[nextLine] < state.blkIndent)
|
|
2552
|
+
return false;
|
|
2553
|
+
if (state.sCount[nextLine] - state.blkIndent >= 4)
|
|
2554
|
+
return false;
|
|
2555
|
+
let pos = state.bMarks[nextLine] + state.tShift[nextLine];
|
|
2556
|
+
if (pos >= state.eMarks[nextLine])
|
|
2557
|
+
return false;
|
|
2558
|
+
const firstCh = state.src.charCodeAt(pos++);
|
|
2559
|
+
if (firstCh !== 124 && firstCh !== 45 && firstCh !== 58)
|
|
2560
|
+
return false;
|
|
2561
|
+
if (pos >= state.eMarks[nextLine])
|
|
2562
|
+
return false;
|
|
2563
|
+
const secondCh = state.src.charCodeAt(pos++);
|
|
2564
|
+
if (secondCh !== 124 && secondCh !== 45 && secondCh !== 58 && !isSpace(secondCh)) {
|
|
2565
|
+
return false;
|
|
2566
|
+
}
|
|
2567
|
+
if (firstCh === 45 && isSpace(secondCh))
|
|
2568
|
+
return false;
|
|
2569
|
+
while (pos < state.eMarks[nextLine]) {
|
|
2570
|
+
const ch = state.src.charCodeAt(pos);
|
|
2571
|
+
if (ch !== 124 && ch !== 45 && ch !== 58 && !isSpace(ch))
|
|
2572
|
+
return false;
|
|
2573
|
+
pos++;
|
|
2574
|
+
}
|
|
2575
|
+
let lineText = getLine(state, startLine + 1);
|
|
2576
|
+
let columns = lineText.split("|");
|
|
2577
|
+
const aligns = [];
|
|
2578
|
+
for (let i = 0;i < columns.length; i++) {
|
|
2579
|
+
const t = columns[i].trim();
|
|
2580
|
+
if (!t) {
|
|
2581
|
+
if (i === 0 || i === columns.length - 1) {
|
|
2582
|
+
continue;
|
|
2583
|
+
} else {
|
|
2584
|
+
return false;
|
|
2585
|
+
}
|
|
2586
|
+
}
|
|
2587
|
+
if (!/^:?-+:?$/.test(t))
|
|
2588
|
+
return false;
|
|
2589
|
+
if (t.charCodeAt(t.length - 1) === 58) {
|
|
2590
|
+
aligns.push(t.charCodeAt(0) === 58 ? "center" : "right");
|
|
2591
|
+
} else if (t.charCodeAt(0) === 58) {
|
|
2592
|
+
aligns.push("left");
|
|
2593
|
+
} else {
|
|
2594
|
+
aligns.push("");
|
|
2595
|
+
}
|
|
2596
|
+
}
|
|
2597
|
+
lineText = getLine(state, startLine).trim();
|
|
2598
|
+
if (lineText.indexOf("|") === -1)
|
|
2599
|
+
return false;
|
|
2600
|
+
if (state.sCount[startLine] - state.blkIndent >= 4)
|
|
2601
|
+
return false;
|
|
2602
|
+
columns = splitCells(lineText, spans);
|
|
2603
|
+
if (columns.length && columns[0] === "")
|
|
2604
|
+
columns.shift();
|
|
2605
|
+
if (columns.length && columns[columns.length - 1] === "")
|
|
2606
|
+
columns.pop();
|
|
2607
|
+
const columnCount = columns.length;
|
|
2608
|
+
if (columnCount === 0 || columnCount !== aligns.length)
|
|
2609
|
+
return false;
|
|
2610
|
+
if (silent)
|
|
2611
|
+
return true;
|
|
2612
|
+
const oldParentType = state.parentType;
|
|
2613
|
+
state.parentType = "table";
|
|
2614
|
+
const terminatorRules = state.md.block.ruler.getRules("blockquote");
|
|
2615
|
+
const token_to = state.push("table_open", "table", 1);
|
|
2616
|
+
const tableLines = [startLine, 0];
|
|
2617
|
+
token_to.map = tableLines;
|
|
2618
|
+
const token_tho = state.push("thead_open", "thead", 1);
|
|
2619
|
+
token_tho.map = [startLine, startLine + 1];
|
|
2620
|
+
const token_htro = state.push("tr_open", "tr", 1);
|
|
2621
|
+
token_htro.map = [startLine, startLine + 1];
|
|
2622
|
+
for (let i = 0;i < columns.length; i++) {
|
|
2623
|
+
const token_ho = state.push("th_open", "th", 1);
|
|
2624
|
+
if (aligns[i]) {
|
|
2625
|
+
token_ho.attrs = [["style", "text-align:" + aligns[i]]];
|
|
2626
|
+
}
|
|
2627
|
+
const token_il = state.push("inline", "", 0);
|
|
2628
|
+
token_il.content = columns[i].trim();
|
|
2629
|
+
token_il.children = [];
|
|
2630
|
+
state.push("th_close", "th", -1);
|
|
2631
|
+
}
|
|
2632
|
+
state.push("tr_close", "tr", -1);
|
|
2633
|
+
state.push("thead_close", "thead", -1);
|
|
2634
|
+
let tbodyLines;
|
|
2635
|
+
let autocompletedCells = 0;
|
|
2636
|
+
for (nextLine = startLine + 2;nextLine < endLine; nextLine++) {
|
|
2637
|
+
if (state.sCount[nextLine] < state.blkIndent)
|
|
2638
|
+
break;
|
|
2639
|
+
let terminate = false;
|
|
2640
|
+
for (let i = 0, l = terminatorRules.length;i < l; i++) {
|
|
2641
|
+
if (terminatorRules[i](state, nextLine, endLine, true)) {
|
|
2642
|
+
terminate = true;
|
|
2643
|
+
break;
|
|
2644
|
+
}
|
|
2645
|
+
}
|
|
2646
|
+
if (terminate)
|
|
2647
|
+
break;
|
|
2648
|
+
lineText = getLine(state, nextLine).trim();
|
|
2649
|
+
if (!lineText)
|
|
2650
|
+
break;
|
|
2651
|
+
if (state.sCount[nextLine] - state.blkIndent >= 4)
|
|
2652
|
+
break;
|
|
2653
|
+
columns = splitCells(lineText, spans);
|
|
2654
|
+
if (columns.length && columns[0] === "")
|
|
2655
|
+
columns.shift();
|
|
2656
|
+
if (columns.length && columns[columns.length - 1] === "")
|
|
2657
|
+
columns.pop();
|
|
2658
|
+
if (columns.length > columnCount) {
|
|
2659
|
+
warnExtraCells(state.env, nextLine, columns.length, columnCount);
|
|
2660
|
+
}
|
|
2661
|
+
autocompletedCells += columnCount - columns.length;
|
|
2662
|
+
if (autocompletedCells > MAX_AUTOCOMPLETED_CELLS)
|
|
2663
|
+
break;
|
|
2664
|
+
if (nextLine === startLine + 2) {
|
|
2665
|
+
const token_tbo = state.push("tbody_open", "tbody", 1);
|
|
2666
|
+
token_tbo.map = tbodyLines = [startLine + 2, 0];
|
|
2667
|
+
}
|
|
2668
|
+
const token_tro = state.push("tr_open", "tr", 1);
|
|
2669
|
+
token_tro.map = [nextLine, nextLine + 1];
|
|
2670
|
+
for (let i = 0;i < columnCount; i++) {
|
|
2671
|
+
const token_tdo = state.push("td_open", "td", 1);
|
|
2672
|
+
if (aligns[i]) {
|
|
2673
|
+
token_tdo.attrs = [["style", "text-align:" + aligns[i]]];
|
|
2674
|
+
}
|
|
2675
|
+
const token_il = state.push("inline", "", 0);
|
|
2676
|
+
token_il.content = columns[i] ? columns[i].trim() : "";
|
|
2677
|
+
token_il.children = [];
|
|
2678
|
+
state.push("td_close", "td", -1);
|
|
2679
|
+
}
|
|
2680
|
+
state.push("tr_close", "tr", -1);
|
|
2681
|
+
}
|
|
2682
|
+
if (tbodyLines) {
|
|
2683
|
+
state.push("tbody_close", "tbody", -1);
|
|
2684
|
+
tbodyLines[1] = nextLine;
|
|
2685
|
+
}
|
|
2686
|
+
state.push("table_close", "table", -1);
|
|
2687
|
+
tableLines[1] = nextLine;
|
|
2688
|
+
state.parentType = oldParentType;
|
|
2689
|
+
state.line = nextLine;
|
|
2690
|
+
return true;
|
|
2691
|
+
};
|
|
2692
|
+
}
|
|
2693
|
+
function gpTable(md, options) {
|
|
2694
|
+
md.block.ruler.at("table", tableRule(options?.spans ?? DEFAULT_SPANS), { alt: ["paragraph", "reference"] });
|
|
2695
|
+
}
|
|
2696
|
+
|
|
2077
2697
|
// src/lib/markdown/table-align.ts
|
|
2078
2698
|
var ALIGN = /^text-align:(left|center|right)$/;
|
|
2079
2699
|
function gpTableAlign(md) {
|
|
@@ -2095,6 +2715,57 @@ th[data-align="center"], td[data-align="center"] { text-align: center; }
|
|
|
2095
2715
|
th[data-align="right"], td[data-align="right"] { text-align: right; }
|
|
2096
2716
|
`;
|
|
2097
2717
|
|
|
2718
|
+
// src/lib/markdown/typography.ts
|
|
2719
|
+
var EM_DASH = /(^|[^-])---(?=[^-]|$)/gm;
|
|
2720
|
+
var EN_DASH_SPACED = /(^|\s)--(?=\s|$)/gm;
|
|
2721
|
+
var EN_DASH = /(^|[^-\s])--(?=[^-\s]|$)/gm;
|
|
2722
|
+
var ELLIPSIS = /\.\.\./g;
|
|
2723
|
+
var CANDIDATE = /--|\.\.\./;
|
|
2724
|
+
function replaceInText(children) {
|
|
2725
|
+
let insideAutolink = 0;
|
|
2726
|
+
for (let i = children.length - 1;i >= 0; i--) {
|
|
2727
|
+
const token = children[i];
|
|
2728
|
+
if (token.type === "text" && !insideAutolink && CANDIDATE.test(token.content)) {
|
|
2729
|
+
token.content = token.content.replace(ELLIPSIS, "…").replace(EM_DASH, "$1—").replace(EN_DASH_SPACED, "$1–").replace(EN_DASH, "$1–");
|
|
2730
|
+
}
|
|
2731
|
+
if (token.type === "link_close" && token.info === "auto")
|
|
2732
|
+
insideAutolink++;
|
|
2733
|
+
if (token.type === "link_open" && token.info === "auto")
|
|
2734
|
+
insideAutolink--;
|
|
2735
|
+
}
|
|
2736
|
+
}
|
|
2737
|
+
var QUOTES = {
|
|
2738
|
+
en: "“”‘’",
|
|
2739
|
+
de: "„“‚‘",
|
|
2740
|
+
"de-ch": "«»‹›",
|
|
2741
|
+
"de-li": "«»‹›",
|
|
2742
|
+
fr: ["« ", " »", "‹ ", " ›"],
|
|
2743
|
+
es: "«»“”",
|
|
2744
|
+
it: "«»“”",
|
|
2745
|
+
pt: "«»“”",
|
|
2746
|
+
"pt-br": "“”‘’",
|
|
2747
|
+
ru: "«»„“",
|
|
2748
|
+
pl: "„”«»",
|
|
2749
|
+
cs: "„“‚‘",
|
|
2750
|
+
sk: "„“‚‘",
|
|
2751
|
+
sv: "””’’",
|
|
2752
|
+
fi: "””’’"
|
|
2753
|
+
};
|
|
2754
|
+
function quotesFor(language) {
|
|
2755
|
+
const tag = (language ?? "en").toLowerCase();
|
|
2756
|
+
return QUOTES[tag] ?? QUOTES[tag.split("-")[0]] ?? QUOTES.en;
|
|
2757
|
+
}
|
|
2758
|
+
function gpTypography(md) {
|
|
2759
|
+
md.disable("replacements");
|
|
2760
|
+
md.core.ruler.after("linkify", "gp_typography", (state) => {
|
|
2761
|
+
for (const token of state.tokens) {
|
|
2762
|
+
if (token.type !== "inline" || !token.children || !CANDIDATE.test(token.content))
|
|
2763
|
+
continue;
|
|
2764
|
+
replaceInText(token.children);
|
|
2765
|
+
}
|
|
2766
|
+
});
|
|
2767
|
+
}
|
|
2768
|
+
|
|
2098
2769
|
// src/lib/two-versions-markers.ts
|
|
2099
2770
|
var YOUR_VERSION_LABEL = "your version";
|
|
2100
2771
|
var ONLINE_VERSION_LABEL = "online version";
|
|
@@ -2316,6 +2987,159 @@ function gfmAlerts(md) {
|
|
|
2316
2987
|
md.core.ruler.after("block", "gp_gfm_alerts", gfmAlertsRule);
|
|
2317
2988
|
}
|
|
2318
2989
|
|
|
2990
|
+
// src/lib/markdown/math.ts
|
|
2991
|
+
import { mathjax } from "mathjax-full/js/mathjax.js";
|
|
2992
|
+
import { TeX } from "mathjax-full/js/input/tex.js";
|
|
2993
|
+
import { SVG } from "mathjax-full/js/output/svg.js";
|
|
2994
|
+
import { liteAdaptor } from "mathjax-full/js/adaptors/liteAdaptor.js";
|
|
2995
|
+
import { RegisterHTMLHandler } from "mathjax-full/js/handlers/html.js";
|
|
2996
|
+
import { AssistiveMmlHandler } from "mathjax-full/js/a11y/assistive-mml.js";
|
|
2997
|
+
import { AllPackages } from "mathjax-full/js/input/tex/AllPackages.js";
|
|
2998
|
+
function findInlineMathEnd(src, start, max) {
|
|
2999
|
+
const after = src.charCodeAt(start + 1);
|
|
3000
|
+
if (after === 32 || after === 9)
|
|
3001
|
+
return -1;
|
|
3002
|
+
let match = start + 1;
|
|
3003
|
+
while ((match = src.indexOf("$", match)) !== -1 && match < max) {
|
|
3004
|
+
let pos = match - 1;
|
|
3005
|
+
while (src.charCodeAt(pos) === 92)
|
|
3006
|
+
pos--;
|
|
3007
|
+
if ((match - pos) % 2 === 1)
|
|
3008
|
+
break;
|
|
3009
|
+
match++;
|
|
3010
|
+
}
|
|
3011
|
+
if (match === -1 || match >= max)
|
|
3012
|
+
return -1;
|
|
3013
|
+
if (match === start + 1)
|
|
3014
|
+
return -2;
|
|
3015
|
+
const before = src.charCodeAt(match - 1);
|
|
3016
|
+
const next = src.charCodeAt(match + 1);
|
|
3017
|
+
if (before === 32 || before === 9 || next >= 48 && next <= 57)
|
|
3018
|
+
return -1;
|
|
3019
|
+
return match;
|
|
3020
|
+
}
|
|
3021
|
+
var scanInlineMath = (src, start, max) => {
|
|
3022
|
+
const end = findInlineMathEnd(src, start, max);
|
|
3023
|
+
return end >= 0 ? end + 1 : end === -2 ? start + 2 : start + 1;
|
|
3024
|
+
};
|
|
3025
|
+
function mathInline(state, silent) {
|
|
3026
|
+
if (state.src.charCodeAt(state.pos) !== 36)
|
|
3027
|
+
return false;
|
|
3028
|
+
const end = findInlineMathEnd(state.src, state.pos, state.posMax);
|
|
3029
|
+
if (end < 0) {
|
|
3030
|
+
const literal = end === -2 ? "$$" : "$";
|
|
3031
|
+
if (!silent)
|
|
3032
|
+
state.pending += literal;
|
|
3033
|
+
state.pos += literal.length;
|
|
3034
|
+
return true;
|
|
3035
|
+
}
|
|
3036
|
+
if (!silent) {
|
|
3037
|
+
const token = state.push("math_inline", "math", 0);
|
|
3038
|
+
token.markup = "$";
|
|
3039
|
+
token.content = state.src.slice(state.pos + 1, end);
|
|
3040
|
+
}
|
|
3041
|
+
state.pos = end + 1;
|
|
3042
|
+
return true;
|
|
3043
|
+
}
|
|
3044
|
+
function mathBlock(state, start, end, silent) {
|
|
3045
|
+
let pos = state.bMarks[start] + state.tShift[start];
|
|
3046
|
+
let max = state.eMarks[start];
|
|
3047
|
+
if (pos + 2 > max)
|
|
3048
|
+
return false;
|
|
3049
|
+
if (state.src.slice(pos, pos + 2) !== "$$")
|
|
3050
|
+
return false;
|
|
3051
|
+
pos += 2;
|
|
3052
|
+
let firstLine = state.src.slice(pos, max);
|
|
3053
|
+
if (silent)
|
|
3054
|
+
return true;
|
|
3055
|
+
let found = false;
|
|
3056
|
+
let lastLine = "";
|
|
3057
|
+
if (firstLine.trim().slice(-2) === "$$") {
|
|
3058
|
+
firstLine = firstLine.trim().slice(0, -2);
|
|
3059
|
+
found = true;
|
|
3060
|
+
}
|
|
3061
|
+
let next = start;
|
|
3062
|
+
while (!found) {
|
|
3063
|
+
next++;
|
|
3064
|
+
if (next >= end)
|
|
3065
|
+
break;
|
|
3066
|
+
pos = state.bMarks[next] + state.tShift[next];
|
|
3067
|
+
max = state.eMarks[next];
|
|
3068
|
+
if (pos < max && state.tShift[next] < state.blkIndent) {
|
|
3069
|
+
break;
|
|
3070
|
+
}
|
|
3071
|
+
if (state.src.slice(pos, max).trim().slice(-2) === "$$") {
|
|
3072
|
+
const lastPos = state.src.slice(0, max).lastIndexOf("$$");
|
|
3073
|
+
lastLine = state.src.slice(pos, lastPos);
|
|
3074
|
+
found = true;
|
|
3075
|
+
}
|
|
3076
|
+
}
|
|
3077
|
+
state.line = next + 1;
|
|
3078
|
+
const token = state.push("math_block", "math", 0);
|
|
3079
|
+
token.block = true;
|
|
3080
|
+
token.content = (firstLine && firstLine.trim() ? firstLine + `
|
|
3081
|
+
` : "") + state.getLines(start + 1, next, state.tShift[start], true) + (lastLine && lastLine.trim() ? lastLine : "");
|
|
3082
|
+
token.map = [start, state.line];
|
|
3083
|
+
token.markup = "$$";
|
|
3084
|
+
return true;
|
|
3085
|
+
}
|
|
3086
|
+
var adaptor = null;
|
|
3087
|
+
function getAdaptor() {
|
|
3088
|
+
if (!adaptor) {
|
|
3089
|
+
adaptor = liteAdaptor();
|
|
3090
|
+
AssistiveMmlHandler(RegisterHTMLHandler(adaptor));
|
|
3091
|
+
}
|
|
3092
|
+
return adaptor;
|
|
3093
|
+
}
|
|
3094
|
+
var PACKAGES = AllPackages.filter((name) => name !== "noerrors" && name !== "noundefined");
|
|
3095
|
+
function gpMath(md) {
|
|
3096
|
+
const html = getAdaptor();
|
|
3097
|
+
let errors = [];
|
|
3098
|
+
const tex = new TeX({
|
|
3099
|
+
packages: PACKAGES,
|
|
3100
|
+
formatError: (jax, err) => {
|
|
3101
|
+
errors.push(err.message);
|
|
3102
|
+
return jax.formatError(err);
|
|
3103
|
+
}
|
|
3104
|
+
});
|
|
3105
|
+
const document = mathjax.document("", { InputJax: tex, OutputJax: new SVG({ fontCache: "none" }) });
|
|
3106
|
+
const typeset = (token, display, env) => {
|
|
3107
|
+
errors = [];
|
|
3108
|
+
const out = html.outerHTML(document.convert(token.content, { display }));
|
|
3109
|
+
for (const message of errors) {
|
|
3110
|
+
if (!env.layoutWarnings)
|
|
3111
|
+
env.layoutWarnings = [];
|
|
3112
|
+
env.layoutWarnings.push({
|
|
3113
|
+
line: token.meta?.line ?? (token.map?.[0] ?? 0) + 1,
|
|
3114
|
+
type: "math_error",
|
|
3115
|
+
message: `This formula could not be typeset: ${message}. It prints in red until it is fixed.`
|
|
3116
|
+
});
|
|
3117
|
+
}
|
|
3118
|
+
return display ? out + `
|
|
3119
|
+
` : out;
|
|
3120
|
+
};
|
|
3121
|
+
md.inline.ruler.after("escape", "math_inline", mathInline);
|
|
3122
|
+
md.block.ruler.after("blockquote", "math_block", mathBlock, {
|
|
3123
|
+
alt: ["paragraph", "reference", "blockquote", "list"]
|
|
3124
|
+
});
|
|
3125
|
+
md.core.ruler.after("inline", "math_lines", (state) => {
|
|
3126
|
+
let line = 1;
|
|
3127
|
+
for (const token of state.tokens) {
|
|
3128
|
+
if (token.map)
|
|
3129
|
+
line = token.map[0] + 1;
|
|
3130
|
+
if (token.type !== "inline" || !token.children)
|
|
3131
|
+
continue;
|
|
3132
|
+
for (const child of token.children) {
|
|
3133
|
+
if (child.type === "math_inline")
|
|
3134
|
+
child.meta = { line };
|
|
3135
|
+
}
|
|
3136
|
+
}
|
|
3137
|
+
});
|
|
3138
|
+
md.renderer.rules.math_inline = (tokens, idx, _options, env) => typeset(tokens[idx], false, env);
|
|
3139
|
+
md.renderer.rules.math_block = (tokens, idx, _options, env) => typeset(tokens[idx], true, env);
|
|
3140
|
+
md.use(gpTable, { spans: { ...DEFAULT_SPANS, 36: scanInlineMath } });
|
|
3141
|
+
}
|
|
3142
|
+
|
|
2319
3143
|
// src/lib/markdown/images.ts
|
|
2320
3144
|
var isSrcsetSpace = (char) => char === "\t" || char === `
|
|
2321
3145
|
` || char === "\f" || char === "\r" || char === " ";
|
|
@@ -2742,14 +3566,17 @@ var BUILTIN_OPTIONAL_PLUGINS = {
|
|
|
2742
3566
|
"markdown-it-sub": unwrapPlugin(markdownItSub),
|
|
2743
3567
|
"markdown-it-sup": unwrapPlugin(markdownItSup),
|
|
2744
3568
|
"markdown-it-abbr": unwrapPlugin(markdownItAbbr),
|
|
2745
|
-
"gutterpress-gfm-alerts": gfmAlerts
|
|
3569
|
+
"gutterpress-gfm-alerts": gfmAlerts,
|
|
3570
|
+
"gutterpress-math": gpMath
|
|
2746
3571
|
};
|
|
2747
|
-
function createMarkdownRenderer(customPlugins) {
|
|
3572
|
+
function createMarkdownRenderer(customPlugins, options) {
|
|
2748
3573
|
const md = new MarkdownIt({
|
|
2749
3574
|
html: true,
|
|
2750
3575
|
linkify: true,
|
|
2751
|
-
typographer: true
|
|
3576
|
+
typographer: true,
|
|
3577
|
+
quotes: quotesFor(options?.language)
|
|
2752
3578
|
});
|
|
3579
|
+
md.use(gpTypography);
|
|
2753
3580
|
md.use(unwrapPlugin(markdownItAttrs));
|
|
2754
3581
|
md.use(unwrapPlugin(markdownItFootnote));
|
|
2755
3582
|
md.use(unwrapPlugin(markdownItDeflist));
|
|
@@ -2759,6 +3586,7 @@ function createMarkdownRenderer(customPlugins) {
|
|
|
2759
3586
|
md.use(plugin, { declaredMarkers });
|
|
2760
3587
|
md.use(gpPinScope);
|
|
2761
3588
|
md.use(gpBlockNames);
|
|
3589
|
+
md.use(gpTable);
|
|
2762
3590
|
md.use(gpTableAlign);
|
|
2763
3591
|
md.use(gpTwoVersions);
|
|
2764
3592
|
registerImageRule(md);
|
|
@@ -2895,7 +3723,7 @@ async function importVendoredEntry(installRoot, packageDir, spec) {
|
|
|
2895
3723
|
try {
|
|
2896
3724
|
entry = await resolvePackageEntry(packageDir);
|
|
2897
3725
|
} catch (cause) {
|
|
2898
|
-
throw new Error(`the downloaded copy of ${spec} under
|
|
3726
|
+
throw new Error(`the downloaded copy of ${spec} under extensions/npm/ is incomplete ` + `(${cause instanceof Error ? cause.message : String(cause)}). ` + `Reinstall it with \`gutterpress ext add ${spec}\`.`, { cause });
|
|
2899
3727
|
}
|
|
2900
3728
|
const entryPath = join(packageDir, ...entry.split("/"));
|
|
2901
3729
|
vendoredRootsOpened.add(installRoot);
|
|
@@ -3115,12 +3943,18 @@ async function loadPlugin(config, baseDir) {
|
|
|
3115
3943
|
if (!config.path && !config.name) {
|
|
3116
3944
|
throw new Error("Plugin manifest entry must specify either `path` or `name`. Got an empty plugin config.");
|
|
3117
3945
|
}
|
|
3118
|
-
if (!config.path && !config.version && config.name
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3946
|
+
if (!config.path && !config.version && config.name) {
|
|
3947
|
+
const bundled = bundledExtension(config.name);
|
|
3948
|
+
if (bundled?.css !== undefined) {
|
|
3949
|
+
return { name: config.name, plugin: noopPlugin, css: bundled.css, options: config.options };
|
|
3950
|
+
}
|
|
3951
|
+
if (BUILTIN_OPTIONAL_PLUGINS[config.name]) {
|
|
3952
|
+
return {
|
|
3953
|
+
name: config.name,
|
|
3954
|
+
plugin: BUILTIN_OPTIONAL_PLUGINS[config.name],
|
|
3955
|
+
options: config.options
|
|
3956
|
+
};
|
|
3957
|
+
}
|
|
3124
3958
|
}
|
|
3125
3959
|
if (config.path) {
|
|
3126
3960
|
const candidatePath = resolve2(baseDir, config.path);
|
|
@@ -3241,4 +4075,4 @@ async function loadPluginsWithCss(configs, baseDir, onError) {
|
|
|
3241
4075
|
};
|
|
3242
4076
|
}
|
|
3243
4077
|
|
|
3244
|
-
export { YOUR_VERSION_LABEL, ONLINE_VERSION_LABEL, TWO_VERSIONS_OPEN, TWO_VERSIONS_CLOSE, buildDeclaredMarkerRegistry, MARKER_CSS, GUTTERPRESS_CSS, TWO_VERSIONS_CSS, TABLE_ALIGN_CSS, setLogLevel, debug, info, warn, error, log,
|
|
4078
|
+
export { BUNDLED_EXTENSIONS, bundledExtension, isBundledExtension, isPathSpecifier, parseExtensionSpecifier, pinnedNpmSpecifier, YOUR_VERSION_LABEL, ONLINE_VERSION_LABEL, TWO_VERSIONS_OPEN, TWO_VERSIONS_CLOSE, buildDeclaredMarkerRegistry, MARKER_CSS, GUTTERPRESS_CSS, TWO_VERSIONS_CSS, TABLE_ALIGN_CSS, slugify, prettify, setLogLevel, debug, info, warn, error, log, parseSrcsetUrlCandidates, collectHtmlImageRefs, createMarkdownRenderer, applyPlugins, collectPluginCss, collectPluginStylePaths, collectPluginStyleGroups, resolveDeclaredStyles, package_default, PACKAGE_META, PACKAGE_VERSION, EXTENSION_MANIFEST_FILENAME, readExtensionMeta, extensionStyleList, extensionEntry, extensionCarries, pathEscapesFolder, assertExtensionContained, resolveExtension, __resetPathPluginCacheForTests, loadPlugin, loadPublishFunction, loadPlugins, loadPluginsWithCss };
|