gutterpress 0.11.22 → 0.11.23-alpha.1
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 +5 -5
- package/dist/{README-3nj919rm.md → README-8ef336pp.md} +1 -1
- package/dist/api/index.js +4 -4
- package/dist/{build-53bw14h7.js → build-09cd1n7s.js} +8 -8
- 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-ke86zsz6.js → cli-5hkmp2wy.js} +70 -40
- package/dist/{cli-kx4hbnx2.js → cli-b0vyjvmt.js} +1 -1
- package/dist/{cli-1hxxwbaq.js → cli-ccp7sxz3.js} +1 -1
- package/dist/{cli-zj5xaepv.js → cli-dd115fa8.js} +22 -6
- package/dist/{cli-8kg0wjdt.js → cli-dtckwda1.js} +1 -1
- package/dist/{cli-1ngqzg8s.js → cli-fe43evmf.js} +21 -5
- package/dist/{cli-ntwqmdnw.js → cli-h17e3mtz.js} +462 -4
- package/dist/{cli-cjftezxr.js → cli-nr6j6300.js} +2 -1
- package/dist/cli.js +12 -12
- package/dist/{doctor-xka1frnx.js → doctor-nddspx4n.js} +3 -3
- package/dist/{engine-p93f06gj.js → engine-892swzzc.js} +2 -2
- package/dist/{engine-0ndvy8vj.js → engine-yjzknt0g.js} +2 -2
- package/dist/{ext-dwfqyy1j.js → ext-zjpen4yx.js} +9 -9
- package/dist/{extension-restore-7vp3vh77.js → extension-restore-jvs60x9b.js} +3 -3
- package/dist/{extension-restore-ct1wk344.js → extension-restore-w8xt4kbq.js} +5 -5
- package/dist/{index-53nrm5j1.js → index-0w2azsk1.js} +1 -1
- package/dist/{index-4v7e621e.js → index-2jpk25en.js} +464 -5
- package/dist/{index-vay3ff1f.js → index-dsvk7q6s.js} +21 -5
- package/dist/{index-6cmn2wpd.js → index-m4hhzg3c.js} +21 -5
- package/dist/{index-kh7fayjv.js → index-zrhyb967.js} +328 -311
- package/dist/index.js +5 -5
- package/dist/lib/build-runner.d.ts +1 -1
- package/dist/lib/extension-manager.d.ts +1 -1
- package/dist/lib/extension-specifier.d.ts +1 -1
- 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/presets.d.ts +1 -1
- package/dist/lib/project-scaffold.d.ts +1 -1
- package/dist/lib/project-templates.d.ts +9 -1
- package/dist/manifest-8f10dr4f.yaml +17 -0
- package/dist/{manifest.schema-399bx3vc.json → manifest.schema-9aeaered.json} +8 -1
- package/dist/{new-1pawj2qf.js → new-xhq8wczn.js} +8 -8
- package/dist/package-zttkgydq.json +10 -0
- package/dist/{plugins-fr4fnzhb.js → plugins-9en8m9y0.js} +3 -3
- package/dist/{plugins-g4dgw7mn.js → plugins-gf0gkjmv.js} +1 -1
- package/dist/{preflight-ept9q57t.js → preflight-negnxg7b.js} +8 -8
- package/dist/preview/file-watcher.d.ts +1 -0
- package/dist/{preview-fxpnjv7k.js → preview-cep2s9cg.js} +8 -8
- package/dist/{publish-zhqqsgmr.js → publish-xery6qc6.js} +8 -8
- package/dist/render.js +470 -11
- package/dist/schema/manifest.types.d.ts +8 -0
- package/dist/theme-9c58td2d.css +76 -0
- package/dist/{validate-t68gvckq.js → validate-3d0sgf4g.js} +8 -8
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -159,7 +159,7 @@ gutterpress new <name> [--kind <id>] [options]
|
|
|
159
159
|
--author <name> Author name to record in the project
|
|
160
160
|
--dir <path> Parent directory to create the project in (default: current directory)
|
|
161
161
|
--folder <name> Folder name to create (default: a slug of the project name)
|
|
162
|
-
--template <id> Starter template: book, zine, technical (default: book)
|
|
162
|
+
--template <id> Starter template: book, zine, technical, paper (default: book)
|
|
163
163
|
--targets <ids> Publish targets recorded in the manifest (comma-separated: dtrpg, itch; or "none") — default: the preset's
|
|
164
164
|
--page-width <pt> Trim width in points, 72pt = 1in (required with --preset custom; optional override otherwise)
|
|
165
165
|
--page-height <pt> Trim height in points, 72pt = 1in (required with --preset custom; optional override otherwise)
|
|
@@ -396,8 +396,8 @@ Add an extension. What `SOURCE` is decides what happens:
|
|
|
396
396
|
as `name@<exact version>`. This does not invoke npm, Bun, Node.js tooling,
|
|
397
397
|
or package install scripts;
|
|
398
398
|
- a **bundled feature** (`markdown-it-mark`, `markdown-it-sub`,
|
|
399
|
-
`markdown-it-sup`, `markdown-it-abbr`, `gutterpress-gfm-alerts
|
|
400
|
-
listed — nothing to install, works offline;
|
|
399
|
+
`markdown-it-sup`, `markdown-it-abbr`, `gutterpress-gfm-alerts`,
|
|
400
|
+
`gutterpress-math`) is simply listed — nothing to install, works offline;
|
|
401
401
|
- a **folder or plugin-file path** is load-tested and listed as a
|
|
402
402
|
manifest-relative path, referenced in place — never copied;
|
|
403
403
|
- a **`.zip` or `.css` file**, or an **http(s) URL**, is validated (every
|
|
@@ -438,7 +438,7 @@ folders it created and nothing else.
|
|
|
438
438
|
gutterpress ext add <source> [dir] [options]
|
|
439
439
|
|
|
440
440
|
--export <name> Named module export to use as the plugin function (npm and path extensions only)
|
|
441
|
-
--look Treat SOURCE as a built-in look id (clean-book, zine, technical-doc): copy it into extensions/ and add it
|
|
441
|
+
--look Treat SOURCE as a built-in look id (clean-book, zine, technical-doc, academic): copy it into extensions/ and add it
|
|
442
442
|
```
|
|
443
443
|
|
|
444
444
|
```sh
|
|
@@ -599,7 +599,7 @@ The binary is self-contained except for the system tools described in [User Guid
|
|
|
599
599
|
|
|
600
600
|
- **`Ghostscript executable not found`** — Ghostscript is required only for PDF/X and ink-coverage checks. Standard Windows installs are auto-detected; for a non-standard install, set `GHOSTSCRIPT_PATH` to the full path of `gs`, `gswin64c.exe`, or `gswin32c.exe`. See [User Guide: Chapter 7 — System Setup](https://github.com/dimm-city/gutterpress/blob/main/examples/gutterpress-user-guide/07-system-setup.md).
|
|
601
601
|
- **`No Chrome or Chromium binary found`** — install a Chromium-based browser or set `CHROMIUM_PATH=/path/to/chrome`. The desktop app includes its own browser and needs no separate browser install.
|
|
602
|
-
- **`Tool "X" not found
|
|
602
|
+
- **`Tool "X" not found; skipping`** during validate — that's the graceful path; the check requires `X` and isn't available. Install the tool or accept the skip.
|
|
603
603
|
- **All validate checks skipped on Windows** — was a bug pre-0.1.7 (used `which`, which isn't on stock Windows); fixed to use `where.exe`.
|
|
604
604
|
|
|
605
605
|
## Links
|
|
@@ -50,7 +50,7 @@ Everything in here stays together on one page.
|
|
|
50
50
|
|
|
51
51
|
## Why six files
|
|
52
52
|
|
|
53
|
-
Gutterpress
|
|
53
|
+
Gutterpress's built-in themes are one short stylesheet each. They style
|
|
54
54
|
bare elements and stop, which is the right size for a plain book and is not an
|
|
55
55
|
architecture. The first book that needs components outgrows one in a week, and
|
|
56
56
|
then re-derives this arrangement from scratch — badly, usually twice.
|
package/dist/api/index.js
CHANGED
|
@@ -101,7 +101,7 @@ import {
|
|
|
101
101
|
substituteVariables,
|
|
102
102
|
syncProject,
|
|
103
103
|
testRemoteAccess
|
|
104
|
-
} from "../index-
|
|
104
|
+
} from "../index-zrhyb967.js";
|
|
105
105
|
import {
|
|
106
106
|
BUILT_IN_STYLE_SET_IDS,
|
|
107
107
|
BUNDLED_EXTENSIONS,
|
|
@@ -138,7 +138,7 @@ import {
|
|
|
138
138
|
setExtensionEnabled,
|
|
139
139
|
updateExtensions,
|
|
140
140
|
validateProjectExtensions
|
|
141
|
-
} from "../index-
|
|
141
|
+
} from "../index-m4hhzg3c.js";
|
|
142
142
|
import {
|
|
143
143
|
EXTENSION_MANIFEST_FILENAME,
|
|
144
144
|
assertExtensionContained,
|
|
@@ -148,12 +148,12 @@ import {
|
|
|
148
148
|
pathEscapesFolder,
|
|
149
149
|
readExtensionMeta,
|
|
150
150
|
resolveExtension
|
|
151
|
-
} from "../index-
|
|
151
|
+
} from "../index-2jpk25en.js";
|
|
152
152
|
import"../index-ht1bcqdd.js";
|
|
153
153
|
import"../index-apc8w9w8.js";
|
|
154
154
|
import {
|
|
155
155
|
BuildError
|
|
156
|
-
} from "../index-
|
|
156
|
+
} from "../index-dsvk7q6s.js";
|
|
157
157
|
import"../index-2ppw6q9v.js";
|
|
158
158
|
import {
|
|
159
159
|
DEFAULT_PRINT_OPTS,
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runBuild,
|
|
3
3
|
splitOutPath
|
|
4
|
-
} from "./cli-
|
|
5
|
-
import"./cli-
|
|
4
|
+
} from "./cli-5hkmp2wy.js";
|
|
5
|
+
import"./cli-ccp7sxz3.js";
|
|
6
6
|
import"./cli-ht1bcqdd.js";
|
|
7
|
-
import"./cli-
|
|
7
|
+
import"./cli-dtckwda1.js";
|
|
8
8
|
import"./cli-2ppw6q9v.js";
|
|
9
9
|
import"./cli-eyyggect.js";
|
|
10
10
|
import"./cli-asap4t1z.js";
|
|
11
11
|
import"./cli-habkc5ng.js";
|
|
12
12
|
import"./cli-v5mp7a6q.js";
|
|
13
|
-
import"./cli-
|
|
14
|
-
import"./cli-
|
|
13
|
+
import"./cli-dd115fa8.js";
|
|
14
|
+
import"./cli-h17e3mtz.js";
|
|
15
15
|
import {
|
|
16
16
|
log
|
|
17
|
-
} from "./cli-
|
|
17
|
+
} from "./cli-b0vyjvmt.js";
|
|
18
18
|
import {
|
|
19
19
|
UsageError,
|
|
20
20
|
parseFormat,
|
|
@@ -22,8 +22,8 @@ import {
|
|
|
22
22
|
rejectExtraPositionals,
|
|
23
23
|
rejectUnknownFlags
|
|
24
24
|
} from "./cli-d8xjns66.js";
|
|
25
|
-
import"./cli-
|
|
26
|
-
import"./cli-
|
|
25
|
+
import"./cli-nr6j6300.js";
|
|
26
|
+
import"./cli-fe43evmf.js";
|
|
27
27
|
import {
|
|
28
28
|
BuildError
|
|
29
29
|
} from "./cli-46ycxe6r.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Chapter One
|
|
2
2
|
|
|
3
3
|
Welcome to {{TITLE}}. This is your first chapter, and it is ready for you to
|
|
4
|
-
make it your own. Everything you see on this page is just an example
|
|
4
|
+
make it your own. Everything you see on this page is just an example --- replace it
|
|
5
5
|
with your own writing whenever you are ready.
|
|
6
6
|
|
|
7
7
|
You write in plain text. Start a new paragraph by leaving a blank line, like
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
@section .title
|
|
2
|
+
|
|
3
|
+
# {{TITLE}}
|
|
4
|
+
|
|
5
|
+
**First Author**^1^ and **Second Author**^2^
|
|
6
|
+
|
|
7
|
+
^1^ Department, Institution\
|
|
8
|
+
^2^ Department, Institution
|
|
9
|
+
|
|
10
|
+
@end-section
|
|
11
|
+
|
|
12
|
+
@section .abstract
|
|
13
|
+
|
|
14
|
+
**Abstract.** State the question, what you did, and what you found, in one
|
|
15
|
+
paragraph a reader can judge the paper by.
|
|
16
|
+
|
|
17
|
+
**Keywords:** first · second · third
|
|
18
|
+
|
|
19
|
+
@end-section
|
|
20
|
+
|
|
21
|
+
## 1 Introduction
|
|
22
|
+
|
|
23
|
+
Say what the problem is and why it matters, then what this paper
|
|
24
|
+
contributes. Cite earlier work with a number in brackets, like [[1]], and
|
|
25
|
+
list it under References below.
|
|
26
|
+
|
|
27
|
+
## 2 Method
|
|
28
|
+
|
|
29
|
+
Write mathematics as you would in LaTeX: $x \in \mathbb{R}^d$ in a line, or
|
|
30
|
+
on lines of its own, numbered with `\tag`:
|
|
31
|
+
|
|
32
|
+
$$
|
|
33
|
+
\hat{\theta} = \operatorname*{arg\,min}_{\theta} \; \frac{1}{n} \sum_{i=1}^{n} \ell\big(f_\theta(x_i), y_i\big)
|
|
34
|
+
\tag{1}
|
|
35
|
+
$$
|
|
36
|
+
|
|
37
|
+
Refer back to it as (1). A footnote goes like this.[^note]
|
|
38
|
+
|
|
39
|
+
[^note]: Notes are collected at the end of the file, before the references.
|
|
40
|
+
|
|
41
|
+
## 3 Results
|
|
42
|
+
|
|
43
|
+
@section .figure
|
|
44
|
+
|
|
45
|
+
**Table 1.** A caption above the table, kept on the same page as it. {.caption}
|
|
46
|
+
|
|
47
|
+
| Method | Error | Cost |
|
|
48
|
+
|:--|--:|--:|
|
|
49
|
+
| Baseline | $1.4 \times 10^{-7}$ | 1025 |
|
|
50
|
+
| This paper | $3.4 \times 10^{-12}$ | 33 |
|
|
51
|
+
|
|
52
|
+
@end-section
|
|
53
|
+
|
|
54
|
+
A figure works the same way: put the image and its caption inside
|
|
55
|
+
`@section .figure`, with `{.caption}` on the caption paragraph.
|
|
56
|
+
|
|
57
|
+
## 4 Conclusion
|
|
58
|
+
|
|
59
|
+
What was shown, and what it means.
|
|
60
|
+
|
|
61
|
+
@section .references
|
|
62
|
+
|
|
63
|
+
## References
|
|
64
|
+
|
|
65
|
+
1. A. Author, *Title of the paper*, Journal, 1 (2026), pp. 1--10. {#ref-1}
|
|
66
|
+
|
|
67
|
+
@end-section
|
|
68
|
+
|
|
69
|
+
[1]: #ref-1
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# {{TITLE}}
|
|
2
2
|
|
|
3
3
|
A zine is short, personal, and made to be photocopied and shared. This page is
|
|
4
|
-
your opening spread
|
|
4
|
+
your opening spread --- keep it punchy.
|
|
5
5
|
|
|
6
6
|
Write a few lines that set the tone. A zine does not need to explain itself; it
|
|
7
7
|
just needs a voice.
|
|
@@ -9,12 +9,18 @@
|
|
|
9
9
|
* mark at the top of a file turns the first heading into a paragraph).
|
|
10
10
|
*
|
|
11
11
|
* Every spelling here is plain ASCII that the renderer turns back into the
|
|
12
|
-
* same character:
|
|
13
|
-
*
|
|
14
|
-
*
|
|
12
|
+
* same character: `gp_typography` (`lib/markdown/typography.ts`) makes
|
|
13
|
+
* `---`, `--` and `...` the dash and ellipsis characters, markdown-it's
|
|
14
|
+
* `smartquotes` curls straight quotes in the book's `language`, and HTML
|
|
15
|
+
* entities cover the rest. So an intentional use stays
|
|
15
16
|
* possible and visible in the source; only the raw pasted character is
|
|
16
|
-
* reported. « » „ ‚ ‹ › are deliberately absent: they are
|
|
17
|
-
*
|
|
17
|
+
* reported. « » „ ‚ ‹ › are deliberately absent: they are the marks the
|
|
18
|
+
* book's `language` prints for other languages, so an author who typed `"`
|
|
19
|
+
* in such a book has nothing to fix, and a pasted one cannot be told apart.
|
|
20
|
+
* The names of the curly quotes say which side they are, not what they do:
|
|
21
|
+
* “ opens an English quotation and closes a German one. One curly character
|
|
22
|
+
* is let through on purpose: a ’ that starts a word (’90s, ’tis), because a
|
|
23
|
+
* typed ' there prints straight — there is nothing else to type.
|
|
18
24
|
*
|
|
19
25
|
* PURE data, no imports: the desktop editor mirrors this module
|
|
20
26
|
* (`packages/desktop/src/lib/editor/special-characters.ts`) to mark the same
|
|
@@ -23,7 +29,7 @@
|
|
|
23
29
|
*/
|
|
24
30
|
/** Stable id for the kind of character, carried on each finding's `code`. */
|
|
25
31
|
export type CharacterCode =
|
|
26
|
-
/** The
|
|
32
|
+
/** The renderer makes it from plain typing (`---`, `"`, `...`). */
|
|
27
33
|
"typographer"
|
|
28
34
|
/** Looks like a quote mark or hyphen but is not one. */
|
|
29
35
|
| "lookalike"
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
stampCreator,
|
|
9
9
|
stripAnnotations,
|
|
10
10
|
transparentPages
|
|
11
|
-
} from "./cli-
|
|
11
|
+
} from "./cli-ccp7sxz3.js";
|
|
12
12
|
import {
|
|
13
13
|
blackTextToGray
|
|
14
14
|
} from "./cli-ht1bcqdd.js";
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
extract,
|
|
18
18
|
lastPageMode,
|
|
19
19
|
resolvePage
|
|
20
|
-
} from "./cli-
|
|
20
|
+
} from "./cli-dtckwda1.js";
|
|
21
21
|
import {
|
|
22
22
|
countLinkAnnotations,
|
|
23
23
|
getImageResolutions,
|
|
@@ -55,6 +55,7 @@ import {
|
|
|
55
55
|
PRESET_IDS,
|
|
56
56
|
TARGETS,
|
|
57
57
|
TARGET_IDS,
|
|
58
|
+
addBuiltInStyleSet,
|
|
58
59
|
addExtension,
|
|
59
60
|
applyDefaultPdfStrictChecks,
|
|
60
61
|
ensureProjectGitignore,
|
|
@@ -70,7 +71,7 @@ import {
|
|
|
70
71
|
uniqueExtensionId,
|
|
71
72
|
withFetchTimeout,
|
|
72
73
|
writeManifestDoc
|
|
73
|
-
} from "./cli-
|
|
74
|
+
} from "./cli-dd115fa8.js";
|
|
74
75
|
import {
|
|
75
76
|
EXTENSION_MANIFEST_FILENAME,
|
|
76
77
|
GUTTERPRESS_CSS,
|
|
@@ -91,7 +92,7 @@ import {
|
|
|
91
92
|
readExtensionMeta,
|
|
92
93
|
resolveDeclaredStyles,
|
|
93
94
|
slugify
|
|
94
|
-
} from "./cli-
|
|
95
|
+
} from "./cli-h17e3mtz.js";
|
|
95
96
|
import {
|
|
96
97
|
PACKAGE_META,
|
|
97
98
|
PACKAGE_VERSION,
|
|
@@ -101,7 +102,7 @@ import {
|
|
|
101
102
|
log,
|
|
102
103
|
setLogLevel,
|
|
103
104
|
warn
|
|
104
|
-
} from "./cli-
|
|
105
|
+
} from "./cli-b0vyjvmt.js";
|
|
105
106
|
import {
|
|
106
107
|
DEBOUNCE,
|
|
107
108
|
UsageError,
|
|
@@ -109,7 +110,7 @@ import {
|
|
|
109
110
|
} from "./cli-d8xjns66.js";
|
|
110
111
|
import {
|
|
111
112
|
getAssetPath
|
|
112
|
-
} from "./cli-
|
|
113
|
+
} from "./cli-fe43evmf.js";
|
|
113
114
|
import {
|
|
114
115
|
BuildError
|
|
115
116
|
} from "./cli-46ycxe6r.js";
|
|
@@ -3024,7 +3025,7 @@ async function collectKnownClasses(ctx, plugins) {
|
|
|
3024
3025
|
var check26 = {
|
|
3025
3026
|
id: "source.markdown.layout-markers",
|
|
3026
3027
|
name: "Layout Markers",
|
|
3027
|
-
description: "Reports @page/@section/@chapter marker arguments Gutterpress could not understand,
|
|
3028
|
+
description: "Reports @page/@section/@chapter marker arguments Gutterpress could not understand, any unknown gp-* class and any other class no stylesheet mentions, a table row with more cells than its table has columns, and a formula that could not be typeset",
|
|
3028
3029
|
category: "source",
|
|
3029
3030
|
phase: "pre-build",
|
|
3030
3031
|
async run(ctx) {
|
|
@@ -3188,14 +3189,14 @@ registerCheck(check27);
|
|
|
3188
3189
|
import { readFile as readFile13 } from "node:fs/promises";
|
|
3189
3190
|
|
|
3190
3191
|
// src/checks/source/character-table.ts
|
|
3191
|
-
var CHARACTER_PATTERN = new RegExp("[\\u0000-\\u0008\\u000B\\u000C\\u000E-\\u001F\\u007F-\\u00A0\\u00AD\\u00B4\\u02BC" + "\\u061C\\u2000-\\u2015\\u2018\\
|
|
3192
|
+
var CHARACTER_PATTERN = new RegExp("[\\u0000-\\u0008\\u000B\\u000C\\u000E-\\u001F\\u007F-\\u00A0\\u00AD\\u00B4\\u02BC" + "\\u061C\\u2000-\\u2015\\u2018\\u201B-\\u201D\\u201F\\u2022\\u2026" + "\\u2028-\\u202F\\u2032\\u2033\\u205F\\u2060\\u2066-\\u2069\\u2190\\u2192" + "\\u2194\\u21D2\\u2212\\u25AA\\u25E6\\u2605\\u2713\\u2714\\u2717\\u3000" + "\\uE000-\\uF8FF\\uFEFF\\uFF02\\uFF07\\uFFFD]" + "|\\p{Emoji_Presentation}|\\p{Extended_Pictographic}(?=\\uFE0F)" + "|(?<=[\\p{L}\\p{N}])\\u2019|\\u2019(?![\\p{L}\\p{N}])", "gu");
|
|
3192
3193
|
var NAMED = {
|
|
3193
3194
|
8212: ["Em dash", "typographer", "---"],
|
|
3194
3195
|
8211: ["En dash", "typographer", "--"],
|
|
3195
|
-
8220: ["
|
|
3196
|
-
8221: ["
|
|
3197
|
-
8216: ["
|
|
3198
|
-
8217: ["
|
|
3196
|
+
8220: ["Left curly quote", "typographer", '"'],
|
|
3197
|
+
8221: ["Right curly quote", "typographer", '"'],
|
|
3198
|
+
8216: ["Left curly single quote", "typographer", "'"],
|
|
3199
|
+
8217: ["Right curly single quote (apostrophe)", "typographer", "'"],
|
|
3199
3200
|
8230: ["Ellipsis character", "typographer", "..."],
|
|
3200
3201
|
700: ["Modifier-letter apostrophe", "lookalike", "'"],
|
|
3201
3202
|
180: ["Acute accent", "lookalike", "'"],
|
|
@@ -3955,7 +3956,7 @@ function reportMissingTools(result) {
|
|
|
3955
3956
|
const affected = checkIds.filter((id) => result.skippedChecks.includes(id));
|
|
3956
3957
|
if (affected.length === 0)
|
|
3957
3958
|
continue;
|
|
3958
|
-
log.warn(`Tool "${tool}" not found
|
|
3959
|
+
log.warn(`Tool "${tool}" not found; skipping: ${affected.join(", ")}`);
|
|
3959
3960
|
}
|
|
3960
3961
|
}
|
|
3961
3962
|
|
|
@@ -4020,11 +4021,12 @@ async function assembleBookHtml(opts) {
|
|
|
4020
4021
|
const title = opts.title ?? "Document";
|
|
4021
4022
|
const projectCss = opts.projectCss ?? "";
|
|
4022
4023
|
const pluginCss = opts.pluginCss ?? "";
|
|
4024
|
+
const language = opts.language ?? "en";
|
|
4023
4025
|
const files = opts.files;
|
|
4024
4026
|
if (files.length === 0) {
|
|
4025
4027
|
throw new Error("No markdown files to render");
|
|
4026
4028
|
}
|
|
4027
|
-
const md = createMarkdownRenderer(opts.plugins);
|
|
4029
|
+
const md = createMarkdownRenderer(opts.plugins, { language });
|
|
4028
4030
|
let bodyContent = "";
|
|
4029
4031
|
const imageRefs = new Set;
|
|
4030
4032
|
for (const file of files) {
|
|
@@ -4036,7 +4038,7 @@ async function assembleBookHtml(opts) {
|
|
|
4036
4038
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
4037
4039
|
throw new Error(`Failed to read file ${file}: ${errorMsg}`);
|
|
4038
4040
|
}
|
|
4039
|
-
const env = {};
|
|
4041
|
+
const env = { docId: slugify(chapterId) };
|
|
4040
4042
|
if (opts.annotateSourceChapters)
|
|
4041
4043
|
env.sourceChapter = chapterId;
|
|
4042
4044
|
const rendered = md.render(content, env);
|
|
@@ -4082,7 +4084,7 @@ ${projectCss.trim()}` : null
|
|
|
4082
4084
|
const lastPage = opts.print && lastPageMode(opts.print);
|
|
4083
4085
|
const printAttrs = (opts.print?.signature && opts.print.signature > 1 ? ` data-gp-signature="${opts.print.signature}"` : "") + (lastPage ? ` data-gp-last-page="${lastPage}"` : "");
|
|
4084
4086
|
return `<!DOCTYPE html>
|
|
4085
|
-
<html lang="
|
|
4087
|
+
<html lang="${language}"${printAttrs}>
|
|
4086
4088
|
<head>
|
|
4087
4089
|
<meta charset="UTF-8">
|
|
4088
4090
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">${opts.printArea ? `
|
|
@@ -4145,6 +4147,7 @@ ${css.trim()}
|
|
|
4145
4147
|
projectCss: inlined.css,
|
|
4146
4148
|
preloadImages: cssAssetCopies.map((c) => c.to),
|
|
4147
4149
|
title: opts.title,
|
|
4150
|
+
language: opts.language,
|
|
4148
4151
|
print: opts.print,
|
|
4149
4152
|
printArea: opts.printArea,
|
|
4150
4153
|
plugins: opts.plugins,
|
|
@@ -4158,6 +4161,7 @@ async function renderChaptersToFile(inputDir, outDir, opts = {}) {
|
|
|
4158
4161
|
await mkdir(outDir, { recursive: true });
|
|
4159
4162
|
const html = await renderChapters(inputDir, {
|
|
4160
4163
|
title: opts.title,
|
|
4164
|
+
language: opts.language,
|
|
4161
4165
|
print: opts.print,
|
|
4162
4166
|
printArea: opts.printArea,
|
|
4163
4167
|
styles: opts.styles,
|
|
@@ -5058,6 +5062,7 @@ async function renderBook(ctx) {
|
|
|
5058
5062
|
const cssAssets = [];
|
|
5059
5063
|
const htmlFile = await renderChaptersToFile(renderDir, workDir, {
|
|
5060
5064
|
title: config.title,
|
|
5065
|
+
language: config.language,
|
|
5061
5066
|
print: config.print,
|
|
5062
5067
|
printArea: { ...config.page, preset: config.preset, spec: config.spec },
|
|
5063
5068
|
styles: config.styles,
|
|
@@ -5212,7 +5217,7 @@ class PdfOutput {
|
|
|
5212
5217
|
const rawPdf = pdfxMode ? path7.join(stage, "raw.pdf") : path7.resolve(pdfFile);
|
|
5213
5218
|
await fsp2.mkdir(path7.dirname(path7.resolve(pdfFile)), { recursive: true });
|
|
5214
5219
|
log.info("Rendering HTML to PDF via the Gutterpress engine (native Chromium pagination)");
|
|
5215
|
-
const { buildNativePdf } = await import("./engine-
|
|
5220
|
+
const { buildNativePdf } = await import("./engine-892swzzc.js");
|
|
5216
5221
|
const engineDiagnostics = await buildNativePdf(htmlFile, rawPdf, {
|
|
5217
5222
|
title: config.title,
|
|
5218
5223
|
author: config.authors.length > 0 ? config.authors.join(", ") : undefined,
|
|
@@ -5514,6 +5519,7 @@ async function renderPreviewBook(inputPath, config, opts) {
|
|
|
5514
5519
|
const { plugins, pluginStyles } = await loadPluginsWithCss(config.extensions, inputPath, (ref, err) => warn(`Skipping plugin "${ref}" in preview — ${err.message}`));
|
|
5515
5520
|
return renderChapters(inputPath, {
|
|
5516
5521
|
title: config.title ?? "Document",
|
|
5522
|
+
language: config.language,
|
|
5517
5523
|
print: config.print,
|
|
5518
5524
|
printArea: config.printArea,
|
|
5519
5525
|
styles: config.styles,
|
|
@@ -6500,6 +6506,43 @@ async function startPreviewServer(options) {
|
|
|
6500
6506
|
};
|
|
6501
6507
|
}
|
|
6502
6508
|
|
|
6509
|
+
// src/lib/project-templates.ts
|
|
6510
|
+
import { isMap, isScalar, isSeq, parseDocument } from "yaml";
|
|
6511
|
+
var BUILT_IN_TEMPLATE_IDS = [
|
|
6512
|
+
"book",
|
|
6513
|
+
"zine",
|
|
6514
|
+
"technical",
|
|
6515
|
+
"paper"
|
|
6516
|
+
];
|
|
6517
|
+
var BUILT_IN_META = {
|
|
6518
|
+
book: {
|
|
6519
|
+
label: "Book",
|
|
6520
|
+
description: "A clean starting point for a novel, memoir, or any long-form book."
|
|
6521
|
+
},
|
|
6522
|
+
zine: {
|
|
6523
|
+
label: "Zine",
|
|
6524
|
+
description: "A short, personal zine made to be printed, folded, and shared."
|
|
6525
|
+
},
|
|
6526
|
+
technical: {
|
|
6527
|
+
label: "Technical document",
|
|
6528
|
+
description: "A manual or guide with steps, reference tables, and code examples."
|
|
6529
|
+
},
|
|
6530
|
+
paper: {
|
|
6531
|
+
label: "Academic paper",
|
|
6532
|
+
description: "A journal-style article with LaTeX math, numbered equations, figures, tables, notes and references.",
|
|
6533
|
+
look: "academic"
|
|
6534
|
+
}
|
|
6535
|
+
};
|
|
6536
|
+
var SKIP_ENTRIES = new Set([
|
|
6537
|
+
".git",
|
|
6538
|
+
"node_modules",
|
|
6539
|
+
"out",
|
|
6540
|
+
"dist",
|
|
6541
|
+
"build",
|
|
6542
|
+
".gutterpress",
|
|
6543
|
+
".DS_Store"
|
|
6544
|
+
]);
|
|
6545
|
+
|
|
6503
6546
|
// src/lib/project-scaffold.ts
|
|
6504
6547
|
import { access, copyFile, cp, mkdir as mkdir4, readdir as readdir5, readFile as readFile22, stat as stat4, writeFile as writeFile5 } from "node:fs/promises";
|
|
6505
6548
|
import { constants as FS, existsSync as existsSync7 } from "node:fs";
|
|
@@ -6507,10 +6550,10 @@ import path12 from "node:path";
|
|
|
6507
6550
|
|
|
6508
6551
|
// src/lib/page-size.ts
|
|
6509
6552
|
import postcss5 from "postcss";
|
|
6510
|
-
import { isMap, Scalar } from "yaml";
|
|
6553
|
+
import { isMap as isMap2, Scalar } from "yaml";
|
|
6511
6554
|
function writePageBounds(doc, page) {
|
|
6512
6555
|
const tolerance = page.tolerance ?? numberAt(doc, ["page", "tolerance"]);
|
|
6513
|
-
if (!
|
|
6556
|
+
if (!isMap2(doc.get("page", true)))
|
|
6514
6557
|
doc.set("page", doc.createNode({}));
|
|
6515
6558
|
doc.setIn(["page", "width"], page.width);
|
|
6516
6559
|
doc.setIn(["page", "height"], page.height);
|
|
@@ -6528,7 +6571,8 @@ function starterOverridesCss() {
|
|
|
6528
6571
|
* Your book's own styles.
|
|
6529
6572
|
*
|
|
6530
6573
|
* This file loads AFTER every extension, so any rule you add here overrides
|
|
6531
|
-
* a look's defaults. A new book has no look until you add one
|
|
6574
|
+
* a look's defaults. A new book has no look until you add one (the paper
|
|
6575
|
+
* template adds the academic look for you):
|
|
6532
6576
|
* gutterpress ext add clean-book <book> --look (a built-in look)
|
|
6533
6577
|
* gutterpress ext add <package> <book> (a look from npm)
|
|
6534
6578
|
* A book has one look at a time; adding another turns the current one off.
|
|
@@ -6650,6 +6694,9 @@ async function scaffoldProject(options) {
|
|
|
6650
6694
|
let openFile = path12.join(projectDir, "chapter-01.md");
|
|
6651
6695
|
try {
|
|
6652
6696
|
await fillTemplateFile(manifestPath, substitutions);
|
|
6697
|
+
const look = customTemplateDir ? undefined : BUILT_IN_META[template].look;
|
|
6698
|
+
if (look)
|
|
6699
|
+
await addBuiltInStyleSet(projectDir, look);
|
|
6653
6700
|
if (preset) {
|
|
6654
6701
|
const { doc, file } = await loadManifestDoc(projectDir);
|
|
6655
6702
|
doc.set("preset", preset);
|
|
@@ -6862,23 +6909,6 @@ function substitute(text, table) {
|
|
|
6862
6909
|
return out;
|
|
6863
6910
|
}
|
|
6864
6911
|
|
|
6865
|
-
// src/lib/project-templates.ts
|
|
6866
|
-
import { isMap as isMap2, isScalar, isSeq, parseDocument } from "yaml";
|
|
6867
|
-
var BUILT_IN_TEMPLATE_IDS = [
|
|
6868
|
-
"book",
|
|
6869
|
-
"zine",
|
|
6870
|
-
"technical"
|
|
6871
|
-
];
|
|
6872
|
-
var SKIP_ENTRIES = new Set([
|
|
6873
|
-
".git",
|
|
6874
|
-
"node_modules",
|
|
6875
|
-
"out",
|
|
6876
|
-
"dist",
|
|
6877
|
-
"build",
|
|
6878
|
-
".gutterpress",
|
|
6879
|
-
".DS_Store"
|
|
6880
|
-
]);
|
|
6881
|
-
|
|
6882
6912
|
// src/lib/extension-import.ts
|
|
6883
6913
|
import { existsSync as existsSync8 } from "node:fs";
|
|
6884
6914
|
import { cp as cp2, mkdir as mkdir6, mkdtemp, readFile as readFile24, rm, writeFile as writeFile7 } from "node:fs/promises";
|
|
@@ -9023,7 +9053,7 @@ async function resolvePublishProvider(id, book) {
|
|
|
9023
9053
|
const ext = await bookExtensions(book);
|
|
9024
9054
|
const npmEntry = ext.extensions.some((c) => !c.path && c.name === id);
|
|
9025
9055
|
if (npmEntry) {
|
|
9026
|
-
const { restoreForCommand: restoreForCommand2 } = await import("./extension-restore-
|
|
9056
|
+
const { restoreForCommand: restoreForCommand2 } = await import("./extension-restore-w8xt4kbq.js");
|
|
9027
9057
|
await restoreForCommand2(book.projectDir, { manifestPath: book.manifestPath, failFast: true });
|
|
9028
9058
|
}
|
|
9029
9059
|
const publishers = await discover(ext);
|
|
@@ -9061,7 +9091,7 @@ function infoFor(p) {
|
|
|
9061
9091
|
}
|
|
9062
9092
|
function pluginProvider(p) {
|
|
9063
9093
|
let loading;
|
|
9064
|
-
const load = () => loading ??= import("./plugins-
|
|
9094
|
+
const load = () => loading ??= import("./plugins-9en8m9y0.js").then((m) => m.loadPublishFunction(p));
|
|
9065
9095
|
return {
|
|
9066
9096
|
info: infoFor(p),
|
|
9067
9097
|
async authenticate() {
|
|
@@ -9548,4 +9578,4 @@ function normalizeProjectKey(projectDir) {
|
|
|
9548
9578
|
}
|
|
9549
9579
|
// src/lib/publish/manifest-publish.ts
|
|
9550
9580
|
import { isMap as isMap4 } from "yaml";
|
|
9551
|
-
export { reportMissingTools, executeValidation, executeAndReport, splitOutPath, runBuild, openPath, startPreviewServer, scaffoldProject, EXTENSION_KINDS, scaffoldExtension,
|
|
9581
|
+
export { reportMissingTools, executeValidation, executeAndReport, splitOutPath, runBuild, openPath, startPreviewServer, BUILT_IN_TEMPLATE_IDS, scaffoldProject, EXTENSION_KINDS, scaffoldExtension, importExtensionFromFile, importExtensionFromUrl, searchNpmExtensions, publishCredentialKey, publishConnectionStatus, listPublishAccounts, connectGoogleDrive, listBookPublishProviders, resolvePublishProvider, resolvePublishFormat, runPublish, connectPublishProvider, disconnectPublishCredential };
|
|
@@ -7,16 +7,16 @@ import {
|
|
|
7
7
|
prettify,
|
|
8
8
|
readExtensionMeta,
|
|
9
9
|
slugify
|
|
10
|
-
} from "./cli-
|
|
10
|
+
} from "./cli-h17e3mtz.js";
|
|
11
11
|
import {
|
|
12
12
|
log
|
|
13
|
-
} from "./cli-
|
|
13
|
+
} from "./cli-b0vyjvmt.js";
|
|
14
14
|
import {
|
|
15
15
|
UsageError
|
|
16
16
|
} from "./cli-d8xjns66.js";
|
|
17
17
|
import {
|
|
18
18
|
getAssetsDir
|
|
19
|
-
} from "./cli-
|
|
19
|
+
} from "./cli-fe43evmf.js";
|
|
20
20
|
import {
|
|
21
21
|
BuildError,
|
|
22
22
|
EXIT_CODES
|
|
@@ -98,7 +98,8 @@ var BUNDLED_EXTENSIONS = [
|
|
|
98
98
|
"markdown-it-sub",
|
|
99
99
|
"markdown-it-sup",
|
|
100
100
|
"markdown-it-abbr",
|
|
101
|
-
"gutterpress-gfm-alerts"
|
|
101
|
+
"gutterpress-gfm-alerts",
|
|
102
|
+
"gutterpress-math"
|
|
102
103
|
];
|
|
103
104
|
function isBundledExtension(name) {
|
|
104
105
|
return BUNDLED_EXTENSIONS.includes(name);
|
|
@@ -114,7 +115,7 @@ function parseExtensionSpecifier(use) {
|
|
|
114
115
|
if (isPathSpecifier(spec))
|
|
115
116
|
return { kind: "path", path: spec };
|
|
116
117
|
if (/\.(m?js|cjs)$/i.test(spec) || !spec.startsWith("@") && spec.includes("/")) {
|
|
117
|
-
throw new Error(`"${spec}" looks like a path
|
|
118
|
+
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.");
|
|
118
119
|
}
|
|
119
120
|
const parsed = parseNpmPluginSpec(spec);
|
|
120
121
|
if (isBundledExtension(parsed.name)) {
|
|
@@ -569,6 +570,15 @@ function mergeShape(cli, manifest, preset) {
|
|
|
569
570
|
}
|
|
570
571
|
return out;
|
|
571
572
|
}
|
|
573
|
+
var LANGUAGE_TAG = /^[a-zA-Z]{2,3}(-[a-zA-Z0-9]{2,8})*$/;
|
|
574
|
+
function resolveLanguage(value) {
|
|
575
|
+
if (value === undefined)
|
|
576
|
+
return "en";
|
|
577
|
+
if (typeof value !== "string" || !LANGUAGE_TAG.test(value)) {
|
|
578
|
+
throw new UsageError(`Manifest field \`language\` must be a language tag such as "en", "de" or "pt-BR", got ${JSON.stringify(value)}.`);
|
|
579
|
+
}
|
|
580
|
+
return value;
|
|
581
|
+
}
|
|
572
582
|
function resolveConfig(cliOverrides, manifest) {
|
|
573
583
|
const presetName = cliOverrides.preset ?? manifest.preset;
|
|
574
584
|
return resolveWithPreset(cliOverrides, manifest, resolvePreset(presetName));
|
|
@@ -656,6 +666,7 @@ function resolveWithPreset(cliOverrides, manifest, preset) {
|
|
|
656
666
|
return {
|
|
657
667
|
title: c.title ?? m.title ?? "Document",
|
|
658
668
|
authors: c.authors ?? m.authors ?? [],
|
|
669
|
+
language: resolveLanguage(c.language ?? m.language),
|
|
659
670
|
preset: preset.id,
|
|
660
671
|
spec: preset.spec,
|
|
661
672
|
styles: c.styles ?? m.styles,
|
|
@@ -1451,9 +1462,14 @@ var RECOMMENDED_EXTENSIONS = [
|
|
|
1451
1462
|
use: "gutterpress-gfm-alerts",
|
|
1452
1463
|
label: "Callouts",
|
|
1453
1464
|
description: "Turn a quote into a boxed note: start it with `> [!NOTE]` (or `TIP`, `IMPORTANT`, `WARNING`, `CAUTION`)."
|
|
1465
|
+
},
|
|
1466
|
+
{
|
|
1467
|
+
use: "gutterpress-math",
|
|
1468
|
+
label: "Math",
|
|
1469
|
+
description: "Write LaTeX math between dollar signs: `$E = mc^2$` in a line, or `$$` … `$$` on lines of their own."
|
|
1454
1470
|
}
|
|
1455
1471
|
];
|
|
1456
|
-
var BUILT_IN_STYLE_SET_IDS = ["clean-book", "zine", "technical-doc"];
|
|
1472
|
+
var BUILT_IN_STYLE_SET_IDS = ["clean-book", "zine", "technical-doc", "academic"];
|
|
1457
1473
|
var mutationQueues = new Map;
|
|
1458
1474
|
function projectKey(projectDir) {
|
|
1459
1475
|
const resolved = path4.resolve(projectDir);
|