gutterpress 0.10.4 → 0.10.5

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 (38) hide show
  1. package/README.md +7 -3
  2. package/dist/api/index.d.ts +7 -3
  3. package/dist/api/index.js +24 -2
  4. package/dist/{audit-6gsbjcyp.js → audit-ax5ps29k.js} +4 -4
  5. package/dist/{build-8gx7gkgw.js → build-79dv44cn.js} +4 -4
  6. package/dist/{cli-7hay1r0h.js → cli-0t4zfevc.js} +1 -1
  7. package/dist/{cli-h617210r.js → cli-5pq315qe.js} +1 -1
  8. package/dist/{cli-zddg7r27.js → cli-chkwtg9m.js} +928 -74
  9. package/dist/{cli-d613m9n5.js → cli-v031r2h6.js} +1 -1
  10. package/dist/cli.js +14 -14
  11. package/dist/{doctor-mrqpw7g3.js → doctor-qejmbv32.js} +2 -2
  12. package/dist/{engine-dzrzyyew.js → engine-fwe8djyn.js} +1 -1
  13. package/dist/{engine-pta3yeyt.js → engine-mtyjc4v6.js} +2 -2
  14. package/dist/{index-cm4dywtk.js → index-ja0p4w5f.js} +1 -1
  15. package/dist/{index-p4yq14qw.js → index-k5hcp8wj.js} +1 -1
  16. package/dist/{index-1z8a090c.js → index-ya1yw5me.js} +972 -120
  17. package/dist/index.js +25 -3
  18. package/dist/lib/markdown/gutterpress-css.d.ts +10 -2
  19. package/dist/lib/open-path.d.ts +27 -0
  20. package/dist/lib/publish/connect-google.d.ts +34 -0
  21. package/dist/lib/publish/connect.d.ts +23 -0
  22. package/dist/lib/publish/google-auth.d.ts +104 -0
  23. package/dist/lib/publish/google-drive.d.ts +88 -0
  24. package/dist/lib/publish/google-errors.d.ts +49 -0
  25. package/dist/lib/publish/providers/gdrive.d.ts +25 -0
  26. package/dist/lib/publish/run-publish.d.ts +14 -1
  27. package/dist/lib/publish/types.d.ts +46 -2
  28. package/dist/lib/remote-auth/token-store.d.ts +1 -1
  29. package/dist/{lint-gmymvnm3.js → lint-wweg6pf0.js} +4 -4
  30. package/dist/{manifest.schema-084rxtwp.json → manifest.schema-hn6ac0ae.json} +25 -0
  31. package/dist/{new-hw7s7jne.js → new-yf8emyp3.js} +4 -4
  32. package/dist/{plugin-0qtfgjr2.js → plugin-dj6crat4.js} +4 -4
  33. package/dist/{preflight-j99dpj5e.js → preflight-d34pzgr6.js} +4 -4
  34. package/dist/{preview-sc3rcrkh.js → preview-g2f5982y.js} +4 -4
  35. package/dist/{publish-xwrwvrh0.js → publish-6vt6yqm4.js} +58 -9
  36. package/dist/schema/manifest.types.d.ts +20 -0
  37. package/dist/{validate-evzfg9m6.js → validate-vjwgxswp.js} +4 -4
  38. package/package.json +1 -1
@@ -524,6 +524,31 @@
524
524
  "description": "Label of the saved credential to use when more than one is stored for this provider."
525
525
  }
526
526
  }
527
+ },
528
+ "gdrive": {
529
+ "type": "object",
530
+ "description": "Google Drive publishing (uploads the finished PDF or zipped HTML export to a Drive folder)",
531
+ "properties": {
532
+ "folder": {
533
+ "type": "string",
534
+ "description": "Drive folder name to find-or-create at My Drive root. Ignored once folderId is recorded.",
535
+ "default": "Gutterpress"
536
+ },
537
+ "folderId": {
538
+ "type": "string",
539
+ "description": "Stable Drive folder id to upload into, picker-set in the desktop app or hand-recorded from the CLI's post-publish tip. Takes precedence over folder when present and the folder still exists."
540
+ },
541
+ "credential": {
542
+ "type": "string",
543
+ "description": "Label of the saved credential to use when more than one Google account is connected. Not a secret — just a reference into the host credential store. Empty or absent uses the default credential."
544
+ },
545
+ "format": {
546
+ "type": "string",
547
+ "description": "Which build output to upload",
548
+ "enum": ["pdf", "html"],
549
+ "default": "pdf"
550
+ }
551
+ }
527
552
  }
