gutterpress 0.11.17-alpha.2 → 0.11.17-alpha.3
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/dist/api/index.d.ts +4 -0
- package/dist/api/index.js +10 -2
- package/dist/{build-1p999cmg.js → build-394c1ee1.js} +4 -4
- package/dist/checks/pdf/index.d.ts +1 -0
- package/dist/checks/pdf/signature.d.ts +3 -0
- package/dist/{cli-70xgehq2.js → cli-3p1e95zc.js} +1 -1
- package/dist/{cli-6z5zthzt.js → cli-9nba5ve6.js} +562 -211
- package/dist/{cli-ppc0vz4b.js → cli-d57bsfpb.js} +1 -1
- package/dist/{cli-gymfg04q.js → cli-jyy9pqf3.js} +15 -10
- package/dist/cli.js +12 -12
- package/dist/{doctor-reqpnn3h.js → doctor-c459qv5j.js} +2 -2
- package/dist/engine/compiler/build.d.ts +3 -2
- package/dist/engine/compiler/postprocess.d.ts +6 -4
- package/dist/engine/shared/synthesis.d.ts +29 -5
- package/dist/{engine-5jzhjjvv.js → engine-3xqgm82d.js} +2 -2
- package/dist/{engine-078ggczp.js → engine-zdb41ay1.js} +1 -1
- package/dist/{ext-dsbfejt3.js → ext-ha7gg8h9.js} +4 -4
- package/dist/{gutterpress-viewer-zkv2stfy.js → gutterpress-viewer-1n793gwd.js} +5 -3
- package/dist/{index-c275p061.js → index-bscfmg5r.js} +1714 -1054
- package/dist/{index-5dcj1vts.js → index-hrx0gfkj.js} +23 -684
- package/dist/index-q1xqxrh9.js +949 -0
- package/dist/index.js +11 -3
- package/dist/lib/black-text-gray.d.ts +38 -8
- package/dist/lib/build-fingerprint.d.ts +2 -0
- package/dist/lib/engine.d.ts +2 -1
- package/dist/lib/lint-rules.d.ts +9 -0
- package/dist/lib/markdown/assemble.d.ts +3 -5
- package/dist/lib/markdown/index.d.ts +3 -8
- package/dist/lib/markdown/renderer.d.ts +9 -1
- package/dist/lib/page-size.d.ts +66 -0
- package/dist/lib/pdf-inspect.d.ts +6 -0
- package/dist/lib/printsafe.d.ts +8 -1
- package/dist/lib/project-scaffold.d.ts +3 -9
- package/dist/lib/remote-auth/github-repos.d.ts +7 -0
- package/dist/lib/remote-auth/online-backup.d.ts +51 -0
- package/dist/lib/snippets.d.ts +3 -0
- package/dist/{manifest.schema-40sfq49z.json → manifest.schema-gh0jjve9.json} +14 -2
- package/dist/{new-m5y2wepr.js → new-kky3z7kv.js} +4 -4
- package/dist/{plugin.js-m4a7m3t4.tpl → plugin.js-cswq7wvd.tpl} +4 -1
- package/dist/{plugin.test.js-6n8ct5e3.tpl → plugin.test.js-xgxrd8hf.tpl} +4 -1
- package/dist/{preflight-bwpqwwny.js → preflight-t8v6szq6.js} +4 -4
- package/dist/preview/file-watcher.d.ts +2 -4
- package/dist/{preview-62y7qhkp.js → preview-cxab4y5x.js} +4 -4
- package/dist/{publish-k2zyt3x6.js → publish-s2mtenb5.js} +4 -4
- package/dist/render.js +30 -5
- package/dist/schema/manifest.types.d.ts +17 -0
- package/dist/{validate-fgwwxtbn.js → validate-xaajdw4x.js} +4 -4
- package/package.json +1 -1
- package/dist/index-eyaj6nkc.js +0 -267
package/dist/index.js
CHANGED
|
@@ -71,6 +71,7 @@ import {
|
|
|
71
71
|
isGitInternalPath,
|
|
72
72
|
isPathSpecifier,
|
|
73
73
|
isSshRemoteUrl,
|
|
74
|
+
isValidRepositoryName,
|
|
74
75
|
knownForgeTokenUrl,
|
|
75
76
|
listBuiltInStyleSets,
|
|
76
77
|
listBuiltInTemplates,
|
|
@@ -102,6 +103,7 @@ import {
|
|
|
102
103
|
readExtensionCss,
|
|
103
104
|
readExtensionMeta,
|
|
104
105
|
readManifestFields,
|
|
106
|
+
readPageSetup,
|
|
105
107
|
readPublishSettings,
|
|
106
108
|
refreshRemoteCopies,
|
|
107
109
|
removeExtension,
|
|
@@ -139,7 +141,9 @@ import {
|
|
|
139
141
|
setActiveStyles,
|
|
140
142
|
setExtensionEnabled,
|
|
141
143
|
setManifestFields,
|
|
144
|
+
setPageSetup,
|
|
142
145
|
setPublishProviderConfig,
|
|
146
|
+
setUpOnlineBackup,
|
|
143
147
|
slugifyProjectName,
|
|
144
148
|
splitOutPath,
|
|
145
149
|
startPreviewServer,
|
|
@@ -148,13 +152,13 @@ import {
|
|
|
148
152
|
testRemoteAccess,
|
|
149
153
|
updateExtensions,
|
|
150
154
|
validateProjectExtensions
|
|
151
|
-
} from "./index-
|
|
155
|
+
} from "./index-bscfmg5r.js";
|
|
152
156
|
import {
|
|
153
157
|
BUILD_DIAGNOSTIC_CODES
|
|
154
|
-
} from "./index-
|
|
158
|
+
} from "./index-hrx0gfkj.js";
|
|
155
159
|
import {
|
|
156
160
|
BuildError
|
|
157
|
-
} from "./index-
|
|
161
|
+
} from "./index-q1xqxrh9.js";
|
|
158
162
|
import {
|
|
159
163
|
DEFAULT_PRINT_OPTS,
|
|
160
164
|
assertMilestone,
|
|
@@ -194,7 +198,9 @@ export {
|
|
|
194
198
|
startPreviewServer,
|
|
195
199
|
splitOutPath,
|
|
196
200
|
slugifyProjectName,
|
|
201
|
+
setUpOnlineBackup,
|
|
197
202
|
setPublishProviderConfig,
|
|
203
|
+
setPageSetup,
|
|
198
204
|
setManifestFields,
|
|
199
205
|
setExtensionEnabled,
|
|
200
206
|
setActiveStyles,
|
|
@@ -237,6 +243,7 @@ export {
|
|
|
237
243
|
refreshRemoteCopies,
|
|
238
244
|
readyProbeExpr,
|
|
239
245
|
readPublishSettings,
|
|
246
|
+
readPageSetup,
|
|
240
247
|
readManifestFields,
|
|
241
248
|
readExtensionMeta,
|
|
242
249
|
readExtensionCss,
|
|
@@ -270,6 +277,7 @@ export {
|
|
|
270
277
|
listBuiltInTemplates,
|
|
271
278
|
listBuiltInStyleSets,
|
|
272
279
|
knownForgeTokenUrl,
|
|
280
|
+
isValidRepositoryName,
|
|
273
281
|
isSshRemoteUrl,
|
|
274
282
|
isPathSpecifier,
|
|
275
283
|
isNoChangesError,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* K-only black text for PDF/X (#331).
|
|
2
|
+
* K-only black text for PDF/X (#331, #336).
|
|
3
3
|
*
|
|
4
4
|
* PRINT-SPEC GAP: print vendors (DriveThruRPG) require body text to print on
|
|
5
5
|
* the black plate alone (100% K). Chromium writes every text fill as
|
|
@@ -21,18 +21,48 @@
|
|
|
21
21
|
* scoped to `BT`…`ET`: on entering a text object whose inherited fill/stroke
|
|
22
22
|
* is near-black RGB we emit `0 g`/`0 G`, and at `ET` we put the original RGB
|
|
23
23
|
* back. A near-black `rg`/`RG` set inside the block is rewritten the same way.
|
|
24
|
-
* Page content streams and Form XObjects are both processed
|
|
25
|
-
* inherited (pre-`Do`) colour is unknowable from its own stream, so only
|
|
26
|
-
* colours set inside the form are considered.
|
|
24
|
+
* Page content streams and Form XObjects are both processed.
|
|
27
25
|
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
26
|
+
* Size threshold (#336): DriveThruRPG recommends rich black for text LARGER
|
|
27
|
+
* than 24pt, so only text at or below {@link LARGE_TEXT_PT} is rewritten. The
|
|
28
|
+
* effective size is `Tf` size × the text matrix's scale (`Tm`) × the CTM's
|
|
29
|
+
* scale (`cm`, restored by `q`/`Q`) — each reduced to √|det| of its 2×2, so
|
|
30
|
+
* rotation and flips do not matter and anisotropic scaling is averaged.
|
|
31
|
+
* `Tz`/`Ts` are ignored. A Form XObject's stream cannot know the CTM it is
|
|
32
|
+
* drawn under, so the page pass records the CTM at each `Do` and the form is
|
|
33
|
+
* sized from that (the smallest, if drawn more than once — K-only large text
|
|
34
|
+
* is harmless, rich small text is not). A form reached any other way (nested
|
|
35
|
+
* in another form, unreferenced) has unknown scale and is treated as small.
|
|
36
|
+
* A `Tf` inside a text object re-evaluates, so one `BT` can switch between
|
|
37
|
+
* K-only and rich as the size crosses the threshold.
|
|
38
|
+
*
|
|
39
|
+
* Underline / strike-through (#336): Chromium (tagged PDF, which the engine
|
|
40
|
+
* always requests) wraps each text run and its decoration in one marked-content
|
|
41
|
+
* span (`/NonStruct <</MCID n>> BDC … EMC`) and paints the decoration as a thin
|
|
42
|
+
* `x y w h re f` outside `BT…ET`. A near-black such rect, thinner than a fifth
|
|
43
|
+
* of the span's small text, is wrapped `q 0 g … Q` so it prints K-only like the
|
|
44
|
+
* text it decorates. A rect outside any span, or in a span with no small text
|
|
45
|
+
* (rules, borders, large headings), is left alone — nothing is guessed.
|
|
46
|
+
*/
|
|
47
|
+
/**
|
|
48
|
+
* DriveThruRPG: black text LARGER than this (in points) may be rich black;
|
|
49
|
+
* at or below it, it must be K-only.
|
|
30
50
|
*/
|
|
51
|
+
export declare const LARGE_TEXT_PT = 24;
|
|
52
|
+
/** What a stream's caller knows that the stream itself cannot. */
|
|
53
|
+
export interface ContentContext {
|
|
54
|
+
/** Scale in effect where the stream starts: 1 for a page, the invoking CTM for a form. 0 = unknown (treated as small). */
|
|
55
|
+
baseScale?: number;
|
|
56
|
+
/** Called for each `Do` with the XObject's resource name and the CTM scale there. */
|
|
57
|
+
onDo?: (name: string, scale: number) => void;
|
|
58
|
+
}
|
|
31
59
|
/**
|
|
32
60
|
* Rewrite near-black RGB fill/stroke to DeviceGray black inside BT…ET of one
|
|
33
|
-
* content stream
|
|
61
|
+
* content stream, for text at or below {@link LARGE_TEXT_PT}, plus the thin
|
|
62
|
+
* decoration rects in that text's marked-content span. Pure string → string;
|
|
63
|
+
* returns the input when nothing changed.
|
|
34
64
|
*/
|
|
35
|
-
export declare function rewriteBlackText(src: string): string;
|
|
65
|
+
export declare function rewriteBlackText(src: string, ctx?: ContentContext): string;
|
|
36
66
|
/**
|
|
37
67
|
* Apply {@link rewriteBlackText} to every page content stream and Form XObject
|
|
38
68
|
* of a PDF. Returns the input bytes untouched when nothing needed rewriting.
|
|
@@ -3,6 +3,8 @@ type PdfxFingerprintConfig = {
|
|
|
3
3
|
resolvedFlavor: "x1a" | "x3";
|
|
4
4
|
iccPath: string | null;
|
|
5
5
|
stripAnnotations: boolean | null;
|
|
6
|
+
/** How near-black text was separated (#331); null when no PDF/X pass ran. Provenance only. */
|
|
7
|
+
blackText?: "icc" | "k-only" | null;
|
|
6
8
|
};
|
|
7
9
|
export type BuildFingerprintInput = {
|
|
8
10
|
command: "build";
|
package/dist/lib/engine.d.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { type BuildDiagnostic } from "../engine/compiler/build.ts";
|
|
2
2
|
import type { Browser as EngineBrowser } from "../engine/shared/cdp.ts";
|
|
3
|
+
import type { LastPageMode } from "../engine/shared/synthesis.ts";
|
|
3
4
|
export type { EngineBrowser };
|
|
4
5
|
/** The subset of `BuildOptions` that has a manifest/CLI source today (B.12). */
|
|
5
6
|
export interface NativePdfOptions {
|
|
6
7
|
title?: string;
|
|
7
8
|
author?: string;
|
|
8
9
|
signature?: number;
|
|
9
|
-
|
|
10
|
+
lastPage?: LastPageMode;
|
|
10
11
|
/**
|
|
11
12
|
* Downgrade the engine's over-wide-content hard error to a warning +
|
|
12
13
|
* diagnostic. The engine's message tells the author to "pass allowShrink to
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type LintLevel = "off" | "warn" | "error";
|
|
2
|
+
/** Read one rule's configured level; unrecognised values are ignored. */
|
|
3
|
+
export declare function ruleLevel(rules: Readonly<Record<string, unknown>> | undefined, id: string): LintLevel | undefined;
|
|
4
|
+
/**
|
|
5
|
+
* The rule ids named by a `gutterpress-disable-next-line <id>[, <id>...]
|
|
6
|
+
* [-- reason]` comment body (the text between the comment delimiters), or
|
|
7
|
+
* null when the comment is not such a directive.
|
|
8
|
+
*/
|
|
9
|
+
export declare function parseDisableDirective(commentText: string): string[] | null;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type LoadedPlugin } from "./renderer";
|
|
2
|
+
import { type PrintPadding } from "../../engine/shared/synthesis.ts";
|
|
2
3
|
/** Reader injected by the host: resolve a project-root-relative file → its text. */
|
|
3
4
|
export type ReadText = (relPath: string) => Promise<string>;
|
|
4
5
|
/**
|
|
@@ -118,14 +119,11 @@ export interface AssembleBookHtmlOptions {
|
|
|
118
119
|
title?: string;
|
|
119
120
|
/**
|
|
120
121
|
* The manifest's `print` padding, written on `<html>` as
|
|
121
|
-
* `data-gp-signature` / `data-gp-
|
|
122
|
+
* `data-gp-signature` / `data-gp-last-page` so the viewer shows the
|
|
122
123
|
* blank pages the PDF build appends (`signaturePadding` in
|
|
123
124
|
* engine/shared/synthesis.ts) and the two page counts agree.
|
|
124
125
|
*/
|
|
125
|
-
print?:
|
|
126
|
-
signature?: number;
|
|
127
|
-
reserveLastPage?: boolean;
|
|
128
|
-
};
|
|
126
|
+
print?: PrintPadding;
|
|
129
127
|
plugins?: LoadedPlugin[];
|
|
130
128
|
pluginCss?: string;
|
|
131
129
|
/** Add a layout-neutral source-file id to source-mapped preview blocks. */
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type LayoutWarning } from "./assemble";
|
|
2
2
|
import { type AssetCopy } from "../asset-inline";
|
|
3
3
|
import type { LoadedPlugin, PluginStyleGroup } from "./renderer";
|
|
4
|
+
import type { PrintPadding } from "../../engine/shared/synthesis.ts";
|
|
4
5
|
export type { LayoutWarning } from "./assemble";
|
|
5
6
|
/**
|
|
6
7
|
* THE canonical "which markdown files make up this book, and in what order?"
|
|
@@ -31,10 +32,7 @@ export declare function resolveActiveMarkdownFiles(inputDir: string, configuredF
|
|
|
31
32
|
export declare function renderChapters(inputDir: string, opts?: {
|
|
32
33
|
title?: string;
|
|
33
34
|
/** See {@link AssembleBookHtmlOptions.print}. */
|
|
34
|
-
print?:
|
|
35
|
-
signature?: number;
|
|
36
|
-
reserveLastPage?: boolean;
|
|
37
|
-
};
|
|
35
|
+
print?: PrintPadding;
|
|
38
36
|
styles?: string[];
|
|
39
37
|
files?: string[] | null;
|
|
40
38
|
plugins?: LoadedPlugin[];
|
|
@@ -73,10 +71,7 @@ export declare function renderChapters(inputDir: string, opts?: {
|
|
|
73
71
|
export declare function renderChaptersToFile(inputDir: string, outDir: string, opts?: {
|
|
74
72
|
title?: string;
|
|
75
73
|
/** See {@link AssembleBookHtmlOptions.print}. */
|
|
76
|
-
print?:
|
|
77
|
-
signature?: number;
|
|
78
|
-
reserveLastPage?: boolean;
|
|
79
|
-
};
|
|
74
|
+
print?: PrintPadding;
|
|
80
75
|
styles?: string[];
|
|
81
76
|
files?: string[] | null;
|
|
82
77
|
plugins?: LoadedPlugin[];
|
|
@@ -62,7 +62,7 @@ export interface GutterpressMarkerLabel {
|
|
|
62
62
|
* One entry in a plugin's declared `markers` table (#240 — "declarative
|
|
63
63
|
* container components in core"). Exactly one of three shapes:
|
|
64
64
|
*
|
|
65
|
-
* - a CONTAINER: `section`/`tag`/`class`/`variants`/`label`/`autoCloseAt`, any/all
|
|
65
|
+
* - a CONTAINER: `section`/`tag`/`class`/`variants`/`label`/`autoCloseAt`/`selfClosing`, any/all
|
|
66
66
|
* optional (a bare `{}` is a valid, if pointless, `<div>` wrapper);
|
|
67
67
|
* - an ALIAS: `alias` (another declared name) + optional `preset`;
|
|
68
68
|
* - a DEPRECATION: `deprecated` (a human-readable retirement message) —
|
|
@@ -132,6 +132,14 @@ export interface GutterpressMarkerDeclaration {
|
|
|
132
132
|
* warns (the default — most likely a forgotten `@end-<name>`).
|
|
133
133
|
*/
|
|
134
134
|
autoCloseAt?: Array<"eof">;
|
|
135
|
+
/**
|
|
136
|
+
* The marker is one element with no body and no `@end-<name>`: `@tape
|
|
137
|
+
* label="..."` emits the element (and its label) and closes it at once, so
|
|
138
|
+
* nothing that follows is nested inside and `@end-<name>` warns. Cannot be
|
|
139
|
+
* combined with `section` or `autoCloseAt`. A `validate` on a self-closing
|
|
140
|
+
* marker always sees empty `blocks` and `text`. Aliases inherit it.
|
|
141
|
+
*/
|
|
142
|
+
selfClosing?: boolean;
|
|
135
143
|
/** This marker is sugar for another declared marker (must name a non-alias, non-deprecated entry). */
|
|
136
144
|
alias?: string;
|
|
137
145
|
/** With `alias`: defaults applied when the invocation line supplies none. */
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { Document } from "yaml";
|
|
2
|
+
import { type PresetId } from "./presets.ts";
|
|
3
|
+
/** Page bounds written to the manifest's `page:` block (points; 72pt = 1in). */
|
|
4
|
+
export interface CustomPageOptions {
|
|
5
|
+
/** Trim width in points (72pt = 1in). */
|
|
6
|
+
width: number;
|
|
7
|
+
/** Trim height in points (72pt = 1in). */
|
|
8
|
+
height: number;
|
|
9
|
+
/** Allowed deviation in points when validating a built PDF. Default 0.5. */
|
|
10
|
+
tolerance?: number;
|
|
11
|
+
}
|
|
12
|
+
/** A page size in points. */
|
|
13
|
+
export interface PageSizePoints {
|
|
14
|
+
width: number;
|
|
15
|
+
height: number;
|
|
16
|
+
}
|
|
17
|
+
/** What an author picks: a preset, plus the trim when the preset is `custom`. */
|
|
18
|
+
export interface PageSizeChoice {
|
|
19
|
+
preset: PresetId;
|
|
20
|
+
/** Required for `custom`; ignored for `dtrpg` / `book` (the preset owns it). */
|
|
21
|
+
page?: PageSizePoints;
|
|
22
|
+
}
|
|
23
|
+
/** A book's page size as currently recorded, read back for the settings UI. */
|
|
24
|
+
export interface PageSetup {
|
|
25
|
+
/** The manifest's preset (`dtrpg` when undeclared — the product default); null when unrecognised. */
|
|
26
|
+
preset: PresetId | null;
|
|
27
|
+
/** The validation bounds the manifest resolves to, or null (custom with no `page:`). */
|
|
28
|
+
bounds: (PageSizePoints & {
|
|
29
|
+
tolerance: number;
|
|
30
|
+
}) | null;
|
|
31
|
+
/** What the book's stylesheets print at, or null when no plain `@page` sets a size. */
|
|
32
|
+
css: (PageSizePoints & {
|
|
33
|
+
file: string;
|
|
34
|
+
}) | null;
|
|
35
|
+
}
|
|
36
|
+
export declare function isPositivePoints(value: unknown): value is number;
|
|
37
|
+
/**
|
|
38
|
+
* Write the manifest's `page:` bounds. `tolerance` defaults to whatever the
|
|
39
|
+
* block already carries, so re-sizing a book never silently resets a
|
|
40
|
+
* hand-tuned tolerance.
|
|
41
|
+
*/
|
|
42
|
+
export declare function writePageBounds(doc: Document, page: CustomPageOptions): void;
|
|
43
|
+
/** The size (points) a choice means: `custom` brings its own, the others are the preset's. */
|
|
44
|
+
export declare function pageSizeForChoice(choice: PageSizeChoice): PageSizePoints;
|
|
45
|
+
/** The `size` value written for a page: `8.5in 11in`, `595pt 842pt`. */
|
|
46
|
+
export declare function formatPageSize(page: PageSizePoints): string;
|
|
47
|
+
/** The size the LAST plain `@page { size }` in the stylesheet sets (cascade: last wins), or null. */
|
|
48
|
+
export declare function readPageSizeFromCss(css: string): PageSizePoints | null;
|
|
49
|
+
/**
|
|
50
|
+
* Point a stylesheet's plain `@page` rule at `page`. Rewrites the existing
|
|
51
|
+
* `size` declaration's value in place — comments, whitespace, other rules and
|
|
52
|
+
* `!important` untouched — or, when no plain `@page` sets a size, appends a
|
|
53
|
+
* minimal rule. An already-matching size leaves the text exactly as it was.
|
|
54
|
+
* Throws when the CSS does not parse (it must never be half-rewritten).
|
|
55
|
+
*/
|
|
56
|
+
export declare function setPageSizeInCss(css: string, page: PageSizePoints): string;
|
|
57
|
+
/** Read a book's page size back from its manifest and stylesheets. */
|
|
58
|
+
export declare function readPageSetup(projectDir: string): Promise<PageSetup>;
|
|
59
|
+
/**
|
|
60
|
+
* Change a book's page size: the manifest's `preset:` + `page:` bounds and the
|
|
61
|
+
* stylesheet's `@page` size, together. Mirrors what the wizard records —
|
|
62
|
+
* `dtrpg` / `book` carry their own bounds (any `page:` block is removed so it
|
|
63
|
+
* cannot shadow them), `custom` records the typed trim. Nothing is written
|
|
64
|
+
* unless the whole choice validates and the stylesheet parses.
|
|
65
|
+
*/
|
|
66
|
+
export declare function setPageSetup(projectDir: string, choice: PageSizeChoice): Promise<PageSetup>;
|
|
@@ -134,6 +134,12 @@ export interface OpPass {
|
|
|
134
134
|
fonts: FontRef[];
|
|
135
135
|
}
|
|
136
136
|
export declare function getOpPass(doc: PDFDocumentProxy): Promise<OpPass>;
|
|
137
|
+
/**
|
|
138
|
+
* Does page `pageNum` (1-based) paint anything at all? False for a page with
|
|
139
|
+
* no content and for one whose operators only set state or clip. A path op
|
|
140
|
+
* carries its painting operator as its first argument (`constructPath`).
|
|
141
|
+
*/
|
|
142
|
+
export declare function pageHasMarks(doc: PDFDocumentProxy, pageNum: number): Promise<boolean>;
|
|
137
143
|
/**
|
|
138
144
|
* Per-image effective DPI = pixel dimension ÷ placed size in inches. Decodes
|
|
139
145
|
* each image (best-effort). Used only by the opt-in image-resolution check.
|
package/dist/lib/printsafe.d.ts
CHANGED
|
@@ -9,8 +9,15 @@ export interface PrintSafeWarning {
|
|
|
9
9
|
line: number;
|
|
10
10
|
column: number;
|
|
11
11
|
}
|
|
12
|
+
export interface CheckCssOptions {
|
|
13
|
+
/** The manifest's `lint.rules`: `off` drops a rule, `warn`/`error` set its severity. */
|
|
14
|
+
rules?: Readonly<Record<string, unknown>>;
|
|
15
|
+
}
|
|
12
16
|
/**
|
|
13
17
|
* Run print-safety checks against a CSS string. Returns one warning per finding
|
|
14
18
|
* (errors for remote URLs / syntax errors; warnings for risky print effects).
|
|
19
|
+
* A `/* gutterpress-disable-next-line <rule-id> *\/` comment silences that
|
|
20
|
+
* rule on the line directly below it; `options.rules` applies the project's
|
|
21
|
+
* per-rule levels (see lint-rules.ts).
|
|
15
22
|
*/
|
|
16
|
-
export declare function checkCss(css: string, from?: string): PrintSafeWarning[];
|
|
23
|
+
export declare function checkCss(css: string, from?: string, options?: CheckCssOptions): PrintSafeWarning[];
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type PresetId } from "./presets.ts";
|
|
2
|
+
import { type CustomPageOptions } from "./page-size.ts";
|
|
2
3
|
/**
|
|
3
4
|
* Which embedded starter template to scaffold from. Each id maps to a directory
|
|
4
5
|
* under `assets/templates/<id>/` (a `manifest.yaml` + a `chapter-01.md`), baked
|
|
@@ -71,15 +72,8 @@ export interface CreateProjectOptions {
|
|
|
71
72
|
/** Version-history mode for the new project. Defaults to `"local-git"`. */
|
|
72
73
|
versionHistory?: ProjectVersionHistoryMode;
|
|
73
74
|
}
|
|
74
|
-
/** Page bounds for {@link CreateProjectOptions.customPage}. */
|
|
75
|
-
export
|
|
76
|
-
/** Trim width in points (72pt = 1in). */
|
|
77
|
-
width: number;
|
|
78
|
-
/** Trim height in points (72pt = 1in). */
|
|
79
|
-
height: number;
|
|
80
|
-
/** Allowed deviation in points when validating a built PDF. Default 0.5. */
|
|
81
|
-
tolerance?: number;
|
|
82
|
-
}
|
|
75
|
+
/** Page bounds for {@link CreateProjectOptions.customPage} (defined in page-size.ts). */
|
|
76
|
+
export type { CustomPageOptions };
|
|
83
77
|
/** The result of a successful scaffold. */
|
|
84
78
|
export interface CreateProjectResult {
|
|
85
79
|
/** Absolute path of the created project directory. */
|
|
@@ -19,6 +19,13 @@ export interface RemoteRepository {
|
|
|
19
19
|
private: boolean;
|
|
20
20
|
defaultBranch: string;
|
|
21
21
|
htmlUrl: string;
|
|
22
|
+
/**
|
|
23
|
+
* Could be an empty repository the author can back a book up to: GitHub
|
|
24
|
+
* reports size 0, and the repository is writable and not archived. A hint
|
|
25
|
+
* for pickers only — a tiny non-empty repository also reports size 0, so
|
|
26
|
+
* the real emptiness check happens when a book is connected (online-backup.ts).
|
|
27
|
+
*/
|
|
28
|
+
maybeEmpty?: boolean;
|
|
22
29
|
}
|
|
23
30
|
/** One branch of a remote repository. */
|
|
24
31
|
export interface RemoteBranch {
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { type RemoteRepository } from "./github-repos.ts";
|
|
2
|
+
import type { SyncOutcome, SyncProjectOptions } from "./sync-types.ts";
|
|
3
|
+
import type { HostCredential, TokenStore } from "./token-store.ts";
|
|
4
|
+
/** What to connect the book to. */
|
|
5
|
+
export type BackupTarget = {
|
|
6
|
+
kind: "create";
|
|
7
|
+
/** Repository name (letters, numbers, `-`, `_`, `.`). */
|
|
8
|
+
name: string;
|
|
9
|
+
/** Defaults to private — a book is not published by backing it up. */
|
|
10
|
+
private?: boolean;
|
|
11
|
+
} | {
|
|
12
|
+
kind: "existing";
|
|
13
|
+
owner: string;
|
|
14
|
+
name: string;
|
|
15
|
+
};
|
|
16
|
+
export interface SetUpOnlineBackupOptions {
|
|
17
|
+
projectDir: string;
|
|
18
|
+
target: BackupTarget;
|
|
19
|
+
/** Explicit credential; wins over the token store. */
|
|
20
|
+
credential?: HostCredential;
|
|
21
|
+
/** Source of the saved GitHub connection when no credential is passed. */
|
|
22
|
+
tokenStore?: TokenStore;
|
|
23
|
+
authorName?: string;
|
|
24
|
+
authorEmail?: string;
|
|
25
|
+
/** Injectable fetch for tests. Defaults to global fetch. */
|
|
26
|
+
fetchImpl?: typeof fetch;
|
|
27
|
+
/** Injectable git transport for tests (passed to `syncProject`). */
|
|
28
|
+
httpClient?: SyncProjectOptions["httpClient"];
|
|
29
|
+
/** Operation log (passed to `syncProject`). */
|
|
30
|
+
logFile?: SyncProjectOptions["logFile"];
|
|
31
|
+
}
|
|
32
|
+
export type BackupSetupFailureReason = "not-connected" | "auth" | "offline" | "no-history" | "already-has-remote" | "invalid-name" | "name-taken" | "not-found" | "no-permission" | "not-empty" | "push-failed";
|
|
33
|
+
export type BackupSetupResult = {
|
|
34
|
+
status: "connected";
|
|
35
|
+
repository: RemoteRepository;
|
|
36
|
+
sync: SyncOutcome;
|
|
37
|
+
} | {
|
|
38
|
+
status: "failed";
|
|
39
|
+
reason: BackupSetupFailureReason;
|
|
40
|
+
/** Plain-language, safe to show verbatim. */
|
|
41
|
+
message: string;
|
|
42
|
+
/** The repository that exists online after a late failure (created or chosen). */
|
|
43
|
+
repository?: RemoteRepository;
|
|
44
|
+
};
|
|
45
|
+
/** True for a name GitHub accepts for a repository. */
|
|
46
|
+
export declare function isValidRepositoryName(name: string): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Connect a locally-versioned book to a GitHub repository and push its
|
|
49
|
+
* history. Never throws for expected outcomes; see the header.
|
|
50
|
+
*/
|
|
51
|
+
export declare function setUpOnlineBackup(options: SetUpOnlineBackupOptions): Promise<BackupSetupResult>;
|
package/dist/lib/snippets.d.ts
CHANGED
|
@@ -87,6 +87,9 @@ export interface MarkerComponent {
|
|
|
87
87
|
* as the renderer resolves them — an alias lists its target's. A variant
|
|
88
88
|
* only adds a class, so one snippet serves them all. */
|
|
89
89
|
variants: string[];
|
|
90
|
+
/** True for a `selfClosing` marker: one element, no body, no `@end-<name>` —
|
|
91
|
+
* the editor inserts the bare marker without a closing pair. */
|
|
92
|
+
selfClosing?: true;
|
|
90
93
|
/** The winning example snippet's body (book, then extension, then core). */
|
|
91
94
|
snippet?: string;
|
|
92
95
|
}
|
|
@@ -169,7 +169,13 @@
|
|
|
169
169
|
},
|
|
170
170
|
"reserveLastPage": {
|
|
171
171
|
"type": "boolean",
|
|
172
|
-
"description": "Guarantee the final page is a blank page added by the build (no background, no page number). When the content already fills a signature exactly, a full signature of blank pages is added. DriveThruRPG reserves the last page for printer information. Preset defaults: dtrpg true, book false."
|
|
172
|
+
"description": "Guarantee the final page is a blank page added by the build (no background, no page number). When the content already fills a signature exactly, a full signature of blank pages is added. DriveThruRPG reserves the last page for printer information. Preset defaults: dtrpg true, book false. Same as `lastPage: blank`; `lastPage` wins when both are set."
|
|
173
|
+
},
|
|
174
|
+
"lastPage": {
|
|
175
|
+
"type": "string",
|
|
176
|
+
"description": "How the interior's last page is reserved for a printer that uses it (DriveThruRPG puts its printer information there). `blank` ends the interior on a blank page the build adds. `short-by-one` pads to one page short of a multiple of `signature` (k x signature - 1), and the printer supplies the last page. Wins over `reserveLastPage`. Not set by any preset.",
|
|
177
|
+
"enum": ["blank", "short-by-one"],
|
|
178
|
+
"examples": ["blank", "short-by-one"]
|
|
173
179
|
}
|
|
174
180
|
}
|
|
175
181
|
},
|
|
@@ -217,7 +223,7 @@
|
|
|
217
223
|
},
|
|
218
224
|
"lint": {
|
|
219
225
|
"type": "object",
|
|
220
|
-
"description": "
|
|
226
|
+
"description": "Lint settings: whether the pre-build lint runs, the markdownlint config, and per-rule level overrides.",
|
|
221
227
|
"properties": {
|
|
222
228
|
"enabled": {
|
|
223
229
|
"type": "boolean",
|
|
@@ -228,6 +234,12 @@
|
|
|
228
234
|
"type": ["string", "null"],
|
|
229
235
|
"description": "Path to a markdownlint config file, relative to the manifest directory. null uses the built-in defaults.",
|
|
230
236
|
"default": null
|
|
237
|
+
},
|
|
238
|
+
"rules": {
|
|
239
|
+
"type": "object",
|
|
240
|
+
"description": "Per-rule level overrides, keyed by rule id: a printsafe rule (printsafe/no-risky-print-effects, printsafe/page-containment, printsafe/no-remote-urls) or a check id such as source.accessibility.heading-order. \"off\" silences the rule; \"warn\" / \"error\" set its severity. An id that matches no rule is ignored. To silence one site instead, put a `gutterpress-disable-next-line <rule-id> -- reason` comment (CSS `/* */` or markdown `<!-- -->`) on the line above it.",
|
|
241
|
+
"additionalProperties": { "enum": ["off", "warn", "error"] },
|
|
242
|
+
"examples": [{ "printsafe/no-risky-print-effects": "off" }]
|
|
231
243
|
}
|
|
232
244
|
}
|
|
233
245
|
},
|
|
@@ -7,16 +7,16 @@ import {
|
|
|
7
7
|
TARGET_IDS,
|
|
8
8
|
scaffoldExtension,
|
|
9
9
|
scaffoldProject
|
|
10
|
-
} from "./cli-
|
|
10
|
+
} from "./cli-9nba5ve6.js";
|
|
11
11
|
import {
|
|
12
12
|
resolveGhostscript
|
|
13
|
-
} from "./cli-
|
|
13
|
+
} from "./cli-3p1e95zc.js";
|
|
14
14
|
import {
|
|
15
15
|
UsageError,
|
|
16
16
|
rejectExtraPositionals,
|
|
17
17
|
rejectUnknownFlags
|
|
18
|
-
} from "./cli-
|
|
19
|
-
import"./cli-
|
|
18
|
+
} from "./cli-d57bsfpb.js";
|
|
19
|
+
import"./cli-jyy9pqf3.js";
|
|
20
20
|
import {
|
|
21
21
|
EXIT_CODES
|
|
22
22
|
} from "./cli-46ycxe6r.js";
|
|
@@ -62,12 +62,15 @@ const PREFIX = "{{PREFIX}}";
|
|
|
62
62
|
* @end-term-box
|
|
63
63
|
*
|
|
64
64
|
* Fields, all optional:
|
|
65
|
-
* section true makes the marker a core @section (no tag/label/autoCloseAt)
|
|
65
|
+
* section true makes the marker a core @section (no tag/label/autoCloseAt/selfClosing)
|
|
66
66
|
* tag wrapper element (default "div")
|
|
67
67
|
* class base class on the wrapper
|
|
68
68
|
* variants extra classes keyed by the marker's bare word
|
|
69
69
|
* label a label element built from one of the marker's attributes
|
|
70
70
|
* autoCloseAt ["eof"] closes an unclosed container at end of file
|
|
71
|
+
* selfClosing true for a marker with no body and no @end-<name>: it emits its
|
|
72
|
+
* element (and label) and closes it at once. Not with autoCloseAt;
|
|
73
|
+
* a `validate` on it sees empty `blocks` and `text`.
|
|
71
74
|
* snippet example content the editor inserts for this component, as a
|
|
72
75
|
* path inside this folder (default: snippets/<name>.md — so
|
|
73
76
|
* `snippets/term-box.md` is term-box's example already)
|
|
@@ -210,6 +210,9 @@ describe("conventions", () => {
|
|
|
210
210
|
for (const at of decl.autoCloseAt ?? []) {
|
|
211
211
|
expect(at).toBe("eof");
|
|
212
212
|
}
|
|
213
|
+
expect(typeof decl.selfClosing === "undefined" || typeof decl.selfClosing === "boolean").toBe(true);
|
|
214
|
+
// A self-closing marker has no frame for autoCloseAt to close.
|
|
215
|
+
if (decl.selfClosing) expect(decl.autoCloseAt).toBeUndefined();
|
|
213
216
|
expect(name).toBeTruthy();
|
|
214
217
|
}
|
|
215
218
|
});
|
|
@@ -218,7 +221,7 @@ describe("conventions", () => {
|
|
|
218
221
|
// The editor inserts this file when an author picks the component, so it
|
|
219
222
|
// is the example of the structure the component expects.
|
|
220
223
|
for (const [name, decl] of Object.entries(markers)) {
|
|
221
|
-
if (decl.deprecated !== undefined || decl.alias !== undefined) continue;
|
|
224
|
+
if (decl.deprecated !== undefined || decl.alias !== undefined || decl.selfClosing) continue;
|
|
222
225
|
const rel = decl.snippet ?? `${pkg.gutterpress?.snippets ?? "snippets"}/${name}.md`;
|
|
223
226
|
if (!existsSync(path.join(root, rel))) continue;
|
|
224
227
|
const snippet = read(rel);
|
|
@@ -2,16 +2,16 @@ import {
|
|
|
2
2
|
executeValidation,
|
|
3
3
|
publishTargetFor,
|
|
4
4
|
reportMissingTools
|
|
5
|
-
} from "./cli-
|
|
5
|
+
} from "./cli-9nba5ve6.js";
|
|
6
6
|
import {
|
|
7
7
|
log
|
|
8
|
-
} from "./cli-
|
|
8
|
+
} from "./cli-3p1e95zc.js";
|
|
9
9
|
import {
|
|
10
10
|
UsageError,
|
|
11
11
|
rejectExtraPositionals,
|
|
12
12
|
rejectUnknownFlags
|
|
13
|
-
} from "./cli-
|
|
14
|
-
import"./cli-
|
|
13
|
+
} from "./cli-d57bsfpb.js";
|
|
14
|
+
import"./cli-jyy9pqf3.js";
|
|
15
15
|
import {
|
|
16
16
|
BuildError,
|
|
17
17
|
EXIT_CODES
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import { type FSWatcher } from 'chokidar';
|
|
8
8
|
import type { ServerState } from './server-context';
|
|
9
9
|
import type { ResolvedExtensionConfig } from '../schema/manifest.types';
|
|
10
|
+
import type { PrintPadding } from '../engine/shared/synthesis.ts';
|
|
10
11
|
/**
|
|
11
12
|
* Rewrite rendered book HTML for the live preview: inject the Gutterpress
|
|
12
13
|
* engine's viewer bundle (`/engine/gutterpress-viewer.js`, embedded the same
|
|
@@ -43,10 +44,7 @@ export declare function generateAndWriteHtml(inputPath: string, tempDir: string,
|
|
|
43
44
|
files?: string[] | null;
|
|
44
45
|
};
|
|
45
46
|
extensions?: ResolvedExtensionConfig[];
|
|
46
|
-
print?:
|
|
47
|
-
signature?: number;
|
|
48
|
-
reserveLastPage?: boolean;
|
|
49
|
-
};
|
|
47
|
+
print?: PrintPadding;
|
|
50
48
|
}, cssAssets: Map<string, string>, imageRefs?: Set<string>): Promise<void>;
|
|
51
49
|
/**
|
|
52
50
|
* Chokidar 5's `ignored` matcher (regex or function) is tested against the
|
|
@@ -7,10 +7,10 @@ import {
|
|
|
7
7
|
runBuild,
|
|
8
8
|
splitOutPath,
|
|
9
9
|
startPreviewServer
|
|
10
|
-
} from "./cli-
|
|
10
|
+
} from "./cli-9nba5ve6.js";
|
|
11
11
|
import {
|
|
12
12
|
log
|
|
13
|
-
} from "./cli-
|
|
13
|
+
} from "./cli-3p1e95zc.js";
|
|
14
14
|
import {
|
|
15
15
|
UsageError,
|
|
16
16
|
parseFormat,
|
|
@@ -18,8 +18,8 @@ import {
|
|
|
18
18
|
rejectExtraPositionals,
|
|
19
19
|
rejectUnknownFlags,
|
|
20
20
|
resolvePort
|
|
21
|
-
} from "./cli-
|
|
22
|
-
import"./cli-
|
|
21
|
+
} from "./cli-d57bsfpb.js";
|
|
22
|
+
import"./cli-jyy9pqf3.js";
|
|
23
23
|
import {
|
|
24
24
|
BuildError
|
|
25
25
|
} from "./cli-46ycxe6r.js";
|
|
@@ -11,17 +11,17 @@ import {
|
|
|
11
11
|
publishProviderFor,
|
|
12
12
|
resolvePublishFormat,
|
|
13
13
|
runPublish
|
|
14
|
-
} from "./cli-
|
|
14
|
+
} from "./cli-9nba5ve6.js";
|
|
15
15
|
import {
|
|
16
16
|
FileTokenStore,
|
|
17
17
|
log
|
|
18
|
-
} from "./cli-
|
|
18
|
+
} from "./cli-3p1e95zc.js";
|
|
19
19
|
import {
|
|
20
20
|
UsageError,
|
|
21
21
|
rejectExtraPositionals,
|
|
22
22
|
rejectUnknownFlags
|
|
23
|
-
} from "./cli-
|
|
24
|
-
import"./cli-
|
|
23
|
+
} from "./cli-d57bsfpb.js";
|
|
24
|
+
import"./cli-jyy9pqf3.js";
|
|
25
25
|
import {
|
|
26
26
|
EXIT_CODES
|
|
27
27
|
} from "./cli-46ycxe6r.js";
|