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,67 @@
1
+ /**
2
+ * Server lifecycle management
3
+ *
4
+ * Handles startup, restart, shutdown, and client connection tracking.
5
+ * Uses the simplified manifest + config pipeline from lib/manifest.
6
+ */
7
+ import type { ResolvedConfig } from '../schema/manifest.types';
8
+ import type { ServerState } from './server-context';
9
+ /**
10
+ * Initialize the preview's temp directory.
11
+ *
12
+ * SERVE-IN-PLACE (this replaces the old whole-tree `copyDirectory(inputPath,
13
+ * tempDir)` + manifest-asset `copyAssets` call): the temp dir is no longer a
14
+ * mirror of the project. It holds ONLY files gutterpress itself generates — right
15
+ * now that's `book.html` (written later by {@link generateAndWriteHtml}) and
16
+ * the PID marker file below. Every other path the served HTML asks for
17
+ * (images, anything else under the project) is read straight from the
18
+ * project directory by the HTTP server (see http-server.ts) — the project is
19
+ * never copied anywhere.
20
+ *
21
+ * This is what makes preview asset resolution identical to the build's BY
22
+ * CONSTRUCTION: both read the same real files off the same real project tree,
23
+ * so there is no separate copy step that can drift from what a build actually
24
+ * ships (the "works in preview, broken in the PDF" bug class). It also means
25
+ * a project's `.env`, `.git`, or any other dotfile is never duplicated into a
26
+ * world-readable temp dir the way the old whole-tree copy did — see
27
+ * http-server.ts's dotfile guard, which is what stands between a request and
28
+ * the project's real dotfiles now that the project is served directly.
29
+ *
30
+ * No longer takes `inputPath`/`config` — both were needed only for the copy
31
+ * steps removed above, and there is nothing left to configure here.
32
+ */
33
+ export declare function initializePreviewDirectories(): Promise<string>;
34
+ /**
35
+ * Validate that the input path exists on the filesystem.
36
+ * No-op for empty input (no-input mode — the desktop desktop app
37
+ * supplies the path via its own folder picker).
38
+ */
39
+ export declare function validateInputPath(inputPath: string): Promise<void>;
40
+ /**
41
+ * Initialize configuration by loading manifest and resolving config.
42
+ * For empty input (no-input mode), skip manifest loading entirely and
43
+ * return a default resolved config.
44
+ */
45
+ export declare function initializeConfiguration(inputPath: string): Promise<ResolvedConfig>;
46
+ /**
47
+ * Restart the preview server with a new input directory.
48
+ *
49
+ * SERVE-IN-PLACE makes this trivially correct where the old copy-based
50
+ * version was not: the HTTP server (http-server.ts) reads `state.
51
+ * currentInputPath` fresh on every request instead of serving a stale mirror,
52
+ * so repointing that one field IS the switch — there is no per-project copy
53
+ * to redo, and therefore no old project's files left behind in the (now
54
+ * shared-nothing, generated-files-only) temp dir the way the previous
55
+ * `copyDirectory(newInputPath, state.tempDir)` could leave a stale mix of two
56
+ * projects' content if it partially failed.
57
+ */
58
+ export declare function restartPreview(newInputPath: string, state: ServerState): Promise<void>;
59
+ /**
60
+ * Perform graceful server shutdown and cleanup.
61
+ *
62
+ * Each step runs independently so that a hang or throw in one (e.g.
63
+ * `previewServer.close()` blocking on a stuck WebSocket client) cannot
64
+ * prevent the temp-dir from being removed. Without this discipline,
65
+ * SIGTERM during a wedged close leaks ~1GB of `/tmp` per session.
66
+ */
67
+ export declare function shutdownServer(state: ServerState): Promise<void>;
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Preview server context and state management
3
+ */
4
+ import type { FSWatcher } from 'chokidar';
5
+ import type { PreviewServerOptions } from '../types';
6
+ import type { ResolvedConfig } from '../schema/manifest.types';
7
+ import type { PreviewServer } from './http-server';
8
+ /**
9
+ * Server lifecycle state
10
+ */
11
+ export interface ServerState {
12
+ /** Current input directory being previewed */
13
+ currentInputPath: string;
14
+ /** File watcher instance */
15
+ currentWatcher: FSWatcher | null;
16
+ /** Pending debounced rebuild timer scheduled by the file watcher */
17
+ rebuildTimer: NodeJS.Timeout | null;
18
+ /** Is currently rebuilding? (prevents overlapping builds) */
19
+ isRebuilding: boolean;
20
+ /** Active rebuild, awaited before a project restart closes its watcher. */
21
+ rebuildPromise?: Promise<void> | null;
22
+ /** node:http + `ws` preview HTTP/WebSocket server instance */
23
+ previewServer: PreviewServer | null;
24
+ /** Is server shutting down? (prevents multiple shutdown calls) */
25
+ isShuttingDown: boolean;
26
+ /** Temporary directory for preview files */
27
+ tempDir: string;
28
+ /** Resolved configuration */
29
+ config: ResolvedConfig;
30
+ /** Server options */
31
+ options: PreviewServerOptions;
32
+ }
33
+ /**
34
+ * Create initial server state
35
+ */
36
+ export declare function createServerState(inputPath: string, tempDir: string, config: ResolvedConfig, options: PreviewServerOptions): ServerState;
@@ -0,0 +1,102 @@
1
+ import {
2
+ previewArgs
3
+ } from "./cli-506tg37g.js";
4
+ import {
5
+ openPath,
6
+ runBuild,
7
+ splitOutPath,
8
+ startPreviewServer
9
+ } from "./cli-7ykx7pp0.js";
10
+ import {
11
+ log
12
+ } from "./cli-h7phg3ka.js";
13
+ import {
14
+ BuildError,
15
+ UsageError,
16
+ parseFormat,
17
+ parsePdfxFlavor,
18
+ rejectExtraPositionals,
19
+ rejectUnknownFlags,
20
+ resolvePort
21
+ } from "./cli-hvqjs342.js";
22
+ import"./cli-5bxx0c4y.js";
23
+ import"./cli-1tyj4bk3.js";
24
+ import"./cli-yja077f6.js";
25
+ import"./cli-37x76zdn.js";
26
+
27
+ // src/commands/preview.ts
28
+ import { defineCommand } from "citty";
29
+ import path from "node:path";
30
+ import fs from "node:fs";
31
+ var preview_default = defineCommand({
32
+ meta: { name: "preview", description: "Live HTML preview with HMR (default), or one-shot build + open for --format pdf|pdfx" },
33
+ args: previewArgs,
34
+ async run({ args, rawArgs }) {
35
+ try {
36
+ rejectUnknownFlags(rawArgs, previewArgs, "preview");
37
+ rejectExtraPositionals(args._, 1, "preview");
38
+ const format = parseFormat(args.format, { default: "html" });
39
+ log.info(`Format: ${format}`);
40
+ const inputPath = args.input ? path.resolve(args.input) : undefined;
41
+ if (inputPath !== undefined) {
42
+ if (!fs.existsSync(inputPath) || !fs.statSync(inputPath).isDirectory()) {
43
+ throw new UsageError(`Input directory does not exist: ${inputPath}`);
44
+ }
45
+ }
46
+ const openFlag = args.open;
47
+ if (format === "html") {
48
+ if (typeof args.manifest === "string") {
49
+ throw new UsageError("--manifest is only supported by preview --format pdf or pdfx; live HTML preview discovers the project manifest from its input directory.");
50
+ }
51
+ await startPreviewServer({
52
+ input: inputPath,
53
+ port: resolvePort(args.port),
54
+ host: args.host || "127.0.0.1",
55
+ noWatch: args.watch === false,
56
+ verbose: !!args.verbose,
57
+ openBrowser: openFlag,
58
+ debug: !!args.debug
59
+ });
60
+ return;
61
+ }
62
+ if (inputPath === undefined) {
63
+ throw new UsageError(`--format ${format} requires an input directory.`);
64
+ }
65
+ const pdfxFlavor = parsePdfxFlavor(args["pdfx-flavor"], format);
66
+ const { outDir, pdfFileOverride } = splitOutPath(typeof args.out === "string" ? args.out : undefined, format);
67
+ const result = await runBuild({
68
+ inputDir: inputPath,
69
+ format,
70
+ outDir,
71
+ pdfFileOverride,
72
+ pdfxFlavor,
73
+ iccPath: typeof args.icc === "string" ? args.icc : undefined,
74
+ manifestPath: typeof args.manifest === "string" ? args.manifest : undefined,
75
+ stripAnnotations: typeof args["strip-annotations"] === "boolean" ? args["strip-annotations"] : undefined,
76
+ skipLint: !!args["skip-lint"],
77
+ skipPreValidate: !!args["skip-pre-validate"],
78
+ skipPostValidate: !!args["skip-post-validate"],
79
+ rawArgs: args
80
+ });
81
+ if (openFlag && result.pdfPath) {
82
+ log.info(`Opening ${result.pdfPath}`);
83
+ try {
84
+ await openPath(result.pdfPath);
85
+ } catch (error) {
86
+ const reason = error instanceof Error ? `: ${error.message}` : "";
87
+ log.warn(`Could not open the PDF automatically${reason}. Open it manually: ${result.pdfPath}`);
88
+ }
89
+ }
90
+ } catch (error) {
91
+ if (error instanceof UsageError || error instanceof BuildError) {
92
+ log.error(error.message);
93
+ process.exit(error.exitCode);
94
+ }
95
+ throw error;
96
+ }
97
+ }
98
+ });
99
+ export {
100
+ resolvePort,
101
+ preview_default as default
102
+ };
@@ -0,0 +1,155 @@
1
+ // Gutterpress preview shell controller (shared by the CLI preview and Electron).
2
+ // Every source change takes one correctness-first path: paginate a fresh hidden
3
+ // full document, then swap it in without flashing unpaginated content.
4
+ //
5
+ // TRANSPORT IS ABSTRACTED: change events arrive through connectChanges(), which
6
+ // uses WebSocket by default but honors window.__GUTTERPRESS_CHANGE_SOURCE so an Electron
7
+ // host can feed the same full-reload signal over IPC.
8
+ (function () {
9
+ 'use strict';
10
+ var active = document.getElementById('gutterpress-active');
11
+ var building = null;
12
+ if (!active) return;
13
+
14
+ // Transparent bridge relay: forward host-toolbar commands to the active book
15
+ // iframe and relay its replies/events back to the host.
16
+ window.addEventListener('message', function (e) {
17
+ try {
18
+ if (window.parent !== window && e.source === window.parent) {
19
+ if (active && active.contentWindow) active.contentWindow.postMessage(e.data, '*');
20
+ } else if (active && e.source === active.contentWindow && window.parent !== window) {
21
+ window.parent.postMessage(e.data, '*');
22
+ }
23
+ } catch (_) {}
24
+ });
25
+
26
+ function fdoc(f) { try { return f.contentDocument; } catch (_) { return null; } }
27
+ function fwin(f) { try { return f.contentWindow; } catch (_) { return null; } }
28
+ function chapterOf(el) {
29
+ var chapter = el.closest && el.closest('[data-chapter-src]');
30
+ return chapter ? chapter.getAttribute('data-chapter-src') : null;
31
+ }
32
+ function blocksInChapter(d, chapter) {
33
+ var all = d.querySelectorAll('[data-source-line]');
34
+ if (!chapter) return all;
35
+ var matched = [];
36
+ for (var i = 0; i < all.length; i++) {
37
+ if (chapterOf(all[i]) === chapter) matched.push(all[i]);
38
+ }
39
+ return matched;
40
+ }
41
+
42
+ // data-source-line resets per source file, so preserve both chapter and line.
43
+ function capture(f) {
44
+ var d = fdoc(f); if (!d) return null;
45
+ var els = d.querySelectorAll('[data-source-line]'), best = null, bestTop = -Infinity;
46
+ for (var i = 0; i < els.length; i++) {
47
+ var r = els[i].getBoundingClientRect();
48
+ if (r.bottom < 0 || r.height === 0) continue;
49
+ if (r.top <= 80 && r.top > bestTop) { bestTop = r.top; best = els[i]; }
50
+ }
51
+ if (!best) {
52
+ for (var j = 0; j < els.length; j++) {
53
+ var rr = els[j].getBoundingClientRect();
54
+ if (rr.bottom > 0 && rr.height > 0) { best = els[j]; break; }
55
+ }
56
+ }
57
+ if (!best) return null;
58
+ return {
59
+ chapter: chapterOf(best),
60
+ line: best.getAttribute('data-source-line'),
61
+ offset: best.getBoundingClientRect().top
62
+ };
63
+ }
64
+
65
+ function restore(f, anchor) {
66
+ if (!anchor) return;
67
+ var w = fwin(f), d = fdoc(f); if (!w || !d) return;
68
+ var els = blocksInChapter(d, anchor.chapter);
69
+ var wanted = parseInt(anchor.line, 10), el = null, bestDiff = Infinity;
70
+ for (var i = 0; i < els.length; i++) {
71
+ var line = parseInt(els[i].getAttribute('data-source-line'), 10);
72
+ if (String(els[i].getAttribute('data-source-line')) === String(anchor.line)) {
73
+ el = els[i];
74
+ break;
75
+ }
76
+ var diff = Math.abs(line - wanted);
77
+ if (diff < bestDiff) { bestDiff = diff; el = els[i]; }
78
+ }
79
+ if (el) w.scrollBy(0, el.getBoundingClientRect().top - anchor.offset);
80
+ }
81
+
82
+ function onReady(f, callback) {
83
+ var w = fwin(f), d = fdoc(f); if (!w || !d) { callback(); return; }
84
+ var hasPaged = !!d.querySelector('script[src*="paged.polyfill"], script[src*="pagedjs"]');
85
+ if (hasPaged) {
86
+ var done = false;
87
+ var finish = function () { if (!done) { done = true; callback(); } };
88
+ w.addEventListener('renderingComplete', finish, { once: true });
89
+ setTimeout(finish, 180000);
90
+ return;
91
+ }
92
+ var attempts = 0;
93
+ (function poll() {
94
+ var current = fdoc(f);
95
+ if (current && current.querySelectorAll('.pagedjs_page').length > 0) { callback(); return; }
96
+ if (attempts++ < 800) setTimeout(poll, 25); else callback();
97
+ })();
98
+ }
99
+
100
+ function swap() {
101
+ // A newer reload invalidates any older hidden pagination. Its callback also
102
+ // checks identity before swapping, so stale work can never win a race.
103
+ if (building && building.parentNode) building.parentNode.removeChild(building);
104
+ building = null;
105
+
106
+ var frame = document.createElement('iframe');
107
+ frame.style.visibility = 'hidden';
108
+ frame.setAttribute('aria-hidden', 'true');
109
+ frame.src = '/book.html?gutterpressshell=1&bust=' + Date.now();
110
+ building = frame;
111
+
112
+ var finished = false;
113
+ function finish() {
114
+ if (finished || building !== frame) return;
115
+ finished = true;
116
+ // Capture at swap time, not rebuild start: the visible frame stays usable
117
+ // while a long book paginates and the user may scroll during that work.
118
+ var anchor = capture(active);
119
+ restore(frame, anchor);
120
+ frame.style.visibility = 'visible';
121
+ frame.removeAttribute('aria-hidden');
122
+ var old = active;
123
+ active = frame;
124
+ building = null;
125
+ requestAnimationFrame(function () {
126
+ requestAnimationFrame(function () {
127
+ if (old && old.parentNode) old.parentNode.removeChild(old);
128
+ });
129
+ });
130
+ }
131
+
132
+ frame.addEventListener('load', function () { onReady(frame, finish); });
133
+ document.body.appendChild(frame);
134
+ }
135
+
136
+ function connectChanges(onMessage) {
137
+ var source = window.__GUTTERPRESS_CHANGE_SOURCE;
138
+ if (source && typeof source.subscribe === 'function') return source.subscribe(onMessage);
139
+ var wsPath = window.__GUTTERPRESS_HMR || '/__gutterpress-hmr';
140
+ var ws = new WebSocket(location.origin.replace(/^http/, 'ws') + wsPath);
141
+ ws.onmessage = function (event) {
142
+ var message;
143
+ try { message = JSON.parse(event.data); } catch (_) { return; }
144
+ onMessage(message);
145
+ };
146
+ return function () { try { ws.close(); } catch (_) {} };
147
+ }
148
+
149
+ connectChanges(function (message) {
150
+ if (!message || !message.type) return;
151
+ // Accept legacy content-update producers, but never perform an isolated
152
+ // chapter splice: a changed boundary can affect every following page.
153
+ if (message.type === 'full-reload' || message.type === 'content-update') swap();
154
+ });
155
+ })();
@@ -0,0 +1,17 @@
1
+ import {
2
+ capabilitiesFor,
3
+ detectProjectSource,
4
+ findEnclosingRepoDir,
5
+ pickSyncRemote,
6
+ repoSubPath,
7
+ syncRemoteFor
8
+ } from "./cli-1tyj4bk3.js";
9
+ import"./cli-37x76zdn.js";
10
+ export {
11
+ syncRemoteFor,
12
+ repoSubPath,
13
+ pickSyncRemote,
14
+ findEnclosingRepoDir,
15
+ detectProjectSource,
16
+ capabilitiesFor
17
+ };
@@ -0,0 +1,233 @@
1
+ import {
2
+ connectPublishProvider,
3
+ listPublishAccounts,
4
+ listPublishProviders,
5
+ openPath,
6
+ publishConnectionStatus,
7
+ publishCredentialKey,
8
+ publishProviderFor,
9
+ runPublish
10
+ } from "./cli-7ykx7pp0.js";
11
+ import {
12
+ FileTokenStore,
13
+ log
14
+ } from "./cli-h7phg3ka.js";
15
+ import {
16
+ EXIT_CODES,
17
+ UsageError,
18
+ rejectExtraPositionals,
19
+ rejectUnknownFlags
20
+ } from "./cli-hvqjs342.js";
21
+ import"./cli-5bxx0c4y.js";
22
+ import"./cli-1tyj4bk3.js";
23
+ import"./cli-yja077f6.js";
24
+ import"./cli-37x76zdn.js";
25
+
26
+ // src/commands/publish.ts
27
+ import { defineCommand } from "citty";
28
+ import path from "node:path";
29
+ async function readTokenFromStdin() {
30
+ if (process.stdin.isTTY)
31
+ return "";
32
+ let data = "";
33
+ for await (const chunk of process.stdin)
34
+ data += chunk;
35
+ return data.trim();
36
+ }
37
+ function emitResult(result, json) {
38
+ if (json) {
39
+ console.log(JSON.stringify(result, null, 2));
40
+ return;
41
+ }
42
+ for (const issue of result.issues) {
43
+ const line = `[${issue.id}] ${issue.message}`;
44
+ if (issue.severity === "error")
45
+ log.error(line);
46
+ else if (issue.severity === "warning")
47
+ log.warn(line);
48
+ else
49
+ log.info(line);
50
+ }
51
+ if (!result.ok) {
52
+ log.error(result.error ?? "Publish failed.");
53
+ return;
54
+ }
55
+ const outcome = result.outcome;
56
+ if (!outcome) {
57
+ log.success("Preflight passed — ready to publish.");
58
+ return;
59
+ }
60
+ if (outcome.kind === "published") {
61
+ log.success(outcome.detail ?? "Published.");
62
+ if (outcome.url)
63
+ log.info(`View it at: ${outcome.url}`);
64
+ for (const step of outcome.followUp ?? [])
65
+ log.info(`Next: ${step}`);
66
+ } else {
67
+ log.success(outcome.detail ?? "Upload package prepared.");
68
+ log.info(`Package folder: ${outcome.packageDir}`);
69
+ log.info(`Upload page: ${outcome.openUrl}`);
70
+ outcome.checklist.forEach((step, i) => log.info(` ${i + 1}. ${step}`));
71
+ }
72
+ }
73
+ var commandArgs = {
74
+ project: {
75
+ type: "positional",
76
+ description: "Project directory (default: cwd)",
77
+ required: false
78
+ },
79
+ provider: {
80
+ type: "string",
81
+ description: "Provider id: itch | drivethrurpg | kdp | azure-swa | shopify"
82
+ },
83
+ list: { type: "boolean", description: "List providers and connection status" },
84
+ connect: {
85
+ type: "boolean",
86
+ description: "Store an API key for --provider (from --token, the provider's env var, or piped stdin)"
87
+ },
88
+ disconnect: { type: "boolean", description: "Forget the stored key for --provider" },
89
+ account: {
90
+ type: "string",
91
+ description: "Named-credential label for --connect/--disconnect, so you can keep several accounts per provider (e.g. --account studio). Omit for the default account."
92
+ },
93
+ token: {
94
+ type: "string",
95
+ description: "API key for --connect (prefer piping via stdin or the provider env var to keep it out of shell history)"
96
+ },
97
+ file: {
98
+ type: "string",
99
+ description: "Artifact to publish (PDF path, or HTML export dir). Default: the manifest's output location"
100
+ },
101
+ manifest: { type: "string", description: "Path to manifest.yaml" },
102
+ "dry-run": { type: "boolean", description: "Preflight only; don't contact the platform" },
103
+ json: { type: "boolean", description: "Machine-readable JSON output (CI)" },
104
+ open: {
105
+ type: "boolean",
106
+ description: "Open the result page / guided upload page in the browser"
107
+ }
108
+ };
109
+ var publish_default = defineCommand({
110
+ meta: {
111
+ name: "publish",
112
+ description: "Publish the built PDF/HTML to a platform (itch.io, DriveThruRPG, Amazon KDP, Azure Static Web Apps, Shopify)"
113
+ },
114
+ args: commandArgs,
115
+ async run({ args, rawArgs }) {
116
+ try {
117
+ rejectUnknownFlags(rawArgs, commandArgs, "publish");
118
+ rejectExtraPositionals(args._, 1, "publish");
119
+ } catch (error) {
120
+ if (error instanceof UsageError) {
121
+ log.error(error.message);
122
+ process.exit(error.exitCode);
123
+ }
124
+ throw error;
125
+ }
126
+ const json = !!args.json;
127
+ const store = new FileTokenStore;
128
+ const deps = {
129
+ tokenStore: store,
130
+ onProgress: json ? undefined : (line) => log.info(line)
131
+ };
132
+ if (args.list) {
133
+ const providers = listPublishProviders();
134
+ const rows = await Promise.all(providers.map(async (p) => {
135
+ const status = await publishConnectionStatus(p, deps);
136
+ const accounts = p.credential.required ? await listPublishAccounts(p, deps) : [];
137
+ return {
138
+ id: p.id,
139
+ label: p.label,
140
+ kind: p.kind,
141
+ format: p.format,
142
+ connected: status.connected,
143
+ accounts
144
+ };
145
+ }));
146
+ if (json) {
147
+ console.log(JSON.stringify(rows, null, 2));
148
+ } else {
149
+ for (const r of rows) {
150
+ const status = r.kind === "guided" ? "no key needed" : r.connected ? "connected" : "not connected";
151
+ log.info(`${r.id.padEnd(13)} ${r.label.padEnd(22)} ${r.kind.padEnd(6)} ${r.format.padEnd(4)} ${status}`);
152
+ for (const acc of r.accounts) {
153
+ log.info(` • ${acc.account ? acc.account : "(default)"}`);
154
+ }
155
+ }
156
+ }
157
+ return;
158
+ }
159
+ const providerId = typeof args.provider === "string" ? args.provider : "";
160
+ if (!providerId) {
161
+ log.error("Specify a provider: gutterpress publish --provider <itch|drivethrurpg|kdp|azure-swa|shopify> (or --list).");
162
+ process.exit(EXIT_CODES.USAGE);
163
+ }
164
+ let provider;
165
+ try {
166
+ provider = publishProviderFor(providerId);
167
+ } catch (e) {
168
+ log.error(e instanceof Error ? e.message : String(e));
169
+ process.exit(EXIT_CODES.USAGE);
170
+ }
171
+ const projectDir = path.resolve(args.project ?? ".");
172
+ const account = typeof args.account === "string" ? args.account.trim() : "";
173
+ if (args.disconnect) {
174
+ await store.delete(publishCredentialKey(provider.info.credential.host, account));
175
+ log.success(`Disconnected ${provider.info.label}${account ? ` (${account})` : ""}.`);
176
+ return;
177
+ }
178
+ if (args.connect) {
179
+ if (!provider.info.credential.required) {
180
+ log.info(`${provider.info.label} is a guided provider — no API key needed. Just run: gutterpress publish --provider ${provider.info.id}`);
181
+ return;
182
+ }
183
+ const envVar = provider.info.credential.envVar;
184
+ const token = typeof args.token === "string" && args.token.trim() || envVar && process.env[envVar]?.trim() || await readTokenFromStdin();
185
+ if (!token) {
186
+ log.error(`No API key given. Pass --token, set ${envVar ?? "the provider env var"}, or pipe the key via stdin.` + (provider.info.credential.tokenUrl ? `
187
+ Create one at: ${provider.info.credential.tokenUrl}` : ""));
188
+ process.exit(EXIT_CODES.USAGE);
189
+ }
190
+ try {
191
+ await connectPublishProvider({
192
+ projectDir,
193
+ providerId: provider.info.id,
194
+ token,
195
+ ...account ? { account } : {},
196
+ manifestPath: typeof args.manifest === "string" ? args.manifest : undefined
197
+ }, deps);
198
+ } catch (e) {
199
+ log.error(e instanceof Error ? e.message : String(e));
200
+ process.exit(e instanceof UsageError ? e.exitCode : EXIT_CODES.FINDINGS);
201
+ }
202
+ log.success(`Connected ${provider.info.label}${account ? ` (${account})` : ""}. The key is stored in your user config, not the project.`);
203
+ return;
204
+ }
205
+ let result;
206
+ try {
207
+ result = await runPublish({
208
+ projectDir,
209
+ providerId: provider.info.id,
210
+ manifestPath: typeof args.manifest === "string" ? args.manifest : undefined,
211
+ artifactPath: typeof args.file === "string" ? args.file : undefined,
212
+ dryRun: !!args["dry-run"]
213
+ }, deps);
214
+ } catch (e) {
215
+ if (e instanceof UsageError) {
216
+ log.error(e.message);
217
+ process.exit(e.exitCode);
218
+ }
219
+ throw e;
220
+ }
221
+ emitResult(result, json);
222
+ if (result.ok && args.open && result.outcome) {
223
+ const target = result.outcome.kind === "guided" ? result.outcome.openUrl : result.outcome.url;
224
+ if (target)
225
+ await openPath(target).catch(() => {});
226
+ }
227
+ if (!result.ok)
228
+ process.exit(EXIT_CODES.FINDINGS);
229
+ }
230
+ });
231
+ export {
232
+ publish_default as default
233
+ };
@@ -0,0 +1,20 @@
1
+ /**
2
+ * gutterpress/render — the PURE, node-free render core.
3
+ *
4
+ * §1/§8 / ADR 0004: this entry deliberately exposes ONLY the browser-safe
5
+ * markdown→HTML→book.html pieces. It transitively imports markdown-it + its
6
+ * plugins, the inlined `markdown-it-paged.js`, and pure helpers — and NOTHING
7
+ * from `node:*`/`fs`/`path`/`url`. This is what the desktop's WebAdapter imports
8
+ * (a *value* import that stays PWA-clean), so the in-browser live preview (#33)
9
+ * can render the opened project entirely client-side with no localhost server
10
+ * and no puppeteer.
11
+ *
12
+ * The CLI build path keeps using `renderChapters` / `renderChaptersToFile` from
13
+ * `./lib/markdown/index.ts` (the node wrapper around this same core).
14
+ */
15
+ export { assembleBookHtml } from "./lib/markdown/assemble";
16
+ export type { AssembleBookHtmlOptions, ReadText, } from "./lib/markdown/assemble";
17
+ export { createMarkdownRenderer, collectPluginCss, applyPlugins } from "./lib/markdown/renderer";
18
+ export type { LoadedPlugin, GutterpressPlugin, GutterpressPluginMetadata, GutterpressPluginExport, } from "./lib/markdown/renderer";
19
+ export { PAGED_CSS } from "./lib/markdown/markdown-it-paged.js";
20
+ export { PAGEDJS_VERSION, PAGEDJS_POLYFILL_MARKER, pagedjsPolyfillTag, pagedjsPolyfillTagRegex, } from "./lib/pagedjs-marker";