528
553
  }
529
554
  },
@@ -5,16 +5,16 @@ import {
5
5
  TARGETS,
6
6
  TARGET_IDS,
7
7
  scaffoldProject
8
- } from "./cli-zddg7r27.js";
8
+ } from "./cli-chkwtg9m.js";
9
9
  import {
10
10
  resolveGhostscript
11
- } from "./cli-h617210r.js";
11
+ } from "./cli-5pq315qe.js";
12
12
  import {
13
13
  UsageError,
14
14
  rejectExtraPositionals,
15
15
  rejectUnknownFlags
16
- } from "./cli-d613m9n5.js";
17
- import"./cli-7hay1r0h.js";
16
+ } from "./cli-v031r2h6.js";
17
+ import"./cli-0t4zfevc.js";
18
18
  import {
19
19
  isToolAvailable
20
20
  } from "./cli-c41yr7he.js";
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  addNpmPlugin,
3
3
  parseNpmPluginSpec
4
- } from "./cli-zddg7r27.js";
5
- import"./cli-h617210r.js";
4
+ } from "./cli-chkwtg9m.js";
5
+ import"./cli-5pq315qe.js";
6
6
  import {
7
7
  UsageError,
8
8
  rejectExtraPositionals,
9
9
  rejectUnknownFlags
10
- } from "./cli-d613m9n5.js";
11
- import"./cli-7hay1r0h.js";
10
+ } from "./cli-v031r2h6.js";
11
+ import"./cli-0t4zfevc.js";
12
12
  import"./cli-c41yr7he.js";
13
13
  import {
14
14
  EXIT_CODES
@@ -2,16 +2,16 @@ import {
2
2
  executeValidation,
3
3
  publishTargetFor,
4
4
  reportMissingTools
5
- } from "./cli-zddg7r27.js";
5
+ } from "./cli-chkwtg9m.js";
6
6
  import {
7
7
  log
8
- } from "./cli-h617210r.js";
8
+ } from "./cli-5pq315qe.js";
9
9
  import {
10
10
  UsageError,
11
11
  rejectExtraPositionals,
12
12
  rejectUnknownFlags
13
- } from "./cli-d613m9n5.js";
14
- import"./cli-7hay1r0h.js";
13
+ } from "./cli-v031r2h6.js";
14
+ import"./cli-0t4zfevc.js";
15
15
  import"./cli-c41yr7he.js";
16
16
  import {
17
17
  EXIT_CODES
@@ -6,10 +6,10 @@ import {
6
6
  runBuild,
7
7
  splitOutPath,
8
8
  startPreviewServer
9
- } from "./cli-zddg7r27.js";
9
+ } from "./cli-chkwtg9m.js";
10
10
  import {
11
11
  log
12
- } from "./cli-h617210r.js";
12
+ } from "./cli-5pq315qe.js";
13
13
  import {
14
14
  UsageError,
15
15
  parseEngine,
@@ -18,8 +18,8 @@ import {
18
18
  rejectExtraPositionals,
19
19
  rejectUnknownFlags,
20
20
  resolvePort
21
- } from "./cli-d613m9n5.js";
22
- import"./cli-7hay1r0h.js";
21
+ } from "./cli-v031r2h6.js";
22
+ import"./cli-0t4zfevc.js";
23
23
  import"./cli-c41yr7he.js";
24
24
  import {
25
25
  BuildError
@@ -1,23 +1,27 @@
1
1
  import {
2
+ connectGoogleDrive,
2
3
  connectPublishProvider,
4
+ disconnectPublishCredential,
3
5
  listPublishAccounts,
4
6
  listPublishProviders,
7
+ loadManifestWithPath,
5
8
  openPath,
6
9
  publishConnectionStatus,
7
10
  publishCredentialKey,
8
11
  publishProviderFor,
12
+ resolvePublishFormat,
9
13
  runPublish
10
- } from "./cli-zddg7r27.js";
14
+ } from "./cli-chkwtg9m.js";
11
15
  import {
12
16
  FileTokenStore,
13
17
  log
14
- } from "./cli-h617210r.js";
18
+ } from "./cli-5pq315qe.js";
15
19
  import {
16
20
  UsageError,
17
21
  rejectExtraPositionals,
18
22
  rejectUnknownFlags
19
- } from "./cli-d613m9n5.js";
20
- import"./cli-7hay1r0h.js";
23
+ } from "./cli-v031r2h6.js";
24
+ import"./cli-0t4zfevc.js";
21
25
  import"./cli-c41yr7he.js";
