gutterpress 0.11.23-alpha.7 → 0.11.23-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/{README-syg2hn83.md → README-8rct3axy.md} +2 -2
- package/dist/api/index.d.ts +3 -3
- package/dist/api/index.js +7 -5
- package/dist/{build-w572wq10.js → build-dg8a566j.js} +8 -7
- package/dist/{cli-eatdqx3z.js → cli-1fy1pm9d.js} +1 -1
- package/dist/cli-65gy8ask.js +82 -0
- package/dist/{cli-3cvq3n1c.js → cli-989eg8jz.js} +186 -83
- package/dist/{cli-6pv84kf3.js → cli-e31jshz6.js} +6 -84
- package/dist/{cli-58fsk6d7.js → cli-k087gj0p.js} +66 -34
- package/dist/{cli-5ba6bm6z.js → cli-s1zt779w.js} +1 -1
- package/dist/{cli-wyg7qstd.js → cli-ttj95aex.js} +3 -3
- package/dist/{cli-mmgtqnmr.js → cli-vhav8g82.js} +1 -1
- package/dist/cli.js +12 -12
- package/dist/{doctor-2f3zqmza.js → doctor-g4a42tcz.js} +3 -3
- package/dist/engine/shared/page-vars.d.ts +32 -0
- package/dist/{engine-4rabsgwq.js → engine-jvkcahr1.js} +2 -1
- package/dist/{engine-wm4fggac.js → engine-wgkaqjsc.js} +3 -3
- package/dist/{ext-0cgky8n3.js → ext-w9d5ftcg.js} +8 -7
- package/dist/{extension-restore-vghc58vx.js → extension-restore-5x4mj79d.js} +3 -3
- package/dist/{extension-restore-e7je32pr.js → extension-restore-as0g38p1.js} +5 -4
- package/dist/{gutterpress-viewer-mafsby5k.js → gutterpress-viewer-ze691rrd.js} +52 -13
- package/dist/{index-2vxzxyyj.js → index-798jt0qc.js} +9 -9
- package/dist/{index-fp7xwvpr.js → index-a4j3xcfp.js} +3 -3
- package/dist/{index-nfysshcc.js → index-c6y0p7jy.js} +249 -139
- package/dist/{index-wm4x7xbf.js → index-fk2kpf2t.js} +58 -26
- package/dist/{index-hphcn7th.js → index-rj5vrhz6.js} +5 -85
- package/dist/index-tayzfr9c.js +99 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +233 -6
- package/dist/lib/book-css.d.ts +56 -0
- package/dist/lib/markdown/assemble.d.ts +58 -0
- package/dist/lib/publish/google-drive.d.ts +12 -4
- package/dist/lib/publish/manifest-publish.d.ts +6 -0
- package/dist/lib/publish/providers/gdrive-folder.d.ts +30 -0
- package/dist/lib/publish/run-publish.d.ts +6 -1
- package/dist/lib/publish/types.d.ts +52 -5
- package/dist/lib/remote-auth/converge-merge.d.ts +3 -3
- package/dist/lib/remote-auth/sync-messages.d.ts +2 -2
- package/dist/lib/root-tokens.d.ts +76 -0
- package/dist/lib/version-changes.d.ts +12 -12
- package/dist/{manifest-79zsgkpn.yaml → manifest-0vwaskj2.yaml} +1 -1
- package/dist/{manifest-2kc56wvw.yaml → manifest-aya31jwt.yaml} +1 -1
- package/dist/{manifest-41ddzm13.yaml → manifest-mffah3hr.yaml} +1 -1
- package/dist/{manifest-sqzm4681.yaml → manifest-wbcv8cbp.yaml} +2 -2
- package/dist/{manifest.schema-93sd7zje.json → manifest.schema-0jgj0jt1.json} +1 -1
- package/dist/{new-88rkrv71.js → new-jtk028rf.js} +8 -7
- package/dist/{page-rules-ytj9p04v.css → page-rules-vnja6grt.css} +2 -2
- package/dist/{plugins-3aj0wc5h.js → plugins-bcbe7xs8.js} +1 -1
- package/dist/{plugins-sprxsz5d.js → plugins-zsm6wv79.js} +3 -3
- package/dist/{preflight-11dg1qkk.js → preflight-cs6mj1d6.js} +8 -7
- package/dist/{preview-nftp782j.js → preview-d1j1g4qf.js} +8 -7
- package/dist/{publish-6tgxfck9.js → publish-7yw4jyrt.js} +24 -8
- package/dist/render.js +65 -24
- package/dist/schema/manifest.types.d.ts +2 -1
- package/dist/{tokens-n82t4k9h.css → tokens-a7grv940.css} +4 -5
- package/dist/{validate-pktqrye5.js → validate-rkcdnzhw.js} +8 -7
- package/package.json +1 -1
- package/dist/index-46ycxe6r.js +0 -18
|
@@ -10,20 +10,13 @@ import {
|
|
|
10
10
|
UsageError,
|
|
11
11
|
addExtension,
|
|
12
12
|
applyDefaultPdfStrictChecks,
|
|
13
|
-
cssLength,
|
|
14
13
|
ensureProjectGitignore,
|
|
15
14
|
extensionConfigFor,
|
|
16
|
-
formatPageSize,
|
|
17
|
-
isNonNegativePoints,
|
|
18
|
-
isPositivePoints,
|
|
19
|
-
judgeRect,
|
|
20
15
|
listProjectExtensions,
|
|
21
16
|
loadManifest,
|
|
22
17
|
loadManifestDoc,
|
|
23
18
|
loadManifestWithPath,
|
|
24
19
|
npmRegistryUrl,
|
|
25
|
-
pageBoxes,
|
|
26
|
-
printAreaMeta,
|
|
27
20
|
publishTargetFor,
|
|
28
21
|
readEntryCss,
|
|
29
22
|
resolveConfig,
|
|
@@ -31,13 +24,12 @@ import {
|
|
|
31
24
|
resolvePort,
|
|
32
25
|
resolveTargets,
|
|
33
26
|
restoreForCommand,
|
|
34
|
-
round3,
|
|
35
27
|
scalarString,
|
|
36
28
|
uniqueExtensionId,
|
|
37
29
|
validatePageMargin,
|
|
38
30
|
withFetchTimeout,
|
|
39
31
|
writeManifestDoc
|
|
40
|
-
} from "./index-
|
|
32
|
+
} from "./index-rj5vrhz6.js";
|
|
41
33
|
import {
|
|
42
34
|
EXTENSION_MANIFEST_FILENAME,
|
|
43
35
|
GUTTERPRESS_CSS,
|
|
@@ -73,7 +65,7 @@ import {
|
|
|
73
65
|
setLogLevel,
|
|
74
66
|
slugify,
|
|
75
67
|
warn
|
|
76
|
-
} from "./index-
|
|
68
|
+
} from "./index-a4j3xcfp.js";
|
|
77
69
|
import {
|
|
78
70
|
blackTextToGray
|
|
79
71
|
} from "./index-ht1bcqdd.js";
|
|
@@ -84,10 +76,18 @@ import {
|
|
|
84
76
|
getAssetPath,
|
|
85
77
|
lastPageMode,
|
|
86
78
|
resolvePage
|
|
87
|
-
} from "./index-
|
|
79
|
+
} from "./index-798jt0qc.js";
|
|
88
80
|
import {
|
|
89
|
-
BuildError
|
|
90
|
-
|
|
81
|
+
BuildError,
|
|
82
|
+
cssLength,
|
|
83
|
+
formatPageSize,
|
|
84
|
+
isNonNegativePoints,
|
|
85
|
+
isPositivePoints,
|
|
86
|
+
judgeRect,
|
|
87
|
+
pageBoxes,
|
|
88
|
+
printAreaMeta,
|
|
89
|
+
round3
|
|
90
|
+
} from "./index-tayzfr9c.js";
|
|
91
91
|
import {
|
|
92
92
|
countLinkAnnotations,
|
|
93
93
|
getImageResolutions,
|
|
@@ -166,8 +166,8 @@ var MSG_OFFLINE = "Your changes are saved on this computer. Gutterpress couldn't
|
|
|
166
166
|
var MSG_AUTH = "The online copy didn't accept the saved sign-in. Sign in again and try again.";
|
|
167
167
|
var MSG_INSECURE_TRANSPORT = "This book's online copy is at an address that isn't secure, so the saved sign-in wasn't sent — sign-ins are never sent over an insecure address. Switch the address to a secure one (starting with https), or to a local loopback address for a server on this computer, to back up.";
|
|
168
168
|
var MSG_BUSY = "The online copy is changing very quickly right now. Your work is saved on this computer — try again in a moment.";
|
|
169
|
-
var MSG_HISTORY_UNREADABLE = `This book's versions can't be read, so backing up can't continue. Your writing is safe — every file is still here on this computer. Use "Repair the online copy"
|
|
170
|
-
var MSG_UNRELATED = `This book and the online copy have no versions in common, so they can't be combined. Either the online copy's address points at a different book, or this book's own versions were lost and started over. Your writing is safe — every file is still here on this computer. Check the online copy's address; if it is correct, use "Repair the online copy"
|
|
169
|
+
var MSG_HISTORY_UNREADABLE = `This book's versions can't be read, so backing up can't continue. Your writing is safe — every file is still here on this computer. Use "Repair the online copy" in Book setup to get versions and backing up working again.`;
|
|
170
|
+
var MSG_UNRELATED = `This book and the online copy have no versions in common, so they can't be combined. Either the online copy's address points at a different book, or this book's own versions were lost and started over. Your writing is safe — every file is still here on this computer. Check the online copy's address; if it is correct, use "Repair the online copy" in Book setup.`;
|
|
171
171
|
var MSG_NO_REMOTE = "This book doesn't have an online copy yet.";
|
|
172
172
|
var MSG_SSH_REMOTE = "This book's online copy uses an SSH address (git@…), which Gutterpress can't back up to. Switch it to the web (HTTPS) address to back up from here.";
|
|
173
173
|
var MSG_NO_BRANCH = "This book isn't on a named revision, so it can't be backed up right now.";
|
|
@@ -202,6 +202,7 @@ function canonicalChapterId(p) {
|
|
|
202
202
|
}
|
|
203
203
|
|
|
204
204
|
// src/lib/markdown/assemble.ts
|
|
205
|
+
import postcss from "postcss";
|
|
205
206
|
function pageGeometryCss(page) {
|
|
206
207
|
if (!page || !isPositivePoints(page.width) || !isPositivePoints(page.height))
|
|
207
208
|
return null;
|
|
@@ -222,6 +223,65 @@ function defaultPageMarginCss(page) {
|
|
|
222
223
|
@page { margin: ${cssLength(DEFAULT_PAGE_MARGIN_PT)}; }
|
|
223
224
|
}`;
|
|
224
225
|
}
|
|
226
|
+
function liftPageRules(css) {
|
|
227
|
+
if (!/@page\b/i.test(css))
|
|
228
|
+
return { layered: css, pages: "" };
|
|
229
|
+
let root;
|
|
230
|
+
try {
|
|
231
|
+
root = postcss.parse(css);
|
|
232
|
+
} catch {
|
|
233
|
+
return { layered: css, pages: "" };
|
|
234
|
+
}
|
|
235
|
+
const found = [];
|
|
236
|
+
root.walkAtRules(/^page$/i, (rule) => {
|
|
237
|
+
found.push(rule);
|
|
238
|
+
});
|
|
239
|
+
const pages = found.map((rule) => {
|
|
240
|
+
let lifted = rule.clone();
|
|
241
|
+
for (let p = rule.parent;p instanceof postcss.AtRule || p instanceof postcss.Rule; p = p.parent) {
|
|
242
|
+
if (p instanceof postcss.AtRule && p.name.toLowerCase() === "layer")
|
|
243
|
+
continue;
|
|
244
|
+
lifted = p.clone({ nodes: [] }).append(lifted);
|
|
245
|
+
}
|
|
246
|
+
rule.remove();
|
|
247
|
+
return lifted.toString();
|
|
248
|
+
});
|
|
249
|
+
return { layered: root.toString(), pages: pages.join(`
|
|
250
|
+
`) };
|
|
251
|
+
}
|
|
252
|
+
var CORE_MARKERS = liftPageRules(`${MARKER_CSS.trim()}
|
|
253
|
+
${TWO_VERSIONS_CSS.trim()}`);
|
|
254
|
+
var CORE_VOCAB = liftPageRules(GUTTERPRESS_CSS.trim());
|
|
255
|
+
function assembleCssChunks(opts) {
|
|
256
|
+
const core = (css) => css ? [{ origin: { kind: "core" }, css }] : [];
|
|
257
|
+
const headed = (title, chunks = []) => chunks.map((chunk, i) => i === 0 ? { ...chunk, css: `/* ${title} */
|
|
258
|
+
${chunk.css.trim()}` } : chunk);
|
|
259
|
+
const pageGeometry = pageGeometryCss(opts.printArea);
|
|
260
|
+
const defaultMargin = defaultPageMarginCss(opts.printArea);
|
|
261
|
+
return [
|
|
262
|
+
...core("@layer gp.marker, gp.vocab;"),
|
|
263
|
+
...core(`/* gutterpress markers */
|
|
264
|
+
@layer gp.marker {
|
|
265
|
+
${CORE_MARKERS.layered.trim()}
|
|
266
|
+
}`),
|
|
267
|
+
...core(CORE_MARKERS.pages && `/* gutterpress markers: page rules */
|
|
268
|
+
${CORE_MARKERS.pages}`),
|
|
269
|
+
...core(`/* gutterpress */
|
|
270
|
+
@layer gp.vocab {
|
|
271
|
+
${CORE_VOCAB.layered.trim()}
|
|
272
|
+
}`),
|
|
273
|
+
...core(CORE_VOCAB.pages && `/* gutterpress: page rules */
|
|
274
|
+
${CORE_VOCAB.pages}`),
|
|
275
|
+
...core(defaultMargin && `/* page margins (default) */
|
|
276
|
+
${defaultMargin}`),
|
|
277
|
+
...headed("extension css", opts.extensions),
|
|
278
|
+
...core(`/* column alignment */
|
|
279
|
+
${TABLE_ALIGN_CSS.trim()}`),
|
|
280
|
+
...headed("project css", opts.book),
|
|
281
|
+
...core(pageGeometry && `/* page geometry (manifest) */
|
|
282
|
+
${pageGeometry}`)
|
|
283
|
+
];
|
|
284
|
+
}
|
|
225
285
|
async function assembleBookHtml(opts) {
|
|
226
286
|
const title = opts.title ?? "Document";
|
|
227
287
|
const projectCss = opts.projectCss ?? "";
|
|
@@ -260,30 +320,11 @@ async function assembleBookHtml(opts) {
|
|
|
260
320
|
imageRefs.add(ref);
|
|
261
321
|
opts.onImageRefs([...imageRefs]);
|
|
262
322
|
}
|
|
263
|
-
const
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
"
|
|
267
|
-
|
|
268
|
-
@layer gp.marker {
|
|
269
|
-
${MARKER_CSS.trim()}
|
|
270
|
-
${TWO_VERSIONS_CSS.trim()}
|
|
271
|
-
}`,
|
|
272
|
-
`/* gutterpress */
|
|
273
|
-
@layer gp.vocab {
|
|
274
|
-
${GUTTERPRESS_CSS.trim()}
|
|
275
|
-
}`,
|
|
276
|
-
defaultMargin ? `/* page margins (default) */
|
|
277
|
-
${defaultMargin}` : null,
|
|
278
|
-
pluginCss ? `/* extension css */
|
|
279
|
-
${pluginCss.trim()}` : null,
|
|
280
|
-
`/* column alignment */
|
|
281
|
-
${TABLE_ALIGN_CSS.trim()}`,
|
|
282
|
-
projectCss ? `/* project css */
|
|
283
|
-
${projectCss.trim()}` : null,
|
|
284
|
-
pageGeometry ? `/* page geometry (manifest) */
|
|
285
|
-
${pageGeometry}` : null
|
|
286
|
-
].filter(Boolean).join(`
|
|
323
|
+
const inlineCss = assembleCssChunks({
|
|
324
|
+
printArea: opts.printArea,
|
|
325
|
+
extensions: pluginCss ? [{ origin: { kind: "extension" }, css: pluginCss }] : [],
|
|
326
|
+
book: projectCss ? [{ origin: { kind: "book" }, css: projectCss }] : []
|
|
327
|
+
}).map((chunk) => chunk.css).join(`
|
|
287
328
|
|
|
288
329
|
`);
|
|
289
330
|
const preloadTags = (opts.preloadImages ?? []).map((href) => `
|
|
@@ -396,7 +437,7 @@ async function listProjectStyles(projectDir, opts = {}) {
|
|
|
396
437
|
import { createHash } from "node:crypto";
|
|
397
438
|
import { readFile } from "node:fs/promises";
|
|
398
439
|
import path2 from "node:path";
|
|
399
|
-
import
|
|
440
|
+
import postcss2 from "postcss";
|
|
400
441
|
var FONT_EXTS = new Set([".woff2", ".woff", ".ttf", ".otf"]);
|
|
401
442
|
var HASHED_ASSET_DIR = "assets";
|
|
402
443
|
var MIME_BY_EXT = {
|
|
@@ -496,15 +537,15 @@ function wrapImportConditions(node, imported) {
|
|
|
496
537
|
const layer = media.match(/\blayer\(([^)]*)\)|\blayer\b/i);
|
|
497
538
|
if (layer) {
|
|
498
539
|
media = media.replace(layer[0], "").trim();
|
|
499
|
-
inner =
|
|
540
|
+
inner = postcss2.atRule({ name: "layer", params: (layer[1] ?? "").trim(), nodes: [inner] });
|
|
500
541
|
}
|
|
501
542
|
const supports = media.match(/\bsupports\(([\s\S]*)\)/i);
|
|
502
543
|
if (supports) {
|
|
503
544
|
media = media.replace(supports[0], "").trim();
|
|
504
|
-
inner =
|
|
545
|
+
inner = postcss2.atRule({ name: "supports", params: (supports[1] ?? "").trim(), nodes: [inner] });
|
|
505
546
|
}
|
|
506
547
|
if (media) {
|
|
507
|
-
inner =
|
|
548
|
+
inner = postcss2.atRule({ name: "media", params: media, nodes: [inner] });
|
|
508
549
|
}
|
|
509
550
|
return inner;
|
|
510
551
|
}
|
|
@@ -526,7 +567,7 @@ async function inlineOne(cssPath, copies, warnings, seen) {
|
|
|
526
567
|
const cssDir = path2.dirname(abs);
|
|
527
568
|
let root;
|
|
528
569
|
try {
|
|
529
|
-
root =
|
|
570
|
+
root = postcss2.parse(source.toString("utf-8"), { from: abs });
|
|
530
571
|
} catch (err) {
|
|
531
572
|
throw new BuildError(`Could not parse CSS: ${abs}
|
|
532
573
|
${err instanceof Error ? err.message : String(err)}`, 1);
|
|
@@ -566,7 +607,7 @@ async function inlineOne(cssPath, copies, warnings, seen) {
|
|
|
566
607
|
for (const { node, target } of imports) {
|
|
567
608
|
const importedAbs = path2.resolve(cssDir, stripUrlSuffix(decodeRef(target)));
|
|
568
609
|
const inlined = await inlineOne(importedAbs, copies, warnings, seen);
|
|
569
|
-
node.replaceWith(wrapImportConditions(node,
|
|
610
|
+
node.replaceWith(wrapImportConditions(node, postcss2.parse(inlined, { from: importedAbs })));
|
|
570
611
|
}
|
|
571
612
|
return root.toString();
|
|
572
613
|
}
|
|
@@ -608,7 +649,7 @@ async function collectStyleDependencies(projectDir, stylePaths) {
|
|
|
608
649
|
}
|
|
609
650
|
let root;
|
|
610
651
|
try {
|
|
611
|
-
root =
|
|
652
|
+
root = postcss2.parse(source, { from: abs });
|
|
612
653
|
} catch {
|
|
613
654
|
return;
|
|
614
655
|
}
|
|
@@ -705,6 +746,7 @@ async function resolveActiveMarkdownFiles(inputDir, configuredFiles) {
|
|
|
705
746
|
async function renderChapters(inputDir, opts = {}) {
|
|
706
747
|
const styles = await resolveActiveStyles(inputDir, opts.styles);
|
|
707
748
|
const inlined = await inlineStyles(inputDir, styles);
|
|
749
|
+
const book = liftPageRules(inlined.css);
|
|
708
750
|
const blocks = [];
|
|
709
751
|
const layers = [];
|
|
710
752
|
const styleWarnings = [];
|
|
@@ -719,10 +761,13 @@ async function renderChapters(inputDir, opts = {}) {
|
|
|
719
761
|
if (!css)
|
|
720
762
|
continue;
|
|
721
763
|
layers.push(group.layer);
|
|
764
|
+
const { layered, pages } = liftPageRules(css);
|
|
722
765
|
blocks.push(`/* ${group.name} */
|
|
723
766
|
@layer ${group.layer} {
|
|
724
|
-
${
|
|
725
|
-
}`
|
|
767
|
+
${layered.trim()}
|
|
768
|
+
}` + (pages ? `
|
|
769
|
+
/* ${group.name}: page rules */
|
|
770
|
+
${pages}` : ""));
|
|
726
771
|
}
|
|
727
772
|
styleWarnings.push(...inlined.warnings);
|
|
728
773
|
if (styleWarnings.length > 0)
|
|
@@ -740,7 +785,8 @@ ${css.trim()}
|
|
|
740
785
|
return assembleBookHtml({
|
|
741
786
|
files,
|
|
742
787
|
readText: (relPath) => readFile2(join(inputDir, canonicalChapterId(relPath)), "utf-8"),
|
|
743
|
-
projectCss:
|
|
788
|
+
projectCss: book.pages ? `${book.layered.trim()}
|
|
789
|
+
${book.pages}` : inlined.css,
|
|
744
790
|
preloadImages: cssAssetCopies.map((c) => c.to),
|
|
745
791
|
title: opts.title,
|
|
746
792
|
language: opts.language,
|
|
@@ -2737,7 +2783,7 @@ registerCheck(check19);
|
|
|
2737
2783
|
import { readFile as readFile11 } from "node:fs/promises";
|
|
2738
2784
|
|
|
2739
2785
|
// src/lib/printsafe.ts
|
|
2740
|
-
import
|
|
2786
|
+
import postcss3 from "postcss";
|
|
2741
2787
|
|
|
2742
2788
|
// src/lib/lint-rules.ts
|
|
2743
2789
|
function ruleLevel(rules, id) {
|
|
@@ -3029,7 +3075,7 @@ function filterFindings(findings, css, rules) {
|
|
|
3029
3075
|
function checkCssRaw(css, from) {
|
|
3030
3076
|
let root;
|
|
3031
3077
|
try {
|
|
3032
|
-
root =
|
|
3078
|
+
root = postcss3.parse(css, from ? { from } : undefined);
|
|
3033
3079
|
} catch (err) {
|
|
3034
3080
|
const e = err;
|
|
3035
3081
|
return [
|
|
@@ -3063,7 +3109,7 @@ function checkCssRaw(css, from) {
|
|
|
3063
3109
|
warnings.push({
|
|
3064
3110
|
rule: rulePageSizeInStylesheet,
|
|
3065
3111
|
severity: "warning",
|
|
3066
|
-
message: `"size" in a stylesheet's @page rule is ignored: the page size comes from the manifest (preset:, or page: width and height —
|
|
3112
|
+
message: `"size" in a stylesheet's @page rule is ignored: the page size comes from the manifest (preset:, or page: width and height — set them in Book setup), which is written after every stylesheet. Remove this declaration; to print at another size, change the manifest.`,
|
|
3067
3113
|
...nodeLoc(decl)
|
|
3068
3114
|
});
|
|
3069
3115
|
return;
|
|
@@ -3199,7 +3245,7 @@ registerCheck(check20);
|
|
|
3199
3245
|
|
|
3200
3246
|
// src/checks/source/css-ownership.ts
|
|
3201
3247
|
import { readFile as readFile12 } from "node:fs/promises";
|
|
3202
|
-
import
|
|
3248
|
+
import postcss4 from "postcss";
|
|
3203
3249
|
import { parse as parseYaml2 } from "yaml";
|
|
3204
3250
|
var CONFIG_NAMES3 = [".gutterpress/css-contract.yaml", ".gutterpress/css-contract.yml"];
|
|
3205
3251
|
async function loadContract(configPath) {
|
|
@@ -3356,7 +3402,7 @@ var check21 = {
|
|
|
3356
3402
|
}
|
|
3357
3403
|
let root;
|
|
3358
3404
|
try {
|
|
3359
|
-
root =
|
|
3405
|
+
root = postcss4.parse(css, { from: absFile });
|
|
3360
3406
|
} catch {
|
|
3361
3407
|
continue;
|
|
3362
3408
|
}
|
|
@@ -3851,7 +3897,7 @@ registerCheck(check25);
|
|
|
3851
3897
|
import { readFile as readFile15 } from "node:fs/promises";
|
|
3852
3898
|
|
|
3853
3899
|
// src/lib/unknown-classes.ts
|
|
3854
|
-
import
|
|
3900
|
+
import postcss5 from "postcss";
|
|
3855
3901
|
var EMITTED = new Set([
|
|
3856
3902
|
"chapter",
|
|
3857
3903
|
"spread",
|
|
@@ -3899,7 +3945,7 @@ function addSelectorClasses(selector, into) {
|
|
|
3899
3945
|
}
|
|
3900
3946
|
function addCssClasses(css, into) {
|
|
3901
3947
|
try {
|
|
3902
|
-
|
|
3948
|
+
postcss5.parse(css).walk((node) => {
|
|
3903
3949
|
if (node.type === "rule")
|
|
3904
3950
|
addSelectorClasses(node.selector, into);
|
|
3905
3951
|
else if (node.type === "atrule") {
|
|
@@ -4097,7 +4143,7 @@ registerCheck(check27);
|
|
|
4097
4143
|
import { readFile as readFile17 } from "node:fs/promises";
|
|
4098
4144
|
|
|
4099
4145
|
// src/checks/source/character-table.ts
|
|
4100
|
-
var CHARACTER_PATTERN = new RegExp("[\\u0000-\\u0008\\u000B\\u000C\\u000E-\\u001F\\u007F-\\u00A0\\u00AD\\u00B4\\u02BC" + "\\u061C\\u2000-\\u2015\\u2018\\u201B-\\u201D\\u201F\\u2022\\u2026" + "\\u2028-\\u202F\\u2032\\u2033\\u205F\\u2060\\u2066-\\u2069\\u2190\\u2192" + "\\u2194\\u21D2\\
|
|
4146
|
+
var CHARACTER_PATTERN = new RegExp("[\\u0000-\\u0008\\u000B\\u000C\\u000E-\\u001F\\u007F-\\u00A0\\u00AD\\u00B4\\u02BC" + "\\u061C\\u2000-\\u2015\\u2018\\u201B-\\u201D\\u201F\\u2022\\u2026" + "\\u2028-\\u202F\\u2032\\u2033\\u205F\\u2060\\u2066-\\u2069\\u2190\\u2192" + "\\u2194\\u21D2\\u25AA\\u25E6\\u2605\\u2713\\u2714\\u2717\\u3000" + "\\uE000-\\uF8FF\\uFEFF\\uFF02\\uFF07\\uFFFD]" + "|\\p{Emoji_Presentation}|\\p{Extended_Pictographic}(?=\\uFE0F)" + "|(?<=[\\p{L}\\p{N}])\\u2019|\\u2019(?![\\p{L}\\p{N}])", "gu");
|
|
4101
4147
|
var NAMED = {
|
|
4102
4148
|
8212: ["Em dash", "typographer", "---"],
|
|
4103
4149
|
8211: ["En dash", "typographer", "--"],
|
|
@@ -4118,7 +4164,6 @@ var NAMED = {
|
|
|
4118
4164
|
8209: ["Non-breaking hyphen", "lookalike", "-"],
|
|
4119
4165
|
8210: ["Figure dash", "lookalike", "-"],
|
|
4120
4166
|
8213: ["Horizontal bar", "lookalike", "---"],
|
|
4121
|
-
8722: ["Minus sign", "lookalike", "-"],
|
|
4122
4167
|
8226: ["Bullet", "symbol", "•"],
|
|
4123
4168
|
9702: ["White bullet", "symbol", "◦"],
|
|
4124
4169
|
9642: ["Small square", "symbol", "▪"],
|
|
@@ -5532,7 +5577,7 @@ class PdfOutput {
|
|
|
5532
5577
|
const rawPdf = pdfxMode ? path7.join(stage, "raw.pdf") : path7.resolve(pdfFile);
|
|
5533
5578
|
await fsp2.mkdir(path7.dirname(path7.resolve(pdfFile)), { recursive: true });
|
|
5534
5579
|
log.info("Rendering HTML to PDF via the Gutterpress engine (native Chromium pagination)");
|
|
5535
|
-
const { buildNativePdf } = await import("./engine-
|
|
5580
|
+
const { buildNativePdf } = await import("./engine-wgkaqjsc.js");
|
|
5536
5581
|
const engineDiagnostics = await buildNativePdf(htmlFile, rawPdf, {
|
|
5537
5582
|
title: config.title,
|
|
5538
5583
|
author: config.authors.length > 0 ? config.authors.join(", ") : undefined,
|
|
@@ -7216,10 +7261,10 @@ function starterOverridesCss() {
|
|
|
7216
7261
|
return `/**
|
|
7217
7262
|
* Your book's own styles. Rules here win over your look's.
|
|
7218
7263
|
*
|
|
7219
|
-
* In the app you rarely need this file:
|
|
7220
|
-
*
|
|
7221
|
-
*
|
|
7222
|
-
*
|
|
7264
|
+
* In the app you rarely need this file: Book setup chooses a look, changes
|
|
7265
|
+
* its fonts and colors (those changes are saved here as :root custom
|
|
7266
|
+
* properties), lists every setting, and sets the page size and margins (in
|
|
7267
|
+
* the manifest).
|
|
7223
7268
|
*
|
|
7224
7269
|
* To change the look from the command line: gutterpress ext remove <old>
|
|
7225
7270
|
* <book>, then gutterpress ext add <look> <book>.
|
|
@@ -8621,7 +8666,7 @@ async function setActiveStyles(projectDir, paths) {
|
|
|
8621
8666
|
import path19 from "node:path";
|
|
8622
8667
|
import { mkdir as mkdir10, readFile as readFile30, writeFile as writeFile12 } from "node:fs/promises";
|
|
8623
8668
|
import git3 from "isomorphic-git";
|
|
8624
|
-
import
|
|
8669
|
+
import postcss6 from "postcss";
|
|
8625
8670
|
|
|
8626
8671
|
// src/lib/remote-auth/transport.ts
|
|
8627
8672
|
import git2 from "isomorphic-git";
|
|
@@ -9087,7 +9132,7 @@ function paragraphs(text) {
|
|
|
9087
9132
|
}
|
|
9088
9133
|
function cssRules(text) {
|
|
9089
9134
|
try {
|
|
9090
|
-
return
|
|
9135
|
+
return postcss6.parse(text).nodes.map((node) => node.toString().trim()).filter((rule) => rule.length > 0);
|
|
9091
9136
|
} catch {
|
|
9092
9137
|
return textLines(text);
|
|
9093
9138
|
}
|
|
@@ -9108,13 +9153,10 @@ function changeHint(filepath, before, after) {
|
|
|
9108
9153
|
}
|
|
9109
9154
|
return count > 0 ? `${plural(count, unit)} changed` : "changed";
|
|
9110
9155
|
}
|
|
9111
|
-
async function
|
|
9112
|
-
const
|
|
9113
|
-
|
|
9114
|
-
}
|
|
9115
|
-
async function listVersionChanges(dir, oid, options = {}) {
|
|
9116
|
-
const cache2 = options.cache ?? {};
|
|
9117
|
-
const parent = await firstParent(dir, cache2, oid);
|
|
9156
|
+
async function listVersionChanges(projectDir, oid) {
|
|
9157
|
+
const dir = await repoDirFor(projectDir);
|
|
9158
|
+
const cache2 = {};
|
|
9159
|
+
const parent = (await git3.readCommit({ fs: gitFs, dir, cache: cache2, oid })).commit.parent[0] ?? null;
|
|
9118
9160
|
const found = [];
|
|
9119
9161
|
await git3.walk({
|
|
9120
9162
|
fs: gitFs,
|
|
@@ -9185,30 +9227,41 @@ async function trackingTip(dir) {
|
|
|
9185
9227
|
}
|
|
9186
9228
|
return resolveOrNull(dir, `refs/remotes/${remote.remote}/${branch}`);
|
|
9187
9229
|
}
|
|
9188
|
-
async function isAncestor(dir, cache2, oid, ancestor) {
|
|
9189
|
-
if (oid === ancestor)
|
|
9190
|
-
return true;
|
|
9191
|
-
try {
|
|
9192
|
-
return await git3.isDescendent({ fs: gitFs, dir, cache: cache2, oid, ancestor });
|
|
9193
|
-
} catch {
|
|
9194
|
-
return false;
|
|
9195
|
-
}
|
|
9196
|
-
}
|
|
9197
9230
|
async function describeVersions(projectDir, entries) {
|
|
9198
9231
|
const dir = await repoDirFor(projectDir);
|
|
9199
|
-
const cache2 = {};
|
|
9200
9232
|
const tip = await trackingTip(dir);
|
|
9233
|
+
if (!tip)
|
|
9234
|
+
return entries.map((entry) => ({ ...entry, backedUp: null }));
|
|
9235
|
+
const cache2 = {};
|
|
9236
|
+
const shallow = await readFile30(path19.join(dir, ".git", "shallow"), "utf8").catch(() => "");
|
|
9237
|
+
const reached = new Set([tip]);
|
|
9238
|
+
const queued = new Set;
|
|
9239
|
+
const queue = [tip];
|
|
9201
9240
|
const out = [];
|
|
9202
9241
|
let olderAreBackedUp = false;
|
|
9203
9242
|
for (const entry of entries) {
|
|
9204
|
-
|
|
9205
|
-
|
|
9206
|
-
|
|
9207
|
-
|
|
9208
|
-
|
|
9209
|
-
|
|
9243
|
+
try {
|
|
9244
|
+
while (!olderAreBackedUp && !reached.has(entry.id) && queue.length > 0) {
|
|
9245
|
+
const oid = queue.shift();
|
|
9246
|
+
const { commit } = await git3.readCommit({ fs: gitFs, dir, cache: cache2, oid });
|
|
9247
|
+
for (const parent of commit.parent)
|
|
9248
|
+
reached.add(parent);
|
|
9249
|
+
if (shallow.includes(oid))
|
|
9250
|
+
continue;
|
|
9251
|
+
for (const parent of commit.parent) {
|
|
9252
|
+
if (queued.has(parent))
|
|
9253
|
+
continue;
|
|
9254
|
+
queued.add(parent);
|
|
9255
|
+
queue.push(parent);
|
|
9256
|
+
}
|
|
9257
|
+
}
|
|
9258
|
+
} catch {
|
|
9259
|
+
queue.length = 0;
|
|
9210
9260
|
}
|
|
9211
|
-
|
|
9261
|
+
const backedUp = olderAreBackedUp || reached.has(entry.id);
|
|
9262
|
+
if (backedUp)
|
|
9263
|
+
olderAreBackedUp = true;
|
|
9264
|
+
out.push({ ...entry, backedUp });
|
|
9212
9265
|
}
|
|
9213
9266
|
return out;
|
|
9214
9267
|
}
|
|
@@ -9258,12 +9311,8 @@ async function listOnlineVersions(options) {
|
|
|
9258
9311
|
const local = await resolveOrNull(dir, branch);
|
|
9259
9312
|
if (!tip || !local)
|
|
9260
9313
|
return { entries: [] };
|
|
9261
|
-
const entries =
|
|
9262
|
-
|
|
9263
|
-
const { files, more } = await listVersionChanges(dir, entry.id, { cache: cache2 });
|
|
9264
|
-
entries.push({ ...entry, changes: files, moreChanges: more, backedUp: true });
|
|
9265
|
-
}
|
|
9266
|
-
return { entries };
|
|
9314
|
+
const entries = await commitsAhead(dir, tip, local, cache2);
|
|
9315
|
+
return { entries: entries.map((entry) => ({ ...entry, backedUp: true })) };
|
|
9267
9316
|
} catch (e) {
|
|
9268
9317
|
const message = e?.message ?? "";
|
|
9269
9318
|
if (message === MSG_NO_REMOTE || message === MSG_SSH_REMOTE)
|
|
@@ -9953,9 +10002,9 @@ function isMergeConflictError(e) {
|
|
|
9953
10002
|
function isCheckoutConflict(e) {
|
|
9954
10003
|
return e?.code === "CheckoutConflictError";
|
|
9955
10004
|
}
|
|
9956
|
-
var CONVERGE_PREPARE_MESSAGE = "Getting your changes ready to combine with the online
|
|
9957
|
-
var CONVERGE_RESTORE_MESSAGE = "Kept both
|
|
9958
|
-
var CONVERGE_MERGE_MESSAGE = "Combined your changes with the online
|
|
10005
|
+
var CONVERGE_PREPARE_MESSAGE = "Getting your changes ready to combine with the online copy's changes";
|
|
10006
|
+
var CONVERGE_RESTORE_MESSAGE = "Kept both takes of the files that can't be combined";
|
|
10007
|
+
var CONVERGE_MERGE_MESSAGE = "Combined your changes with the online copy's";
|
|
9959
10008
|
var MARKER_UNSAFE_EXT = /\.svg$/i;
|
|
9960
10009
|
var OUR_LABEL = YOUR_VERSION_LABEL;
|
|
9961
10010
|
var THEIR_LABEL = ONLINE_VERSION_LABEL;
|
|
@@ -10485,8 +10534,8 @@ var API_BASE3 = "https://api.github.com";
|
|
|
10485
10534
|
var REQUEST_TIMEOUT_MS4 = 15000;
|
|
10486
10535
|
var MAX_NAME_LENGTH = 100;
|
|
10487
10536
|
var MSG = {
|
|
10488
|
-
notConnected: "Connect your GitHub account first
|
|
10489
|
-
auth: "GitHub didn't accept the saved sign-in. Sign in to GitHub again
|
|
10537
|
+
notConnected: "Connect your GitHub account first, then set up the online copy.",
|
|
10538
|
+
auth: "GitHub didn't accept the saved sign-in. Sign in to GitHub again and try again.",
|
|
10490
10539
|
offline: "Gutterpress couldn't reach GitHub. Check your internet connection and try again. Nothing was changed.",
|
|
10491
10540
|
noHistory: "Turn on version history for this book first. The online copy holds the versions Gutterpress keeps on this computer.",
|
|
10492
10541
|
alreadyHasRemote: "This book already has an online copy.",
|
|
@@ -11659,13 +11708,13 @@ async function createFolder(fetchImpl, accessToken, name) {
|
|
|
11659
11708
|
throw await driveFailure(res, `Couldn't create the Google Drive folder "${name}"`);
|
|
11660
11709
|
return await res.json();
|
|
11661
11710
|
}
|
|
11662
|
-
async function
|
|
11711
|
+
async function findFoldersByName(fetchImpl, accessToken, name, limit = 1) {
|
|
11663
11712
|
const q = `name='${escapeDriveQueryValue(name)}' and mimeType='${FOLDER_MIME}' and trashed=false`;
|
|
11664
11713
|
const params = new URLSearchParams({
|
|
11665
11714
|
q,
|
|
11666
11715
|
fields: "files(id,name)",
|
|
11667
11716
|
orderBy: "modifiedTime desc",
|
|
11668
|
-
pageSize:
|
|
11717
|
+
pageSize: String(limit)
|
|
11669
11718
|
});
|
|
11670
11719
|
const res = await driveFetch(fetchImpl, `${DRIVE_API_BASE}/files?${params.toString()}`, {
|
|
11671
11720
|
method: "GET",
|
|
@@ -11674,10 +11723,10 @@ async function findFolderByName(fetchImpl, accessToken, name) {
|
|
|
11674
11723
|
if (!res.ok)
|
|
11675
11724
|
throw await driveFailure(res, `Couldn't look up the Google Drive folder "${name}"`);
|
|
11676
11725
|
const body = await res.json();
|
|
11677
|
-
return body.files
|
|
11726
|
+
return body.files ?? [];
|
|
11678
11727
|
}
|
|
11679
11728
|
async function ensureFolder(fetchImpl, accessToken, name) {
|
|
11680
|
-
const found = await
|
|
11729
|
+
const [found] = await findFoldersByName(fetchImpl, accessToken, name);
|
|
11681
11730
|
if (found)
|
|
11682
11731
|
return found;
|
|
11683
11732
|
return createFolder(fetchImpl, accessToken, name);
|
|
@@ -11810,8 +11859,80 @@ async function resumableUpload(fetchImpl, accessToken, opts) {
|
|
|
11810
11859
|
}
|
|
11811
11860
|
}
|
|
11812
11861
|
|
|
11813
|
-
// src/lib/publish/providers/gdrive.ts
|
|
11862
|
+
// src/lib/publish/providers/gdrive-folder.ts
|
|
11814
11863
|
var DEFAULT_FOLDER_NAME = "Gutterpress";
|
|
11864
|
+
var NO_OWN_FOLDER = { myFolderId: "", myFolder: "", myFolderFor: "", myFolderAccount: "" };
|
|
11865
|
+
function readConfig(req) {
|
|
11866
|
+
const text = (key) => {
|
|
11867
|
+
const value = req.config[key];
|
|
11868
|
+
return (typeof value === "string" ? value.trim() : "") || undefined;
|
|
11869
|
+
};
|
|
11870
|
+
return {
|
|
11871
|
+
folder: text("folder"),
|
|
11872
|
+
folderId: text("folderId"),
|
|
11873
|
+
myFolderId: text("myFolderId"),
|
|
11874
|
+
myFolder: text("myFolder"),
|
|
11875
|
+
myFolderFor: text("myFolderFor"),
|
|
11876
|
+
myFolderAccount: text("myFolderAccount"),
|
|
11877
|
+
account: req.deps.credentialAccount?.trim() ?? ""
|
|
11878
|
+
};
|
|
11879
|
+
}
|
|
11880
|
+
async function resolveFolder(req, accessToken) {
|
|
11881
|
+
const fetchImpl = req.deps.fetch ?? globalThis.fetch;
|
|
11882
|
+
const cfg = readConfig(req);
|
|
11883
|
+
let found = [];
|
|
11884
|
+
if (cfg.folderId) {
|
|
11885
|
+
const folder = await getFolderById(fetchImpl, accessToken, cfg.folderId);
|
|
11886
|
+
if (folder)
|
|
11887
|
+
found = [folder];
|
|
11888
|
+
} else if (cfg.folder) {
|
|
11889
|
+
found = await findFoldersByName(fetchImpl, accessToken, cfg.folder, 2);
|
|
11890
|
+
}
|
|
11891
|
+
const first = found[0];
|
|
11892
|
+
const book = { title: cfg.folder || cfg.folderId || "", reachable: !cfg.folderId || !!first };
|
|
11893
|
+
if (cfg.myFolderId) {
|
|
11894
|
+
const bookKey = cfg.folderId || cfg.folder;
|
|
11895
|
+
if (bookKey && cfg.myFolderFor === bookKey && (cfg.myFolderAccount ?? "") === cfg.account) {
|
|
11896
|
+
const mine = await getFolderById(fetchImpl, accessToken, cfg.myFolderId);
|
|
11897
|
+
return mine ? { state: "mine", destination: toDestination(mine), book } : { state: "unreachable", book, mine: cfg.myFolder || cfg.myFolderId };
|
|
11898
|
+
}
|
|
11899
|
+
if (book.reachable) {
|
|
11900
|
+
await req.deps.selections?.setSettings(req.project.projectDir, "gdrive", NO_OWN_FOLDER);
|
|
11901
|
+
}
|
|
11902
|
+
}
|
|
11903
|
+
if (cfg.folderId) {
|
|
11904
|
+
return first ? { state: "book", destination: toDestination(first) } : { state: "unreachable", book };
|
|
11905
|
+
}
|
|
11906
|
+
if (cfg.folder) {
|
|
11907
|
+
return {
|
|
11908
|
+
state: "by-name",
|
|
11909
|
+
name: cfg.folder,
|
|
11910
|
+
...first ? { destination: toDestination(first) } : {},
|
|
11911
|
+
several: found.length > 1
|
|
11912
|
+
};
|
|
11913
|
+
}
|
|
11914
|
+
return { state: "unset" };
|
|
11915
|
+
}
|
|
11916
|
+
async function uploadFolder(where, fetchImpl, accessToken) {
|
|
11917
|
+
switch (where.state) {
|
|
11918
|
+
case "unreachable":
|
|
11919
|
+
throw new Error(where.mine ? `Your own Drive folder "${where.mine}" for this book can't be reached any more: it was trashed or deleted, or belongs to another Google account. Choose a folder you can reach on the Google Drive step (it is saved for you only).` : `This book publishes to the Drive folder "${where.book.title}", which this Google account can't reach: it isn't shared with Gutterpress under this account, or it was trashed or deleted. The book keeps its folder for everyone else. To publish to a folder you can reach, choose one for yourself on the Google Drive step in the desktop app (saved for you only), or pass --folder-id <id> or --folder <name> to "gutterpress publish" for one run.`);
|
|
11920
|
+
case "unset":
|
|
11921
|
+
return toDestination(await ensureFolder(fetchImpl, accessToken, DEFAULT_FOLDER_NAME));
|
|
11922
|
+
case "by-name":
|
|
11923
|
+
return where.destination ?? toDestination(await createFolder(fetchImpl, accessToken, where.name));
|
|
11924
|
+
default:
|
|
11925
|
+
return where.destination;
|
|
11926
|
+
}
|
|
11927
|
+
}
|
|
11928
|
+
function folderUrl(id) {
|
|
11929
|
+
return `https://drive.google.com/drive/folders/${id}`;
|
|
11930
|
+
}
|
|
11931
|
+
function toDestination(folder) {
|
|
11932
|
+
return { id: folder.id, title: folder.name, url: folderUrl(folder.id) };
|
|
11933
|
+
}
|
|
11934
|
+
|
|
11935
|
+
// src/lib/publish/providers/gdrive.ts
|
|
11815
11936
|
var NOT_CONNECTED_MESSAGE = "Google Drive isn't connected. Run `gutterpress publish --provider gdrive --connect` (or set GDRIVE_REFRESH_TOKEN) first.";
|
|
11816
11937
|
var info5 = {
|
|
11817
11938
|
id: "gdrive",
|
|
@@ -11830,13 +11951,6 @@ var info5 = {
|
|
|
11830
11951
|
},
|
|
11831
11952
|
destinations: { label: "Folder", canCreate: true }
|
|
11832
11953
|
};
|
|
11833
|
-
function readConfig(req) {
|
|
11834
|
-
const cfg = req.config;
|
|
11835
|
-
return {
|
|
11836
|
-
folder: cfg.folder?.trim() || undefined,
|
|
11837
|
-
folderId: cfg.folderId?.trim() || undefined
|
|
11838
|
-
};
|
|
11839
|
-
}
|
|
11840
11954
|
function formatBytes(bytes) {
|
|
11841
11955
|
if (bytes < 1024 * 1024)
|
|
11842
11956
|
return `${(bytes / 1024).toFixed(0)} KB`;
|
|
@@ -11858,22 +11972,6 @@ async function getAccessToken(req) {
|
|
|
11858
11972
|
const accessToken = await mintAccessToken(resolved, req.deps.fetch ?? globalThis.fetch);
|
|
11859
11973
|
return { accessToken, source: resolved.source };
|
|
11860
11974
|
}
|
|
11861
|
-
async function resolveFolder(fetchImpl, accessToken, cfg) {
|
|
11862
|
-
if (cfg.folderId) {
|
|
11863
|
-
const folder = await getFolderById(fetchImpl, accessToken, cfg.folderId);
|
|
11864
|
-
if (!folder) {
|
|
11865
|
-
throw new Error(`The Drive folder recorded in publish.gdrive.folderId ("${cfg.folderId}") can't be found — it may have been trashed or the id copied wrong. Pick the folder again.`);
|
|
11866
|
-
}
|
|
11867
|
-
return folder;
|
|
11868
|
-
}
|
|
11869
|
-
return ensureFolder(fetchImpl, accessToken, cfg.folder || DEFAULT_FOLDER_NAME);
|
|
11870
|
-
}
|
|
11871
|
-
function folderUrl(id) {
|
|
11872
|
-
return `https://drive.google.com/drive/folders/${id}`;
|
|
11873
|
-
}
|
|
11874
|
-
function toDestination(folder) {
|
|
11875
|
-
return { id: folder.id, title: folder.name, url: folderUrl(folder.id) };
|
|
11876
|
-
}
|
|
11877
11975
|
var ZIP_CHUNK_BYTES = 64 * 1024;
|
|
11878
11976
|
function yieldToEventLoop() {
|
|
11879
11977
|
return new Promise((resolve6) => setImmediate(resolve6));
|
|
@@ -12000,9 +12098,12 @@ var gdriveProvider = {
|
|
|
12000
12098
|
const folder = await createFolder(req.deps.fetch ?? globalThis.fetch, accessToken, name);
|
|
12001
12099
|
return toDestination(folder);
|
|
12002
12100
|
},
|
|
12101
|
+
async destinationStatus(req) {
|
|
12102
|
+
const { accessToken } = await getAccessToken(req);
|
|
12103
|
+
return resolveFolder(req, accessToken);
|
|
12104
|
+
},
|
|
12003
12105
|
async upload(req) {
|
|
12004
12106
|
const fetchImpl = req.deps.fetch ?? globalThis.fetch;
|
|
12005
|
-
const cfg = readConfig(req);
|
|
12006
12107
|
const { accessToken } = await getAccessToken(req);
|
|
12007
12108
|
const isHtml = req.artifact.format === "html";
|
|
12008
12109
|
const source = isHtml ? await zipHtmlExport(req.artifact.path, req.project.title, (msg) => req.deps.onProgress?.(msg)) : {
|
|
@@ -12020,10 +12121,11 @@ var gdriveProvider = {
|
|
|
12020
12121
|
}
|
|
12021
12122
|
}
|
|
12022
12123
|
req.deps.onProgress?.("Resolving the Drive folder…");
|
|
12023
|
-
const
|
|
12124
|
+
const where = await resolveFolder(req, accessToken);
|
|
12125
|
+
const folder = await uploadFolder(where, fetchImpl, accessToken);
|
|
12024
12126
|
const fileName = source.fileName;
|
|
12025
12127
|
const existing = await findFileInFolder(fetchImpl, accessToken, folder.id, fileName);
|
|
12026
|
-
req.deps.onProgress?.(existing ? `Updating "${fileName}" in "${folder.
|
|
12128
|
+
req.deps.onProgress?.(existing ? `Updating "${fileName}" in "${folder.title}"…` : `Uploading "${fileName}" to "${folder.title}"…`);
|
|
12027
12129
|
let lastReported = -1;
|
|
12028
12130
|
const file = await resumableUpload(fetchImpl, accessToken, {
|
|
12029
12131
|
...existing ? { fileId: existing.id } : {},
|
|
@@ -12043,11 +12145,11 @@ var gdriveProvider = {
|
|
|
12043
12145
|
return {
|
|
12044
12146
|
kind: "published",
|
|
12045
12147
|
url: file.webViewLink,
|
|
12046
|
-
detail: `Uploaded "${fileName}" to the "${folder.
|
|
12148
|
+
detail: `Uploaded "${fileName}" to the "${folder.title}" folder in your Google Drive${existing ? " (updated the existing file)" : ""}.` + (where.state === "by-name" && where.several ? ` Several of your folders are named "${where.name}"; this is the most recently changed one: ${folder.url}` : ""),
|
|
12047
12149
|
followUp: [
|
|
12048
12150
|
"To share it, open it in Drive and use the Share button — Gutterpress never changes who can see your files.",
|
|
12049
12151
|
isHtml ? "Google Drive stores files, not live websites — download and unzip it to view the export, or publish it as a real site with the Azure Static Web Apps provider." : undefined,
|
|
12050
|
-
|
|
12152
|
+
where.state === "unset" ? `Tip (CLI): record the folder id in the manifest (publish.gdrive.folderId: "${folder.id}") so renaming the folder in Drive can never break publishing.` : undefined
|
|
12051
12153
|
].filter((s) => !!s)
|
|
12052
12154
|
};
|
|
12053
12155
|
} finally {
|
|
@@ -12659,7 +12761,7 @@ async function resolvePublishProvider(id, book) {
|
|
|
12659
12761
|
const ext = await bookExtensions(book);
|
|
12660
12762
|
const npmEntry = ext.extensions.some((c) => !c.path && c.name === id);
|
|
12661
12763
|
if (npmEntry) {
|
|
12662
|
-
const { restoreForCommand: restoreForCommand2 } = await import("./extension-restore-
|
|
12764
|
+
const { restoreForCommand: restoreForCommand2 } = await import("./extension-restore-5x4mj79d.js");
|
|
12663
12765
|
await restoreForCommand2(book.projectDir, { manifestPath: book.manifestPath, failFast: true });
|
|
12664
12766
|
}
|
|
12665
12767
|
const publishers = await discover(ext);
|
|
@@ -12697,7 +12799,7 @@ function infoFor(p) {
|
|
|
12697
12799
|
}
|
|
12698
12800
|
function pluginProvider(p) {
|
|
12699
12801
|
let loading;
|
|
12700
|
-
const load = () => loading ??= import("./plugins-
|
|
12802
|
+
const load = () => loading ??= import("./plugins-bcbe7xs8.js").then((m) => m.loadPublishFunction(p));
|
|
12701
12803
|
return {
|
|
12702
12804
|
info: infoFor(p),
|
|
12703
12805
|
async authenticate() {
|
|
@@ -12766,7 +12868,8 @@ async function requestFor(provider, options, deps) {
|
|
|
12766
12868
|
const publishSettings = manifest.publish ?? {};
|
|
12767
12869
|
const providerConfig = {
|
|
12768
12870
|
...publishSettings[provider.info.id] ?? {},
|
|
12769
|
-
...(await deps.selections?.settings(options.projectDir))?.[provider.info.id] ?? {}
|
|
12871
|
+
...(await deps.selections?.settings(options.projectDir))?.[provider.info.id] ?? {},
|
|
12872
|
+
...options.settings
|
|
12770
12873
|
};
|
|
12771
12874
|
const bookAccount = typeof providerConfig.credential === "string" ? providerConfig.credential.trim() : "";
|
|
12772
12875
|
const effectiveAccount = bookAccount || deps.credentialAccount;
|
|
@@ -13145,19 +13248,26 @@ async function savePublishSettings(projectDir, providerId, values, selections) {
|
|
|
13145
13248
|
if (inside !== null) {
|
|
13146
13249
|
shared[key] = inside;
|
|
13147
13250
|
mine[key] = "";
|
|
13148
|
-
} else if (isDir || key === "credential") {
|
|
13251
|
+
} else if (isDir || key === "credential" || providerId === "gdrive" && key.startsWith("myFolder")) {
|
|
13149
13252
|
mine[key] = isDir && text ? path31.resolve(projectDir, text) : text;
|
|
13150
13253
|
shared[key] = "";
|
|
13151
13254
|
} else {
|
|
13152
13255
|
shared[key] = value;
|
|
13153
13256
|
}
|
|
13154
13257
|
}
|
|
13258
|
+
const inManifest = (await readPublishSettings(projectDir))[providerId] ?? {};
|
|
13259
|
+
if ("myFolderId" in mine) {
|
|
13260
|
+
const own = !!mine.myFolderId;
|
|
13261
|
+
const account = mine.credential ?? (await selections.settings(projectDir))[providerId]?.credential;
|
|
13262
|
+
mine.myFolder = own ? mine.myFolder ?? "" : "";
|
|
13263
|
+
mine.myFolderFor = own ? String(inManifest.folderId || inManifest.folder || "") : "";
|
|
13264
|
+
mine.myFolderAccount = own ? account ?? String(inManifest.credential ?? "") : "";
|
|
13265
|
+
}
|
|
13155
13266
|
if (Object.keys(mine).length > 0)
|
|
13156
13267
|
await selections.setSettings(projectDir, providerId, mine);
|
|
13157
|
-
const inManifest = (await readPublishSettings(projectDir))[providerId] ?? {};
|
|
13158
13268
|
const changes = Object.fromEntries(Object.entries(shared).filter(([key, value]) => value !== "" || (key in inManifest)));
|
|
13159
13269
|
if (Object.keys(changes).length > 0)
|
|
13160
13270
|
await setPublishProviderConfig(projectDir, providerId, changes);
|
|
13161
13271
|
return readPublishSettings(projectDir, selections);
|
|
13162
13272
|
}
|
|
13163
|
-
export { SYNC_SNAPSHOT_MESSAGE, resolveActiveStyles, listProjectStyles, getChecks, getCheckById, resolveCheckSelectors, formatReport, ruleRemoteUrls, ruleRiskyProps, ruleSyntax, checkCss, inspectImage, runChecks, checkToolAvailability, reportMissingTools, executeValidation, executeAndReport, splitOutPath, runBuild, openPath, startPreviewServer, defaultConfigDir, FileTokenStore, extractUrlCredential, getSystemDiagnostics, readPageSetup, setPageSetup, slugifyProjectName, escapeYamlScalar, scaffoldProject, adoptFolder, EXTENSION_KINDS, RESERVED_PREFIX, resolveExtensionPrefix, scaffoldExtension, BUILT_IN_TEMPLATE_IDS, listBuiltInTemplates, saveProjectAsTemplate, listCustomTemplates, importTemplateFromFolder, SNIPPETS_DIR, extractVariables, substituteVariables, listSnippets, saveSnippet, deleteSnippet, listMergedSnippets, listMarkerComponents, listLocationVariants, importExtensionFromFile, importExtensionFromUrl, MAX_SEARCH_BYTES, SEARCH_KEYWORDS, searchNpmExtensions, setManifestFields, readManifestFields, setActiveStyles, VERSION_CHANGES_SHOWN, describeVersions, listOnlineVersions, compareVersionFile, exportVersionTree, AUTO_SNAPSHOT_DEFAULT_MINUTES, AUTO_SYNC_MIN_MINUTES, AUTO_SYNC_MAX_MINUTES, AUTO_SYNC_DEFAULT_MINUTES, AUTO_SYNC_PUSH_INTERVAL_MINUTES, autoSnapshotDelayMs, autoSyncDelayMs, isGitInternalPath, resolveGitHubClientId, GITHUB_HOST, GitHubAuthProvider, GDRIVE_HOST, resolveGoogleClientId, resolveGoogleClientSecret, GOOGLE_NOT_CONFIGURED_MESSAGE, requireGoogleClientCredentials, pkceChallengeFromVerifier, GoogleAuthProvider, revokeGoogleCredential, publishCredentialKey, publishConnectionStatus, listPublishAccounts, connectGoogleDrive, listGitHubRepositories, listRepoBooks, listGitHubBranches, syncProject, refreshRemoteCopies, checkRemoteUpdates, isValidRepositoryName, setUpOnlineBackup, sanitizeCloneFolderName, cloneRepository, isSshRemoteUrl, testRemoteAccess, knownForgeTokenUrl, connectGenericHost, parseRemoteOrigin, forgeKindForHost, diagnoseProjectRemote, renameRevision, deleteRevision, REPAIR_SNAPSHOT_MESSAGE, repairOnlineBackup, scorchedEarth, listPublishProviders, publishProviderFor, listBookPublishProviders, resolvePublishProvider, resolvePublishFormat, resolvePublishRequest, runPublish, connectPublishProvider, disconnectPublishCredential, PublishSelectionsStore, readPublishSettings, setPublishProviderConfig, savePublishSettings };
|
|
13273
|
+
export { SYNC_SNAPSHOT_MESSAGE, assembleCssChunks, relDisplay, resolveActiveStyles, listProjectStyles, getChecks, getCheckById, resolveCheckSelectors, formatReport, ruleRemoteUrls, ruleRiskyProps, ruleSyntax, checkCss, inspectImage, runChecks, checkToolAvailability, reportMissingTools, executeValidation, executeAndReport, splitOutPath, runBuild, openPath, startPreviewServer, defaultConfigDir, FileTokenStore, extractUrlCredential, getSystemDiagnostics, readPageSetup, setPageSetup, slugifyProjectName, escapeYamlScalar, scaffoldProject, adoptFolder, EXTENSION_KINDS, RESERVED_PREFIX, resolveExtensionPrefix, scaffoldExtension, BUILT_IN_TEMPLATE_IDS, listBuiltInTemplates, saveProjectAsTemplate, listCustomTemplates, importTemplateFromFolder, SNIPPETS_DIR, extractVariables, substituteVariables, listSnippets, saveSnippet, deleteSnippet, listMergedSnippets, listMarkerComponents, listLocationVariants, importExtensionFromFile, importExtensionFromUrl, MAX_SEARCH_BYTES, SEARCH_KEYWORDS, searchNpmExtensions, setManifestFields, readManifestFields, setActiveStyles, VERSION_CHANGES_SHOWN, listVersionChanges, describeVersions, listOnlineVersions, compareVersionFile, exportVersionTree, AUTO_SNAPSHOT_DEFAULT_MINUTES, AUTO_SYNC_MIN_MINUTES, AUTO_SYNC_MAX_MINUTES, AUTO_SYNC_DEFAULT_MINUTES, AUTO_SYNC_PUSH_INTERVAL_MINUTES, autoSnapshotDelayMs, autoSyncDelayMs, isGitInternalPath, resolveGitHubClientId, GITHUB_HOST, GitHubAuthProvider, GDRIVE_HOST, resolveGoogleClientId, resolveGoogleClientSecret, GOOGLE_NOT_CONFIGURED_MESSAGE, requireGoogleClientCredentials, pkceChallengeFromVerifier, GoogleAuthProvider, revokeGoogleCredential, publishCredentialKey, publishConnectionStatus, listPublishAccounts, connectGoogleDrive, listGitHubRepositories, listRepoBooks, listGitHubBranches, syncProject, refreshRemoteCopies, checkRemoteUpdates, isValidRepositoryName, setUpOnlineBackup, sanitizeCloneFolderName, cloneRepository, isSshRemoteUrl, testRemoteAccess, knownForgeTokenUrl, connectGenericHost, parseRemoteOrigin, forgeKindForHost, diagnoseProjectRemote, renameRevision, deleteRevision, REPAIR_SNAPSHOT_MESSAGE, repairOnlineBackup, scorchedEarth, listPublishProviders, publishProviderFor, listBookPublishProviders, resolvePublishProvider, resolvePublishFormat, resolvePublishRequest, runPublish, connectPublishProvider, disconnectPublishCredential, PublishSelectionsStore, readPublishSettings, setPublishProviderConfig, savePublishSettings };
|