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.
Files changed (230) hide show
  1. package/README.md +422 -0
  2. package/dist/CGATS21_CRPC1-g0e3k7kr.icc +0 -0
  3. package/dist/api/index.d.ts +76 -0
  4. package/dist/api/index.js +272 -0
  5. package/dist/assets/preview/scripts/pagedjs-bridge.d.ts +1 -0
  6. package/dist/assets/preview/scripts/pagedjs-interface.d.ts +1 -0
  7. package/dist/assets/preview/scripts/preview-shell.d.ts +1 -0
  8. package/dist/audit-1jrwwacz.js +66 -0
  9. package/dist/build-5s92kgpc.js +77 -0
  10. package/dist/chapter-01-6fn9pvd0.md +31 -0
  11. package/dist/chapter-01-7jwqg1ct.md +20 -0
  12. package/dist/chapter-01-jj8ftn4c.md +29 -0
  13. package/dist/chapter-01-rkpyvjna.md +26 -0
  14. package/dist/checks/asset/approved-fonts.d.ts +3 -0
  15. package/dist/checks/asset/extensions.d.ts +41 -0
  16. package/dist/checks/asset/font-license.d.ts +3 -0
  17. package/dist/checks/asset/image-alpha.d.ts +3 -0
  18. package/dist/checks/asset/image-color-space.d.ts +3 -0
  19. package/dist/checks/asset/image-file-size.d.ts +3 -0
  20. package/dist/checks/asset/image-resolution.d.ts +3 -0
  21. package/dist/checks/asset/image-tac.d.ts +3 -0
  22. package/dist/checks/asset/index.d.ts +7 -0
  23. package/dist/checks/formatter.d.ts +3 -0
  24. package/dist/checks/heuristic/index.d.ts +4 -0
  25. package/dist/checks/heuristic/layer-count.d.ts +3 -0
  26. package/dist/checks/heuristic/placement-variance.d.ts +3 -0
  27. package/dist/checks/heuristic/section-density.d.ts +3 -0
  28. package/dist/checks/heuristic/text-density.d.ts +3 -0
  29. package/dist/checks/pdf/bleed.d.ts +3 -0
  30. package/dist/checks/pdf/bookmarks.d.ts +3 -0
  31. package/dist/checks/pdf/color-spaces.d.ts +3 -0
  32. package/dist/checks/pdf/cross-refs.d.ts +3 -0
  33. package/dist/checks/pdf/embedded-fonts.d.ts +3 -0
  34. package/dist/checks/pdf/image-resolution.d.ts +3 -0
  35. package/dist/checks/pdf/index.d.ts +15 -0
  36. package/dist/checks/pdf/ink-coverage.d.ts +3 -0
  37. package/dist/checks/pdf/page-labels.d.ts +3 -0
  38. package/dist/checks/pdf/page-size.d.ts +3 -0
  39. package/dist/checks/pdf/pdfx-markers.d.ts +3 -0
  40. package/dist/checks/pdf/pdfx-metadata.d.ts +3 -0
  41. package/dist/checks/pdf/pdfx-structure.d.ts +6 -0
  42. package/dist/checks/pdf/qpdf-structure.d.ts +3 -0
  43. package/dist/checks/pdf/rasterized-pages.d.ts +3 -0
  44. package/dist/checks/pdf/toc-links.d.ts +3 -0
  45. package/dist/checks/pdf/transparency.d.ts +3 -0
  46. package/dist/checks/policy.d.ts +61 -0
  47. package/dist/checks/register-builtins.d.ts +17 -0
  48. package/dist/checks/registry.d.ts +40 -0
  49. package/dist/checks/runner.d.ts +25 -0
  50. package/dist/checks/source/accessibility-alt-text.d.ts +3 -0
  51. package/dist/checks/source/accessibility-heading-order.d.ts +3 -0
  52. package/dist/checks/source/config-file.d.ts +8 -0
  53. package/dist/checks/source/htmlhint.d.ts +3 -0
  54. package/dist/checks/source/index.d.ts +6 -0
  55. package/dist/checks/source/local-refs.d.ts +3 -0
  56. package/dist/checks/source/markdownlint.d.ts +3 -0
  57. package/dist/checks/source/stylelint.d.ts +3 -0
  58. package/dist/checks/tool-check.d.ts +23 -0
  59. package/dist/checks/types.d.ts +52 -0
  60. package/dist/cli-1tyj4bk3.js +124 -0
  61. package/dist/cli-37x76zdn.js +4 -0
  62. package/dist/cli-506tg37g.js +26 -0
  63. package/dist/cli-5bxx0c4y.js +464 -0
  64. package/dist/cli-7ykx7pp0.js +12378 -0
  65. package/dist/cli-h7phg3ka.js +746 -0
  66. package/dist/cli-hvqjs342.js +284 -0
  67. package/dist/cli-yja077f6.js +92 -0
  68. package/dist/cli.js +157 -0
  69. package/dist/constants.d.ts +17 -0
  70. package/dist/doctor-25zjt8dz.js +57 -0
  71. package/dist/favicon-wkbm9cjn.ico +0 -0
  72. package/dist/git-http-yrb4ag6z.js +17 -0
  73. package/dist/index-1tyj4bk3.js +124 -0
  74. package/dist/index-37x76zdn.js +4 -0
  75. package/dist/index-3h3fef7r.js +15218 -0
  76. package/dist/index-5bxx0c4y.js +464 -0
  77. package/dist/index-yja077f6.js +92 -0
  78. package/dist/index.d.ts +32 -0
  79. package/dist/index.js +310 -0
  80. package/dist/lib/app-heartbeat.d.ts +102 -0
  81. package/dist/lib/asset-inline.d.ts +73 -0
  82. package/dist/lib/browser-pool.d.ts +17 -0
  83. package/dist/lib/build-error.d.ts +52 -0
  84. package/dist/lib/build-fingerprint.d.ts +15 -0
  85. package/dist/lib/build-preflight.d.ts +43 -0
  86. package/dist/lib/build-runner.d.ts +161 -0
  87. package/dist/lib/build-staging.d.ts +64 -0
  88. package/dist/lib/chromium.d.ts +20 -0
  89. package/dist/lib/cli-args.d.ts +45 -0
  90. package/dist/lib/desktop.d.ts +14 -0
  91. package/dist/lib/diagnostics.d.ts +64 -0
  92. package/dist/lib/embedded-assets.d.ts +29 -0
  93. package/dist/lib/exec.d.ts +84 -0
  94. package/dist/lib/fetch-timeout.d.ts +41 -0
  95. package/dist/lib/ghostscript.d.ts +48 -0
  96. package/dist/lib/host-policy.d.ts +75 -0
  97. package/dist/lib/image-inspect.d.ts +32 -0
  98. package/dist/lib/install-hints.d.ts +21 -0
  99. package/dist/lib/lint-runner.d.ts +10 -0
  100. package/dist/lib/manifest-config.d.ts +31 -0
  101. package/dist/lib/manifest-doc.d.ts +25 -0
  102. package/dist/lib/manifest.d.ts +41 -0
  103. package/dist/lib/markdown/assemble.d.ts +78 -0
  104. package/dist/lib/markdown/chapter-id.d.ts +24 -0
  105. package/dist/lib/markdown/images.d.ts +34 -0
  106. package/dist/lib/markdown/index.d.ts +78 -0
  107. package/dist/lib/markdown/markdown-it-paged.d.ts +30 -0
  108. package/dist/lib/markdown/plugins.d.ts +69 -0
  109. package/dist/lib/markdown/renderer.d.ts +111 -0
  110. package/dist/lib/npm-plugin-installer.d.ts +33 -0
  111. package/dist/lib/open-path.d.ts +5 -0
  112. package/dist/lib/output-paths.d.ts +23 -0
  113. package/dist/lib/pagedjs-marker.d.ts +42 -0
  114. package/dist/lib/pagedjs.d.ts +26 -0
  115. package/dist/lib/pagination.d.ts +169 -0
  116. package/dist/lib/pdf-inspect.d.ts +123 -0
  117. package/dist/lib/pdf-parse.d.ts +57 -0
  118. package/dist/lib/plugin-manager.d.ts +108 -0
  119. package/dist/lib/plugin-vendor.d.ts +107 -0
  120. package/dist/lib/presets.d.ts +45 -0
  121. package/dist/lib/printsafe.d.ts +17 -0
  122. package/dist/lib/project-scaffold.d.ts +116 -0
  123. package/dist/lib/project-source.d.ts +140 -0
  124. package/dist/lib/project-templates.d.ts +49 -0
  125. package/dist/lib/publish/butler.d.ts +10 -0
  126. package/dist/lib/publish/command-runner.d.ts +18 -0
  127. package/dist/lib/publish/connect.d.ts +23 -0
  128. package/dist/lib/publish/manifest-publish.d.ts +9 -0
  129. package/dist/lib/publish/providers/azure-swa.d.ts +3 -0
  130. package/dist/lib/publish/providers/drivethrurpg.d.ts +10 -0
  131. package/dist/lib/publish/providers/guided.d.ts +3 -0
  132. package/dist/lib/publish/providers/itch.d.ts +5 -0
  133. package/dist/lib/publish/providers/kdp.d.ts +9 -0
  134. package/dist/lib/publish/providers/shopify.d.ts +5 -0
  135. package/dist/lib/publish/registry.d.ts +5 -0
  136. package/dist/lib/publish/run-publish.d.ts +30 -0
  137. package/dist/lib/publish/selections.d.ts +25 -0
  138. package/dist/lib/publish/types.d.ts +258 -0
  139. package/dist/lib/remote-auth/clone.d.ts +87 -0
  140. package/dist/lib/remote-auth/conflict-resolution.d.ts +29 -0
  141. package/dist/lib/remote-auth/diagnose.d.ts +77 -0
  142. package/dist/lib/remote-auth/generic-auth.d.ts +97 -0
  143. package/dist/lib/remote-auth/git-http.d.ts +85 -0
  144. package/dist/lib/remote-auth/github-auth.d.ts +69 -0
  145. package/dist/lib/remote-auth/github-repos.d.ts +64 -0
  146. package/dist/lib/remote-auth/operation-log.d.ts +66 -0
  147. package/dist/lib/remote-auth/recovery/abort-interrupted-operation.d.ts +103 -0
  148. package/dist/lib/remote-auth/recovery/backup.d.ts +113 -0
  149. package/dist/lib/remote-auth/recovery/classify.d.ts +109 -0
  150. package/dist/lib/remote-auth/recovery/context.d.ts +47 -0
  151. package/dist/lib/remote-auth/recovery/dispatch.d.ts +33 -0
  152. package/dist/lib/remote-auth/recovery/failsafe.d.ts +33 -0
  153. package/dist/lib/remote-auth/recovery/inspect.d.ts +74 -0
  154. package/dist/lib/remote-auth/recovery/manual-guidance.d.ts +28 -0
  155. package/dist/lib/remote-auth/recovery/outcome-mapping.d.ts +58 -0
  156. package/dist/lib/remote-auth/recovery/policy.d.ts +47 -0
  157. package/dist/lib/remote-auth/recovery/recover-auth.d.ts +42 -0
  158. package/dist/lib/remote-auth/recovery/recover-binary-conflict.d.ts +37 -0
  159. package/dist/lib/remote-auth/recovery/recover-corrupt-index.d.ts +40 -0
  160. package/dist/lib/remote-auth/recovery/recover-detached-head.d.ts +70 -0
  161. package/dist/lib/remote-auth/recovery/recover-interrupted-cherry-pick.d.ts +23 -0
  162. package/dist/lib/remote-auth/recovery/recover-interrupted-merge.d.ts +28 -0
  163. package/dist/lib/remote-auth/recovery/recover-interrupted-rebase.d.ts +39 -0
  164. package/dist/lib/remote-auth/recovery/recover-merge-conflict.d.ts +34 -0
  165. package/dist/lib/remote-auth/recovery/recover-missing-git-dir.d.ts +37 -0
  166. package/dist/lib/remote-auth/recovery/recover-missing-objects.d.ts +56 -0
  167. package/dist/lib/remote-auth/recovery/recover-network.d.ts +34 -0
  168. package/dist/lib/remote-auth/recovery/recover-non-fast-forward.d.ts +27 -0
  169. package/dist/lib/remote-auth/recovery/recover-stale-lock.d.ts +76 -0
  170. package/dist/lib/remote-auth/recovery/recover-unrelated-histories.d.ts +44 -0
  171. package/dist/lib/remote-auth/recovery/recover-wrong-remote.d.ts +35 -0
  172. package/dist/lib/remote-auth/recovery/types.d.ts +235 -0
  173. package/dist/lib/remote-auth/resolution-plan.d.ts +64 -0
  174. package/dist/lib/remote-auth/sync-messages.d.ts +26 -0
  175. package/dist/lib/remote-auth/sync-types.d.ts +225 -0
  176. package/dist/lib/remote-auth/sync.d.ts +45 -0
  177. package/dist/lib/remote-auth/test-access.d.ts +47 -0
  178. package/dist/lib/remote-auth/test-support/git-http-server.d.ts +71 -0
  179. package/dist/lib/remote-auth/token-store.d.ts +95 -0
  180. package/dist/lib/remote-auth/transport.d.ts +105 -0
  181. package/dist/lib/slug.d.ts +28 -0
  182. package/dist/lib/snippets.d.ts +39 -0
  183. package/dist/lib/source-provider.d.ts +244 -0
  184. package/dist/lib/static-serve.d.ts +54 -0
  185. package/dist/lib/style-resolver.d.ts +30 -0
  186. package/dist/lib/theme-import.d.ts +70 -0
  187. package/dist/lib/theme-manager.d.ts +128 -0
  188. package/dist/lib/tool-probe.d.ts +37 -0
  189. package/dist/lib/validation-exec.d.ts +47 -0
  190. package/dist/lib/validation-profile.d.ts +18 -0
  191. package/dist/lib/version.d.ts +9 -0
  192. package/dist/lint-f63nxjfj.js +65 -0
  193. package/dist/manifest-n1gh3qw5.yaml +9 -0
  194. package/dist/manifest-ryyg71nf.yaml +9 -0
  195. package/dist/manifest.schema-rn1dpdpn.json +564 -0
  196. package/dist/new-7b08a42h.js +105 -0
  197. package/dist/paged.polyfill-n95pbxfn.js +33288 -0
  198. package/dist/pagedjs-bridge-vn4hk9fx.js +111 -0
  199. package/dist/pagedjs-interface-80g3xa8p.js +498 -0
  200. package/dist/platform.d.ts +100 -0
  201. package/dist/plugin-wf2cbmwc.js +129 -0
  202. package/dist/preflight-tg4mpz1h.js +222 -0
  203. package/dist/preview/file-watcher.d.ts +174 -0
  204. package/dist/preview/http-server.d.ts +45 -0
  205. package/dist/preview/lifecycle.d.ts +67 -0
  206. package/dist/preview/server-context.d.ts +36 -0
  207. package/dist/preview-h2bwbb2x.js +102 -0
  208. package/dist/preview-shell-rghtfmc8.js +155 -0
  209. package/dist/project-source-0tg0r6vm.js +17 -0
  210. package/dist/publish-ztaet53r.js +233 -0
  211. package/dist/render.d.ts +20 -0
  212. package/dist/render.js +682 -0
  213. package/dist/repair-jkp4n3j8.js +171 -0
  214. package/dist/schema/manifest.types.d.ts +218 -0
  215. package/dist/server.d.ts +34 -0
  216. package/dist/source-provider-hp96b5jf.js +46 -0
  217. package/dist/test-helpers/testkit.d.ts +91 -0
  218. package/dist/theme-0yzvthe8.css +65 -0
  219. package/dist/theme-570zmh2t.css +58 -0
  220. package/dist/theme-6a2fngc8.json +6 -0
  221. package/dist/theme-cd6efzjw.json +6 -0
  222. package/dist/theme-nya4nqh6.css +70 -0
  223. package/dist/theme-tqfypc1w.json +6 -0
  224. package/dist/theme-xt0hjb1b.json +6 -0
  225. package/dist/theme-zz2ktzqs.css +60 -0
  226. package/dist/types.d.ts +31 -0
  227. package/dist/utils/file-utils.d.ts +53 -0
  228. package/dist/utils/logger.d.ts +59 -0
  229. package/dist/validate-k2drs19j.js +99 -0
  230. package/package.json +102 -0
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Output location + artifact naming, by convention rather than configuration.
3
+ *
4
+ * A book builds to `<manifestDir>/dist/<title-slug>/`, and its artifacts are
5
+ * `<title-slug>-<format>.pdf`. This replaces the manifest's `output.dir` /
6
+ * `output.filename` / `output.html` block: the slug keeps several books in one
7
+ * tree apart, and the format is in the artifact name because the extension
8
+ * cannot tell a PDF from a PDF/X one (they previously shared a single
9
+ * configured filename, so building both left only the last).
10
+ *
11
+ * `--out` remains for per-invocation placement (CI, one-offs).
12
+ */
13
+ export declare const DIST_DIRNAME = "dist";
14
+ /** The rendered book document. Fixed: the desktop and index.html load it by name. */
15
+ export declare const BOOK_HTML = "book.html";
16
+ /** Slug identifying one book. Falls back to `book` for an unsluggable title. */
17
+ export declare function bookSlug(title: string | undefined): string;
18
+ /**
19
+ * A book's output directory. Anchored on the MANIFEST's directory, not the CWD,
20
+ * so building several projects from one working directory cannot collide.
21
+ */
22
+ export declare function resolveOutputDir(manifestDir: string, title: string | undefined): string;
23
+ export declare function artifactName(title: string | undefined, format: "pdf" | "pdfx"): string;
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Single source of truth for the Paged.js polyfill `<script>` slot.
3
+ *
4
+ * PURE / node-free by design: this module imports nothing (no `node:*`, no `fs`),
5
+ * so it can be shared by BOTH the pure, browser-usable HTML assembler
6
+ * (`markdown/assemble.ts`) and the node-side build/preview rewriters
7
+ * (`build-runner.ts`, `pagedjs.ts`, `preview/file-watcher.ts`).
8
+ *
9
+ * The contract between the assembler and every rewriter is the stable
10
+ * `data-pagedjs-polyfill` MARKER ATTRIBUTE — never a URL, filename, or version
11
+ * substring. Core emits the marker; the rewriters find/strip/replace it by
12
+ * attribute. A pagedjs version bump or attribute reorder therefore cannot
13
+ * silently break the strip/replace passes, and the un-rewritten `book.html`
14
+ * carries NO network dependency (there is no live CDN URL to leak).
15
+ */
16
+ /**
17
+ * Pinned Paged.js version. Bump HERE only — the value is emitted purely as
18
+ * documentation on the marker tag; matching never depends on it.
19
+ */
20
+ export declare const PAGEDJS_VERSION = "0.4.3";
21
+ /** Stable marker attribute identifying the Paged.js polyfill script slot. */
22
+ export declare const PAGEDJS_POLYFILL_MARKER = "data-pagedjs-polyfill";
23
+ /**
24
+ * The polyfill `<script>` slot Gutterpress core emits into `book.html`. Carries the
25
+ * stable marker (with the intended version as its value, for greppability) and
26
+ * NO `src` — an un-rewritten `book.html` has zero network dependency. Every
27
+ * consumer replaces this slot with a locally-vendored polyfill before the book
28
+ * is ever loaded (build staging, the no-Chromium runtime fallback, live preview).
29
+ */
30
+ export declare function pagedjsPolyfillTag(version?: string): string;
31
+ /**
32
+ * Match the polyfill `<script>` slot. Matches EITHER the stable marker attribute
33
+ * (core output) OR a `paged.polyfill` `src` (legacy CDN / vendored copy that a
34
+ * staging/patch pass has already swapped in) — so the same matcher works at every
35
+ * stage of the pipeline. Deliberately matches `paged.polyfill` (the version-
36
+ * stable FILENAME), never a bare `pagedjs` substring, so the navigation toolbar
37
+ * scripts (`pagedjs-interface.js` / `pagedjs-bridge.js`) are left untouched.
38
+ *
39
+ * Attribute-order tolerant and version-agnostic. Returns a FRESH RegExp per call
40
+ * so the `g` flag's `lastIndex` is never shared between callers.
41
+ */
42
+ export declare function pagedjsPolyfillTagRegex(): RegExp;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Inline script that polyfills Paged.js's missing break-inside: avoid support.
3
+ *
4
+ * Paged.js has an avoidBreakInside() method but never calls it. This handler
5
+ * intercepts onBreakToken and, when the break lands inside an element with
6
+ * data-break-inside="avoid", moves the break to before that element.
7
+ *
8
+ * Uses a data attribute (not CSS) because source nodes are disconnected from
9
+ * the DOM when onBreakToken fires, so getComputedStyle returns empty values.
10
+ *
11
+ * Must be registered via PagedConfig.before (runs before Paged.js renders).
12
+ */
13
+ export declare const BREAK_INSIDE_HANDLER: string;
14
+ /**
15
+ * Inject the Paged.js polyfill + render-complete marker into an HTML STRING.
16
+ *
17
+ * Pure so the build can paginate an in-memory copy: the shipped `book.html`
18
+ * must never carry the polyfill `<script src>` (it is a build-time engine, not
19
+ * part of the artifact), and the pagination server serves this patched string
20
+ * as an overlay instead of writing it to disk.
21
+ */
22
+ export declare function patchHtmlStringForPagedjs(html: string, vendorPath: string): string;
23
+ /**
24
+ * File-in-place wrapper around {@link patchHtmlStringForPagedjs}.
25
+ */
26
+ export declare function patchHtmlForPagedjs(htmlPath: string, vendorPath: string): Promise<void>;
@@ -0,0 +1,169 @@
1
+ import type { Page } from "puppeteer-core";
2
+ /**
3
+ * Render/pagination (ARCH finding #9, extracted from build-runner.ts): drives
4
+ * headless Chromium through Paged.js to fully paginate a staged HTML document,
5
+ * either printing it to PDF or serializing the paginated DOM to static HTML.
6
+ * Owns: the embedded static HTTP file server both render paths need (a local
7
+ * origin so relative asset URLs resolve), the shared navigate+wait+liveness
8
+ * sequence (`paginateAndCapture`), the default PDF renderer, and build-time
9
+ * static-HTML pagination. build-runner.ts's two `OutputStrategy` classes call
10
+ * into this module for the actual pagination work and never touch a puppeteer
11
+ * `Page` themselves.
12
+ */
13
+ /** An in-memory response served instead of reading a file from disk. */
14
+ export interface ServerOverlay {
15
+ body: string | Buffer;
16
+ contentType: string;
17
+ }
18
+ /**
19
+ * Start a localhost static file server rooted at `dir`, with optional in-memory
20
+ * `overlays` keyed by URL path (e.g. `/book.html`).
21
+ *
22
+ * Overlays are what let the build paginate WITHOUT staging a second copy of the
23
+ * project. `outDir` is served directly; the Paged.js-patched `book.html` and the
24
+ * vendored polyfill are supplied from memory, so the engine never has to be
25
+ * written into the shipped artifact and no asset is copied twice. This mirrors
26
+ * the preview server, which has always served `/vendor/*` as a virtual overlay
27
+ * rather than copying it per project.
28
+ *
29
+ * Path-traversal protection, the MIME map, and the actual file response are
30
+ * the shared `./static-serve` primitives (`resolveStaticPath` + `serveFile`)
31
+ * also used by preview/http-server.ts — a request that resolves outside `dir`
32
+ * gets 403; a missing file gets 404 from `serveFile` itself.
33
+ */
34
+ export declare function createStaticFileServer(dir: string, defaultFile: string, overlays?: Record<string, ServerOverlay>): Promise<{
35
+ port: number;
36
+ close: () => Promise<void>;
37
+ }>;
38
+ /** Input handed to a PDF renderer: a URL serving the staged HTML + assets. */
39
+ export interface PdfRenderInput {
40
+ /** URL of the staged HTML on a local HTTP server (assets resolve relative). */
41
+ url: string;
42
+ /** Absolute path the renderer must write the finished PDF to. */
43
+ outPdf: string;
44
+ /** Hard ceiling for navigation + pagination + PDF generation. */
45
+ timeoutMs: number;
46
+ /**
47
+ * When set, after printing the PDF the renderer also serializes the
48
+ * already-paginated DOM (the same DOM it just printed) and writes it to this
49
+ * path as raw static HTML. Lets ONE pagination pass emit BOTH the PDF and the
50
+ * static desktop HTML, so screen and PDF come from the same artifact. The
51
+ * serialize is read-only and runs AFTER `page.pdf()`, so it cannot affect the
52
+ * PDF. Optional; injected renderers that cannot serialize may ignore it.
53
+ */
54
+ captureStaticHtmlTo?: string;
55
+ }
56
+ /**
57
+ * A PDF renderer drives a browser engine to load `url`, wait for fonts +
58
+ * Paged.js (`window.__PAGED_RENDERED__ === true`), measure the first
59
+ * `.pagedjs_page`, and write a borderless PDF at that exact page size to
60
+ * `outPdf` with backgrounds printed.
61
+ *
62
+ * The default ({@link puppeteerPdfRenderer}) drives a system/bundled Chromium.
63
+ * The Electron desktop injects one backed by its own `webContents.printToPDF`,
64
+ * so the packaged app needs no external browser (ADR 0002, Phase 4).
65
+ */
66
+ export type PdfRenderer = (input: PdfRenderInput) => Promise<void>;
67
+ /** Hard ceiling for navigation + pagination + PDF generation. Large books need
68
+ * this budget; it is also the puppeteer protocolTimeout for the pooled browser. */
69
+ export declare const RENDER_TIMEOUT_MS: number;
70
+ /** Tracks the last-seen `.pagedjs_page` count and when it last advanced. */
71
+ export interface PaginationLivenessState {
72
+ count: number;
73
+ lastAdvanceAt: number;
74
+ }
75
+ export interface PaginationLivenessResult {
76
+ stalled: boolean;
77
+ state: PaginationLivenessState;
78
+ }
79
+ /**
80
+ * Pure stall-detection decision (finding #19), extracted out of the polling
81
+ * loop below so it is unit-testable with a fake page-count source instead of
82
+ * a real puppeteer `page`. Given the latest `.pagedjs_page` count poll and the
83
+ * previously tracked state, decide whether pagination has stalled — the count
84
+ * has not advanced for at least `stallWindowMs` — and return the updated
85
+ * state (advancing resets the liveness clock; a flat or regressed count
86
+ * leaves `lastAdvanceAt` untouched).
87
+ */
88
+ export declare function evaluatePaginationLiveness(count: number, now: number, state: PaginationLivenessState, stallWindowMs: number): PaginationLivenessResult;
89
+ /**
90
+ * Drive a puppeteer `page` to fully paginate the document at `url`: set the
91
+ * viewport + timeouts, navigate (waiting for network idle so vendored assets +
92
+ * the polyfill load), wait for web fonts, then block until Paged.js signals
93
+ * `window.__PAGED_RENDERED__ === true`.
94
+ *
95
+ * While waiting, a background poller checks the `.pagedjs_page` count every
96
+ * `STALL_POLL_INTERVAL_MS` and logs it (so a long build visibly advances
97
+ * instead of sitting silent), and fails fast with a BuildError the moment
98
+ * `evaluatePaginationLiveness` decides the count has stopped advancing for
99
+ * `STALL_WINDOW_MS` — instead of a wedged Paged.js run silently consuming the
100
+ * full `timeoutMs` / `RENDER_TIMEOUT_MS` budget (up to an hour) before anyone
101
+ * finds out. `timeoutMs` (== `RENDER_TIMEOUT_MS` at every call site) remains
102
+ * the outer budget for legitimately slow-but-advancing books.
103
+ *
104
+ * Policy (owner's call, superseding an earlier "warn and ship partial output"
105
+ * behavior): pagination either completes — `__PAGED_RENDERED__` fires — or the
106
+ * build FAILS. A stall (count plateaus, whether at zero or after some pages)
107
+ * and an outright wait timeout are BOTH treated as an incomplete render and
108
+ * throw a `BuildError`; neither path falls through to let a caller print/
109
+ * serialize whatever partial DOM exists. A silently-truncated "successful"
110
+ * print-ready PDF is worse than a build that fails loudly — non-technical
111
+ * authors have no way to notice half their book is missing. The stall check
112
+ * still fails fast (within `stallWindowMs` of the last advance) rather than
113
+ * waiting out the full `timeoutMs` budget.
114
+ *
115
+ * Shared navigate+wait sequence for BOTH render paths. Callers keep their own
116
+ * tails: the PDF path calls `page.pdf()`; the static-HTML path serializes the
117
+ * DOM — neither tail runs unless this function returns normally, i.e. unless
118
+ * pagination actually completed. Per-caller knobs (viewport, timeout,
119
+ * liveness window) are passed in so behavior is never silently changed;
120
+ * `livenessConfig` defaults to the production constants and exists as a seam
121
+ * for tests to shrink the poll/stall windows instead of waiting 60+ real
122
+ * seconds.
123
+ */
124
+ export declare function paginateAndCapture(page: Page, url: string, timeoutMs: number, viewport?: {
125
+ width: number;
126
+ height: number;
127
+ }, livenessConfig?: {
128
+ pollIntervalMs: number;
129
+ stallWindowMs: number;
130
+ }): Promise<void>;
131
+ /**
132
+ * Close a CSS string value that Paged.js deliberately left unterminated.
133
+ *
134
+ * Paged.js's StringSets handler writes its string-set results as inline custom
135
+ * properties with an OPENING quote and NO closing quote (paged.polyfill.js:
136
+ * `fragment.style.setProperty(\`--pagedjs-string-first-${name}\`, \`"${…}\`)`).
137
+ * Live that is harmless: `setProperty` parses each value in isolation and the
138
+ * CSS tokenizer auto-closes a string token at end-of-value. But the moment the
139
+ * DOM is SERIALIZED, all four of those properties land in ONE `style` attribute
140
+ * joined by `;` — and on reparse the first unterminated string swallows the
141
+ * declarations that follow it (`"1; --pagedjs-string-last-guideSection: "`).
142
+ * The consumer, `content: "C." var(--pagedjs-string-first-guideSection)`, then
143
+ * becomes invalid at computed-value time and the footer disappears.
144
+ *
145
+ * Given the raw property text, return it with a closing `"` appended when the
146
+ * string token does not terminate. Rules follow CSS Syntax §4.3.5 "consume a
147
+ * string token": a backslash escapes the next code point, and a backslash at
148
+ * end-of-input is dropped (it cannot escape the quote we are about to add).
149
+ * Values that are already terminated — including ones this function has already
150
+ * fixed — are returned unchanged, so it is idempotent. Values that are not a
151
+ * quoted string at all are left alone.
152
+ */
153
+ export declare function closeUnterminatedCssString(value: string): string;
154
+ /**
155
+ * Build-time pagination (SSG model): drive headless Chromium to fully paginate
156
+ * the book with Paged.js, then serialize the resulting already-fragmented DOM
157
+ * to a static HTML string. Paged.js's polisher injects its layout CSS as
158
+ * `<style>` elements INTO the DOM, so the serialized markup carries everything
159
+ * needed to render the pages with NO runtime pagination engine.
160
+ *
161
+ * Serves `outDir` itself (images resolve relative to `book.html`, exactly as
162
+ * they will in the shipped artifact) with the engine supplied as overlays.
163
+ */
164
+ export declare function paginateToStaticHtml(htmlFile: string): Promise<string>;
165
+ /**
166
+ * Render `htmlFile` (in its own `outDir`) to a PDF, serving that directory with
167
+ * the pagination engine supplied as in-memory overlays.
168
+ */
169
+ export declare function renderHtmlToPdf(htmlFile: string, outPdf: string, renderer?: PdfRenderer, captureStaticHtmlTo?: string): Promise<void>;
@@ -0,0 +1,123 @@
1
+ /**
2
+ * In-process PDF inspection via unpdf (a serverless-tuned PDF.js build).
3
+ *
4
+ * This is the pure-JS replacement for the Poppler suite (pdfinfo, pdffonts,
5
+ * pdfimages, pdftotext) and the general qpdf inspection used by the post-build
6
+ * validation checks. It has ZERO system dependency and — unlike raw pdfjs-dist,
7
+ * whose `legacy` build eagerly evaluates canvas/DOMMatrix code — unpdf bundles
8
+ * cleanly under `bun build --compile` (verified). See ADR 0002.
9
+ *
10
+ * NOT replaced here (still system tools, by design):
11
+ * - Ghostscript (gs): ink coverage + PDF/X CMYK conversion — no JS equivalent.
12
+ * - qpdf: PDF/X OutputIntent/DOCINFO structure checks (pdfx-*) — needs raw
13
+ * catalog/object access pdfjs has no public API for, and qpdf is already
14
+ * mandatory whenever PDF/X is produced.
15
+ *
16
+ * Fidelity notes (accepted in ADR 0002):
17
+ * - Structural integrity (`isLoadable`) is a "does it parse" gate, not a deep
18
+ * `qpdf --check` of xref/stream-length integrity.
19
+ * - Image DPI requires decoding the image to read its pixel dimensions and is
20
+ * therefore best-effort; bleed-box reads fall back to a raw-byte scan because
21
+ * pdfjs exposes no TrimBox/BleedBox accessor.
22
+ *
23
+ * Loaded documents are cached per path (invalidated on size/mtime change) so a
24
+ * single validation run parses a large PDF once across all checks.
25
+ */
26
+ import type { PDFDocumentProxy, PDFPageProxy } from "unpdf/pdfjs";
27
+ /**
28
+ * Cap on distinct cached documents (audit B3). One validation run touches a
29
+ * single PDF across ~13 checks (one entry), so this only bounds accumulation
30
+ * ACROSS runs in a long-lived host (the Electron desktop validating many
31
+ * projects over a session). Without it, `docCache` grew one never-freed parsed
32
+ * document per distinct path ever validated. LRU eviction destroys the evicted
33
+ * document so its decoded pages/fonts/images are released, not just unreferenced.
34
+ * (Exported so tests derive their eviction fixtures from the real cap.)
35
+ */
36
+ export declare const DOC_CACHE_MAX = 8;
37
+ /**
38
+ * Load (and cache) a PDF as a PDF.js document proxy. Returns null if the file
39
+ * is missing or cannot be parsed at all. Concurrent callers for the same path
40
+ * share one parse.
41
+ */
42
+ export declare function loadPdf(path: string): Promise<PDFDocumentProxy | null>;
43
+ /**
44
+ * Retain the document cache for the duration of a run. The check runner is a
45
+ * public lib export served by a long-lived host (the desktop), where two runs
46
+ * CAN overlap — e.g. a Problems-panel lint run and a publish preflight. An
47
+ * unconditional `clearPdfCache()` at either run's end would destroy documents
48
+ * the other run is actively reading (getPage/getOperatorList then throw
49
+ * "Transport destroyed") and would void the eviction grace protecting its
50
+ * evicted-but-held documents. So each run holds a scope instead: the returned
51
+ * release function decrements the count and performs the clear only when the
52
+ * LAST active scope releases. Release is idempotent — extra calls are no-ops.
53
+ */
54
+ export declare function retainPdfCache(): () => void;
55
+ /**
56
+ * Destroy and drop every cached document, including evicted ones still inside
57
+ * their destroy grace (their timers are cancelled). This is the FORCEFUL,
58
+ * unconditional reclaim — it ignores active retain scopes, so hosts should
59
+ * prefer `retainPdfCache()` (which clears when the last overlapping run
60
+ * releases); the check runner uses that scope. Exposed for tests and for
61
+ * hosts that know no run is in flight.
62
+ */
63
+ export declare function clearPdfCache(): void;
64
+ /** Test-only introspection: evicted documents still awaiting grace destruction. */
65
+ export declare function pendingGraceDestroyCount(): number;
66
+ /** Page dimensions in PostScript points (1/72") for the given 1-based page. */
67
+ export declare function getPageSize(page: PDFPageProxy): {
68
+ w: number;
69
+ h: number;
70
+ };
71
+ /** Number of top-level outline (bookmark) entries; 0 if none. */
72
+ export declare function getOutlineCount(doc: PDFDocumentProxy): Promise<number>;
73
+ /** Page label array, or null when the PDF declares no explicit labels. */
74
+ export declare function getPageLabels(doc: PDFDocumentProxy): Promise<string[] | null>;
75
+ /**
76
+ * Count link annotations across the whole document. `stopAtFirst` short-circuits
77
+ * for the boolean "are there any links?" question (TOC-links check).
78
+ */
79
+ export declare function countLinkAnnotations(doc: PDFDocumentProxy, stopAtFirst?: boolean): Promise<number>;
80
+ interface TextPass {
81
+ /** Non-whitespace-stripped text per page (index 0 = page 1). */
82
+ textByPage: string[];
83
+ /** Every text run's baseline origin, for layout-variance analysis. */
84
+ positions: Array<{
85
+ x: number;
86
+ y: number;
87
+ }>;
88
+ }
89
+ export declare function getTextPass(doc: PDFDocumentProxy): Promise<TextPass>;
90
+ export interface ImageRef {
91
+ /** XObject resource name (or "(inline)" for inline images). */
92
+ name: string;
93
+ /** Rendered width/height on the page, in points (from the CTM). */
94
+ placedW: number;
95
+ placedH: number;
96
+ /** 1-based page number. */
97
+ page: number;
98
+ }
99
+ export interface FontRef {
100
+ name: string;
101
+ embedded: boolean;
102
+ }
103
+ interface OpPass {
104
+ imagesByPage: Map<number, ImageRef[]>;
105
+ fonts: FontRef[];
106
+ }
107
+ export declare function getOpPass(doc: PDFDocumentProxy): Promise<OpPass>;
108
+ /**
109
+ * Per-image effective DPI = pixel dimension ÷ placed size in inches. Decodes
110
+ * each image (best-effort). Used only by the opt-in image-resolution check.
111
+ */
112
+ export declare function getImageResolutions(doc: PDFDocumentProxy): Promise<Array<{
113
+ page: number;
114
+ xDpi: number;
115
+ yDpi: number;
116
+ }>>;
117
+ /**
118
+ * "Does it parse" gate: load every page. Returns true if the whole document is
119
+ * traversable. This is NOT a deep xref/stream-length integrity check — it only
120
+ * catches PDFs that are actually broken/unparseable (ADR 0002).
121
+ */
122
+ export declare function isLoadable(doc: PDFDocumentProxy): Promise<boolean>;
123
+ export {};
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Read a PDF as a latin1 string for literal ASCII-marker scanning.
3
+ *
4
+ * latin1 maps every byte 0x00–0xFF to exactly one char (lossless for binary
5
+ * data) — never use utf8 here, which mangles non-text bytes. This is the
6
+ * in-process replacement for the previous `grep -ao <marker> file.pdf` usage
7
+ * and is a behavioral equivalent, including grep's one limitation: markers that
8
+ * live inside FlateDecode-compressed streams are not visible to a raw byte
9
+ * scan. grep had the identical blind spot, so callers see no behavior change.
10
+ *
11
+ * Used by the transparency, color-spaces, and bleed checks. All other PDF
12
+ * inspection now goes through the structured PDF.js reader in pdf-inspect.ts.
13
+ */
14
+ export declare function readPdfBytes(pdfPath: string): Promise<string>;
15
+ /**
16
+ * Parse ink coverage from `gs -sDEVICE=inkcov` output.
17
+ *
18
+ * Ghostscript has no pure-JS equivalent (it stays a system tool — see ADR 0002),
19
+ * so the inkcov path remains shell-based here.
20
+ */
21
+ export declare function parseInkCov(out: string): {
22
+ c: number;
23
+ m: number;
24
+ y: number;
25
+ k: number;
26
+ sum: number;
27
+ }[];
28
+ export interface InkCoveragePage {
29
+ page: number;
30
+ c: number;
31
+ m: number;
32
+ y: number;
33
+ k: number;
34
+ tac: number;
35
+ }
36
+ /**
37
+ * Discriminated result for {@link getPerPageInkCoverage} (finding #51).
38
+ * Ghostscript failing (crash, corrupt PDF, missing binary, a Windows PATH
39
+ * mismatch — see finding #3) must be distinguishable from a legitimately
40
+ * measured, empty-pages result: both used to collapse to the same `[]`,
41
+ * which let the ink-coverage check silently PASS a book it never actually
42
+ * measured.
43
+ */
44
+ export type InkCoverageResult = {
45
+ ok: true;
46
+ pages: InkCoveragePage[];
47
+ } | {
48
+ ok: false;
49
+ error: string;
50
+ };
51
+ /**
52
+ * Get per-page ink coverage using Ghostscript's inkcov device.
53
+ * Returns `{ ok: true, pages }` with per-page CMYK coverage (in percentages)
54
+ * on success, or `{ ok: false, error }` if gs could not be run/parsed —
55
+ * callers must surface the failure, not treat it as "0 pages measured".
56
+ */
57
+ export declare function getPerPageInkCoverage(pdfPath: string): Promise<InkCoverageResult>;
@@ -0,0 +1,108 @@
1
+ import { type NpmPluginInstallOptions } from "./npm-plugin-installer";
2
+ /** Folder (relative to the project root) imported local plugins are copied to. */
3
+ export { PLUGINS_DIR } from "./plugin-vendor";
4
+ /** How a plugin entry is referenced in the manifest. */
5
+ export type PluginKind = "local" | "npm";
6
+ /** One configured plugin, as surfaced to the manager UI. */
7
+ export interface ProjectPluginEntry {
8
+ /** Stable reference: the manifest `path` (local) or `name` (npm). */
9
+ ref: string;
10
+ /** `"local"` when referenced by file path, `"npm"` when by package name. */
11
+ kind: PluginKind;
12
+ /** Per-project enable flag. Absent in the manifest defaults to `true`. */
13
+ enabled: boolean;
14
+ /** Exact installed npm version. Absent for local, built-in, and legacy entries. */
15
+ version?: string;
16
+ /** Named module export selected as the plugin function. */
17
+ export?: string;
18
+ /** Non-fatal install notices, currently used for legacy SHA-1 registry entries. */
19
+ warnings?: string[];
20
+ }
21
+ interface PluginManagerInstallOptions extends NpmPluginInstallOptions {
22
+ exportName?: string;
23
+ __testFailBeforeManifestCommit?: () => void | Promise<void>;
24
+ }
25
+ /** Serialize all plugin filesystem + manifest mutations for one project. */
26
+ export declare function withPluginMutationLock<T>(projectDir: string, mutation: () => Promise<T>): Promise<T>;
27
+ /** Result of attempting to load one configured plugin. */
28
+ export interface PluginValidationResult {
29
+ ref: string;
30
+ kind: PluginKind;
31
+ /** Mirrors the manifest enable flag. Disabled plugins are not load-tested. */
32
+ enabled: boolean;
33
+ /** `true` when the plugin loaded OK (or is disabled and skipped). */
34
+ ok: boolean;
35
+ /** The loader's fail-fast error message when `ok` is `false`. */
36
+ error?: string;
37
+ }
38
+ /** A curated markdown feature an author can turn on. */
39
+ export interface RecommendedPlugin {
40
+ /** The npm package name (also the manifest entry that "Add" writes). */
41
+ name: string;
42
+ /** Short, plain-language feature name shown as the row title (the package
43
+ * name is demoted to secondary text — a non-technical author shouldn't have
44
+ * to read `markdown-it-*` ids to pick a feature). */
45
+ label: string;
46
+ /** One-line author-friendly description. */
47
+ description: string;
48
+ /**
49
+ * True when gutterpress ships this plugin (see `BUILTIN_OPTIONAL_PLUGINS`):
50
+ * "Add" enables it instantly, no install, works offline. All entries below
51
+ * are built-in — the always-on defaults (attrs/footnote/deflist, applied
52
+ * unconditionally in renderer.ts) are intentionally NOT listed here, since
53
+ * recommending the author "add" something already active is pure confusion.
54
+ */
55
+ builtin: true;
56
+ }
57
+ /**
58
+ * Curated, BUILT-IN opt-in markdown features. Each is bundled with gutterpress
59
+ * (`BUILTIN_OPTIONAL_PLUGINS`), so clicking "Add" writes the manifest entry AND
60
+ * the feature works immediately — no terminal, no install, offline. This is the
61
+ * non-technical-author happy path: "turn on a feature → it works".
62
+ */
63
+ export declare const RECOMMENDED_PLUGINS: RecommendedPlugin[];
64
+ /**
65
+ * List the project's configured plugins with their per-project enable flag.
66
+ * Returns `[]` when there is no manifest or no `plugins:` list.
67
+ *
68
+ * For object-form entries, the kind is taken from the manifest KEY (`path:` →
69
+ * local, `name:` → npm) rather than guessing from the value. This correctly
70
+ * classifies e.g. `path: plugins/foo.js` (no `./` prefix) as local. Scalar
71
+ * (string) entries fall back to the {@link isLocalRef} heuristic.
72
+ */
73
+ export declare function listProjectPlugins(projectDir: string): Promise<ProjectPluginEntry[]>;
74
+ /**
75
+ * Set the per-project enabled flag for the plugin identified by `ref` (its
76
+ * path or npm name). A string-form entry is normalised to an object entry so
77
+ * the flag can be attached. Persists to the manifest (preserving comments).
78
+ * Throws when no entry matches `ref`.
79
+ */
80
+ export declare function setPluginEnabled(projectDir: string, ref: string, enabled: boolean): Promise<void>;
81
+ /**
82
+ * Install an npm markdown-it plugin without an external package manager, then
83
+ * record its exact version in the manifest. Built-in optional plugins remain
84
+ * offline: adding one only records its bundled package name.
85
+ */
86
+ export declare function addNpmPlugin(projectDir: string, packageSpec: string, exportName?: string): Promise<ProjectPluginEntry>;
87
+ /** @internal Dependency/fault injection for focused installer tests. */
88
+ export declare function addNpmPluginWithOptions(projectDir: string, packageSpec: string, options?: PluginManagerInstallOptions): Promise<ProjectPluginEntry>;
89
+ /**
90
+ * Import a local plugin by copying the source file OR folder into the
91
+ * project's `plugins/` directory and adding a manifest entry that references
92
+ * the copied path (so the plugin travels with the project). Returns the new
93
+ * entry. Throws when `sourcePath` does not exist.
94
+ */
95
+ export declare function addLocalPlugin(projectDir: string, sourcePath: string): Promise<ProjectPluginEntry & {
96
+ path: string;
97
+ }>;
98
+ /**
99
+ * Validate every configured plugin by attempting to LOAD it through the
100
+ * existing lib loader (`loadPlugin`). Disabled plugins are reported as
101
+ * disabled and NOT load-tested. Loader errors are CAUGHT and surfaced per
102
+ * plugin (never thrown through) so the UI can flag erroring plugins clearly.
103
+ *
104
+ * This reuses the fail-fast loader path verbatim (§5) — including its
105
+ * "not found / install it" message for unresolvable npm packages — rather than
106
+ * reimplementing resolution.
107
+ */
108
+ export declare function validateProjectPlugins(projectDir: string): Promise<PluginValidationResult[]>;
@@ -0,0 +1,107 @@
1
+ /** Project-relative folder shared by local and vendored npm plugins. */
2
+ export declare const PLUGINS_DIR = "plugins";
3
+ export declare const VENDORED_NPM_DIR = "npm";
4
+ export declare const VENDOR_RECEIPT_FILE = ".gutterpress-install.json";
5
+ export declare const VENDOR_RECEIPT_VERSION = 2;
6
+ export interface ParsedNpmPluginSpec {
7
+ name: string;
8
+ /** Exact version, semver range, or dist-tag requested after the package name. */
9
+ selector?: string;
10
+ }
11
+ export interface VendorPackageReceipt {
12
+ /** POSIX path relative to the versioned install root. */
13
+ path: string;
14
+ name: string;
15
+ version: string;
16
+ tarball: string;
17
+ integrity: string;
18
+ /** True only for old registry entries that offered no SHA-256-or-stronger SRI. */
19
+ legacySha1: boolean;
20
+ /** ESM/import-condition package entry, when the package exposes one. */
21
+ entry?: string;
22
+ /** CommonJS/require-condition package entry, when different or available. */
23
+ requireEntry?: string;
24
+ /** Declared production dependency/required-peer name -> package receipt path. */
25
+ dependencies: Record<string, string>;
26
+ }
27
+ export interface VendorSkippedDependency {
28
+ from: string;
29
+ name: string;
30
+ selector: string;
31
+ kind: "optional" | "optional-peer";
32
+ reason: string;
33
+ }
34
+ export interface VendorReceipt {
35
+ schemaVersion: typeof VENDOR_RECEIPT_VERSION;
36
+ root: {
37
+ name: string;
38
+ version: string;
39
+ packagePath: string;
40
+ /** POSIX path relative to the versioned install root. */
41
+ entry: string;
42
+ format: "module" | "commonjs";
43
+ };
44
+ packages: VendorPackageReceipt[];
45
+ skipped: VendorSkippedDependency[];
46
+ tree: {
47
+ algorithm: "sha256";
48
+ digest: string;
49
+ files: number;
50
+ bytes: number;
51
+ };
52
+ }
53
+ export interface VerifiedVendorPlugin {
54
+ installRoot: string;
55
+ entryPath: string;
56
+ format: "module" | "commonjs";
57
+ packages: VerifiedVendorPackage[];
58
+ receipt: VendorReceipt;
59
+ }
60
+ export interface VerifiedVendorPackage {
61
+ path: string;
62
+ name: string;
63
+ packageDir: string;
64
+ manifest: Record<string, unknown>;
65
+ entryPath?: string;
66
+ requireEntryPath?: string;
67
+ dependencies: Record<string, string>;
68
+ }
69
+ export interface PackageResolutionTarget {
70
+ target: string;
71
+ /** Export-map targets are exact; legacy targets use Node-style fallbacks. */
72
+ exact: boolean;
73
+ }
74
+ export interface VendorTreeDigest {
75
+ digest: string;
76
+ files: number;
77
+ bytes: number;
78
+ }
79
+ export declare function isValidNpmPackageName(name: string): boolean;
80
+ /** Parse `name`, `name@selector`, `@scope/name`, or `@scope/name@selector`. */
81
+ export declare function parseNpmPluginSpec(input: string): ParsedNpmPluginSpec;
82
+ export declare function isExactNpmVersion(version: string): boolean;
83
+ /** Root containing one pinned package's private `node_modules` tree. */
84
+ export declare function vendoredNpmPluginRoot(projectDir: string, name: string, version: string): string;
85
+ /** npm-compatible package location within a versioned vendor root. */
86
+ export declare function vendoredNpmPluginPackageDir(installRoot: string, name: string): string;
87
+ export declare function toPosixPath(value: string): string;
88
+ export declare function packageEntryFormat(manifest: Record<string, unknown>, relativeEntry: string): "module" | "commonjs";
89
+ /** Reject names that alias, fail, or escape on supported Windows filesystems. */
90
+ export declare function assertWindowsSafeRelativePath(relative: string): void;
91
+ /** Canonical key for case-insensitive, Unicode-normalizing Windows aliases. */
92
+ export declare function windowsPathKey(relative: string): string;
93
+ /** Resolve export conditions/patterns without consulting any ambient filesystem. */
94
+ export declare function packageResolutionTargets(manifest: Record<string, unknown>, subpath: string, condition: "import" | "require"): PackageResolutionTarget[];
95
+ /** Resolve a package's import entry without Node/Bun package-name resolution. */
96
+ export declare function resolvePackageEntry(packageDir: string, packageJson?: Record<string, unknown>, condition?: "import" | "require"): Promise<string>;
97
+ /** SHA-256 every contained regular file and its canonical relative path. */
98
+ export declare function computeVendorTreeDigest(root: string): Promise<VendorTreeDigest>;
99
+ /** Resolve a vendor root without trusting lexical project containment. */
100
+ export declare function resolveVendoredPluginInstallRoot(projectDir: string, expectedName: string, expectedVersion: string): Promise<string | null>;
101
+ /**
102
+ * Verify a schema-v2 receipt and the complete contained tree. `null` means no
103
+ * new-format marker exists, so an exact version may still be legacy metadata.
104
+ * A present but invalid marker is always a hard failure, never a global-cache
105
+ * fallback.
106
+ */
107
+ export declare function verifyVendoredPlugin(projectDir: string, expectedName: string, expectedVersion: string): Promise<VerifiedVendorPlugin | null>;