22
26
  import {
23
27
  EXIT_CODES
@@ -29,6 +33,7 @@ import"./cli-37x76zdn.js";
29
33
  // src/commands/publish.ts
30
34
  import { defineCommand } from "citty";
31
35
  import path from "node:path";
36
+ import { fstatSync } from "node:fs";
32
37
  async function readTokenFromStdin() {
33
38
  if (process.stdin.isTTY)
34
39
  return "";
@@ -37,6 +42,16 @@ async function readTokenFromStdin() {
37
42
  data += chunk;
38
43
  return data.trim();
39
44
  }
45
+ function stdinLooksPiped() {
46
+ if (process.stdin.isTTY)
47
+ return false;
48
+ try {
49
+ const st = fstatSync(0);
50
+ return st.isFIFO() || st.isFile();
51
+ } catch {
52
+ return false;
53
+ }
54
+ }
40
55
  function emitResult(result, json) {
41
56
  if (json) {
42
57
  console.log(JSON.stringify(result, null, 2));
@@ -81,7 +96,7 @@ var commandArgs = {
81
96
  },
82
97
  provider: {
83
98
  type: "string",
84
- description: "Provider id: itch | drivethrurpg | kdp | azure-swa | shopify"
99
+ description: "Provider id: itch | drivethrurpg | kdp | azure-swa | shopify | gdrive"
85
100
  },
86
101
  list: { type: "boolean", description: "List providers and connection status" },
87
102
  connect: {
@@ -112,7 +127,7 @@ var commandArgs = {
112
127
  var publish_default = defineCommand({
113
128
  meta: {
114
129
  name: "publish",
115
- description: "Publish the built PDF/HTML to a platform (itch.io, DriveThruRPG, Amazon KDP, Azure Static Web Apps, Shopify)"
130
+ description: "Publish the built PDF/HTML to a platform (itch.io, DriveThruRPG, Amazon KDP, Azure Static Web Apps, Shopify, Google Drive)"
116
131
  },
117
132
  args: commandArgs,
118
133
  async run({ args, rawArgs }) {
@@ -133,15 +148,25 @@ var publish_default = defineCommand({
133
148
  onProgress: json ? undefined : (line) => log.info(line)
134
149
  };
135
150
  if (args.list) {
151
+ const projectDir2 = path.resolve(args.project ?? ".");
152
+ const manifestArg = typeof args.manifest === "string" ? args.manifest : undefined;
153
+ let publishSettings = {};
154
+ try {
155
+ const { manifest } = await loadManifestWithPath(manifestArg ?? projectDir2, {
156
+ explicit: manifestArg !== undefined
157
+ });
158
+ publishSettings = manifest.publish ?? {};
159
+ } catch {}
136
160
  const providers = listPublishProviders();
137
161
  const rows = await Promise.all(providers.map(async (p) => {
138
162
  const status = await publishConnectionStatus(p, deps);
139
163
  const accounts = p.credential.required ? await listPublishAccounts(p, deps) : [];
164
+ const providerConfig = publishSettings[p.id] ?? {};
140
165
  return {
141
166
  id: p.id,
142
167
  label: p.label,
143
168
  kind: p.kind,
144
- format: p.format,
169
+ format: resolvePublishFormat(p, providerConfig),
145
170
  connected: status.connected,
146
171
  accounts
147
172
  };
@@ -161,7 +186,7 @@ var publish_default = defineCommand({
161
186
  }
162
187
  const providerId = typeof args.provider === "string" ? args.provider : "";
163
188
  if (!providerId) {
164
- log.error("Specify a provider: gutterpress publish --provider <itch|drivethrurpg|kdp|azure-swa|shopify> (or --list).");
189
+ log.error("Specify a provider: gutterpress publish --provider <itch|drivethrurpg|kdp|azure-swa|shopify|gdrive> (or --list).");
165
190
  process.exit(EXIT_CODES.USAGE);
166
191
  }
167
192
  let provider;
@@ -174,7 +199,8 @@ var publish_default = defineCommand({
174
199
  const projectDir = path.resolve(args.project ?? ".");
175
200
  const account = typeof args.account === "string" ? args.account.trim() : "";
176
201
  if (args.disconnect) {
177
- await store.delete(publishCredentialKey(provider.info.credential.host, account));
202
+ const key = publishCredentialKey(provider.info.credential.host, account);
203
+ await disconnectPublishCredential(key, deps, { awaitRevoke: true });
178
204
  log.success(`Disconnected ${provider.info.label}${account ? ` (${account})` : ""}.`);
179
205
  return;
180
206
  }
@@ -183,6 +209,29 @@ var publish_default = defineCommand({
183
209
  log.info(`${provider.info.label} is a guided provider — no API key needed. Just run: gutterpress publish --provider ${provider.info.id}`);
184
210
  return;
185
211
  }
212
+ if (provider.info.credential.connect === "oauth") {
213
+ const envVar2 = provider.info.credential.envVar;
214
+ const tokenGiven = typeof args.token === "string" && args.token.trim().length > 0;
215
+ const envGiven = !!(envVar2 && process.env[envVar2]?.trim());
216
+ const stdinGiven = tokenGiven || envGiven ? false : stdinLooksPiped();
217
+ if (tokenGiven || envGiven || stdinGiven) {
218
+ log.error(`${provider.info.label} connects through your browser, not a pasted key — ` + `drop --token${envVar2 ? ` and unset ${envVar2}` : ""}${stdinGiven ? " and remove the piped input" : ""}, then run ` + `"gutterpress publish --provider ${provider.info.id} --connect".`);
219
+ process.exit(EXIT_CODES.USAGE);
220
+ }
221
+ try {
222
+ const result2 = await connectGoogleDrive({ ...account ? { account } : {} }, deps, {
223
+ onAuthUrl: (url) => {
224
+ log.info("Opening your browser to connect Google Drive…");
225
+ log.info(`If it didn't open, visit: ${url}`);
226
+ }
227
+ });
228
+ log.success(`Connected ${provider.info.label}${account ? ` (${account})` : ""}${result2.email ? ` — ${result2.email}` : ""}.`);
229
+ } catch (e) {
230
+ log.error(e instanceof Error ? e.message : String(e));
231
+ process.exit(EXIT_CODES.FINDINGS);
232
+ }
233
+ return;
234
+ }
186
235
  const envVar = provider.info.credential.envVar;
187
236
  const token = typeof args.token === "string" && args.token.trim() || envVar && process.env[envVar]?.trim() || await readTokenFromStdin();
188
237
  if (!token) {
@@ -59,6 +59,26 @@ interface PublishSettings {
59
59
  /** Saved-credential label to use (see PublishSettings doc). */
60
60
  credential?: string;
61
61
  };
62
+ gdrive?: {
63
+ /** Display name of the target Drive folder; created at My Drive root if
64
+ * missing. Default when unset: "Gutterpress". */
65
+ folder?: string;
66
+ /** Stable Drive folder id (picker-set in the desktop app, or hand-recorded
67
+ * from the CLI's post-publish tip). Takes precedence over `folder` when
68
+ * present and the folder still exists. */
69
+ folderId?: string;
70
+ /** Saved-credential label to use (see PublishSettings doc). */
71
+ credential?: string;
72
+ /**
73
+ * Which build output to publish (#221 phase 3, D8) — gdrive is the one
74
+ * provider that supports more than one. "pdf" (default when unset): the
75
+ * finished PDF. "html": the website export, zipped into one
76
+ * `<title>-website.zip` before upload (Drive is file delivery, not web
77
+ * hosting). An unrecognized value is ignored, not an error — see
78
+ * `run-publish.ts`'s `resolvePublishFormat`.
79
+ */
80
+ format?: "pdf" | "html";
81
+ };
62
82
  }
63
83
  export interface GutterpressManifest {
64
84
  title?: string;
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  executeAndReport
3
- } from "./cli-zddg7r27.js";
3
+ } from "./cli-chkwtg9m.js";
4
4
  import {
5
5
  log
6
- } from "./cli-h617210r.js";
6
+ } from "./cli-5pq315qe.js";
7
7
  import {
8
8
  UsageError,
9
9
  rejectExtraPositionals,
10
10
  rejectUnknownFlags
11
- } from "./cli-d613m9n5.js";
12
- import"./cli-7hay1r0h.js";
11
+ } from "./cli-v031r2h6.js";
12
+ import"./cli-0t4zfevc.js";
13
13
  import"./cli-c41yr7he.js";
14
14
  import {
15
15
  EXIT_CODES
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gutterpress",
3
- "version": "0.10.4",
3
+ "version": "0.10.5",
4
4
  "description": "Markdown-to-PDF converter for professional print layout using a native Chromium print engine and Ghostscript.",
5
5
  "author": "itlackey",
6
6
  "license": "MPL-2.0",