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,32 @@
1
+ /**
2
+ * Dependency-free raster image header reader — the in-process replacement for
3
+ * ImageMagick `identify` used by the asset checks (Phase 3 of ADR 0002).
4
+ *
5
+ * Why not `sharp`? sharp is the most capable option but is a native addon whose
6
+ * platform binaries are resolved through `node_modules` at runtime — exactly the
7
+ * pattern that breaks `bun build --compile` (ADR 0001 §1/§3). A small header
8
+ * parser for the formats print authors actually use (PNG, JPEG, TIFF) keeps a
9
+ * single code path that bundles into the standalone binary AND runs in the
10
+ * Electron desktop, with zero system/native dependency.
11
+ *
12
+ * Scope: width/height, x/y DPI, alpha presence, and a coarse color-space token
13
+ * ("srgb" | "gray" | "cmyk"). This matches what the three asset checks consume.
14
+ * Tokens are lowercased to line up with the lowercased `identify %[colorspace]`
15
+ * values the existing config compares against.
16
+ *
17
+ * DPI parity note: like `identify`, an image with no density metadata is treated
18
+ * as 72 DPI (ImageMagick's default) so the opt-in min-DPI check behaves as before.
19
+ */
20
+ export type ColorSpace = "srgb" | "gray" | "cmyk" | "";
21
+ export interface ImageInfo {
22
+ width: number;
23
+ height: number;
24
+ /** Effective DPI; defaults to 72 when the file carries no density metadata. */
25
+ xDpi: number;
26
+ yDpi: number;
27
+ hasAlpha: boolean;
28
+ colorSpace: ColorSpace;
29
+ }
30
+ /** Inspect a PNG/JPEG/TIFF file; returns null for unreadable/unknown formats. */
31
+ export declare function inspectImage(path: string): Promise<ImageInfo | null>;
32
+ export declare function collectImageFiles(dirs: string[], exts: readonly string[], ignore?: readonly string[]): Promise<string[]>;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Canonical per-tool install-hint copy — the text a stuck non-technical
3
+ * author actually reads when a build fails because gs/qpdf/Chromium isn't
4
+ * installed.
5
+ *
6
+ * This is the single source of truth. `build-preflight.ts` (preflight error),
7
+ * `diagnostics.ts` (desktop Help/About dialog + `gutterpress doctor`), and
8
+ * `chromium.ts` (`requireChromiumExecutable`'s thrown error) all import
9
+ * from here instead of hand-copying the per-platform install commands —
10
+ * previously three diverging copies existed (see
11
+ * docs/reviews/2026-07-10-architecture-critical-review.md, finding #15).
12
+ */
13
+ export interface InstallHint {
14
+ /** Human label for the tool, used in "Install <label>:" headers. */
15
+ label: string;
16
+ /** Indented, per-platform install commands. No header, no trailing newline. */
17
+ body: string;
18
+ }
19
+ export declare const INSTALL_HINTS: Record<"chromium" | "gs" | "qpdf", InstallHint>;
20
+ /** "Install <label>:\n<body>" — the full standalone hint (diagnostics/doctor). */
21
+ export declare function fullInstallHint(tool: keyof typeof INSTALL_HINTS): string;
@@ -0,0 +1,10 @@
1
+ export interface LintRunnerOptions {
2
+ files?: string;
3
+ manifest?: string;
4
+ }
5
+ export interface LintRunnerResult {
6
+ ok: boolean;
7
+ riskyCount: number;
8
+ filesLinted: number;
9
+ }
10
+ export declare function runLint(opts?: LintRunnerOptions): Promise<LintRunnerResult>;
@@ -0,0 +1,31 @@
1
+ /** The author-facing manifest subset the Config view can read + write. */
2
+ export interface ProjectConfigFields {
3
+ title?: string;
4
+ authors?: string[];
5
+ /** `source.files` — the markdown inputs (null means "all chapter files"). */
6
+ sourceFiles?: string[] | null;
7
+ }
8
+ /**
9
+ * Apply the author-facing manifest field updates in a single yaml round-trip.
10
+ * Only the keys present in `updates` are written; everything else is left
11
+ * untouched (so unrelated comments + sections survive). `sourceFiles: null`
12
+ * deletes the `source.files` entry (back to "all chapter files").
13
+ */
14
+ export declare function setManifestFields(projectDir: string, updates: ProjectConfigFields): Promise<ProjectConfigFields>;
15
+ /**
16
+ * Read the author-facing manifest subset for the Config view's Details section.
17
+ * Loads via the same shared {@link loadManifestDoc} every other manifest reader/
18
+ * writer in this module uses (ARCH finding #25 — this used to re-implement
19
+ * loadManifestDoc's read-and-parse inline) and surfaces empty/absent fields as
20
+ * empty strings so the form inputs are editable.
21
+ */
22
+ export declare function readManifestFields(projectDir: string): Promise<ProjectConfigFields>;
23
+ /**
24
+ * Replace the manifest's entire `styles:` list with `paths`. This is the
25
+ * generic "which stylesheets are active" control the unified Config view's
26
+ * Styles section drives — toggling a stylesheet on/off or reordering the active
27
+ * set. Theme-apply still owns copying the theme folder; this only rewrites the
28
+ * list entry order. `paths` are project-relative, forward-slash strings (how
29
+ * they appear in the manifest, e.g. `themes/zine/theme.css`, `styles/print.css`).
30
+ */
31
+ export declare function setActiveStyles(projectDir: string, paths: string[]): Promise<string[]>;
@@ -0,0 +1,25 @@
1
+ import { YAMLSeq } from "yaml";
2
+ import type { Document } from "yaml";
3
+ /** Resolve `manifest.yaml` inside a project dir. */
4
+ export declare function resolveManifestPath(projectDir: string): string;
5
+ /** Load the manifest as a yaml Document (empty doc when absent). */
6
+ export declare function loadManifestDoc(projectDir: string): Promise<{
7
+ doc: Document.Parsed;
8
+ file: string;
9
+ }>;
10
+ /** Atomically write the doc back, creating the project dir if needed. */
11
+ export declare function writeManifestDoc(file: string, doc: Document.Parsed): Promise<void>;
12
+ /** The named sequence node, creating (and attaching) an empty one if missing. */
13
+ export declare function ensureSeq(doc: Document.Parsed, key: string): YAMLSeq;
14
+ /**
15
+ * Unwrap a yaml seq item (or `getIn`-style Pair) to its string value: `null`
16
+ * when the item isn't a string. Handles both a bare Scalar/Pair-shaped node
17
+ * (`{ value: … }`, as `doc.get(key, true)` returns for seq items) and a
18
+ * plain JS string (as a freshly-constructed `Scalar`'s `.value` or a raw
19
+ * array entry would be).
20
+ *
21
+ * ARCH finding #25: this was two near-duplicate helpers — `unwrapScalar`
22
+ * (manifest-config.ts) and `styleHrefOf` (theme-manager.ts) — with the same
23
+ * shape-sniffing logic. One implementation here, consumed by both.
24
+ */
25
+ export declare function scalarString(item: unknown): string | null;
@@ -0,0 +1,41 @@
1
+ import type { GutterpressManifest, ResolvedConfig } from "../schema/manifest.types";
2
+ /**
3
+ * The manifest file name Gutterpress recognizes.
4
+ * Single source of truth — any code that needs to find/match a manifest file
5
+ * (project scanning, GitHub repo book discovery, …) should consume this
6
+ * instead of hardcoding the names.
7
+ */
8
+ export declare const MANIFEST_FILENAMES: readonly ["manifest.yaml"];
9
+ /** True when a directory contains any recognized project manifest file. */
10
+ export declare function hasProjectManifest(dir: string): boolean;
11
+ /**
12
+ * Load a recognized manifest from a given path or CWD.
13
+ * Returns an empty object if the file doesn't exist.
14
+ */
15
+ export declare function loadManifest(pathOrDir?: string): Promise<GutterpressManifest>;
16
+ /**
17
+ * Load a recognized manifest and return its contents, directory, and resolved path.
18
+ * Returns an empty manifest, a null path, and the current working directory if none is found —
19
+ * UNLESS `explicit` is set (ARCH finding #12/PR #98): a caller that resolved
20
+ * `pathOrDir` from a user-supplied `--manifest` flag (as opposed to a project
21
+ * directory being scanned for a manifest that may legitimately not exist) must
22
+ * pass `{ explicit: true }` so a missing/typo'd path throws instead of
23
+ * silently resolving to an empty manifest. A typo like `--manifest
24
+ * ./typo.yaml` previously fell through to the "no manifest" default AND left
25
+ * `manifestDir` pointing at the nonexistent path itself
26
+ * (`resolve("./typo.yaml")`), so a later `path.resolve(manifestDir,
27
+ * config.output.dir)` could create build output beneath a directory named
28
+ * after the missing file.
29
+ */
30
+ export declare function loadManifestWithPath(pathOrDir?: string, opts?: {
31
+ explicit?: boolean;
32
+ }): Promise<{
33
+ manifest: GutterpressManifest;
34
+ manifestDir: string;
35
+ manifestPath: string | null;
36
+ }>;
37
+ /**
38
+ * Merge CLI args > manifest > preset defaults into a fully-resolved config.
39
+ * Any field explicitly set in `cliOverrides` wins, then manifest, then preset.
40
+ */
41
+ export declare function resolveConfig(cliOverrides: Partial<GutterpressManifest>, manifest: GutterpressManifest): ResolvedConfig;
@@ -0,0 +1,78 @@
1
+ import { type LoadedPlugin } from "./renderer";
2
+ /** Reader injected by the host: resolve a project-root-relative file → its text. */
3
+ export type ReadText = (relPath: string) => Promise<string>;
4
+ /**
5
+ * One author-mistake warning emitted by `markdown-it-paged` (ARCH finding #4).
6
+ * Mirrors the shape `markdown-it-paged.js`'s `warn()` pushes onto
7
+ * `env.layoutWarnings` — see that file's header comment for the 8 warning
8
+ * `type`s (`ambiguous_marker_token`, `section_without_page`, `nested_spread`,
9
+ * `continue_without_section`, `spread_without_pages`, `spread_eof_close`,
10
+ * `page_outside_spread`, `implicit_page`).
11
+ */
12
+ export interface LayoutWarning {
13
+ line: number;
14
+ type: string;
15
+ message: string;
16
+ marker?: unknown;
17
+ }
18
+ export interface AssembleBookHtmlOptions {
19
+ /** Ordered list of project-root-relative `.md` files to concatenate. */
20
+ files: string[];
21
+ /** Async reader the assembler uses to fetch each file's contents. */
22
+ readText: ReadText;
23
+ /**
24
+ * Fully-inlined project CSS (fonts already embedded as `data:` URIs by
25
+ * `lib/asset-inline.ts`). Emitted as a `<style data-project-css>` block —
26
+ * NOT as `<link href>`.
27
+ *
28
+ * Inlining is what makes a stylesheet's location irrelevant to the output, so
29
+ * themes (`themes/<id>/theme.css`) and shared design systems
30
+ * (`../design-guide/styles/guide.css`) need no copying, no flattening and no
31
+ * destination indirection. It is also what Paged.js does to the document
32
+ * anyway — it deletes every `<link>`/`<style>` and re-emits the CSS inline —
33
+ * so a `<link>` never survived the render path to begin with.
34
+ */
35
+ projectCss?: string;
36
+ title?: string;
37
+ plugins?: LoadedPlugin[];
38
+ pluginCss?: string;
39
+ /**
40
+ * Add `data-chapter-src="<file>"` to the same source-mapped block elements
41
+ * that receive `data-source-line`. The historical option name is retained as
42
+ * public API, but no wrapper is emitted: even `display: contents` changes CSS
43
+ * selector relationships such as `body > *`, `:first-child`, and cross-file
44
+ * siblings, which can change pagination. Off by default; build output is
45
+ * unaffected.
46
+ */
47
+ wrapChapters?: boolean;
48
+ /**
49
+ * ARCH finding #4: per-chapter callback receiving any `env.layoutWarnings`
50
+ * `markdown-it-paged` computed while rendering `file` (only called when
51
+ * that chapter produced at least one). `file` is the same canonical
52
+ * chapter id used for `data-chapter-src`, so a host can attribute a warning
53
+ * to the exact source file. Additive/optional — omitting it reproduces the
54
+ * prior throwaway-env behavior exactly, so this cannot change output for
55
+ * existing callers (e.g. the desktop's WebAdapter, which still gets a plain
56
+ * `Promise<string>` back).
57
+ */
58
+ onChapterWarnings?: (file: string, warnings: LayoutWarning[]) => void;
59
+ /**
60
+ * Every image reference the assembled document emits, deduped and in document
61
+ * order — markdown image tokens (recorded by `registerImageRule`) plus raw
62
+ * HTML `<img src>` found by scanning the output.
63
+ *
64
+ * This is what makes "referenced means shipped" true: the build turns these
65
+ * into its copy plan (`planImageCopies`), so no author-maintained directory
66
+ * list can drift from what the book actually uses.
67
+ */
68
+ onImageRefs?: (refs: string[]) => void;
69
+ }
70
+ /**
71
+ * Assemble a single `book.html` string from the given markdown files.
72
+ *
73
+ * Pure: every input (the file list, their contents via `readText`, the resolved
74
+ * CSS hrefs) is supplied by the caller. Mirrors the exact `<head>`/body/CSS
75
+ * emission the old `renderChapters` produced, so the CLI output is byte-identical
76
+ * for identical inputs.
77
+ */
78
+ export declare function assembleBookHtml(opts: AssembleBookHtmlOptions): Promise<string>;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Canonical chapter identity.
3
+ *
4
+ * A chapter is identified by ONE canonical string everywhere it crosses a
5
+ * boundary: project-root-relative, forward slashes, no `./` prefix, no
6
+ * duplicate slashes. This single form is used by:
7
+ *
8
+ * - preview source blocks' `data-chapter-src` tagging
9
+ * (lib/markdown/assemble.ts assembleBookHtml — index.ts's renderChapters
10
+ * is now just the thin node:fs wrapper around it)
11
+ * - preview source inspection and chapter-scoped scroll restoration
12
+ * (preview/file-watcher.ts)
13
+ * - the desktop's editor↔preview sync scoping
14
+ * (packages/desktop +page.svelte editorChapter)
15
+ *
16
+ * WHY: manifest `source.files` entries are author-written and arrive in many
17
+ * spellings (`./chapters/03.md`, `chapters\03.md` on Windows, `chapters//03.md`),
18
+ * while the watcher broadcasts `path.relative(inputPath, file)`. Before this
19
+ * helper the build tagged the manifest string VERBATIM, so any `./`-prefixed
20
+ * or backslashed manifest entry made source-attribution and scroll-restoration
21
+ * lookups miss every `data-chapter-src` in the live DOM (and the desktop's
22
+ * editor↔preview chapter scoping silently broke the same way).
23
+ */
24
+ export declare function canonicalChapterId(p: string): string;
@@ -0,0 +1,34 @@
1
+ import type MarkdownIt from "markdown-it";
2
+ /**
3
+ * Markdown-it `image` renderer rule that RECORDS every image reference the
4
+ * document emits, on `env.imageRefs`.
5
+ *
6
+ * This replaces the previous `normalizeImageSrc` rewriter, which collapsed
7
+ * `temp/images/…` and `./images/…` to `images/…`. That rewrite had zero
8
+ * producers anywhere in the codebase or its history, and it silently broke any
9
+ * author who kept art in a folder literally named `temp/images/` — the HTML
10
+ * pointed at `images/<file>`, which no code path ever created, and adding the
11
+ * folder to the old `source.assets` list could not fix it.
12
+ *
13
+ * Recording instead of rewriting is what lets the build copy exactly the files
14
+ * the book references (`lib/asset-inline.ts` → `planImageCopies`), so the
15
+ * author's own folder layout is the layout that ships. Paths are emitted
16
+ * verbatim; the build resolves them against the project root, which is the
17
+ * frame `book.html` is served from.
18
+ */
19
+ /** Env slot the rule appends to. Absent when nothing referenced an image. */
20
+ export interface ImageRefEnv {
21
+ imageRefs?: string[];
22
+ }
23
+ export declare function registerImageRule(md: MarkdownIt): void;
24
+ /**
25
+ * Collect local image references from raw HTML in rendered output.
26
+ *
27
+ * Covers `src` on `<img>` AND every candidate in a `srcset` (on `<img>` or on
28
+ * `<source>` inside `<picture>`). A responsive image's candidates are real files
29
+ * the browser may choose: the preview serves them straight from the project so
30
+ * they look fine, but the build only ships what the copy plan names — so a
31
+ * candidate that never entered the plan 404s during pagination and drops out of
32
+ * the PDF silently. Scanning only `src` was exactly that gap.
33
+ */
34
+ export declare function collectHtmlImageRefs(html: string): string[];
@@ -0,0 +1,78 @@
1
+ import { type LayoutWarning } from "./assemble";
2
+ import { type AssetCopy } from "../asset-inline";
3
+ import type { LoadedPlugin } from "./renderer";
4
+ export type { LayoutWarning } from "./assemble";
5
+ export { createMarkdownRenderer } from "./renderer";
6
+ /**
7
+ * THE canonical "which markdown files make up this book, and in what order?"
8
+ * resolver — markdown's counterpart to `resolveActiveStyles` (style-resolver.ts).
9
+ * Both `renderChapters` below AND validation/lint (validation-exec.ts,
10
+ * lint-runner.ts) call this, so what gets checked is always what gets rendered
11
+ * (2026-07-28 duplication audit — those two used to each re-derive their own
12
+ * recursive-glob approximation of "the book's markdown files" instead of
13
+ * calling this):
14
+ * 1. `configuredFiles` (the manifest `source.files` list), if it has entries,
15
+ * in that order; else
16
+ * 2. every `.md` file directly inside `inputDir` — NOT recursive, since a
17
+ * book's chapters live at the project root by convention — alphabetically.
18
+ * Returned entries are exactly as authored/discovered (relative to `inputDir`,
19
+ * un-normalised); callers that need a readable path must resolve them the same
20
+ * way `renderChapters` does below (`join(inputDir, canonicalChapterId(f))`).
21
+ */
22
+ export declare function resolveActiveMarkdownFiles(inputDir: string, configuredFiles?: string[] | null): Promise<string[]>;
23
+ /**
24
+ * Render all chapter markdown files to a single HTML string.
25
+ *
26
+ * If files are specified, they will be included in the provided order.
27
+ * If files are not specified, all .md files in the directory will be included in alphabetical order.
28
+ *
29
+ * This is the thin **Node wrapper** around the pure `assembleBookHtml`
30
+ * (`./assemble.ts`): it resolves the CSS list + the file list off disk and
31
+ * supplies a `node:fs/promises`-backed `readText`. The pure assembler owns the
32
+ * markdown→HTML→book.html work, so the browser/PWA WebAdapter can reuse the
33
+ * exact same render path with a File System Access reader (#33).
34
+ */
35
+ export declare function renderChapters(inputDir: string, opts?: {
36
+ title?: string;
37
+ styles?: string[];
38
+ files?: string[] | null;
39
+ plugins?: LoadedPlugin[];
40
+ pluginCss?: string;
41
+ /** Add chapter identity to source-mapped blocks for preview inspection. */
42
+ wrapChapters?: boolean;
43
+ /**
44
+ * ARCH finding #4: per-chapter author-mistake warnings computed by
45
+ * markdown-it-paged (`env.layoutWarnings`), forwarded straight through
46
+ * from {@link assembleBookHtml}. See that option's docstring — omitting
47
+ * it is fully backward compatible.
48
+ */
49
+ onChapterWarnings?: (file: string, warnings: LayoutWarning[]) => void;
50
+ /** See {@link assembleBookHtml}'s option of the same name. */
51
+ onImageRefs?: (refs: string[]) => void;
52
+ /**
53
+ * Files the inlined CSS needs alongside the book (content-addressed images
54
+ * too large to embed). The build adds these to its copy plan.
55
+ */
56
+ onCssAssets?: (copies: AssetCopy[]) => void;
57
+ /** Non-fatal notices from the inliner (e.g. a remote `url()` left as-is). */
58
+ onStyleWarnings?: (warnings: string[]) => void;
59
+ }): Promise<string>;
60
+ /**
61
+ * Render chapters and write the result to a file.
62
+ *
63
+ * The output filename is fixed at `book.html` (BOOK_HTML_FILENAME) — the
64
+ * gutterpress desktop (`index.html`) loads this via a relative iframe `src`.
65
+ */
66
+ export declare function renderChaptersToFile(inputDir: string, outDir: string, opts?: {
67
+ title?: string;
68
+ styles?: string[];
69
+ files?: string[] | null;
70
+ plugins?: LoadedPlugin[];
71
+ pluginCss?: string;
72
+ /** ARCH finding #4 — see {@link renderChapters}'s option of the same name. */
73
+ onChapterWarnings?: (file: string, warnings: LayoutWarning[]) => void;
74
+ /** See {@link renderChapters}'s options of the same names. */
75
+ onImageRefs?: (refs: string[]) => void;
76
+ onCssAssets?: (copies: AssetCopy[]) => void;
77
+ onStyleWarnings?: (warnings: string[]) => void;
78
+ }): Promise<string>;
@@ -0,0 +1,30 @@
1
+ export default function plugin(md: any, pluginOptions?: {}): void;
2
+ /**
3
+ * Minimal Paged.js-friendly CSS for the classes this plugin emits.
4
+ * Consumers should inject this into <head> after their user stylesheets so
5
+ * the layout contract (page/section/column breaks) wins at equal specificity.
6
+ *
7
+ * Also ships five author-facing image/block utility classes (CLAUDE.md §0 —
8
+ * a behavior broadly useful to non-technical authors belongs in core, not a
9
+ * project layer; see UX finding M17). markdown-it-attrs is bundled by
10
+ * default (renderer.ts), so `![Art](x.jpg){.full-bleed}` already attaches
11
+ * the class to the rendered `<img>` — these rules are what make that class
12
+ * actually do something print-safe:
13
+ *
14
+ * .center — centers a block element (margin-inline: auto).
15
+ * .float-left — floats left with clearance margins.
16
+ * .float-right — floats right with clearance margins.
17
+ * .full-width — fills the page's content width (100%).
18
+ * .full-bleed — forces its own page (break-before) and cancels the
19
+ * page's LEFT/RIGHT margins via Paged.js's real
20
+ * `--pagedjs-margin-left`/`--pagedjs-margin-right` custom
21
+ * properties (set per-page by the polyfill from the active
22
+ * `@page` rule — see pagedjs/src/polisher/base.js), so
23
+ * content spans the page edge-to-edge horizontally. This
24
+ * does NOT cancel the top/bottom margins, extend past the
25
+ * trim into printer bleed overage, apply a named `@page`
26
+ * template, or remove headers/footers — none of that is
27
+ * implemented; the custom-property fallback of 0 means it
28
+ * degrades to plain full-width outside a Paged.js render.
29
+ */
30
+ export const PAGED_CSS: "\n.md-page-break { break-before: page; }\n.page { break-before: page; }\n.spread { break-before: page; }\n.section { break-inside: avoid; }\n.section.col-split { break-inside: auto; }\n.md-column-break { break-after: column; height: 0; font-size: 0; line-height: 0; visibility: hidden; }\n\n.center { display: block; margin-left: auto; margin-right: auto; max-width: 100%; }\n.float-left { float: left; margin: 0 1em 1em 0; max-width: 50%; }\n.float-right { float: right; margin: 0 0 1em 1em; max-width: 50%; }\n.full-width { display: block; width: 100%; max-width: 100%; }\n.full-bleed {\n display: block;\n break-before: page;\n max-width: none;\n width: calc(100% + var(--pagedjs-margin-left, 0px) + var(--pagedjs-margin-right, 0px));\n margin-left: calc(-1 * var(--pagedjs-margin-left, 0px));\n margin-right: calc(-1 * var(--pagedjs-margin-right, 0px));\n}\n";
@@ -0,0 +1,69 @@
1
+ import type { ResolvedPluginConfig } from "../../schema/manifest.types";
2
+ import type { LoadedPlugin } from "./renderer";
3
+ export type { GutterpressPlugin, GutterpressPluginMetadata, GutterpressPluginExport, LoadedPlugin, } from "./renderer";
4
+ export { applyPlugins, collectPluginCss } from "./renderer";
5
+ /** Test-only mutation seam between snapshot completion and snapshot verification. */
6
+ export declare function __setVendorSnapshotHookForTests(hook?: (sourceRoot: string, snapshotRoot: string) => void | Promise<void>): void;
7
+ export declare function clearVendoredPluginResolver(baseDir: string, packageName: string, version: string): void;
8
+ /** Test-only: reset the path-plugin cache between test cases. */
9
+ export declare function __resetPathPluginCacheForTests(): void;
10
+ /**
11
+ * Load a single plugin from a file path or npm package.
12
+ *
13
+ * Throws if the plugin cannot be resolved, imported, or doesn't export a
14
+ * valid plugin function. The error message identifies which manifest entry
15
+ * failed so users can find it.
16
+ *
17
+ * Path plugins always go through the mtime cache (see the call below): it is
18
+ * correct in both a one-shot CLI build and the long-lived Electron host that
19
+ * runs `runBuild` in-process, so no caller-selected cache mode is needed.
20
+ */
21
+ export declare function loadPlugin(config: ResolvedPluginConfig, baseDir: string): Promise<LoadedPlugin>;
22
+ /**
23
+ * Load all plugins from the resolved configuration.
24
+ *
25
+ * Two failure modes, selected by whether `onError` is supplied:
26
+ *
27
+ * - **Fail-fast (no `onError`)** — the default for build/export/validate. If
28
+ * any plugin fails to load, the whole operation aborts with the underlying
29
+ * error. A final artifact must never silently omit author-configured
30
+ * formatting.
31
+ * - **Degrade-and-report (`onError` supplied)** — for the LIVE PREVIEW. A
32
+ * plugin that can't load (e.g. a vendored folder was omitted when a
33
+ * project was copied) is skipped, `onError` is invoked with the
34
+ * offending ref + error, and the rest of the document still renders. This
35
+ * is NOT silent skipping (the failure mode §5 warns against): the caller
36
+ * surfaces every skip loudly (preview warns in its log; the Plugins panel
37
+ * shows the plugin error with fix instructions).
38
+ *
39
+ * Path plugins are loaded through the mtime cache in `loadPlugin` regardless
40
+ * of mode (finding #5): an edited plugin reloads across renders while an
41
+ * unedited one is never re-imported, correct in both a one-shot CLI build and
42
+ * the long-lived Electron host.
43
+ */
44
+ export declare function loadPlugins(configs: ResolvedPluginConfig[], baseDir: string, onError?: (pluginRef: string, error: Error) => void): Promise<LoadedPlugin[]>;
45
+ /** Result of {@link loadPluginsWithCss}: loaded plugins ready for `applyPlugins`
46
+ * plus their concatenated CSS ready for injection into the rendered document. */
47
+ export interface LoadedPluginsWithCss {
48
+ /** `undefined` (not `[]`) when there were no configs to load — matches the
49
+ * `plugins?:` field the renderer options expect, so callers can pass this
50
+ * straight through without an `?? []` at every call site. */
51
+ plugins: LoadedPlugin[] | undefined;
52
+ pluginCss: string;
53
+ }
54
+ /**
55
+ * Shared "load plugins -> collect their CSS" preamble (ARCH finding #53).
56
+ * Both real render paths — build/export's fail-fast `renderBook`
57
+ * (build-runner.ts) and the live preview's degrade-and-report
58
+ * `renderPreviewBook` (preview/file-watcher.ts) — did this in lockstep,
59
+ * differing ONLY in whether `onError` was supplied. `onError` presence still
60
+ * selects fail-fast vs degrade-and-report (see {@link loadPlugins}) and the
61
+ * matching path-plugin cache mode; this helper just removes the duplicated
62
+ * wiring around it.
63
+ *
64
+ * A `configs` of `undefined`/empty short-circuits WITHOUT calling
65
+ * `loadPlugins` at all (`plugins: undefined`, `pluginCss: ""`) — matching
66
+ * both call sites' prior behavior of never plugin-loading when the manifest
67
+ * declares no plugins.
68
+ */
69
+ export declare function loadPluginsWithCss(configs: ResolvedPluginConfig[] | undefined | null, baseDir: string, onError?: (pluginRef: string, error: Error) => void): Promise<LoadedPluginsWithCss>;
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Pure (node-free) markdown rendering core.
3
+ *
4
+ * §1/§8 / ADR 0004: this module imports ONLY pure JS — markdown-it and its
5
+ * plugins, the inlined `markdown-it-paged.js`, and the node-free leveled
6
+ * logger (console-only). It contains NO `node:*`,
7
+ * NO `fs`/`path`/`url`, and NO filesystem access, so it can be imported by the
8
+ * browser renderer (the PWA WebAdapter, #33) AND bundled into the
9
+ * `bun build --compile` CLI binary alike.
10
+ *
11
+ * The plugin *author* types and the markdown-it factory live here (not in
12
+ * `plugins.ts`) precisely because `plugins.ts` is the node-coupled plugin
13
+ * *loader* (`node:fs`/`node:path`/`node:url`/`node:module`). Splitting the pure
14
+ * factory out keeps the browser import graph free of node code. `plugins.ts`
15
+ * re-exports these for backward compatibility, so existing callers are
16
+ * unaffected.
17
+ */
18
+ import MarkdownIt from "markdown-it";
19
+ /**
20
+ * Plugin author API.
21
+ *
22
+ * A gutterpress plugin is a standard markdown-it plugin — any plugin from npm
23
+ * with the signature `(md, options) => void` will work, including the entire
24
+ * markdown-it plugin ecosystem.
25
+ *
26
+ * Authors of *new* plugins can `import type { GutterpressPlugin } from
27
+ * 'gutterpress'` for type-only support; no runtime dependency on
28
+ * gutterpress is required (or recommended).
29
+ */
30
+ export type GutterpressPlugin = (md: MarkdownIt, options?: Record<string, unknown>) => void;
31
+ /**
32
+ * Optional metadata a plugin may export alongside its default plugin function.
33
+ * Surfaced in load-time log lines so users can see which plugins are active.
34
+ */
35
+ export interface GutterpressPluginMetadata {
36
+ name?: string;
37
+ version?: string;
38
+ description?: string;
39
+ author?: string;
40
+ keywords?: string[];
41
+ }
42
+ /**
43
+ * Full shape a plugin module may export. Only `default` is required.
44
+ *
45
+ * ```ts
46
+ * const plugin: GutterpressPlugin = (md) => { ... };
47
+ * export default plugin;
48
+ * export const metadata: GutterpressPluginMetadata = { name: 'my-plugin', version: '1.0.0' };
49
+ * export const css = `.my-class { color: red; }`;
50
+ * ```
51
+ */
52
+ export interface GutterpressPluginExport {
53
+ default: GutterpressPlugin;
54
+ metadata?: GutterpressPluginMetadata;
55
+ /** CSS injected into <head> after user stylesheets. Use sparingly — has equal cascade specificity. */
56
+ css?: string;
57
+ }
58
+ /** Internal representation of a loaded plugin, ready for `md.use()`. */
59
+ export interface LoadedPlugin {
60
+ name: string;
61
+ plugin: GutterpressPlugin;
62
+ metadata?: GutterpressPluginMetadata;
63
+ css?: string;
64
+ options: Record<string, unknown>;
65
+ }
66
+ /**
67
+ * Bundled, opt-in markdown plugins keyed by their npm name. Enabling one of
68
+ * these (manifest `plugins: - <name>` or the desktop's plugin manager) resolves
69
+ * it from HERE — no project install, no network, works offline and in the
70
+ * compiled binary. The plugin loader (`plugins.ts`) consults this map before
71
+ * trying to resolve a package from the project's node_modules, so a
72
+ * non-technical author gets the feature instantly instead of a "not installed"
73
+ * error. (attrs/footnote/deflist are NOT here — they are always-on defaults
74
+ * applied unconditionally below.)
75
+ */
76
+ export declare const BUILTIN_OPTIONAL_PLUGINS: Record<string, GutterpressPlugin>;
77
+ /**
78
+ * Create a fully-configured MarkdownIt instance.
79
+ *
80
+ * Built-in pipeline (runs before any user plugins):
81
+ * markdown-it-attrs → markdown-it-footnote → markdown-it-deflist →
82
+ * markdown-it-source-map → markdown-it-paged
83
+ *
84
+ * markdown-it-deflist adds the standard (PHP Markdown Extra / Pandoc)
85
+ * definition-list syntax — `Term` / `: definition` — emitting plain
86
+ * `<dl><dt><dd>`. It is not in CommonMark/markdown-it core; this is the
87
+ * canonical markdown-it plugin for it.
88
+ *
89
+ * Block container syntax (`:::name ... :::`) was removed 2026-05-17 in favor
90
+ * of the @marker family. See docs/migrations/2026-05-removing-container-syntax.md
91
+ * for the migration mapping.
92
+ *
93
+ * GFM-style `> [!NOTE]` alerts were also moved into the DC plugin on the
94
+ * same date because the emitted classes (dc-alert, dc-vibe-callout, etc.)
95
+ * are DC-branded. Core should not leak DC identifiers.
96
+ *
97
+ * @param customPlugins - Optional array of custom plugins to load
98
+ */
99
+ export declare function createMarkdownRenderer(customPlugins?: LoadedPlugin[]): MarkdownIt;
100
+ /**
101
+ * Apply loaded plugins to a markdown-it instance.
102
+ *
103
+ * Throws if a plugin's `(md, options) => void` call itself throws — usually
104
+ * a sign that the plugin is incompatible with this markdown-it version or
105
+ * has a bug in its `apply` phase.
106
+ */
107
+ export declare function applyPlugins(md: MarkdownIt, plugins: LoadedPlugin[]): void;
108
+ /**
109
+ * Collect CSS from all loaded plugins, concatenated in load order.
110
+ */
111
+ export declare function collectPluginCss(plugins: LoadedPlugin[]): string;
@@ -0,0 +1,33 @@
1
+ export interface NpmPluginInstallLimits {
2
+ metadataBytes: number;
3
+ packageTarballBytes: number;
4
+ totalNetworkBytes: number;
5
+ packageFileBytes: number;
6
+ totalUnpackedBytes: number;
7
+ totalFiles: number;
8
+ totalPackages: number;
9
+ dependencyDepth: number;
10
+ }
11
+ type FetchFn = typeof globalThis.fetch;
12
+ export interface NpmPluginInstallOptions {
13
+ /** Dependency injection for focused tests; production uses global fetch. */
14
+ fetch?: FetchFn;
15
+ signal?: AbortSignal;
16
+ /** Test/specialized-host limits; production defaults stay deliberately hard. */
17
+ limits?: Partial<NpmPluginInstallLimits>;
18
+ }
19
+ export interface InstalledNpmPlugin {
20
+ name: string;
21
+ version: string;
22
+ installRoot: string;
23
+ /** Previous same-version directory held until the manifest commits. */
24
+ backupRoot: string | null;
25
+ warnings: string[];
26
+ }
27
+ /** Download and publish a fresh, receipt-backed vendor tree. Never reuses bytes. */
28
+ export declare function installNpmPlugin(projectDirInput: string, packageSpec: string, options?: NpmPluginInstallOptions): Promise<InstalledNpmPlugin>;
29
+ /** Finish a successful vendor+manifest transaction. */
30
+ export declare function finalizeNpmPluginInstall(installed: InstalledNpmPlugin): Promise<void>;
31
+ /** Restore the previous same-version tree (or remove a new one) after failure. */
32
+ export declare function rollbackNpmPluginInstall(installed: InstalledNpmPlugin): Promise<void>;
33
+ export {};
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Open a file in the user's default OS desktop. Detached + unref'd so the
3
+ * caller can exit immediately without waiting on the desktop process.
4
+ */
5
+ export declare function openPath(filePath: string): Promise<void>;