gutterpress 0.11.10 → 0.11.11-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 +3 -3
- package/dist/api/index.js +2 -2
- package/dist/{build-83dnh2qe.js → build-pjd42x09.js} +4 -4
- package/dist/checks/asset/extensions.d.ts +2 -2
- package/dist/checks/policy.d.ts +5 -7
- package/dist/checks/register-builtins.d.ts +6 -6
- package/dist/checks/registry.d.ts +1 -1
- package/dist/{cli-79tsqp3p.js → cli-1kdtzgxm.js} +1 -1
- package/dist/{cli-mv1mhpkk.js → cli-d2he8zph.js} +6 -6
- package/dist/{cli-b36za51e.js → cli-ny50k8md.js} +3 -3
- package/dist/{cli-30j93gzt.js → cli-tjhn2mdn.js} +3 -3
- package/dist/cli.js +12 -12
- package/dist/{doctor-sy4gc8r9.js → doctor-qkh9byxa.js} +2 -2
- package/dist/engine/shared/cdp.d.ts +5 -9
- package/dist/engine/shared/pdf-inspect.d.ts +0 -4
- package/dist/{engine-mwshptgf.js → engine-132czsq9.js} +1 -1
- package/dist/{engine-3gwctsty.js → engine-bgd4aa99.js} +2 -2
- package/dist/{ext-a7ffvyc0.js → ext-271xnh70.js} +4 -4
- package/dist/{index-dzp0hc2c.js → index-b6p1fh61.js} +1 -1
- package/dist/{index-r4wvy5v3.js → index-mw8b25yx.js} +3 -3
- package/dist/{index-0cvkvpkg.js → index-ssjh6tnd.js} +7 -7
- package/dist/index.js +3 -3
- package/dist/lib/asset-inline.d.ts +1 -2
- package/dist/lib/build-error.d.ts +4 -6
- package/dist/lib/build-fingerprint.d.ts +3 -4
- package/dist/lib/build-preflight.d.ts +4 -6
- package/dist/lib/build-runner.d.ts +24 -35
- package/dist/lib/build-staging.d.ts +3 -5
- package/dist/lib/cli-args.d.ts +1 -1
- package/dist/lib/desktop.d.ts +2 -8
- package/dist/lib/engine.d.ts +2 -2
- package/dist/lib/exec.d.ts +3 -6
- package/dist/lib/fetch-timeout.d.ts +3 -4
- package/dist/lib/ghostscript.d.ts +1 -1
- package/dist/lib/host-policy.d.ts +6 -8
- package/dist/lib/image-inspect.d.ts +2 -2
- package/dist/lib/install-hints.d.ts +2 -3
- package/dist/lib/manifest-config.d.ts +2 -3
- package/dist/lib/manifest-doc.d.ts +2 -3
- package/dist/lib/manifest.d.ts +4 -7
- package/dist/lib/markdown/assemble.d.ts +7 -13
- package/dist/lib/markdown/gutterpress-css.d.ts +6 -9
- package/dist/lib/markdown/images.d.ts +0 -7
- package/dist/lib/markdown/index.d.ts +7 -11
- package/dist/lib/markdown/markers.d.ts +3 -4
- package/dist/lib/markdown/plugins.d.ts +9 -12
- package/dist/lib/markdown/renderer.d.ts +10 -14
- package/dist/lib/missing-asset-placeholder.d.ts +2 -5
- package/dist/lib/output-paths.d.ts +4 -5
- package/dist/lib/pdf-inspect.d.ts +5 -5
- package/dist/lib/pdf-parse.d.ts +6 -7
- package/dist/lib/presets.d.ts +2 -3
- package/dist/lib/project-source.d.ts +3 -4
- package/dist/lib/publish/command-runner.d.ts +1 -1
- package/dist/lib/publish/connect-google.d.ts +2 -2
- package/dist/lib/publish/types.d.ts +3 -3
- package/dist/lib/remote-auth/clone.d.ts +2 -2
- package/dist/lib/remote-auth/converge-merge.d.ts +1 -1
- package/dist/lib/remote-auth/diagnose.d.ts +3 -3
- package/dist/lib/remote-auth/generic-auth.d.ts +1 -1
- package/dist/lib/remote-auth/git-http.d.ts +5 -5
- package/dist/lib/remote-auth/github-auth.d.ts +3 -3
- package/dist/lib/remote-auth/github-repos.d.ts +4 -4
- package/dist/lib/remote-auth/sync-types.d.ts +1 -1
- package/dist/lib/remote-auth/sync.d.ts +1 -1
- package/dist/lib/remote-auth/test-access.d.ts +1 -1
- package/dist/lib/remote-auth/token-store.d.ts +1 -1
- package/dist/lib/remote-auth/transport.d.ts +3 -3
- package/dist/lib/render-parity-raster.d.ts +28 -0
- package/dist/lib/render-parity.d.ts +4 -1
- package/dist/lib/source-provider.d.ts +4 -5
- package/dist/lib/static-serve.d.ts +8 -13
- package/dist/lib/style-resolver.d.ts +1 -1
- package/dist/lib/targets.d.ts +1 -5
- package/dist/lib/tool-probe.d.ts +2 -3
- package/dist/lib/validation-exec.d.ts +3 -4
- package/dist/{new-994trd8k.js → new-7w4ezfpy.js} +4 -4
- package/dist/platform.d.ts +8 -41
- package/dist/{preflight-2rtrakyf.js → preflight-f3h6arjp.js} +4 -4
- package/dist/preview/file-watcher.d.ts +3 -5
- package/dist/preview/lifecycle.d.ts +9 -17
- package/dist/{preview-bridge-b4jbtb79.js → preview-bridge-8jhd1wpb.js} +1 -1
- package/dist/{preview-interface-9rwz21yw.js → preview-interface-twd6nsf5.js} +74 -13
- package/dist/{preview-shell-tqndvhbx.js → preview-shell-y8yrm3f0.js} +8 -19
- package/dist/{preview-n9s46142.js → preview-y39jrpbs.js} +4 -4
- package/dist/{publish-wte9548r.js → publish-tvj3xh8m.js} +4 -4
- package/dist/render.d.ts +5 -5
- package/dist/render.js +2 -2
- package/dist/schema/manifest.types.d.ts +2 -2
- package/dist/utils/logger.d.ts +1 -2
- package/dist/{validate-jfsh3m1c.js → validate-9enr4ecc.js} +4 -4
- package/package.json +3 -3
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Pure (node-free) markdown rendering core.
|
|
3
3
|
*
|
|
4
|
-
* §1/§8
|
|
4
|
+
* §1/§8: this module imports ONLY pure JS — markdown-it and its
|
|
5
5
|
* plugins, Gutterpress's inlined marker parser (`markers.js`), and the node-free
|
|
6
6
|
* leveled logger (console-only). It contains NO `node:*`,
|
|
7
7
|
* NO `fs`/`path`/`url`, and NO filesystem access, so it can be imported by the
|
|
8
|
-
* browser
|
|
8
|
+
* browser AND bundled into the
|
|
9
9
|
* `bun build --compile` CLI binary alike.
|
|
10
10
|
*
|
|
11
11
|
* The plugin *author* types and the markdown-it factory live here (not in
|
|
@@ -201,22 +201,18 @@ export declare const BUILTIN_OPTIONAL_PLUGINS: Record<string, GutterpressPlugin>
|
|
|
201
201
|
* `<dl><dt><dd>`. It is not in CommonMark/markdown-it core; this is the
|
|
202
202
|
* canonical markdown-it plugin for it.
|
|
203
203
|
*
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
* for the
|
|
204
|
+
* There is no block container syntax (`:::name ... :::`): the @marker family
|
|
205
|
+
* is the wrapped-block surface. See
|
|
206
|
+
* docs/migrations/2026-05-removing-container-syntax.md for the mapping.
|
|
207
207
|
*
|
|
208
|
-
* GFM-style `> [!NOTE]` alerts
|
|
209
|
-
* same date because the emitted classes (dc-alert, dc-vibe-callout, etc.)
|
|
210
|
-
* were DC-branded — core should not leak DC identifiers. #237 (0.10.7)
|
|
211
|
-
* restored a core-owned, unbranded equivalent as an OPT-IN bundled feature —
|
|
208
|
+
* GFM-style `> [!NOTE]` alerts are an OPT-IN bundled feature (#237) —
|
|
212
209
|
* `gfm-alerts.ts`, registered below as `gutterpress-gfm-alerts` — emitting
|
|
213
210
|
* only the standard GitHub five (NOTE/TIP/IMPORTANT/WARNING/CAUTION) as
|
|
214
211
|
* neutral `gp-alert`/`gp-alert-<type>` structure (see that file's header).
|
|
215
|
-
*
|
|
216
|
-
*
|
|
217
|
-
*
|
|
218
|
-
*
|
|
219
|
-
* literal blockquote, unchanged — this feature is opt-in, not a default.
|
|
212
|
+
* Core emits no branded identifiers: branded extra types (e.g. DC's
|
|
213
|
+
* `[!DM]`/`[!VIBE]`/`[!ORIGIN]`) and their class names belong in project
|
|
214
|
+
* plugins, layered on top of (or independent from) this primitive. A project
|
|
215
|
+
* using neither renders `> [!NOTE]` as a literal blockquote.
|
|
220
216
|
*
|
|
221
217
|
* #240 — before `gutterpressMarkers` is applied, every loaded plugin's
|
|
222
218
|
* declared `markers` table (if any) is merged into ONE registry via
|
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* A visible stand-in for an image the book references but does not have.
|
|
3
3
|
*
|
|
4
|
-
* WHY THIS EXISTS: a missing image
|
|
4
|
+
* WHY THIS EXISTS: without it, a missing image aborts the whole build
|
|
5
5
|
* (`Could not copy asset … ENOENT`). For a non-technical author that is the
|
|
6
6
|
* worst possible failure mode — one stale image path in a 273-page book and
|
|
7
7
|
* nothing renders at all, with a filesystem error as the only explanation.
|
|
8
8
|
* Worse, it makes the book unbuildable by anyone who does not already have
|
|
9
|
-
* the missing file
|
|
10
|
-
* was in: two chapters referenced art that exists nowhere in the repo, so
|
|
11
|
-
* every tool and every reviewer had to hand-patch placeholders in to build
|
|
12
|
-
* it at all.
|
|
9
|
+
* the missing file.
|
|
13
10
|
*
|
|
14
11
|
* The fix is NOT to substitute something invisible. A silently-blank image
|
|
15
12
|
* is how a missing illustration ships to print. This paints an unmistakable
|
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
* Output location + artifact naming, by convention rather than configuration.
|
|
3
3
|
*
|
|
4
4
|
* A book builds to `<manifestDir>/dist/<title-slug>/`, and its artifacts are
|
|
5
|
-
* `<title-slug>-<format>.pdf
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* configured filename, so building both left only the last).
|
|
5
|
+
* `<title-slug>-<format>.pdf` — a convention, not manifest configuration: the
|
|
6
|
+
* slug keeps several books in one tree apart, and the format is in the
|
|
7
|
+
* artifact name because the extension cannot tell a PDF from a PDF/X one (a
|
|
8
|
+
* shared filename would leave only the last one built).
|
|
10
9
|
*
|
|
11
10
|
* `--out` remains for per-invocation placement (CI, one-offs).
|
|
12
11
|
*/
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* pdfimages, pdftotext) and the general qpdf inspection used by the post-build
|
|
6
6
|
* validation checks. It has ZERO system dependency and — unlike raw pdfjs-dist,
|
|
7
7
|
* whose `legacy` build eagerly evaluates canvas/DOMMatrix code — unpdf bundles
|
|
8
|
-
* cleanly under `bun build --compile` (verified).
|
|
8
|
+
* cleanly under `bun build --compile` (verified).
|
|
9
9
|
*
|
|
10
10
|
* NOT replaced here (still system tools, by design):
|
|
11
11
|
* - Ghostscript (gs): ink coverage + PDF/X CMYK conversion — no JS equivalent.
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* catalog/object access pdfjs has no public API for, and qpdf is already
|
|
14
14
|
* mandatory whenever PDF/X is produced.
|
|
15
15
|
*
|
|
16
|
-
* Fidelity notes (accepted
|
|
16
|
+
* Fidelity notes (accepted):
|
|
17
17
|
* - Structural integrity (`isLoadable`) is a "does it parse" gate, not a deep
|
|
18
18
|
* `qpdf --check` of xref/stream-length integrity.
|
|
19
19
|
* - Image DPI requires decoding the image to read its pixel dimensions and is
|
|
@@ -25,10 +25,10 @@
|
|
|
25
25
|
*/
|
|
26
26
|
import type { PDFDocumentProxy, PDFPageProxy } from "unpdf/pdfjs";
|
|
27
27
|
/**
|
|
28
|
-
* Cap on distinct cached documents
|
|
28
|
+
* Cap on distinct cached documents. One validation run touches a
|
|
29
29
|
* single PDF across ~13 checks (one entry), so this only bounds accumulation
|
|
30
30
|
* ACROSS runs in a long-lived host (the Electron desktop validating many
|
|
31
|
-
* projects over a session). Without it, `docCache`
|
|
31
|
+
* projects over a session). Without it, `docCache` grows one never-freed parsed
|
|
32
32
|
* document per distinct path ever validated. LRU eviction destroys the evicted
|
|
33
33
|
* document so its decoded pages/fonts/images are released, not just unreferenced.
|
|
34
34
|
* (Exported so tests derive their eviction fixtures from the real cap.)
|
|
@@ -146,6 +146,6 @@ export declare function getImageResolutions(doc: PDFDocumentProxy): Promise<Arra
|
|
|
146
146
|
/**
|
|
147
147
|
* "Does it parse" gate: load every page. Returns true if the whole document is
|
|
148
148
|
* traversable. This is NOT a deep xref/stream-length integrity check — it only
|
|
149
|
-
* catches PDFs that are actually broken/unparseable
|
|
149
|
+
* catches PDFs that are actually broken/unparseable.
|
|
150
150
|
*/
|
|
151
151
|
export declare function isLoadable(doc: PDFDocumentProxy): Promise<boolean>;
|
package/dist/lib/pdf-parse.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export declare function readPdfBytes(pdfPath: string): Promise<string>;
|
|
|
15
15
|
/**
|
|
16
16
|
* Parse ink coverage from `gs -sDEVICE=inkcov` output.
|
|
17
17
|
*
|
|
18
|
-
* Ghostscript has no pure-JS equivalent (it stays a system tool
|
|
18
|
+
* Ghostscript has no pure-JS equivalent (it stays a system tool),
|
|
19
19
|
* so the inkcov path remains shell-based here.
|
|
20
20
|
*/
|
|
21
21
|
export declare function parseInkCov(out: string): {
|
|
@@ -34,12 +34,11 @@ interface InkCoveragePage {
|
|
|
34
34
|
tac: number;
|
|
35
35
|
}
|
|
36
36
|
/**
|
|
37
|
-
* Discriminated result for {@link getPerPageInkCoverage}
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
* measured.
|
|
37
|
+
* Discriminated result for {@link getPerPageInkCoverage}. Ghostscript failing
|
|
38
|
+
* (crash, corrupt PDF, missing binary, a Windows PATH mismatch) must be
|
|
39
|
+
* distinguishable from a legitimately measured, empty-pages result:
|
|
40
|
+
* collapsing both to the same `[]` would let the ink-coverage check silently
|
|
41
|
+
* PASS a book it never actually measured.
|
|
43
42
|
*/
|
|
44
43
|
export type InkCoverageResult = {
|
|
45
44
|
ok: true;
|
package/dist/lib/presets.d.ts
CHANGED
|
@@ -24,7 +24,7 @@ export type PresetId = (typeof PRESET_IDS)[number];
|
|
|
24
24
|
export declare const DTRPG_PRESET: VendorPreset;
|
|
25
25
|
/**
|
|
26
26
|
* A neutral, vendor-agnostic default for authors who aren't targeting a
|
|
27
|
-
* specific print vendor
|
|
27
|
+
* specific print vendor. Standard 6x9in trade-book trim size,
|
|
28
28
|
* no vendor total-area-coverage (TAC) cap, and no PDF/X forcing:
|
|
29
29
|
*
|
|
30
30
|
* - `page`: 6in x 9in (432 x 648pt) — the common generic trade paperback trim.
|
|
@@ -57,8 +57,7 @@ export declare function warnOnce(id: string, message: string, sink?: (msg: strin
|
|
|
57
57
|
/** Test-only reset hook — clears all warn-once dedup state. */
|
|
58
58
|
export declare function resetWarnOnce(): void;
|
|
59
59
|
/**
|
|
60
|
-
* Resolve a manifest/CLI `preset` value to the {@link VendorPreset} it names
|
|
61
|
-
* (UX finding M48).
|
|
60
|
+
* Resolve a manifest/CLI `preset` value to the {@link VendorPreset} it names.
|
|
62
61
|
*
|
|
63
62
|
* - Unset (`undefined`): defaults to `dtrpg`. That is the PRODUCT default,
|
|
64
63
|
* not a compatibility accident (ADR 0008): Gutterpress's primary audience
|
|
@@ -41,7 +41,7 @@ export type ProjectSource = {
|
|
|
41
41
|
* What the UI may offer for a given source. Derived purely from the source
|
|
42
42
|
* type; no I/O.
|
|
43
43
|
*
|
|
44
|
-
* NOTE
|
|
44
|
+
* NOTE: today the desktop only reads `canSnapshot` (it gates the
|
|
45
45
|
* StatusBar "Version history" affordance). The other flags —
|
|
46
46
|
* `canEnableVersionHistory`, `canViewHistory`, `canRestoreSnapshot`, `canRead`,
|
|
47
47
|
* `canWriteLocal`, `authManagedByApp` — are computed and part of the DTO but
|
|
@@ -51,9 +51,8 @@ export type ProjectSource = {
|
|
|
51
51
|
*
|
|
52
52
|
* Deliberately NO `canSync` here: syncability is a credential-aware question
|
|
53
53
|
* only `diagnoseProjectRemote().canSync` (remote-auth/diagnose.ts) can answer.
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
* were a recurring source of contradictory sync behavior. Remote PRESENCE, for
|
|
54
|
+
* A second, weaker `canSync` here (= hasRemote, any protocol, no credential
|
|
55
|
+
* check) would be a source of contradictory sync behavior. Remote PRESENCE, for
|
|
57
56
|
* display purposes, lives on the classification itself (`source.hasRemote`).
|
|
58
57
|
*/
|
|
59
58
|
export interface ProjectCapabilities {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { CommandRunner } from "./types.ts";
|
|
2
2
|
/**
|
|
3
|
-
* Default idle budget
|
|
3
|
+
* Default idle budget: applied BY THE RUNNER whenever
|
|
4
4
|
* `timeoutMs` is omitted, so no call site (a provider upload, a
|
|
5
5
|
* `commandExists` probe) can silently regain hang-forever behavior by
|
|
6
6
|
* forgetting to pass it. `timeoutMs: 0` is the explicit opt-out. Idle, not
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shared Google Drive connect flow (#221) — the ONE implementation behind
|
|
3
|
-
* both the CLI's `--connect` branch and
|
|
4
|
-
*
|
|
3
|
+
* both the CLI's `--connect` branch and the desktop's connect route, mirroring
|
|
4
|
+
* how `connect.ts` is shared for pasted-token providers.
|
|
5
5
|
*
|
|
6
6
|
* Unlike `connectPublishProvider` (verify-before-store for a PASTED token),
|
|
7
7
|
* this flow is verify-by-construction: `GoogleAuthProvider.connect()` only
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* (DriveThruRPG, Amazon KDP), stages a validated upload package and hands the
|
|
7
7
|
* author a checklist + the platform's upload URL ("guided" publishing).
|
|
8
8
|
*
|
|
9
|
-
* Architecture mirrors the remote-auth subsystem
|
|
9
|
+
* Architecture mirrors the remote-auth subsystem:
|
|
10
10
|
* - The lib NEVER touches OS keychains, the network, or child processes
|
|
11
11
|
* directly through ambient globals — hosts inject a {@link TokenStore},
|
|
12
12
|
* and tests inject {@link PublishDeps.fetch} / {@link PublishDeps.runCommand}.
|
|
@@ -89,7 +89,7 @@ export interface PublishProviderInfo {
|
|
|
89
89
|
* browser consent flow (see `google-auth.ts`'s `GoogleAuthProvider` for
|
|
90
90
|
* the gdrive precedent). UIs branch on this to swap the paste-a-key form
|
|
91
91
|
* for a "Connect …" button; {@link connectPublishProvider} REJECTS oauth
|
|
92
|
-
* providers outright so the
|
|
92
|
+
* providers outright so the paste-a-token path can never store an
|
|
93
93
|
* unverifiable credential for one (#221).
|
|
94
94
|
*/
|
|
95
95
|
connect?: "token" | "oauth";
|
|
@@ -135,7 +135,7 @@ export type CommandRunner = (cmd: string, args: string[], options?: {
|
|
|
135
135
|
/** Called once per output line — drives live progress logs. */
|
|
136
136
|
onOutput?: (line: string) => void;
|
|
137
137
|
/**
|
|
138
|
-
* Idle-kill budget in ms
|
|
138
|
+
* Idle-kill budget in ms. If the child produces no output and
|
|
139
139
|
* has not exited within this window, it is SIGKILL'd and the run rejects
|
|
140
140
|
* with a timeout error, so a stalled upload can't hang publish forever.
|
|
141
141
|
* Omitted / undefined = the runner's default (defaultCommandRunner applies
|
|
@@ -54,9 +54,9 @@ export interface CloneRepositoryResult {
|
|
|
54
54
|
*/
|
|
55
55
|
export declare function sanitizeCloneFolderName(name: string): string;
|
|
56
56
|
/**
|
|
57
|
-
* Clone a remote repository over smart HTTPS into `dir
|
|
57
|
+
* Clone a remote repository over smart HTTPS into `dir`.
|
|
58
58
|
*
|
|
59
|
-
* - HTTPS only (isomorphic-git has no SSH
|
|
59
|
+
* - HTTPS only (isomorphic-git has no SSH).
|
|
60
60
|
* - `singleBranch` always; `depth` opts into shallow (full by default — see
|
|
61
61
|
* the WHY on {@link CloneRepositoryOptions.depth}).
|
|
62
62
|
* - Tokens embedded in the URL are stripped and (when a `tokenStore` is
|
|
@@ -32,7 +32,7 @@ export interface ConvergeResult {
|
|
|
32
32
|
export declare const CONVERGE_PREPARE_MESSAGE = "Getting your changes ready to combine with the online version";
|
|
33
33
|
/** Snapshot message for the post-merge restore commit (kept-both/edits). */
|
|
34
34
|
export declare const CONVERGE_RESTORE_MESSAGE = "Kept both versions of the files that can't be combined";
|
|
35
|
-
/** The merge commit message
|
|
35
|
+
/** The merge commit message. */
|
|
36
36
|
export declare const CONVERGE_MERGE_MESSAGE = "Combined your changes with the online version";
|
|
37
37
|
/**
|
|
38
38
|
* diff3 merge that NEVER reports a conflict: clean hunks merge exactly like
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Project remote diagnostics (#14
|
|
2
|
+
* Project remote diagnostics (#14).
|
|
3
3
|
*
|
|
4
4
|
* Pure-lib replacement for the issue's original shell diagnostics
|
|
5
5
|
* (`git status` / `git remote -v` / `git branch --show-current` — all
|
|
@@ -26,7 +26,7 @@ export type ForgeKind = "github" | "gitea" | "forgejo" | "gitlab" | "bitbucket"
|
|
|
26
26
|
* - `ready-to-sync` — HTTPS remote with a stored credential (sync lands
|
|
27
27
|
* with #15's sync phase; the plumbing is in place).
|
|
28
28
|
* - `ssh-use-own-tools` — SSH remote: full local features, sync externally
|
|
29
|
-
*
|
|
29
|
+
* . The UI layers the "switch to HTTPS" hint on recognized hosts.
|
|
30
30
|
*/
|
|
31
31
|
export type RemoteGuidanceId = "local-only" | "connect-github-to-sync" | "https-connect-server" | "ready-to-sync" | "ssh-use-own-tools";
|
|
32
32
|
export interface ProjectRemoteDiagnosis {
|
|
@@ -45,7 +45,7 @@ export interface ProjectRemoteDiagnosis {
|
|
|
45
45
|
/** Token-settings deep link for recognized non-GitHub forges. */
|
|
46
46
|
tokenSettingsUrl: string | null;
|
|
47
47
|
/**
|
|
48
|
-
*
|
|
48
|
+
* hasRemote && smart-HTTPS && credential stored. The sync
|
|
49
49
|
* flow (#15 D5) is live, so this is the real "offer the Sync action"
|
|
50
50
|
* gate, not a future-capability hint.
|
|
51
51
|
*/
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Timeout wrapper for the isomorphic-git HTTP client
|
|
2
|
+
* Timeout wrapper for the isomorphic-git HTTP client.
|
|
3
3
|
*
|
|
4
4
|
* Every git transport call in this subsystem (`git.fetch`/`git.push`/
|
|
5
5
|
* `git.clone`) is invoked with no timeout: if the TCP connection succeeds but
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* guard every fetch with `AbortSignal.timeout`; this brings the same discipline
|
|
12
12
|
* to the git transport, at the one place a default client is chosen.
|
|
13
13
|
*
|
|
14
|
-
* Design (
|
|
14
|
+
* Design (a naive deadline on `request()` is WRONG for pushes):
|
|
15
15
|
* isomorphic-git passes upload bodies as an ARRAY of buffers, which the node
|
|
16
16
|
* client collects and sends with Content-Length — `request()` then resolves
|
|
17
17
|
* only when the response HEADERS arrive, i.e. after the ENTIRE pack upload.
|
|
@@ -67,9 +67,9 @@ export declare const SMALL_BODY_MAX_BYTES: number;
|
|
|
67
67
|
* {@link SMALL_BODY_MAX_BYTES}. isomorphic-git always passes bodies as arrays
|
|
68
68
|
* of byte chunks, so small ones are sizable synchronously. Any chunk WITHOUT
|
|
69
69
|
* a numeric byteLength makes the body unsizable → NOT small, so it gets the
|
|
70
|
-
* long upload backstop rather than the idle deadline as a total cap (
|
|
71
|
-
*
|
|
72
|
-
*
|
|
70
|
+
* long upload backstop rather than the idle deadline as a total cap (do not
|
|
71
|
+
* count unsizable chunks as 0 bytes — that is the exact opposite of that
|
|
72
|
+
* intent).
|
|
73
73
|
*/
|
|
74
74
|
export declare function isSmallBody(body: unknown): boolean;
|
|
75
75
|
/**
|
|
@@ -10,7 +10,7 @@ export interface DeviceCodeInfo {
|
|
|
10
10
|
/** Minimum seconds between token polls. */
|
|
11
11
|
interval: number;
|
|
12
12
|
}
|
|
13
|
-
/** Host-supplied callbacks for the interactive connect flow
|
|
13
|
+
/** Host-supplied callbacks for the interactive connect flow. */
|
|
14
14
|
export interface HostCallbacks {
|
|
15
15
|
/** Called once with the code/URL so the UI can display them. */
|
|
16
16
|
onUserCode(info: DeviceCodeInfo): void;
|
|
@@ -25,7 +25,7 @@ export interface HostCallbacks {
|
|
|
25
25
|
*/
|
|
26
26
|
export declare function resolveGitHubClientId(explicit?: string): string;
|
|
27
27
|
export declare const GITHUB_HOST = "github.com";
|
|
28
|
-
/** Author-friendly message for connectivity failures
|
|
28
|
+
/** Author-friendly message for connectivity failures. */
|
|
29
29
|
export declare const OFFLINE_MESSAGE = "Couldn't reach GitHub. Check your connection and try again.";
|
|
30
30
|
export interface GitHubAuthProviderOptions {
|
|
31
31
|
/** Explicit client id (overrides env + default). */
|
|
@@ -35,7 +35,7 @@ export interface GitHubAuthProviderOptions {
|
|
|
35
35
|
/** Injectable sleep for tests (so polling tests run instantly). */
|
|
36
36
|
sleepImpl?: (ms: number) => Promise<void>;
|
|
37
37
|
}
|
|
38
|
-
/** GitHub device-flow credential acquisition
|
|
38
|
+
/** GitHub device-flow credential acquisition. */
|
|
39
39
|
export declare class GitHubAuthProvider {
|
|
40
40
|
private readonly clientId;
|
|
41
41
|
private readonly fetchImpl;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* GitHub repo discovery (#15
|
|
2
|
+
* GitHub repo discovery (#15).
|
|
3
3
|
*
|
|
4
4
|
* Plain `fetch` against the GitHub REST API — deliberately no `@octokit`
|
|
5
5
|
* dependency. Lists every repository the user can access (`GET /user/repos`,
|
|
6
|
-
* the OAuth `repo`-scope model
|
|
6
|
+
* the OAuth `repo`-scope model), the
|
|
7
7
|
* branches of a chosen repository, and (via the Git Trees API) the gutterpress
|
|
8
8
|
* book projects inside a repo. The two REST listings paginate; the Git Trees
|
|
9
9
|
* call is a single request that handles the API's `truncated` flag instead. All
|
|
@@ -31,8 +31,8 @@ export interface GitHubApiOptions {
|
|
|
31
31
|
/**
|
|
32
32
|
* List every repository the user can access — own, collaborator, and org
|
|
33
33
|
* member — via `GET /user/repos` (paginated). The OAuth `repo` scope makes
|
|
34
|
-
* the full set visible with zero install/selection steps
|
|
35
|
-
*
|
|
34
|
+
* the full set visible with zero install/selection steps. `sort=pushed` puts
|
|
35
|
+
* recently-active books first; callers must
|
|
36
36
|
* PRESERVE this order (the picker renders it as "most recent first").
|
|
37
37
|
*/
|
|
38
38
|
export declare function listGitHubRepositories(credential: HostCredential, options?: GitHubApiOptions): Promise<RemoteRepository[]>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Type/interface declarations for snapshot-first sync
|
|
3
|
-
* (#15
|
|
3
|
+
* (#15). Shared by the orchestrator, transport and
|
|
4
4
|
* convergence modules share ONE definition of each result/option shape.
|
|
5
5
|
* Pure type surface — no runtime code.
|
|
6
6
|
*/
|
|
@@ -17,7 +17,7 @@ export declare function isPushRejected(e: unknown): boolean;
|
|
|
17
17
|
*/
|
|
18
18
|
export declare function isUnrelatedHistories(e: unknown): boolean;
|
|
19
19
|
/**
|
|
20
|
-
* Snapshot-first sync
|
|
20
|
+
* Snapshot-first sync. Serialized on the per-repo lock; one
|
|
21
21
|
* function-scoped object cache, released on return.
|
|
22
22
|
*
|
|
23
23
|
* If someone pushes between our fetch and our push, the push is rejected and
|
|
@@ -39,7 +39,7 @@ export declare const FAILURE_MESSAGES: Record<RemoteAccessFailureReason, string>
|
|
|
39
39
|
* - Never throws — every outcome is a classified {@link RemoteAccessResult}.
|
|
40
40
|
* - SSH URLs return `ssh-unsupported` with zero network traffic.
|
|
41
41
|
* - Credentials embedded in the URL are stripped and used for auth when no
|
|
42
|
-
* explicit credential is supplied
|
|
42
|
+
* explicit credential is supplied — they never leak onward.
|
|
43
43
|
* - `defaultBranch` comes from the server's `HEAD` symref when advertised.
|
|
44
44
|
*/
|
|
45
45
|
export declare function testRemoteAccess(options: TestRemoteAccessOptions): Promise<RemoteAccessResult>;
|
|
@@ -14,7 +14,7 @@ export interface HostCredential {
|
|
|
14
14
|
createdAt: number;
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
|
-
* Host-keyed credential vault contract
|
|
17
|
+
* Host-keyed credential vault contract. Implementations
|
|
18
18
|
* are provided by the HOST APP (Electron safeStorage, CLI 0600 file); the lib
|
|
19
19
|
* only consumes this interface.
|
|
20
20
|
*/
|
|
@@ -19,8 +19,8 @@ export declare function isCredentialTransmissionSafe(url: string): boolean;
|
|
|
19
19
|
/**
|
|
20
20
|
* Thrown by {@link onAuthFor} when a stored credential EXISTS but the remote
|
|
21
21
|
* URL fails {@link isCredentialTransmissionSafe} (non-loopback http). Loud and
|
|
22
|
-
* typed on purpose: the
|
|
23
|
-
*
|
|
22
|
+
* typed on purpose: silently withholding the credential surfaces as a 401 →
|
|
23
|
+
* "auth" → "reconnect" loop. The `code` string is the
|
|
24
24
|
* STABLE contract (matchable across dynamic-import boundaries).
|
|
25
25
|
*/
|
|
26
26
|
export declare class InsecureTransportError extends Error {
|
|
@@ -70,7 +70,7 @@ export declare function failureOutcome(e: unknown, snapshotId?: string): {
|
|
|
70
70
|
export declare function setupErrorMessage(e: unknown): string | null;
|
|
71
71
|
/**
|
|
72
72
|
* Snapshot-first step used by syncProject
|
|
73
|
-
|
|
73
|
+
*: commit any unsaved work in the WHOLE repo BEFORE any network
|
|
74
74
|
* or merge step, so a forced post-merge checkout can never discard it. The
|
|
75
75
|
* working-tree check runs lazily at action time on the caller's function-scoped
|
|
76
76
|
* object cache (released with the operation).
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Diff } from "./render-parity.ts";
|
|
2
|
+
export interface RgbImage {
|
|
3
|
+
w: number;
|
|
4
|
+
h: number;
|
|
5
|
+
/** Packed RGB, 3 bytes per pixel. */
|
|
6
|
+
data: Uint8Array;
|
|
7
|
+
}
|
|
8
|
+
/** Parse a binary PPM (P6, maxval 255) — what `pdftoppm` writes by default. */
|
|
9
|
+
export declare function parsePpm(buf: Uint8Array): RgbImage;
|
|
10
|
+
/**
|
|
11
|
+
* Count pixels where any channel differs by more than `tolerance` (a fraction
|
|
12
|
+
* of 255; 0.01 = 1%), and return a copy of `cand` with those pixels painted
|
|
13
|
+
* red. Images of different sizes differ everywhere and get no diff image.
|
|
14
|
+
*/
|
|
15
|
+
export declare function comparePixels(base: RgbImage, cand: RgbImage, tolerance: number): {
|
|
16
|
+
differing: number;
|
|
17
|
+
marked: RgbImage | null;
|
|
18
|
+
};
|
|
19
|
+
/** Encode an RGB image as a PNG (8-bit truecolour, no filtering). */
|
|
20
|
+
export declare function encodePng(img: RgbImage): Uint8Array;
|
|
21
|
+
/**
|
|
22
|
+
* Raster-compare the first `pageCount` pages of two PDFs. Returns one `raster`
|
|
23
|
+
* diff per differing page and writes `diff-NNN.png` for each into `outDir`.
|
|
24
|
+
*/
|
|
25
|
+
export declare function rasterDiffs(basePdf: string, candPdf: string, pageCount: number, outDir: string, options?: {
|
|
26
|
+
dpi?: number;
|
|
27
|
+
tolerance?: number;
|
|
28
|
+
}): Promise<Diff[]>;
|
|
@@ -41,7 +41,7 @@ export declare function extractReport(pdfPath: string): Promise<Report>;
|
|
|
41
41
|
* rounded to 3 decimals before it gets here.
|
|
42
42
|
*/
|
|
43
43
|
export declare function serializeReport(report: Report): string;
|
|
44
|
-
export type WaiverKind = "page-count" | "page-size" | "text" | "image";
|
|
44
|
+
export type WaiverKind = "page-count" | "page-size" | "text" | "image" | "raster";
|
|
45
45
|
export interface Waiver {
|
|
46
46
|
/** 1-based page number. Omit for kind "page-count" (there is no page). */
|
|
47
47
|
page?: number;
|
|
@@ -70,6 +70,9 @@ export interface CompareOptions {
|
|
|
70
70
|
/** Points. Applies to text run and image extents (x/y/w/h). Default 0.5. */
|
|
71
71
|
tolerance?: number;
|
|
72
72
|
waivers?: Waiver[];
|
|
73
|
+
/** Diffs found outside the report — the `raster` diffs of `compare
|
|
74
|
+
* --raster` (render-parity-raster.ts) — waived like every other kind. */
|
|
75
|
+
extraDiffs?: Diff[];
|
|
73
76
|
}
|
|
74
77
|
export interface CompareResult {
|
|
75
78
|
/** Diffs NOT excused by any waiver — non-empty means the gate fails. */
|
|
@@ -105,7 +105,7 @@ export interface SourceProvider {
|
|
|
105
105
|
/**
|
|
106
106
|
* Run `fn` exclusively per resolved project dir (FIFO promise chaining).
|
|
107
107
|
* Exported for the remote-clone surface (#15) so clone/fetch operations share
|
|
108
|
-
* the SAME queue as snapshot/restore —
|
|
108
|
+
* the SAME queue as snapshot/restore — one per-repo lock.
|
|
109
109
|
*/
|
|
110
110
|
export declare function withRepoLock<T>(projectDir: string, fn: () => Promise<T>): Promise<T>;
|
|
111
111
|
/**
|
|
@@ -164,7 +164,7 @@ export declare function stageChanges(dir: string, changes: WorkdirChanges, cache
|
|
|
164
164
|
/**
|
|
165
165
|
* True when the working tree differs from the index (added/modified/deleted
|
|
166
166
|
* files). Used to skip empty snapshots. Exported (lock-free) for the sync
|
|
167
|
-
* surface (#15
|
|
167
|
+
* surface (#15) — callers outside a lock should prefer the
|
|
168
168
|
* provider operations.
|
|
169
169
|
*/
|
|
170
170
|
export declare function hasPendingChanges(dir: string, cache?: GitCache): Promise<boolean>;
|
|
@@ -177,14 +177,13 @@ export declare function hasPendingChanges(dir: string, cache?: GitCache): Promis
|
|
|
177
177
|
* sync-check path per the sync-simplicity mandate): this is for build
|
|
178
178
|
* *provenance* — the build fingerprint records whether the tree was clean at
|
|
179
179
|
* build time, where a `git add`-ed-but-not-committed change must still count
|
|
180
|
-
* as dirty (the
|
|
181
|
-
* WORKDIR-vs-STAGE-only check silently dropped it).
|
|
180
|
+
* as dirty (the WORKDIR-vs-STAGE-only check silently drops it).
|
|
182
181
|
*/
|
|
183
182
|
export declare function hasUncommittedChanges(dir: string, cache?: GitCache): Promise<boolean>;
|
|
184
183
|
/**
|
|
185
184
|
* Lock-free snapshot of the full working tree (stage everything + commit).
|
|
186
185
|
*
|
|
187
|
-
* Exported for the sync surface (#15
|
|
186
|
+
* Exported for the sync surface (#15): `syncProject` holds
|
|
188
187
|
* the per-repo lock for snapshot → fetch → merge → push as ONE sequence, so it
|
|
189
188
|
* needs the lock-free internal rather than `provider.snapshot()` (taking the
|
|
190
189
|
* per-method lock inside the sync lock would deadlock the FIFO queue).
|
|
@@ -4,20 +4,15 @@ import http from "node:http";
|
|
|
4
4
|
* in this package: the build-time pagination server and PDF-render server
|
|
5
5
|
* (build-runner.ts) and the live preview server (preview/http-server.ts).
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* in preview vs build-time pagination with no error, a silent divergence
|
|
10
|
-
* class. One table now; add a new extension once.
|
|
7
|
+
* One table for every server: a type added to only one would render
|
|
8
|
+
* differently in preview vs build-time pagination with no error.
|
|
11
9
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* servers above. Added below; if a third image format shows up, add it to
|
|
19
|
-
* BOTH tables in the same commit (asset-inline.ts is out of scope for this
|
|
20
|
-
* PR — see docs/reviews/duplication-audit-2026-07-28.md).
|
|
10
|
+
* `asset-inline.ts`'s `MIME_BY_EXT` is a separate table answering a separate
|
|
11
|
+
* question ("what Content-Type does a data: URI need when embedding this file
|
|
12
|
+
* inline" vs. this table's "what Content-Type does an HTTP response need"). A
|
|
13
|
+
* new image format must be added to BOTH tables in the same commit, or (as
|
|
14
|
+
* once happened with `.webp`/`.avif`) a copied image is served as
|
|
15
|
+
* `application/octet-stream`.
|
|
21
16
|
*/
|
|
22
17
|
export declare const STATIC_MIME: Record<string, string>;
|
|
23
18
|
/**
|
|
@@ -34,7 +34,7 @@ export declare function resolveActiveStyles(projectDir: string, manifestStyles?:
|
|
|
34
34
|
* the way the manifest stores them — project-relative, e.g.
|
|
35
35
|
* `../../shared/styles/components.css` — so toggling one on writes the right
|
|
36
36
|
* entry. Omit it (or pass the project itself) for the single-project case, which
|
|
37
|
-
*
|
|
37
|
+
* scans only the project.
|
|
38
38
|
*/
|
|
39
39
|
export declare function listProjectStyles(projectDir: string, opts?: {
|
|
40
40
|
repoRoot?: string;
|
package/dist/lib/targets.d.ts
CHANGED
|
@@ -17,9 +17,6 @@ import { type VendorPreset } from "./presets";
|
|
|
17
17
|
* skipped because its tools are missing becomes a synthetic error, so
|
|
18
18
|
* "validated for dtrpg" can never silently mean "the dtrpg checks didn't
|
|
19
19
|
* run".
|
|
20
|
-
*
|
|
21
|
-
* Grown from the old `validate --profile dtrpg` (validation-profile.ts,
|
|
22
|
-
* deleted): the profile was this exact idea hardcoded for one destination.
|
|
23
20
|
*/
|
|
24
21
|
/** The deep-partial preset shape a target may overlay. */
|
|
25
22
|
export type TargetOverlay = {
|
|
@@ -77,8 +74,7 @@ export declare function overlayPreset(preset: VendorPreset, target: PublishTarge
|
|
|
77
74
|
* The strict-PDF fill-ins applied to EVERY post-build PDF validation
|
|
78
75
|
* regardless of preset/target: any of these left `undefined` by the config
|
|
79
76
|
* becomes an error-severity check, without overwriting an author's explicit
|
|
80
|
-
* choice (including an explicit disable).
|
|
81
|
-
* validation-profile.ts (ARCH #21).
|
|
77
|
+
* choice (including an explicit disable).
|
|
82
78
|
*/
|
|
83
79
|
export declare const DEFAULT_STRICT_PDF_CHECKS: readonly ["pdf.structure.qpdf", "pdf.print.pdfx-markers", "pdf.print.pdfx-metadata", "pdf.print.embedded-fonts"];
|
|
84
80
|
export declare function applyDefaultPdfStrictChecks(config: ResolvedConfig): ResolvedConfig;
|
package/dist/lib/tool-probe.d.ts
CHANGED
|
@@ -19,9 +19,8 @@
|
|
|
19
19
|
*
|
|
20
20
|
* One implementation; one place to fix bugs. Spawning goes through
|
|
21
21
|
* exec.ts's `execCapture`, which also owns the shared, correctly
|
|
22
|
-
* delimiter-joined `enhancedPath`
|
|
23
|
-
*
|
|
24
|
-
* docs/reviews 2026-07-10-architecture-critical-review.md, finding #3).
|
|
22
|
+
* delimiter-joined `enhancedPath` — do not keep a second copy of that PATH
|
|
23
|
+
* construction here.
|
|
25
24
|
*/
|
|
26
25
|
/**
|
|
27
26
|
* Returns true if `tool` is resolvable via the platform's path-probe command.
|
|
@@ -30,10 +30,9 @@ export interface ValidationExecutionArgs {
|
|
|
30
30
|
* only, without touching the manifest's `validate.source.stylelint`
|
|
31
31
|
* setting on disk (#272 — one CSS gate, not two). Set by the build
|
|
32
32
|
* pipeline's `runQualityGates` (build-runner.ts) from `--skip-lint` /
|
|
33
|
-
* `config.lint.enabled: false`, so that flag disables just
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* panel) leaves this unset and gets the manifest's own setting.
|
|
33
|
+
* `config.lint.enabled: false`, so that flag disables just this one check.
|
|
34
|
+
* Every other caller (`gutterpress validate`/`preflight`, the desktop
|
|
35
|
+
* Problems panel) leaves this unset and gets the manifest's own setting.
|
|
37
36
|
*/
|
|
38
37
|
skipStylelint?: boolean;
|
|
39
38
|
/**
|