gutterpress 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +422 -0
- package/dist/CGATS21_CRPC1-g0e3k7kr.icc +0 -0
- package/dist/api/index.d.ts +76 -0
- package/dist/api/index.js +272 -0
- package/dist/assets/preview/scripts/pagedjs-bridge.d.ts +1 -0
- package/dist/assets/preview/scripts/pagedjs-interface.d.ts +1 -0
- package/dist/assets/preview/scripts/preview-shell.d.ts +1 -0
- package/dist/audit-1jrwwacz.js +66 -0
- package/dist/build-5s92kgpc.js +77 -0
- package/dist/chapter-01-6fn9pvd0.md +31 -0
- package/dist/chapter-01-7jwqg1ct.md +20 -0
- package/dist/chapter-01-jj8ftn4c.md +29 -0
- package/dist/chapter-01-rkpyvjna.md +26 -0
- package/dist/checks/asset/approved-fonts.d.ts +3 -0
- package/dist/checks/asset/extensions.d.ts +41 -0
- package/dist/checks/asset/font-license.d.ts +3 -0
- package/dist/checks/asset/image-alpha.d.ts +3 -0
- package/dist/checks/asset/image-color-space.d.ts +3 -0
- package/dist/checks/asset/image-file-size.d.ts +3 -0
- package/dist/checks/asset/image-resolution.d.ts +3 -0
- package/dist/checks/asset/image-tac.d.ts +3 -0
- package/dist/checks/asset/index.d.ts +7 -0
- package/dist/checks/formatter.d.ts +3 -0
- package/dist/checks/heuristic/index.d.ts +4 -0
- package/dist/checks/heuristic/layer-count.d.ts +3 -0
- package/dist/checks/heuristic/placement-variance.d.ts +3 -0
- package/dist/checks/heuristic/section-density.d.ts +3 -0
- package/dist/checks/heuristic/text-density.d.ts +3 -0
- package/dist/checks/pdf/bleed.d.ts +3 -0
- package/dist/checks/pdf/bookmarks.d.ts +3 -0
- package/dist/checks/pdf/color-spaces.d.ts +3 -0
- package/dist/checks/pdf/cross-refs.d.ts +3 -0
- package/dist/checks/pdf/embedded-fonts.d.ts +3 -0
- package/dist/checks/pdf/image-resolution.d.ts +3 -0
- package/dist/checks/pdf/index.d.ts +15 -0
- package/dist/checks/pdf/ink-coverage.d.ts +3 -0
- package/dist/checks/pdf/page-labels.d.ts +3 -0
- package/dist/checks/pdf/page-size.d.ts +3 -0
- package/dist/checks/pdf/pdfx-markers.d.ts +3 -0
- package/dist/checks/pdf/pdfx-metadata.d.ts +3 -0
- package/dist/checks/pdf/pdfx-structure.d.ts +6 -0
- package/dist/checks/pdf/qpdf-structure.d.ts +3 -0
- package/dist/checks/pdf/rasterized-pages.d.ts +3 -0
- package/dist/checks/pdf/toc-links.d.ts +3 -0
- package/dist/checks/pdf/transparency.d.ts +3 -0
- package/dist/checks/policy.d.ts +61 -0
- package/dist/checks/register-builtins.d.ts +17 -0
- package/dist/checks/registry.d.ts +40 -0
- package/dist/checks/runner.d.ts +25 -0
- package/dist/checks/source/accessibility-alt-text.d.ts +3 -0
- package/dist/checks/source/accessibility-heading-order.d.ts +3 -0
- package/dist/checks/source/config-file.d.ts +8 -0
- package/dist/checks/source/htmlhint.d.ts +3 -0
- package/dist/checks/source/index.d.ts +6 -0
- package/dist/checks/source/local-refs.d.ts +3 -0
- package/dist/checks/source/markdownlint.d.ts +3 -0
- package/dist/checks/source/stylelint.d.ts +3 -0
- package/dist/checks/tool-check.d.ts +23 -0
- package/dist/checks/types.d.ts +52 -0
- package/dist/cli-1tyj4bk3.js +124 -0
- package/dist/cli-37x76zdn.js +4 -0
- package/dist/cli-506tg37g.js +26 -0
- package/dist/cli-5bxx0c4y.js +464 -0
- package/dist/cli-7ykx7pp0.js +12378 -0
- package/dist/cli-h7phg3ka.js +746 -0
- package/dist/cli-hvqjs342.js +284 -0
- package/dist/cli-yja077f6.js +92 -0
- package/dist/cli.js +157 -0
- package/dist/constants.d.ts +17 -0
- package/dist/doctor-25zjt8dz.js +57 -0
- package/dist/favicon-wkbm9cjn.ico +0 -0
- package/dist/git-http-yrb4ag6z.js +17 -0
- package/dist/index-1tyj4bk3.js +124 -0
- package/dist/index-37x76zdn.js +4 -0
- package/dist/index-3h3fef7r.js +15218 -0
- package/dist/index-5bxx0c4y.js +464 -0
- package/dist/index-yja077f6.js +92 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.js +310 -0
- package/dist/lib/app-heartbeat.d.ts +102 -0
- package/dist/lib/asset-inline.d.ts +73 -0
- package/dist/lib/browser-pool.d.ts +17 -0
- package/dist/lib/build-error.d.ts +52 -0
- package/dist/lib/build-fingerprint.d.ts +15 -0
- package/dist/lib/build-preflight.d.ts +43 -0
- package/dist/lib/build-runner.d.ts +161 -0
- package/dist/lib/build-staging.d.ts +64 -0
- package/dist/lib/chromium.d.ts +20 -0
- package/dist/lib/cli-args.d.ts +45 -0
- package/dist/lib/desktop.d.ts +14 -0
- package/dist/lib/diagnostics.d.ts +64 -0
- package/dist/lib/embedded-assets.d.ts +29 -0
- package/dist/lib/exec.d.ts +84 -0
- package/dist/lib/fetch-timeout.d.ts +41 -0
- package/dist/lib/ghostscript.d.ts +48 -0
- package/dist/lib/host-policy.d.ts +75 -0
- package/dist/lib/image-inspect.d.ts +32 -0
- package/dist/lib/install-hints.d.ts +21 -0
- package/dist/lib/lint-runner.d.ts +10 -0
- package/dist/lib/manifest-config.d.ts +31 -0
- package/dist/lib/manifest-doc.d.ts +25 -0
- package/dist/lib/manifest.d.ts +41 -0
- package/dist/lib/markdown/assemble.d.ts +78 -0
- package/dist/lib/markdown/chapter-id.d.ts +24 -0
- package/dist/lib/markdown/images.d.ts +34 -0
- package/dist/lib/markdown/index.d.ts +78 -0
- package/dist/lib/markdown/markdown-it-paged.d.ts +30 -0
- package/dist/lib/markdown/plugins.d.ts +69 -0
- package/dist/lib/markdown/renderer.d.ts +111 -0
- package/dist/lib/npm-plugin-installer.d.ts +33 -0
- package/dist/lib/open-path.d.ts +5 -0
- package/dist/lib/output-paths.d.ts +23 -0
- package/dist/lib/pagedjs-marker.d.ts +42 -0
- package/dist/lib/pagedjs.d.ts +26 -0
- package/dist/lib/pagination.d.ts +169 -0
- package/dist/lib/pdf-inspect.d.ts +123 -0
- package/dist/lib/pdf-parse.d.ts +57 -0
- package/dist/lib/plugin-manager.d.ts +108 -0
- package/dist/lib/plugin-vendor.d.ts +107 -0
- package/dist/lib/presets.d.ts +45 -0
- package/dist/lib/printsafe.d.ts +17 -0
- package/dist/lib/project-scaffold.d.ts +116 -0
- package/dist/lib/project-source.d.ts +140 -0
- package/dist/lib/project-templates.d.ts +49 -0
- package/dist/lib/publish/butler.d.ts +10 -0
- package/dist/lib/publish/command-runner.d.ts +18 -0
- package/dist/lib/publish/connect.d.ts +23 -0
- package/dist/lib/publish/manifest-publish.d.ts +9 -0
- package/dist/lib/publish/providers/azure-swa.d.ts +3 -0
- package/dist/lib/publish/providers/drivethrurpg.d.ts +10 -0
- package/dist/lib/publish/providers/guided.d.ts +3 -0
- package/dist/lib/publish/providers/itch.d.ts +5 -0
- package/dist/lib/publish/providers/kdp.d.ts +9 -0
- package/dist/lib/publish/providers/shopify.d.ts +5 -0
- package/dist/lib/publish/registry.d.ts +5 -0
- package/dist/lib/publish/run-publish.d.ts +30 -0
- package/dist/lib/publish/selections.d.ts +25 -0
- package/dist/lib/publish/types.d.ts +258 -0
- package/dist/lib/remote-auth/clone.d.ts +87 -0
- package/dist/lib/remote-auth/conflict-resolution.d.ts +29 -0
- package/dist/lib/remote-auth/diagnose.d.ts +77 -0
- package/dist/lib/remote-auth/generic-auth.d.ts +97 -0
- package/dist/lib/remote-auth/git-http.d.ts +85 -0
- package/dist/lib/remote-auth/github-auth.d.ts +69 -0
- package/dist/lib/remote-auth/github-repos.d.ts +64 -0
- package/dist/lib/remote-auth/operation-log.d.ts +66 -0
- package/dist/lib/remote-auth/recovery/abort-interrupted-operation.d.ts +103 -0
- package/dist/lib/remote-auth/recovery/backup.d.ts +113 -0
- package/dist/lib/remote-auth/recovery/classify.d.ts +109 -0
- package/dist/lib/remote-auth/recovery/context.d.ts +47 -0
- package/dist/lib/remote-auth/recovery/dispatch.d.ts +33 -0
- package/dist/lib/remote-auth/recovery/failsafe.d.ts +33 -0
- package/dist/lib/remote-auth/recovery/inspect.d.ts +74 -0
- package/dist/lib/remote-auth/recovery/manual-guidance.d.ts +28 -0
- package/dist/lib/remote-auth/recovery/outcome-mapping.d.ts +58 -0
- package/dist/lib/remote-auth/recovery/policy.d.ts +47 -0
- package/dist/lib/remote-auth/recovery/recover-auth.d.ts +42 -0
- package/dist/lib/remote-auth/recovery/recover-binary-conflict.d.ts +37 -0
- package/dist/lib/remote-auth/recovery/recover-corrupt-index.d.ts +40 -0
- package/dist/lib/remote-auth/recovery/recover-detached-head.d.ts +70 -0
- package/dist/lib/remote-auth/recovery/recover-interrupted-cherry-pick.d.ts +23 -0
- package/dist/lib/remote-auth/recovery/recover-interrupted-merge.d.ts +28 -0
- package/dist/lib/remote-auth/recovery/recover-interrupted-rebase.d.ts +39 -0
- package/dist/lib/remote-auth/recovery/recover-merge-conflict.d.ts +34 -0
- package/dist/lib/remote-auth/recovery/recover-missing-git-dir.d.ts +37 -0
- package/dist/lib/remote-auth/recovery/recover-missing-objects.d.ts +56 -0
- package/dist/lib/remote-auth/recovery/recover-network.d.ts +34 -0
- package/dist/lib/remote-auth/recovery/recover-non-fast-forward.d.ts +27 -0
- package/dist/lib/remote-auth/recovery/recover-stale-lock.d.ts +76 -0
- package/dist/lib/remote-auth/recovery/recover-unrelated-histories.d.ts +44 -0
- package/dist/lib/remote-auth/recovery/recover-wrong-remote.d.ts +35 -0
- package/dist/lib/remote-auth/recovery/types.d.ts +235 -0
- package/dist/lib/remote-auth/resolution-plan.d.ts +64 -0
- package/dist/lib/remote-auth/sync-messages.d.ts +26 -0
- package/dist/lib/remote-auth/sync-types.d.ts +225 -0
- package/dist/lib/remote-auth/sync.d.ts +45 -0
- package/dist/lib/remote-auth/test-access.d.ts +47 -0
- package/dist/lib/remote-auth/test-support/git-http-server.d.ts +71 -0
- package/dist/lib/remote-auth/token-store.d.ts +95 -0
- package/dist/lib/remote-auth/transport.d.ts +105 -0
- package/dist/lib/slug.d.ts +28 -0
- package/dist/lib/snippets.d.ts +39 -0
- package/dist/lib/source-provider.d.ts +244 -0
- package/dist/lib/static-serve.d.ts +54 -0
- package/dist/lib/style-resolver.d.ts +30 -0
- package/dist/lib/theme-import.d.ts +70 -0
- package/dist/lib/theme-manager.d.ts +128 -0
- package/dist/lib/tool-probe.d.ts +37 -0
- package/dist/lib/validation-exec.d.ts +47 -0
- package/dist/lib/validation-profile.d.ts +18 -0
- package/dist/lib/version.d.ts +9 -0
- package/dist/lint-f63nxjfj.js +65 -0
- package/dist/manifest-n1gh3qw5.yaml +9 -0
- package/dist/manifest-ryyg71nf.yaml +9 -0
- package/dist/manifest.schema-rn1dpdpn.json +564 -0
- package/dist/new-7b08a42h.js +105 -0
- package/dist/paged.polyfill-n95pbxfn.js +33288 -0
- package/dist/pagedjs-bridge-vn4hk9fx.js +111 -0
- package/dist/pagedjs-interface-80g3xa8p.js +498 -0
- package/dist/platform.d.ts +100 -0
- package/dist/plugin-wf2cbmwc.js +129 -0
- package/dist/preflight-tg4mpz1h.js +222 -0
- package/dist/preview/file-watcher.d.ts +174 -0
- package/dist/preview/http-server.d.ts +45 -0
- package/dist/preview/lifecycle.d.ts +67 -0
- package/dist/preview/server-context.d.ts +36 -0
- package/dist/preview-h2bwbb2x.js +102 -0
- package/dist/preview-shell-rghtfmc8.js +155 -0
- package/dist/project-source-0tg0r6vm.js +17 -0
- package/dist/publish-ztaet53r.js +233 -0
- package/dist/render.d.ts +20 -0
- package/dist/render.js +682 -0
- package/dist/repair-jkp4n3j8.js +171 -0
- package/dist/schema/manifest.types.d.ts +218 -0
- package/dist/server.d.ts +34 -0
- package/dist/source-provider-hp96b5jf.js +46 -0
- package/dist/test-helpers/testkit.d.ts +91 -0
- package/dist/theme-0yzvthe8.css +65 -0
- package/dist/theme-570zmh2t.css +58 -0
- package/dist/theme-6a2fngc8.json +6 -0
- package/dist/theme-cd6efzjw.json +6 -0
- package/dist/theme-nya4nqh6.css +70 -0
- package/dist/theme-tqfypc1w.json +6 -0
- package/dist/theme-xt0hjb1b.json +6 -0
- package/dist/theme-zz2ktzqs.css +60 -0
- package/dist/types.d.ts +31 -0
- package/dist/utils/file-utils.d.ts +53 -0
- package/dist/utils/logger.d.ts +59 -0
- package/dist/validate-k2drs19j.js +99 -0
- package/package.json +102 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { resolveConfig } from "./manifest";
|
|
2
|
+
import { BuildError } from "./build-error";
|
|
3
|
+
import { type Gates } from "./build-preflight";
|
|
4
|
+
import { type PdfRenderer, type PdfRenderInput } from "./pagination";
|
|
5
|
+
export type { PdfRenderer, PdfRenderInput };
|
|
6
|
+
export type BuildFormat = "html" | "pdf" | "pdfx";
|
|
7
|
+
export type PdfxFlavor = "x1a" | "x3";
|
|
8
|
+
export { BuildError };
|
|
9
|
+
export interface BuildRunnerOptions {
|
|
10
|
+
inputDir: string;
|
|
11
|
+
format: BuildFormat;
|
|
12
|
+
outDir?: string;
|
|
13
|
+
pdfFileOverride?: string | null;
|
|
14
|
+
title?: string;
|
|
15
|
+
pdfxFlavor?: PdfxFlavor;
|
|
16
|
+
iccPath?: string;
|
|
17
|
+
manifestPath?: string;
|
|
18
|
+
stripAnnotations?: boolean;
|
|
19
|
+
skipLint?: boolean;
|
|
20
|
+
skipPreValidate?: boolean;
|
|
21
|
+
skipPostValidate?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Optional PDF renderer override. When provided, the build uses it instead of
|
|
24
|
+
* launching Chromium via puppeteer, and the Chromium preflight is skipped.
|
|
25
|
+
* The Electron desktop injects one backed by `webContents.printToPDF`.
|
|
26
|
+
*/
|
|
27
|
+
pdfRenderer?: PdfRenderer;
|
|
28
|
+
/**
|
|
29
|
+
* Keep the pooled headless browser alive after the build returns. A one-shot
|
|
30
|
+
* CLI build leaves this false so the process can exit; a long-lived
|
|
31
|
+
* preview/watch server sets it true so the browser stays warm across rebuilds
|
|
32
|
+
* (every rebuild then skips the ~1–2s Chromium launch). The server owns
|
|
33
|
+
* `closeBrowser()` on shutdown.
|
|
34
|
+
*/
|
|
35
|
+
keepBrowserAlive?: boolean;
|
|
36
|
+
rawArgs: Record<string, unknown>;
|
|
37
|
+
}
|
|
38
|
+
export interface BuildRunnerResult {
|
|
39
|
+
outDir: string;
|
|
40
|
+
/**
|
|
41
|
+
* The published `book.html`, or `null` for a one-file delivery (`--out x.pdf`,
|
|
42
|
+
* a desktop export) where only the PDF is delivered and everything else is
|
|
43
|
+
* discarded with the work dir. Returning a work-dir path here would hand the
|
|
44
|
+
* caller a filename that is already deleted by the time they see it.
|
|
45
|
+
*/
|
|
46
|
+
htmlPath: string | null;
|
|
47
|
+
pdfPath: string | null;
|
|
48
|
+
/** As {@link htmlPath}: `null` when nothing but the artifact was published. */
|
|
49
|
+
fingerprintPath: string | null;
|
|
50
|
+
}
|
|
51
|
+
export interface SplitOutPath {
|
|
52
|
+
outDir?: string;
|
|
53
|
+
pdfFileOverride: string | null;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Split --out into outDir + optional pdfFileOverride.
|
|
57
|
+
* - For pdf/pdfx, accept "*.pdf" forms (file path) and split into dirname + path.
|
|
58
|
+
* - For html or any non-.pdf string, treat as a directory.
|
|
59
|
+
*/
|
|
60
|
+
export declare function splitOutPath(outArg: string | undefined, format: BuildFormat): SplitOutPath;
|
|
61
|
+
/**
|
|
62
|
+
* Everything the build stages + output strategies need, resolved once up front:
|
|
63
|
+
* the requested format, absolute input/output dirs, the manifest dir (for
|
|
64
|
+
* plugin + ICC resolution), the merged config, and the lint/validate gates.
|
|
65
|
+
* Assembled by {@link resolveBuildContext}; consumed by {@link runQualityGates},
|
|
66
|
+
* {@link renderBook}, and the {@link OutputStrategy} implementations.
|
|
67
|
+
*/
|
|
68
|
+
/**
|
|
69
|
+
* Where a finished build is delivered. The build itself always writes to a
|
|
70
|
+
* scratch `workDir`; this says what happens to it afterwards.
|
|
71
|
+
*
|
|
72
|
+
* The distinction is structural, not a flag: `rm` appears in exactly one branch
|
|
73
|
+
* of {@link publishBuild}, the `project` one, whose path is always computed by
|
|
74
|
+
* `resolveOutputDir` from the manifest. A caller-supplied path is a different
|
|
75
|
+
* variant that reaches different code, so no `--out` value can be deleted —
|
|
76
|
+
* there is no code path that would do it.
|
|
77
|
+
*/
|
|
78
|
+
export type PublishTarget =
|
|
79
|
+
/** gutterpress's own `dist/<slug>/`. Replaced wholesale, so stale files vanish. */
|
|
80
|
+
{
|
|
81
|
+
kind: "project";
|
|
82
|
+
dir: string;
|
|
83
|
+
}
|
|
84
|
+
/** `--out <dir>`: the user's directory. Files are added; nothing is removed. */
|
|
85
|
+
| {
|
|
86
|
+
kind: "directory";
|
|
87
|
+
dir: string;
|
|
88
|
+
}
|
|
89
|
+
/** `--out <file.pdf>` / the desktop's Save dialog: ONE file, nothing else. */
|
|
90
|
+
| {
|
|
91
|
+
kind: "file";
|
|
92
|
+
file: string;
|
|
93
|
+
};
|
|
94
|
+
export interface BuildContext {
|
|
95
|
+
opts: BuildRunnerOptions;
|
|
96
|
+
format: BuildFormat;
|
|
97
|
+
inputDir: string;
|
|
98
|
+
outDir: string;
|
|
99
|
+
manifestDir: string;
|
|
100
|
+
config: ReturnType<typeof resolveConfig>;
|
|
101
|
+
gates: Gates;
|
|
102
|
+
/**
|
|
103
|
+
* Where the build actually writes. A build assembles a COMPLETE output tree
|
|
104
|
+
* here and only then replaces `outDir` with it, so a build is atomic (a crash
|
|
105
|
+
* leaves the previous output untouched) and stale files cannot survive — the
|
|
106
|
+
* work dir starts empty, so whatever is not rebuilt simply is not there.
|
|
107
|
+
*
|
|
108
|
+
* It is a sibling of `outDir` rather than an OS temp dir so the final publish
|
|
109
|
+
* is a same-filesystem `rename`.
|
|
110
|
+
*/
|
|
111
|
+
workDir: string;
|
|
112
|
+
/** What to do with `workDir` once the build succeeds. */
|
|
113
|
+
target: PublishTarget;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Stage 1 — load the manifest, merge CLI overrides into the resolved config,
|
|
117
|
+
* pick the output dir, and compute the lint/validate gates. Pure planning: no
|
|
118
|
+
* filesystem writes, no browser, no logging beyond computeGates' own
|
|
119
|
+
* flags-ignored notice. Everything downstream reads from the returned context.
|
|
120
|
+
*/
|
|
121
|
+
export declare function resolveBuildContext(opts: BuildRunnerOptions): Promise<BuildContext>;
|
|
122
|
+
/**
|
|
123
|
+
* Stage 3 — load configured plugins, render the markdown chapters to
|
|
124
|
+
* `outDir/book.html`, and copy user asset directories. Returns the path to the
|
|
125
|
+
* rendered book.html both output strategies then paginate. This is the shared
|
|
126
|
+
* pre-format work; the per-format tails live in the strategies.
|
|
127
|
+
*
|
|
128
|
+
* ARCH finding #4: markdown-it-paged computes typed, line-numbered
|
|
129
|
+
* author-mistake warnings (`env.layoutWarnings`) that every real render path
|
|
130
|
+
* used to discard silently. `renderChaptersToFile`'s `onChapterWarnings`
|
|
131
|
+
* threads them back out here so a final artifact never omits a marker
|
|
132
|
+
* mistake without at least telling the author about it in the build log.
|
|
133
|
+
* Exported (not just for the pipeline) so this stage is unit-testable
|
|
134
|
+
* without driving the full `runBuild` pagination/PDF machinery.
|
|
135
|
+
*/
|
|
136
|
+
export declare function renderBook(ctx: BuildContext): Promise<string>;
|
|
137
|
+
/**
|
|
138
|
+
* Resolve the effective ICC profile for a PDF/X build (extracted from the pdfx
|
|
139
|
+
* branch so it is unit-testable in isolation). Relative paths are tried against
|
|
140
|
+
* the manifest dir first, then cwd. As a convenience the unspecified default
|
|
141
|
+
* profile (`CGATS21_CRPC1.icc`, no explicit `--icc`) falls back to the embedded
|
|
142
|
+
* copy shipped in the binary. Throws BuildError(exitCode 2) if nothing resolves.
|
|
143
|
+
*/
|
|
144
|
+
export declare function resolveIccProfile(icc: string, manifestDir: string, explicitIccPath: string | undefined): Promise<string>;
|
|
145
|
+
/**
|
|
146
|
+
* Orchestrate a build: resolve the context, mkdir the output, preflight tools
|
|
147
|
+
* (non-html), pre-warm the browser when this build will paginate in Chromium,
|
|
148
|
+
* run the quality gates, render the book, then hand off to the per-format output
|
|
149
|
+
* strategy for pagination + finalize. The heavy lifting lives in the named
|
|
150
|
+
* stages + strategies above (plus ./build-preflight, ./build-staging, and
|
|
151
|
+
* ./pagination); this reads as the pipeline it is.
|
|
152
|
+
*
|
|
153
|
+
* Everything from the prewarm decision onward runs inside a try/finally that
|
|
154
|
+
* closes the pooled browser (unless `keepBrowserAlive` is set) — finding #50:
|
|
155
|
+
* previously the close only happened on the success tail (inside
|
|
156
|
+
* `finalizeBuild`), so a prewarmed Chromium leaked whenever a quality gate,
|
|
157
|
+
* the render, or pagination itself threw. `closeBrowser()` is a no-op if
|
|
158
|
+
* nothing was launched (including the injected-renderer path, which never
|
|
159
|
+
* uses the pool), so it is safe to call unconditionally here.
|
|
160
|
+
*/
|
|
161
|
+
export declare function runBuild(opts: BuildRunnerOptions): Promise<BuildRunnerResult>;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTML string-rewriting for the shippable artifact: turns the raw
|
|
3
|
+
* serialized-paginated DOM that pagination produces into the static desktop HTML
|
|
4
|
+
* (or the runtime-pagination fallback). Pure string/fs transforms — no browser.
|
|
5
|
+
*
|
|
6
|
+
* The former `stagePaginationInput` is GONE. It copied `book.html` plus every
|
|
7
|
+
* asset directory into a temp dir purely so relative URLs would resolve against
|
|
8
|
+
* some root, which cost a second full copy of every asset per build and made the
|
|
9
|
+
* staged tree a second place assets could go missing. `book.html` is now
|
|
10
|
+
* self-contained (CSS and fonts inlined by `lib/asset-inline.ts`), so the
|
|
11
|
+
* pagination pass serves `outDir` directly with in-memory overlays for the
|
|
12
|
+
* engine — see `createStaticFileServer`'s `overlays` in `./pagination.ts`.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Remove the Paged.js pagination ENGINE from an already-paginated, serialized
|
|
16
|
+
* document so the browser renders the static pages as-is and never re-paginates.
|
|
17
|
+
* Strips (a) the polyfill `<script src>` and (b) the inline break-inside handler.
|
|
18
|
+
* Navigation toolbar scripts are NOT touched — they only scroll between pages
|
|
19
|
+
* that already exist, which is not DOM-pagination.
|
|
20
|
+
*/
|
|
21
|
+
export declare function stripPaginationRuntime(html: string): string;
|
|
22
|
+
/**
|
|
23
|
+
* Rewrite the build's ephemeral pagination origin back to document-relative
|
|
24
|
+
* URLs.
|
|
25
|
+
*
|
|
26
|
+
* Paged.js absolutizes every non-`data:` CSS `url()` against the sheet's origin
|
|
27
|
+
* (`replaceUrls`, paged.polyfill.js), so the serialized document comes back
|
|
28
|
+
* pointing at `http://127.0.0.1:<port>/…` — a port that dies with the build.
|
|
29
|
+
* Left alone, a shipped `book.html` references a dead origin for every
|
|
30
|
+
* content-addressed image.
|
|
31
|
+
*
|
|
32
|
+
* The leading slash is stripped along with the origin ON PURPOSE: `book.html`
|
|
33
|
+
* sits at the artifact root, so `assets/x.png` is correct and `/assets/x.png`
|
|
34
|
+
* would break any deployment under a subpath (GitHub Pages project sites).
|
|
35
|
+
*/
|
|
36
|
+
export declare function stripPaginationOrigin(html: string): string;
|
|
37
|
+
/**
|
|
38
|
+
* Inject the navigation-only toolbar scripts (page nav, zoom, view modes) into
|
|
39
|
+
* the static document head. These read the pre-rendered `.pagedjs_page`
|
|
40
|
+
* elements; they do not paginate.
|
|
41
|
+
*/
|
|
42
|
+
export declare function injectNavigationScripts(html: string): string;
|
|
43
|
+
/**
|
|
44
|
+
* Turn a raw serialized paginated document into the shippable static desktop
|
|
45
|
+
* `book.html`: copy the navigation toolbar scripts, strip the pagination engine
|
|
46
|
+
* and the build's ephemeral origin, wire the nav scripts, and write the file.
|
|
47
|
+
* Shared by the HTML format and the PDF unification path.
|
|
48
|
+
*/
|
|
49
|
+
export declare function finalizeStaticBook(rawSerializedHtml: string, htmlFile: string, outDir: string): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Fallback for `--format html` when no headless browser is available: ship the
|
|
52
|
+
* Paged.js polyfill + nav scripts so the BROWSER paginates at load time (the
|
|
53
|
+
* pre-SSG behavior). Slower at runtime and not pre-paginated, but it works with
|
|
54
|
+
* no Chromium at build.
|
|
55
|
+
*/
|
|
56
|
+
export declare function shipRuntimePaginatedHtml(htmlFile: string, outDir: string): Promise<void>;
|
|
57
|
+
/**
|
|
58
|
+
* Create a unique scratch directory under the OS temp dir. Now used ONLY for
|
|
59
|
+
* PDF/X intermediates (`raw.pdf`, Ghostscript work files) — never for staging
|
|
60
|
+
* assets. Must not be resolved against `process.cwd()`: `runBuild` is exported
|
|
61
|
+
* and called by the desktop host, so writing scratch dirs into the caller's
|
|
62
|
+
* directory is a hidden side effect. Callers remove it in a `finally`.
|
|
63
|
+
*/
|
|
64
|
+
export declare function createStageRoot(): Promise<string>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the path to a system Chrome/Chromium binary, or undefined if none found.
|
|
3
|
+
*
|
|
4
|
+
* Resolution order:
|
|
5
|
+
* 1. CHROMIUM_PATH / PUPPETEER_EXECUTABLE_PATH env vars
|
|
6
|
+
* 2. Hard-coded standard install paths (Chrome / Edge / Brave / Chromium
|
|
7
|
+
* on Linux, macOS, Windows)
|
|
8
|
+
* 3. PATH probe via `which` / `where.exe` for common binary names
|
|
9
|
+
* (catches Scoop, Chocolatey, Homebrew, portable installs, and any
|
|
10
|
+
* Chromium variant the user added to PATH manually)
|
|
11
|
+
*
|
|
12
|
+
* Prefer requireChromiumExecutable() for build paths that cannot continue
|
|
13
|
+
* without it — it surfaces a multi-line install-instructions error.
|
|
14
|
+
*/
|
|
15
|
+
export declare function resolveChromiumExecutable(): Promise<string | undefined>;
|
|
16
|
+
/**
|
|
17
|
+
* Like resolveChromiumExecutable() but throws with actionable install instructions
|
|
18
|
+
* when no Chrome/Chromium is found on the system.
|
|
19
|
+
*/
|
|
20
|
+
export declare function requireChromiumExecutable(): Promise<string>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { BuildFormat, PdfxFlavor } from "./build-runner.ts";
|
|
2
|
+
export { EXIT_CODES } from "./build-error.ts";
|
|
3
|
+
/** A recoverable "bad CLI usage" error carrying the process exit code. */
|
|
4
|
+
export declare class UsageError extends Error {
|
|
5
|
+
exitCode: number;
|
|
6
|
+
constructor(message: string, exitCode?: number);
|
|
7
|
+
}
|
|
8
|
+
interface CliArgumentDefinition {
|
|
9
|
+
type?: "boolean" | "string" | "enum" | "positional";
|
|
10
|
+
alias?: string | readonly string[];
|
|
11
|
+
}
|
|
12
|
+
type CliArgumentDefinitions = Readonly<Record<string, CliArgumentDefinition>>;
|
|
13
|
+
/**
|
|
14
|
+
* Reject option names citty would otherwise retain and silently ignore, and
|
|
15
|
+
* reject value-taking options whose value is absent.
|
|
16
|
+
*
|
|
17
|
+
* This scans raw argv rather than the parsed object so a positional name used
|
|
18
|
+
* as an option (for example, `build --input`) cannot masquerade as a declared
|
|
19
|
+
* flag. Citty parses in non-strict mode and turns a valueless string option
|
|
20
|
+
* into `""`; catching that from raw argv is the only way to distinguish an
|
|
21
|
+
* omitted option from a typo. A dash-prefixed token is still a legitimate
|
|
22
|
+
* string value unless it names an option declared by this command.
|
|
23
|
+
*/
|
|
24
|
+
export declare function rejectUnknownFlags(rawArgs: readonly string[], declared: CliArgumentDefinitions, commandName: string): void;
|
|
25
|
+
/**
|
|
26
|
+
* Reject CLI positionals beyond the ones a command declares (UX finding M46).
|
|
27
|
+
*
|
|
28
|
+
* Citty's parser keeps every raw positional token in `args._` even after
|
|
29
|
+
* `type: "positional"` args have claimed their share — it shifts values off a
|
|
30
|
+
* COPY of `_` for each declared positional arg, but never trims the original
|
|
31
|
+
* array. So a command with one declared positional silently drops a second
|
|
32
|
+
* one instead of erroring, e.g. `gutterpress build a b` builds `a` and never
|
|
33
|
+
* mentions `b`. Call this near the top of a command's `run()`, passing
|
|
34
|
+
* `(args as { _: unknown[] })._` and how many positionals the command itself
|
|
35
|
+
* declares, to turn that into a named `UsageError` instead.
|
|
36
|
+
*/
|
|
37
|
+
export declare function rejectExtraPositionals(positionals: unknown[] | undefined, expectedCount: number, commandName: string): void;
|
|
38
|
+
/** Parse `--format`, falling back to the caller-supplied default. */
|
|
39
|
+
export declare function parseFormat(raw: unknown, opts: {
|
|
40
|
+
default: BuildFormat;
|
|
41
|
+
}): BuildFormat;
|
|
42
|
+
/** Parse `--pdfx-flavor`, which is only valid alongside `--format pdfx`. */
|
|
43
|
+
export declare function parsePdfxFlavor(raw: unknown, format: BuildFormat): PdfxFlavor | undefined;
|
|
44
|
+
/** Parse `--port`, defaulting to {@link NETWORK.DEFAULT_PORT} (0 = OS-assigned). */
|
|
45
|
+
export declare function resolvePort(raw: unknown): number;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Output filename constants for the build pipeline.
|
|
3
|
+
*
|
|
4
|
+
* Historically this file also emitted "desktop chrome" (toolbar + folder
|
|
5
|
+
* picker + GH clone modal) into the build output so the directory was a
|
|
6
|
+
* self-hostable site. That chrome was removed 2026-05-18 when the desktop
|
|
7
|
+
* was extracted into packages/desktop (Electron + SvelteKit). The CLI build
|
|
8
|
+
* now produces a "naked" book.html with Paged.js polyfill and the
|
|
9
|
+
* pagedjs-interface/bridge scripts injected — no toolbar.
|
|
10
|
+
*
|
|
11
|
+
* Power users who want a hosted UI launch the desktop app or write their
|
|
12
|
+
* own iframe wrapper around book.html.
|
|
13
|
+
*/
|
|
14
|
+
export declare const BOOK_HTML_FILENAME = "book.html";
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* System diagnostics — surfaces tool availability + versions for the
|
|
3
|
+
* desktop's Help/About dialog and the `gutterpress doctor` CLI command.
|
|
4
|
+
*
|
|
5
|
+
* Reuses `resolveChromiumExecutable`, `findTool`, and `isToolAvailable` for
|
|
6
|
+
* tool detection. Install-hint copy lives in `./install-hints.ts` — the
|
|
7
|
+
* single source of truth also consumed by build-runner.ts's preflight and
|
|
8
|
+
* chromium.ts's `requireChromiumExecutable` — not duplicated here. Probes
|
|
9
|
+
* are run in parallel; total wall time is dominated by the slowest
|
|
10
|
+
* `--version` invocation (~50-200ms per tool that's present, ~5ms per tool
|
|
11
|
+
* that's missing).
|
|
12
|
+
*/
|
|
13
|
+
export interface ToolStatus {
|
|
14
|
+
/**
|
|
15
|
+
* Stable machine id for this tool, independent of the human-readable
|
|
16
|
+
* `name`/`bin` display strings (e.g. "chromium", "gs", "qpdf"). Consumers
|
|
17
|
+
* that need to single out a specific tool (the desktop's doctor route
|
|
18
|
+
* excludes the bundled-Chromium entry from the "external tools" list) MUST
|
|
19
|
+
* match on this field, not on `bin`/`name` — those are presentation text
|
|
20
|
+
* and can be reworded without notice (UX L10).
|
|
21
|
+
*/
|
|
22
|
+
id: string;
|
|
23
|
+
name: string;
|
|
24
|
+
/** The canonical CLI/binary name being probed (gs, qpdf, etc). */
|
|
25
|
+
bin: string;
|
|
26
|
+
/** True if the binary is resolvable on PATH or via fixed-path scan. */
|
|
27
|
+
found: boolean;
|
|
28
|
+
/** Absolute path on disk if found. */
|
|
29
|
+
path?: string;
|
|
30
|
+
/** First line of `<bin> --version` output if found and the call succeeded. */
|
|
31
|
+
version?: string;
|
|
32
|
+
/**
|
|
33
|
+
* What features depend on this tool.
|
|
34
|
+
* "required" — the feature breaks without it
|
|
35
|
+
* "optional" — the feature degrades / skips gracefully
|
|
36
|
+
*/
|
|
37
|
+
usedBy: Array<{
|
|
38
|
+
feature: string;
|
|
39
|
+
severity: "required" | "optional";
|
|
40
|
+
}>;
|
|
41
|
+
/** Multi-line, per-platform install hint. Always present. */
|
|
42
|
+
installHint: string;
|
|
43
|
+
}
|
|
44
|
+
export interface SystemDiagnostics {
|
|
45
|
+
/** Gutterpress lib version */
|
|
46
|
+
libVersion: string;
|
|
47
|
+
platform: {
|
|
48
|
+
os: string;
|
|
49
|
+
arch: string;
|
|
50
|
+
release: string;
|
|
51
|
+
node: string;
|
|
52
|
+
};
|
|
53
|
+
tools: ToolStatus[];
|
|
54
|
+
/** Existing CLI config/credential directory; reporting it never relocates data. */
|
|
55
|
+
configDir: string;
|
|
56
|
+
/** Path to the docs page with deeper info. */
|
|
57
|
+
docsUrl: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Probe every external tool the lib could spawn and return a structured
|
|
61
|
+
* report. Safe to call repeatedly; the slowest path is ~200ms when every
|
|
62
|
+
* tool is present (one `--version` per tool, in parallel).
|
|
63
|
+
*/
|
|
64
|
+
export declare function getSystemDiagnostics(): Promise<SystemDiagnostics>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embedded preview assets (favicon, manifest schema, paged.js polyfill,
|
|
3
|
+
* iframe interface + cross-origin bridge).
|
|
4
|
+
*
|
|
5
|
+
* `with { type: "file" }` imports are the canonical embedding mechanism for
|
|
6
|
+
* assets that must be accessible in all three runtime contexts:
|
|
7
|
+
*
|
|
8
|
+
* - bun build --compile (standalone binary):
|
|
9
|
+
* Bun embeds the file at a bunfs path and the import returns that absolute
|
|
10
|
+
* bunfs path as a string. All modules are merged into one root file in
|
|
11
|
+
* bunfs, so new URL("../assets/...", import.meta.url) does NOT work here
|
|
12
|
+
* because import.meta.url points to the bundle root, not the source file.
|
|
13
|
+
* with { type: "file" } correctly gives the embedded absolute path.
|
|
14
|
+
*
|
|
15
|
+
* - bun run src/cli.ts (development):
|
|
16
|
+
* The import returns the real absolute disk path to the asset file.
|
|
17
|
+
*
|
|
18
|
+
* - Node.js via dist/ (Electron in-process):
|
|
19
|
+
* bun build --target node copies assets alongside the output JS with
|
|
20
|
+
* hashed filenames and rewrites imports to relative strings like
|
|
21
|
+
* "./favicon-abc123.ico". We resolve these relative to __libdir so
|
|
22
|
+
* readFile always gets an absolute path regardless of CWD.
|
|
23
|
+
*
|
|
24
|
+
* On first use we copy everything into a per-process temp directory and return
|
|
25
|
+
* that path, letting call sites use plain readFile/cp without caring about
|
|
26
|
+
* the source format.
|
|
27
|
+
*/
|
|
28
|
+
export declare function getAssetsDir(): Promise<string>;
|
|
29
|
+
export declare function getAssetPath(relPath: string): Promise<string>;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Join `dir` onto the front of `existingPath` using `sep` (defaults to the
|
|
3
|
+
* current platform's `node:path` delimiter — `:` on POSIX, `;` on Windows).
|
|
4
|
+
* A pure function so the delimiter behavior is unit-testable without
|
|
5
|
+
* needing to actually run on every OS — see exec.test.ts.
|
|
6
|
+
*/
|
|
7
|
+
export declare function buildEnhancedPath(dir: string, existingPath: string, sep?: string): string;
|
|
8
|
+
/** Gutterpress's own node_modules/.bin so locally installed tools are found. */
|
|
9
|
+
export declare const localBin: string;
|
|
10
|
+
/**
|
|
11
|
+
* PATH with `localBin` prepended, correctly delimiter-joined. Single source
|
|
12
|
+
* of truth for every spawn in the lib — `run` and `execCapture` below use
|
|
13
|
+
* it, and tool-probe.ts's `isToolAvailable`/`findTool` get it for free by
|
|
14
|
+
* calling `execCapture` instead of keeping their own copy (previously a
|
|
15
|
+
* literal `:` here corrupted PATH on Windows while tool-probe.ts's copy of
|
|
16
|
+
* the same logic used `delimiter` correctly — see docs/reviews
|
|
17
|
+
* 2026-07-10-architecture-critical-review.md, finding #3).
|
|
18
|
+
*/
|
|
19
|
+
export declare const enhancedPath: string;
|
|
20
|
+
/**
|
|
21
|
+
* Spawn a child process, inherit stdio, reject on non-zero exit.
|
|
22
|
+
*/
|
|
23
|
+
export declare function run(cmd: string, args: string[], opts?: {
|
|
24
|
+
cwd?: string;
|
|
25
|
+
}): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* After the child's 'exit', stdio data can still be in flight — buffered in
|
|
28
|
+
* the pipes, or written by a grandchild that inherited them (the SWA CLI
|
|
29
|
+
* spawns StaticSitesClient). Settling on 'exit' truncates that output, so we
|
|
30
|
+
* settle on 'close' (stdio flushed) — but a detached grandchild can hold the
|
|
31
|
+
* pipes open forever, so 'exit' arms this grace and we settle with whatever
|
|
32
|
+
* has arrived when it expires. The grace is an IDLE window, re-armed on every
|
|
33
|
+
* post-exit chunk: a grandchild actively streaming (StaticSitesClient still
|
|
34
|
+
* printing the deployment URL) is never cut mid-stream, while a silent
|
|
35
|
+
* daemon holding the pipe still settles one grace-width after exit.
|
|
36
|
+
*/
|
|
37
|
+
export declare const EXIT_FLUSH_GRACE_MS = 2000;
|
|
38
|
+
export interface SpawnCaptureOptions {
|
|
39
|
+
cwd?: string;
|
|
40
|
+
/** Full child environment — callers compose it (no ambient default here). */
|
|
41
|
+
env?: NodeJS.ProcessEnv;
|
|
42
|
+
/** Kill budget in ms. 0/undefined = no timer. */
|
|
43
|
+
timeoutMs?: number;
|
|
44
|
+
/** "total" (default): one-shot deadline. "idle": re-armed on every chunk,
|
|
45
|
+
* so only complete output silence kills the child. */
|
|
46
|
+
timeoutMode?: "total" | "idle";
|
|
47
|
+
/** Raw chunk tap, called per stream as data arrives. */
|
|
48
|
+
onChunk?: (stream: "stdout" | "stderr", text: string) => void;
|
|
49
|
+
/** Keep only the trailing N chars of each captured stream (unbounded when
|
|
50
|
+
* unset) — bounds memory for hours-long progress streams. */
|
|
51
|
+
captureLimit?: number;
|
|
52
|
+
/** Override {@link EXIT_FLUSH_GRACE_MS} (tests). */
|
|
53
|
+
exitGraceMs?: number;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The lib's single "spawn, buffer stdout/stderr, settle" core. Resolves with
|
|
57
|
+
* the exit code/signal for ANY exit (callers decide whether non-zero is an
|
|
58
|
+
* error); rejects only on spawn error or timeout kill. Every timer is cleared
|
|
59
|
+
* on settle and `unref()`d so a pending call can never keep the process alive
|
|
60
|
+
* on its own. `execCapture` below and publish's `defaultCommandRunner` are
|
|
61
|
+
* thin adapters over this — do not grow parallel spawn loops elsewhere
|
|
62
|
+
* (previously four copies existed with different bug profiles — see
|
|
63
|
+
* docs/reviews 2026-07-10-architecture-critical-review.md, finding #16).
|
|
64
|
+
*/
|
|
65
|
+
export declare function spawnCapture(cmd: string, args: string[], opts?: SpawnCaptureOptions): Promise<{
|
|
66
|
+
code: number | null;
|
|
67
|
+
signal: NodeJS.Signals | null;
|
|
68
|
+
stdout: string;
|
|
69
|
+
stderr: string;
|
|
70
|
+
}>;
|
|
71
|
+
/**
|
|
72
|
+
* Spawn and capture stdout/stderr. Rejects on non-zero exit, on spawn
|
|
73
|
+
* error, or — when `timeoutMs` is given — if the child hasn't exited in
|
|
74
|
+
* time (it is then SIGKILLed). A thin adapter over {@link spawnCapture};
|
|
75
|
+
* build-fingerprint.ts, diagnostics.ts, and tool-probe.ts all call this
|
|
76
|
+
* instead of keeping their own copies.
|
|
77
|
+
*/
|
|
78
|
+
export declare function execCapture(cmd: string, args: string[], opts?: {
|
|
79
|
+
timeoutMs?: number;
|
|
80
|
+
cwd?: string;
|
|
81
|
+
}): Promise<{
|
|
82
|
+
stdout: string;
|
|
83
|
+
stderr: string;
|
|
84
|
+
}>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared network deadline + author-friendly error mapping for the CLI's
|
|
3
|
+
* direct `fetch` call sites (GitHub auth/API, the butler download). ONE copy
|
|
4
|
+
* of the policy, so a fix here reaches every site (the old per-site clones
|
|
5
|
+
* let the dropped-timeout bug below survive in two of three copies):
|
|
6
|
+
*
|
|
7
|
+
* - The deadline is a TOTAL budget (`AbortSignal.timeout` keeps ticking
|
|
8
|
+
* through any body read done inside `run`), COMPOSED with the caller's
|
|
9
|
+
* cancellation signal via `AbortSignal.any` — the old
|
|
10
|
+
* `signal ?? AbortSignal.timeout(...)` pattern silently DROPPED the
|
|
11
|
+
* timeout whenever a caller passed a signal.
|
|
12
|
+
* - A caller abort ("AbortError") is rethrown untouched, so cancellation
|
|
13
|
+
* keeps its site-specific handling.
|
|
14
|
+
* - A fired deadline ("TimeoutError") maps to `timeoutMessage`.
|
|
15
|
+
* - Every other failure (DNS, TLS, socket reset) maps to `offlineMessage`,
|
|
16
|
+
* with the underlying error attached as `cause`.
|
|
17
|
+
*
|
|
18
|
+
* (The isomorphic-git transport has its own idle/total timer design —
|
|
19
|
+
* remote-auth/git-http.ts — because that client accepts no AbortSignal.)
|
|
20
|
+
*/
|
|
21
|
+
/** An operation error that already has its final classification and message. */
|
|
22
|
+
export declare class FetchPassthroughError extends Error {
|
|
23
|
+
}
|
|
24
|
+
/** An author-friendly HTTP status error that should not be remapped. */
|
|
25
|
+
export declare class FriendlyHttpError extends FetchPassthroughError {
|
|
26
|
+
}
|
|
27
|
+
/** A timeout, DNS, TLS, or socket failure that an optional download may skip. */
|
|
28
|
+
export declare class FetchUnavailableError extends Error {
|
|
29
|
+
}
|
|
30
|
+
export interface FetchTimeoutOptions {
|
|
31
|
+
/** TOTAL deadline in ms, covering everything `run` does with the signal. */
|
|
32
|
+
timeoutMs: number;
|
|
33
|
+
/** Optional caller cancellation, composed with the deadline. */
|
|
34
|
+
signal?: AbortSignal;
|
|
35
|
+
/** Message when the deadline fires. Defaults to the offline mapping. */
|
|
36
|
+
timeoutMessage?: string;
|
|
37
|
+
/** Message for network-level failures (string, or built from the cause). */
|
|
38
|
+
offlineMessage: string | ((cause: unknown) => string);
|
|
39
|
+
}
|
|
40
|
+
/** Run one fetch-shaped operation under the policy described in the header. */
|
|
41
|
+
export declare function withFetchTimeout<T>(options: FetchTimeoutOptions, run: (signal: AbortSignal) => Promise<T>): Promise<T>;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve the Ghostscript command on every supported platform.
|
|
3
|
+
*
|
|
4
|
+
* Resolution order is explicit override, platform-specific PATH names, then
|
|
5
|
+
* conventional versioned Windows installer directories. The optional
|
|
6
|
+
* arguments make the Windows branch testable on non-Windows CI; production
|
|
7
|
+
* callers always use the current platform and environment.
|
|
8
|
+
*/
|
|
9
|
+
export declare function resolveGhostscript(targetPlatform?: NodeJS.Platform, env?: NodeJS.ProcessEnv): Promise<string | undefined>;
|
|
10
|
+
/**
|
|
11
|
+
* Strip all annotations from a PDF using qpdf.
|
|
12
|
+
*
|
|
13
|
+
* Chromium embeds internal link annotations (from HTML `id` attributes)
|
|
14
|
+
* that are not permitted in PDF/X output. Removing them before Ghostscript
|
|
15
|
+
* prevents the "Annotation not TrapNet or PrinterMark" warning and keeps
|
|
16
|
+
* the output in strict PDF/X compliance.
|
|
17
|
+
*/
|
|
18
|
+
export declare function stripAnnotations(pdfPath: string, stagingDir: string): Promise<void>;
|
|
19
|
+
type PdfxFlavor = "x1a" | "x3";
|
|
20
|
+
/**
|
|
21
|
+
* Generate the PostScript definition file for PDF/X output intent + GCR.
|
|
22
|
+
*/
|
|
23
|
+
export declare function makePdfxDefPs(params: {
|
|
24
|
+
iccPath: string;
|
|
25
|
+
pdfx: PdfxFlavor;
|
|
26
|
+
title: string;
|
|
27
|
+
maxTac?: number;
|
|
28
|
+
}): string;
|
|
29
|
+
/**
|
|
30
|
+
* Stamp the Creator metadata field on an existing PDF.
|
|
31
|
+
*
|
|
32
|
+
* Uses pdf-lib (pure JS, MIT) rather than Ghostscript, so the plain-PDF build
|
|
33
|
+
* path needs no system tool at all — gs is now required only for PDF/X CMYK
|
|
34
|
+
* conversion (ADR 0002). `updateMetadata: false` keeps pdf-lib from rewriting
|
|
35
|
+
* the ModDate/Producer so the only change is the /Creator field.
|
|
36
|
+
*/
|
|
37
|
+
export declare function stampCreator(pdfPath: string): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Convert an RGB PDF to CMYK PDF/X using Ghostscript.
|
|
40
|
+
*/
|
|
41
|
+
export declare function convertToPdfxCmyk(inputPdf: string, outPdf: string, config: {
|
|
42
|
+
iccPath: string;
|
|
43
|
+
pdfx: PdfxFlavor;
|
|
44
|
+
title?: string;
|
|
45
|
+
maxTac?: number;
|
|
46
|
+
stagingDir: string;
|
|
47
|
+
}): Promise<void>;
|
|
48
|
+
export {};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host-timer POLICY (pure) extracted from the source-provider abstraction.
|
|
3
|
+
*
|
|
4
|
+
* These helpers are the testable core of the desktop host's automatic-snapshot
|
|
5
|
+
* and automatic-sync timers: they turn a persisted, possibly-partial user
|
|
6
|
+
* settings object into a concrete debounce/cadence delay (ms) — or `null` when
|
|
7
|
+
* the feature is switched off. The timers themselves live in the Electron main
|
|
8
|
+
* process (CLAUDE.md §8); this module owns ONLY the clamping/default policy so
|
|
9
|
+
* both the CLI and the desktop resolve delays identically.
|
|
10
|
+
*
|
|
11
|
+
* Nothing here touches Git, the filesystem, or `isomorphic-git` — it is the
|
|
12
|
+
* host-facing cadence policy, deliberately separate from `source-provider.ts`'s
|
|
13
|
+
* SourceProvider operations.
|
|
14
|
+
*/
|
|
15
|
+
/** User-facing auto-snapshot policy (mirrors the desktop's settings group). */
|
|
16
|
+
export interface AutoSnapshotPolicy {
|
|
17
|
+
/** Master switch — automatic snapshots default ON. */
|
|
18
|
+
autoSnapshot: boolean;
|
|
19
|
+
/** Minutes of quiet after the last edit before a snapshot fires. */
|
|
20
|
+
autoSnapshotMinutes: number;
|
|
21
|
+
}
|
|
22
|
+
/** Cadence bounds: never below 5 minutes (commit-per-keystroke guard), never
|
|
23
|
+
* above a day (a longer value means the user effectively wants it off). */
|
|
24
|
+
export declare const AUTO_SNAPSHOT_MIN_MINUTES = 5;
|
|
25
|
+
export declare const AUTO_SNAPSHOT_MAX_MINUTES: number;
|
|
26
|
+
export declare const AUTO_SNAPSHOT_DEFAULT_MINUTES = 10;
|
|
27
|
+
/** User-facing auto-sync policy (mirrors the desktop's settings group). */
|
|
28
|
+
export interface AutoSyncPolicy {
|
|
29
|
+
/** Master switch — automatic sync defaults ON when a remote is configured. */
|
|
30
|
+
autoSync: boolean;
|
|
31
|
+
/** Periodic safety cadence in minutes (clamped, like the snapshot cadence). */
|
|
32
|
+
autoSyncMinutes: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Cadence bounds for the periodic safety sync. The floor (1 min) is lower than
|
|
36
|
+
* the snapshot floor because a network round-trip is cheaper than a full tree
|
|
37
|
+
* walk, and the transparent-sync plan targets ~2 min as the default cadence.
|
|
38
|
+
* The ceiling matches the snapshot ceiling (one day = effectively paused).
|
|
39
|
+
*/
|
|
40
|
+
export declare const AUTO_SYNC_MIN_MINUTES = 1;
|
|
41
|
+
export declare const AUTO_SYNC_MAX_MINUTES: number;
|
|
42
|
+
export declare const AUTO_SYNC_DEFAULT_MINUTES = 2;
|
|
43
|
+
/**
|
|
44
|
+
* Resolve the debounce delay (ms) for the host's auto-snapshot timer, or
|
|
45
|
+
* `null` when automatic snapshots are disabled. Pure — the testable core of
|
|
46
|
+
* the trigger policy (the timer itself lives in the Electron main process).
|
|
47
|
+
*
|
|
48
|
+
* Defensive about persisted settings: a missing policy means "defaults"
|
|
49
|
+
* (enabled, 10 min); a non-finite/absurd minutes value falls back to the
|
|
50
|
+
* default and is then clamped into [5, 1440].
|
|
51
|
+
*/
|
|
52
|
+
export declare function autoSnapshotDelayMs(policy: Partial<AutoSnapshotPolicy> | undefined): number | null;
|
|
53
|
+
/**
|
|
54
|
+
* Resolve the periodic-safety-sync interval (ms) for the host's auto-sync
|
|
55
|
+
* orchestrator, or `null` when auto-sync is disabled. Pure — the testable core
|
|
56
|
+
* of the trigger policy (the timer and the actual `syncProject` call live in
|
|
57
|
+
* the Electron main process, per CLAUDE.md §8).
|
|
58
|
+
*
|
|
59
|
+
* Modelled exactly on `autoSnapshotDelayMs`: a missing or partial policy means
|
|
60
|
+
* "defaults" (enabled, 2 min); a non-finite/absurd minutes value falls back to
|
|
61
|
+
* the default and is then clamped into [AUTO_SYNC_MIN_MINUTES,
|
|
62
|
+
* AUTO_SYNC_MAX_MINUTES].
|
|
63
|
+
*
|
|
64
|
+
* Note: the host orchestrator ALSO debounces on file-change triggers; this
|
|
65
|
+
* cadence governs only the periodic safety timer (§4.2 "Periodic safety").
|
|
66
|
+
*/
|
|
67
|
+
export declare function autoSyncDelayMs(policy: Partial<AutoSyncPolicy> | undefined): number | null;
|
|
68
|
+
/**
|
|
69
|
+
* True when a changed path is internal Git state (any `.git` segment). The
|
|
70
|
+
* host's project watcher and auto-snapshot triggers must IGNORE these: the
|
|
71
|
+
* automatic snapshot itself writes under `.git`, and treating that as a
|
|
72
|
+
* content change would re-trigger preview reloads / re-arm the timer forever.
|
|
73
|
+
* Accepts absolute paths, relative paths, or bare basenames.
|
|
74
|
+
*/
|
|
75
|
+
export declare function isGitInternalPath(p: string): boolean;
|