gutterpress 0.11.23-alpha.7 → 0.11.23-beta.2
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 +3 -1
- package/dist/{README-syg2hn83.md → README-8rct3axy.md} +2 -2
- package/dist/api/index.d.ts +3 -3
- package/dist/api/index.js +8 -6
- package/dist/{build-w572wq10.js → build-3e18wnqj.js} +9 -8
- package/dist/{cli-mmgtqnmr.js → cli-0ep11b0q.js} +1 -1
- package/dist/cli-65gy8ask.js +82 -0
- package/dist/{cli-6pv84kf3.js → cli-88arpdke.js} +6 -84
- package/dist/{cli-eatdqx3z.js → cli-9n9kg58f.js} +1 -1
- package/dist/{cli-58fsk6d7.js → cli-pd2cje5b.js} +187 -44
- package/dist/{cli-3cvq3n1c.js → cli-pnrararp.js} +189 -85
- package/dist/{cli-wyg7qstd.js → cli-tgnyvra3.js} +15 -5
- package/dist/{cli-31anr0r9.js → cli-v0evdpdf.js} +68 -28
- package/dist/{cli-5ba6bm6z.js → cli-x7gcdg6w.js} +1 -1
- package/dist/cli.js +12 -12
- package/dist/{doctor-2f3zqmza.js → doctor-2f4s9dyn.js} +3 -3
- package/dist/engine/compiler/postprocess.d.ts +3 -0
- package/dist/engine/shared/page-vars.d.ts +32 -0
- package/dist/engine/shared/pdf-inspect.d.ts +33 -0
- package/dist/{engine-4rabsgwq.js → engine-c4pxz79g.js} +2 -1
- package/dist/{engine-wm4fggac.js → engine-cs5g2ez0.js} +3 -3
- package/dist/{ext-0cgky8n3.js → ext-70gv86v5.js} +9 -8
- package/dist/{extension-restore-vghc58vx.js → extension-restore-chj5nx3t.js} +3 -3
- package/dist/{extension-restore-e7je32pr.js → extension-restore-pd87p8r2.js} +5 -4
- package/dist/{gutterpress-agent-d29ry3ak.js → gutterpress-agent-wyryqehx.js} +13 -4
- package/dist/{gutterpress-viewer-mafsby5k.js → gutterpress-viewer-ywkf49q5.js} +90 -166
- package/dist/{index-nfysshcc.js → index-0k43evt0.js} +309 -155
- package/dist/{index-wm4x7xbf.js → index-2t1gdma7.js} +178 -35
- package/dist/{index-cw03e9p4.js → index-7j3hkwya.js} +68 -28
- package/dist/{index-fp7xwvpr.js → index-80vg3ed6.js} +15 -5
- package/dist/{index-2vxzxyyj.js → index-swfdgn2n.js} +10 -10
- package/dist/index-tayzfr9c.js +99 -0
- package/dist/{index-hphcn7th.js → index-ytjkvwy5.js} +5 -85
- package/dist/index.d.ts +2 -0
- package/dist/index.js +234 -7
- package/dist/lib/book-css.d.ts +56 -0
- package/dist/lib/markdown/assemble.d.ts +58 -0
- package/dist/lib/markdown/gutterpress-css.d.ts +1 -1
- 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/source-provider.d.ts +27 -0
- package/dist/lib/version-changes.d.ts +26 -16
- 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-d61n5cn0.js} +9 -8
- package/dist/{page-rules-ytj9p04v.css → page-rules-vnja6grt.css} +2 -2
- package/dist/{plugins-3aj0wc5h.js → plugins-0hhw6s17.js} +1 -1
- package/dist/{plugins-sprxsz5d.js → plugins-e0n46s6m.js} +3 -3
- package/dist/{preflight-11dg1qkk.js → preflight-fjayhjr5.js} +9 -8
- package/dist/{preview-nftp782j.js → preview-h815jrfb.js} +9 -8
- package/dist/{publish-6tgxfck9.js → publish-ft39zgma.js} +25 -9
- package/dist/render.js +77 -26
- package/dist/schema/manifest.types.d.ts +2 -1
- package/dist/{source-provider-n7vehh6t.js → source-provider-j1w7byeq.js} +5 -1
- package/dist/{source-provider-tgzet3j5.js → source-provider-tjaf303m.js} +5 -1
- package/dist/test-helpers/vocabulary.d.ts +12 -0
- package/dist/{tokens-n82t4k9h.css → tokens-a7grv940.css} +4 -5
- package/dist/{validate-pktqrye5.js → validate-b201dbrb.js} +9 -8
- package/package.json +1 -1
- package/dist/index-46ycxe6r.js +0 -18
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
stampCreator,
|
|
9
9
|
stripAnnotations,
|
|
10
10
|
transparentPages
|
|
11
|
-
} from "./cli-
|
|
11
|
+
} from "./cli-0ep11b0q.js";
|
|
12
12
|
import {
|
|
13
13
|
blackTextToGray
|
|
14
14
|
} from "./cli-ht1bcqdd.js";
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
MARGIN_BOX_IGNORED_PROPERTIES,
|
|
18
18
|
getAssetPath,
|
|
19
19
|
lastPageMode
|
|
20
|
-
} from "./cli-
|
|
20
|
+
} from "./cli-pd2cje5b.js";
|
|
21
21
|
import {
|
|
22
22
|
countLinkAnnotations,
|
|
23
23
|
getImageResolutions,
|
|
@@ -42,7 +42,7 @@ import {
|
|
|
42
42
|
import {
|
|
43
43
|
hasUncommittedChanges,
|
|
44
44
|
listWorkdirChanges
|
|
45
|
-
} from "./cli-
|
|
45
|
+
} from "./cli-v0evdpdf.js";
|
|
46
46
|
import {
|
|
47
47
|
detectProjectSource,
|
|
48
48
|
repoSubPath
|
|
@@ -56,17 +56,11 @@ import {
|
|
|
56
56
|
TARGET_IDS,
|
|
57
57
|
addExtension,
|
|
58
58
|
applyDefaultPdfStrictChecks,
|
|
59
|
-
cssLength,
|
|
60
59
|
ensureProjectGitignore,
|
|
61
|
-
formatPageSize,
|
|
62
|
-
isPositivePoints,
|
|
63
|
-
judgeRect,
|
|
64
60
|
loadManifest,
|
|
65
61
|
loadManifestDoc,
|
|
66
62
|
loadManifestWithPath,
|
|
67
63
|
npmRegistryUrl,
|
|
68
|
-
pageBoxes,
|
|
69
|
-
printAreaMeta,
|
|
70
64
|
publishTargetFor,
|
|
71
65
|
resolveConfig,
|
|
72
66
|
resolveConfigForTarget,
|
|
@@ -75,7 +69,7 @@ import {
|
|
|
75
69
|
uniqueExtensionId,
|
|
76
70
|
withFetchTimeout,
|
|
77
71
|
writeManifestDoc
|
|
78
|
-
} from "./cli-
|
|
72
|
+
} from "./cli-88arpdke.js";
|
|
79
73
|
import {
|
|
80
74
|
EXTENSION_MANIFEST_FILENAME,
|
|
81
75
|
GUTTERPRESS_CSS,
|
|
@@ -96,7 +90,7 @@ import {
|
|
|
96
90
|
readExtensionMeta,
|
|
97
91
|
resolveDeclaredStyles,
|
|
98
92
|
slugify
|
|
99
|
-
} from "./cli-
|
|
93
|
+
} from "./cli-tgnyvra3.js";
|
|
100
94
|
import {
|
|
101
95
|
PACKAGE_META,
|
|
102
96
|
PACKAGE_VERSION,
|
|
@@ -106,12 +100,20 @@ import {
|
|
|
106
100
|
log,
|
|
107
101
|
setLogLevel,
|
|
108
102
|
warn
|
|
109
|
-
} from "./cli-
|
|
103
|
+
} from "./cli-9n9kg58f.js";
|
|
110
104
|
import {
|
|
111
105
|
DEBOUNCE,
|
|
112
106
|
UsageError,
|
|
113
107
|
resolvePort
|
|
114
108
|
} from "./cli-d8xjns66.js";
|
|
109
|
+
import {
|
|
110
|
+
cssLength,
|
|
111
|
+
formatPageSize,
|
|
112
|
+
isPositivePoints,
|
|
113
|
+
judgeRect,
|
|
114
|
+
pageBoxes,
|
|
115
|
+
printAreaMeta
|
|
116
|
+
} from "./cli-65gy8ask.js";
|
|
115
117
|
import {
|
|
116
118
|
BuildError
|
|
117
119
|
} from "./cli-46ycxe6r.js";
|
|
@@ -1596,7 +1598,7 @@ function checkCssRaw(css, from) {
|
|
|
1596
1598
|
warnings.push({
|
|
1597
1599
|
rule: rulePageSizeInStylesheet,
|
|
1598
1600
|
severity: "warning",
|
|
1599
|
-
message: `"size" in a stylesheet's @page rule is ignored: the page size comes from the manifest (preset:, or page: width and height —
|
|
1601
|
+
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.`,
|
|
1600
1602
|
...nodeLoc(decl)
|
|
1601
1603
|
});
|
|
1602
1604
|
return;
|
|
@@ -3097,7 +3099,7 @@ registerCheck(check27);
|
|
|
3097
3099
|
import { readFile as readFile13 } from "node:fs/promises";
|
|
3098
3100
|
|
|
3099
3101
|
// src/checks/source/character-table.ts
|
|
3100
|
-
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\\
|
|
3102
|
+
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");
|
|
3101
3103
|
var NAMED = {
|
|
3102
3104
|
8212: ["Em dash", "typographer", "---"],
|
|
3103
3105
|
8211: ["En dash", "typographer", "--"],
|
|
@@ -3118,7 +3120,6 @@ var NAMED = {
|
|
|
3118
3120
|
8209: ["Non-breaking hyphen", "lookalike", "-"],
|
|
3119
3121
|
8210: ["Figure dash", "lookalike", "-"],
|
|
3120
3122
|
8213: ["Horizontal bar", "lookalike", "---"],
|
|
3121
|
-
8722: ["Minus sign", "lookalike", "-"],
|
|
3122
3123
|
8226: ["Bullet", "symbol", "•"],
|
|
3123
3124
|
9702: ["White bullet", "symbol", "◦"],
|
|
3124
3125
|
9642: ["Small square", "symbol", "▪"],
|
|
@@ -3858,6 +3859,7 @@ function canonicalChapterId(p) {
|
|
|
3858
3859
|
}
|
|
3859
3860
|
|
|
3860
3861
|
// src/lib/markdown/assemble.ts
|
|
3862
|
+
import postcss5 from "postcss";
|
|
3861
3863
|
function pageGeometryCss(page) {
|
|
3862
3864
|
if (!page || !isPositivePoints(page.width) || !isPositivePoints(page.height))
|
|
3863
3865
|
return null;
|
|
@@ -3878,6 +3880,65 @@ function defaultPageMarginCss(page) {
|
|
|
3878
3880
|
@page { margin: ${cssLength(DEFAULT_PAGE_MARGIN_PT)}; }
|
|
3879
3881
|
}`;
|
|
3880
3882
|
}
|
|
3883
|
+
function liftPageRules(css) {
|
|
3884
|
+
if (!/@page\b/i.test(css))
|
|
3885
|
+
return { layered: css, pages: "" };
|
|
3886
|
+
let root;
|
|
3887
|
+
try {
|
|
3888
|
+
root = postcss5.parse(css);
|
|
3889
|
+
} catch {
|
|
3890
|
+
return { layered: css, pages: "" };
|
|
3891
|
+
}
|
|
3892
|
+
const found = [];
|
|
3893
|
+
root.walkAtRules(/^page$/i, (rule) => {
|
|
3894
|
+
found.push(rule);
|
|
3895
|
+
});
|
|
3896
|
+
const pages = found.map((rule) => {
|
|
3897
|
+
let lifted = rule.clone();
|
|
3898
|
+
for (let p = rule.parent;p instanceof postcss5.AtRule || p instanceof postcss5.Rule; p = p.parent) {
|
|
3899
|
+
if (p instanceof postcss5.AtRule && p.name.toLowerCase() === "layer")
|
|
3900
|
+
continue;
|
|
3901
|
+
lifted = p.clone({ nodes: [] }).append(lifted);
|
|
3902
|
+
}
|
|
3903
|
+
rule.remove();
|
|
3904
|
+
return lifted.toString();
|
|
3905
|
+
});
|
|
3906
|
+
return { layered: root.toString(), pages: pages.join(`
|
|
3907
|
+
`) };
|
|
3908
|
+
}
|
|
3909
|
+
var CORE_MARKERS = liftPageRules(`${MARKER_CSS.trim()}
|
|
3910
|
+
${TWO_VERSIONS_CSS.trim()}`);
|
|
3911
|
+
var CORE_VOCAB = liftPageRules(GUTTERPRESS_CSS.trim());
|
|
3912
|
+
function assembleCssChunks(opts) {
|
|
3913
|
+
const core = (css) => css ? [{ origin: { kind: "core" }, css }] : [];
|
|
3914
|
+
const headed = (title, chunks = []) => chunks.map((chunk2, i) => i === 0 ? { ...chunk2, css: `/* ${title} */
|
|
3915
|
+
${chunk2.css.trim()}` } : chunk2);
|
|
3916
|
+
const pageGeometry = pageGeometryCss(opts.printArea);
|
|
3917
|
+
const defaultMargin = defaultPageMarginCss(opts.printArea);
|
|
3918
|
+
return [
|
|
3919
|
+
...core("@layer gp.marker, gp.vocab;"),
|
|
3920
|
+
...core(`/* gutterpress markers */
|
|
3921
|
+
@layer gp.marker {
|
|
3922
|
+
${CORE_MARKERS.layered.trim()}
|
|
3923
|
+
}`),
|
|
3924
|
+
...core(CORE_MARKERS.pages && `/* gutterpress markers: page rules */
|
|
3925
|
+
${CORE_MARKERS.pages}`),
|
|
3926
|
+
...core(`/* gutterpress */
|
|
3927
|
+
@layer gp.vocab {
|
|
3928
|
+
${CORE_VOCAB.layered.trim()}
|
|
3929
|
+
}`),
|
|
3930
|
+
...core(CORE_VOCAB.pages && `/* gutterpress: page rules */
|
|
3931
|
+
${CORE_VOCAB.pages}`),
|
|
3932
|
+
...core(defaultMargin && `/* page margins (default) */
|
|
3933
|
+
${defaultMargin}`),
|
|
3934
|
+
...headed("extension css", opts.extensions),
|
|
3935
|
+
...core(`/* column alignment */
|
|
3936
|
+
${TABLE_ALIGN_CSS.trim()}`),
|
|
3937
|
+
...headed("project css", opts.book),
|
|
3938
|
+
...core(pageGeometry && `/* page geometry (manifest) */
|
|
3939
|
+
${pageGeometry}`)
|
|
3940
|
+
];
|
|
3941
|
+
}
|
|
3881
3942
|
async function assembleBookHtml(opts) {
|
|
3882
3943
|
const title = opts.title ?? "Document";
|
|
3883
3944
|
const projectCss = opts.projectCss ?? "";
|
|
@@ -3916,30 +3977,11 @@ async function assembleBookHtml(opts) {
|
|
|
3916
3977
|
imageRefs.add(ref);
|
|
3917
3978
|
opts.onImageRefs([...imageRefs]);
|
|
3918
3979
|
}
|
|
3919
|
-
const
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
"
|
|
3923
|
-
|
|
3924
|
-
@layer gp.marker {
|
|
3925
|
-
${MARKER_CSS.trim()}
|
|
3926
|
-
${TWO_VERSIONS_CSS.trim()}
|
|
3927
|
-
}`,
|
|
3928
|
-
`/* gutterpress */
|
|
3929
|
-
@layer gp.vocab {
|
|
3930
|
-
${GUTTERPRESS_CSS.trim()}
|
|
3931
|
-
}`,
|
|
3932
|
-
defaultMargin ? `/* page margins (default) */
|
|
3933
|
-
${defaultMargin}` : null,
|
|
3934
|
-
pluginCss ? `/* extension css */
|
|
3935
|
-
${pluginCss.trim()}` : null,
|
|
3936
|
-
`/* column alignment */
|
|
3937
|
-
${TABLE_ALIGN_CSS.trim()}`,
|
|
3938
|
-
projectCss ? `/* project css */
|
|
3939
|
-
${projectCss.trim()}` : null,
|
|
3940
|
-
pageGeometry ? `/* page geometry (manifest) */
|
|
3941
|
-
${pageGeometry}` : null
|
|
3942
|
-
].filter(Boolean).join(`
|
|
3980
|
+
const inlineCss = assembleCssChunks({
|
|
3981
|
+
printArea: opts.printArea,
|
|
3982
|
+
extensions: pluginCss ? [{ origin: { kind: "extension" }, css: pluginCss }] : [],
|
|
3983
|
+
book: projectCss ? [{ origin: { kind: "book" }, css: projectCss }] : []
|
|
3984
|
+
}).map((chunk2) => chunk2.css).join(`
|
|
3943
3985
|
|
|
3944
3986
|
`);
|
|
3945
3987
|
const preloadTags = (opts.preloadImages ?? []).map((href) => `
|
|
@@ -3972,6 +4014,7 @@ async function resolveActiveMarkdownFiles(inputDir, configuredFiles) {
|
|
|
3972
4014
|
async function renderChapters(inputDir, opts = {}) {
|
|
3973
4015
|
const styles = await resolveActiveStyles(inputDir, opts.styles);
|
|
3974
4016
|
const inlined = await inlineStyles(inputDir, styles);
|
|
4017
|
+
const book = liftPageRules(inlined.css);
|
|
3975
4018
|
const blocks = [];
|
|
3976
4019
|
const layers = [];
|
|
3977
4020
|
const styleWarnings = [];
|
|
@@ -3986,10 +4029,13 @@ async function renderChapters(inputDir, opts = {}) {
|
|
|
3986
4029
|
if (!css)
|
|
3987
4030
|
continue;
|
|
3988
4031
|
layers.push(group.layer);
|
|
4032
|
+
const { layered, pages } = liftPageRules(css);
|
|
3989
4033
|
blocks.push(`/* ${group.name} */
|
|
3990
4034
|
@layer ${group.layer} {
|
|
3991
|
-
${
|
|
3992
|
-
}`
|
|
4035
|
+
${layered.trim()}
|
|
4036
|
+
}` + (pages ? `
|
|
4037
|
+
/* ${group.name}: page rules */
|
|
4038
|
+
${pages}` : ""));
|
|
3993
4039
|
}
|
|
3994
4040
|
styleWarnings.push(...inlined.warnings);
|
|
3995
4041
|
if (styleWarnings.length > 0)
|
|
@@ -4007,7 +4053,8 @@ ${css.trim()}
|
|
|
4007
4053
|
return assembleBookHtml({
|
|
4008
4054
|
files,
|
|
4009
4055
|
readText: (relPath) => readFile16(join(inputDir, canonicalChapterId(relPath)), "utf-8"),
|
|
4010
|
-
projectCss:
|
|
4056
|
+
projectCss: book.pages ? `${book.layered.trim()}
|
|
4057
|
+
${book.pages}` : inlined.css,
|
|
4011
4058
|
preloadImages: cssAssetCopies.map((c) => c.to),
|
|
4012
4059
|
title: opts.title,
|
|
4013
4060
|
language: opts.language,
|
|
@@ -5056,7 +5103,7 @@ class PdfOutput {
|
|
|
5056
5103
|
const rawPdf = pdfxMode ? path7.join(stage, "raw.pdf") : path7.resolve(pdfFile);
|
|
5057
5104
|
await fsp2.mkdir(path7.dirname(path7.resolve(pdfFile)), { recursive: true });
|
|
5058
5105
|
log.info("Rendering HTML to PDF via the Gutterpress engine (native Chromium pagination)");
|
|
5059
|
-
const { buildNativePdf } = await import("./engine-
|
|
5106
|
+
const { buildNativePdf } = await import("./engine-c4pxz79g.js");
|
|
5060
5107
|
const engineDiagnostics = await buildNativePdf(htmlFile, rawPdf, {
|
|
5061
5108
|
title: config.title,
|
|
5062
5109
|
author: config.authors.length > 0 ? config.authors.join(", ") : undefined,
|
|
@@ -6379,10 +6426,10 @@ function starterOverridesCss() {
|
|
|
6379
6426
|
return `/**
|
|
6380
6427
|
* Your book's own styles. Rules here win over your look's.
|
|
6381
6428
|
*
|
|
6382
|
-
* In the app you rarely need this file:
|
|
6383
|
-
*
|
|
6384
|
-
*
|
|
6385
|
-
*
|
|
6429
|
+
* In the app you rarely need this file: Book setup chooses a look, changes
|
|
6430
|
+
* its fonts and colors (those changes are saved here as :root custom
|
|
6431
|
+
* properties), lists every setting, and sets the page size and margins (in
|
|
6432
|
+
* the manifest).
|
|
6386
6433
|
*
|
|
6387
6434
|
* To change the look from the command line: gutterpress ext remove <old>
|
|
6388
6435
|
* <book>, then gutterpress ext add <look> <book>.
|
|
@@ -6524,7 +6571,7 @@ async function scaffoldProject(options) {
|
|
|
6524
6571
|
let versionHistoryError;
|
|
6525
6572
|
if (requested === "local-git") {
|
|
6526
6573
|
try {
|
|
6527
|
-
const { providerFor } = await import("./source-provider-
|
|
6574
|
+
const { providerFor } = await import("./source-provider-j1w7byeq.js");
|
|
6528
6575
|
const provider = providerFor({ type: "local-folder", path: projectDir });
|
|
6529
6576
|
await provider.initVersionHistory({
|
|
6530
6577
|
projectDir,
|
|
@@ -7878,13 +7925,13 @@ async function createFolder(fetchImpl, accessToken, name) {
|
|
|
7878
7925
|
throw await driveFailure(res, `Couldn't create the Google Drive folder "${name}"`);
|
|
7879
7926
|
return await res.json();
|
|
7880
7927
|
}
|
|
7881
|
-
async function
|
|
7928
|
+
async function findFoldersByName(fetchImpl, accessToken, name, limit = 1) {
|
|
7882
7929
|
const q = `name='${escapeDriveQueryValue(name)}' and mimeType='${FOLDER_MIME}' and trashed=false`;
|
|
7883
7930
|
const params = new URLSearchParams({
|
|
7884
7931
|
q,
|
|
7885
7932
|
fields: "files(id,name)",
|
|
7886
7933
|
orderBy: "modifiedTime desc",
|
|
7887
|
-
pageSize:
|
|
7934
|
+
pageSize: String(limit)
|
|
7888
7935
|
});
|
|
7889
7936
|
const res = await driveFetch(fetchImpl, `${DRIVE_API_BASE}/files?${params.toString()}`, {
|
|
7890
7937
|
method: "GET",
|
|
@@ -7893,10 +7940,10 @@ async function findFolderByName(fetchImpl, accessToken, name) {
|
|
|
7893
7940
|
if (!res.ok)
|
|
7894
7941
|
throw await driveFailure(res, `Couldn't look up the Google Drive folder "${name}"`);
|
|
7895
7942
|
const body = await res.json();
|
|
7896
|
-
return body.files
|
|
7943
|
+
return body.files ?? [];
|
|
7897
7944
|
}
|
|
7898
7945
|
async function ensureFolder(fetchImpl, accessToken, name) {
|
|
7899
|
-
const found = await
|
|
7946
|
+
const [found] = await findFoldersByName(fetchImpl, accessToken, name);
|
|
7900
7947
|
if (found)
|
|
7901
7948
|
return found;
|
|
7902
7949
|
return createFolder(fetchImpl, accessToken, name);
|
|
@@ -8029,8 +8076,80 @@ async function resumableUpload(fetchImpl, accessToken, opts) {
|
|
|
8029
8076
|
}
|
|
8030
8077
|
}
|
|
8031
8078
|
|
|
8032
|
-
// src/lib/publish/providers/gdrive.ts
|
|
8079
|
+
// src/lib/publish/providers/gdrive-folder.ts
|
|
8033
8080
|
var DEFAULT_FOLDER_NAME = "Gutterpress";
|
|
8081
|
+
var NO_OWN_FOLDER = { myFolderId: "", myFolder: "", myFolderFor: "", myFolderAccount: "" };
|
|
8082
|
+
function readConfig(req) {
|
|
8083
|
+
const text = (key) => {
|
|
8084
|
+
const value = req.config[key];
|
|
8085
|
+
return (typeof value === "string" ? value.trim() : "") || undefined;
|
|
8086
|
+
};
|
|
8087
|
+
return {
|
|
8088
|
+
folder: text("folder"),
|
|
8089
|
+
folderId: text("folderId"),
|
|
8090
|
+
myFolderId: text("myFolderId"),
|
|
8091
|
+
myFolder: text("myFolder"),
|
|
8092
|
+
myFolderFor: text("myFolderFor"),
|
|
8093
|
+
myFolderAccount: text("myFolderAccount"),
|
|
8094
|
+
account: req.deps.credentialAccount?.trim() ?? ""
|
|
8095
|
+
};
|
|
8096
|
+
}
|
|
8097
|
+
async function resolveFolder(req, accessToken) {
|
|
8098
|
+
const fetchImpl = req.deps.fetch ?? globalThis.fetch;
|
|
8099
|
+
const cfg = readConfig(req);
|
|
8100
|
+
let found = [];
|
|
8101
|
+
if (cfg.folderId) {
|
|
8102
|
+
const folder = await getFolderById(fetchImpl, accessToken, cfg.folderId);
|
|
8103
|
+
if (folder)
|
|
8104
|
+
found = [folder];
|
|
8105
|
+
} else if (cfg.folder) {
|
|
8106
|
+
found = await findFoldersByName(fetchImpl, accessToken, cfg.folder, 2);
|
|
8107
|
+
}
|
|
8108
|
+
const first = found[0];
|
|
8109
|
+
const book = { title: cfg.folder || cfg.folderId || "", reachable: !cfg.folderId || !!first };
|
|
8110
|
+
if (cfg.myFolderId) {
|
|
8111
|
+
const bookKey = cfg.folderId || cfg.folder;
|
|
8112
|
+
if (bookKey && cfg.myFolderFor === bookKey && (cfg.myFolderAccount ?? "") === cfg.account) {
|
|
8113
|
+
const mine = await getFolderById(fetchImpl, accessToken, cfg.myFolderId);
|
|
8114
|
+
return mine ? { state: "mine", destination: toDestination(mine), book } : { state: "unreachable", book, mine: cfg.myFolder || cfg.myFolderId };
|
|
8115
|
+
}
|
|
8116
|
+
if (book.reachable) {
|
|
8117
|
+
await req.deps.selections?.setSettings(req.project.projectDir, "gdrive", NO_OWN_FOLDER);
|
|
8118
|
+
}
|
|
8119
|
+
}
|
|
8120
|
+
if (cfg.folderId) {
|
|
8121
|
+
return first ? { state: "book", destination: toDestination(first) } : { state: "unreachable", book };
|
|
8122
|
+
}
|
|
8123
|
+
if (cfg.folder) {
|
|
8124
|
+
return {
|
|
8125
|
+
state: "by-name",
|
|
8126
|
+
name: cfg.folder,
|
|
8127
|
+
...first ? { destination: toDestination(first) } : {},
|
|
8128
|
+
several: found.length > 1
|
|
8129
|
+
};
|
|
8130
|
+
}
|
|
8131
|
+
return { state: "unset" };
|
|
8132
|
+
}
|
|
8133
|
+
async function uploadFolder(where, fetchImpl, accessToken) {
|
|
8134
|
+
switch (where.state) {
|
|
8135
|
+
case "unreachable":
|
|
8136
|
+
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.`);
|
|
8137
|
+
case "unset":
|
|
8138
|
+
return toDestination(await ensureFolder(fetchImpl, accessToken, DEFAULT_FOLDER_NAME));
|
|
8139
|
+
case "by-name":
|
|
8140
|
+
return where.destination ?? toDestination(await createFolder(fetchImpl, accessToken, where.name));
|
|
8141
|
+
default:
|
|
8142
|
+
return where.destination;
|
|
8143
|
+
}
|
|
8144
|
+
}
|
|
8145
|
+
function folderUrl(id) {
|
|
8146
|
+
return `https://drive.google.com/drive/folders/${id}`;
|
|
8147
|
+
}
|
|
8148
|
+
function toDestination(folder) {
|
|
8149
|
+
return { id: folder.id, title: folder.name, url: folderUrl(folder.id) };
|
|
8150
|
+
}
|
|
8151
|
+
|
|
8152
|
+
// src/lib/publish/providers/gdrive.ts
|
|
8034
8153
|
var NOT_CONNECTED_MESSAGE = "Google Drive isn't connected. Run `gutterpress publish --provider gdrive --connect` (or set GDRIVE_REFRESH_TOKEN) first.";
|
|
8035
8154
|
var info5 = {
|
|
8036
8155
|
id: "gdrive",
|
|
@@ -8049,13 +8168,6 @@ var info5 = {
|
|
|
8049
8168
|
},
|
|
8050
8169
|
destinations: { label: "Folder", canCreate: true }
|
|
8051
8170
|
};
|
|
8052
|
-
function readConfig(req) {
|
|
8053
|
-
const cfg = req.config;
|
|
8054
|
-
return {
|
|
8055
|
-
folder: cfg.folder?.trim() || undefined,
|
|
8056
|
-
folderId: cfg.folderId?.trim() || undefined
|
|
8057
|
-
};
|
|
8058
|
-
}
|
|
8059
8171
|
function formatBytes(bytes) {
|
|
8060
8172
|
if (bytes < 1024 * 1024)
|
|
8061
8173
|
return `${(bytes / 1024).toFixed(0)} KB`;
|
|
@@ -8077,22 +8189,6 @@ async function getAccessToken(req) {
|
|
|
8077
8189
|
const accessToken = await mintAccessToken(resolved, req.deps.fetch ?? globalThis.fetch);
|
|
8078
8190
|
return { accessToken, source: resolved.source };
|
|
8079
8191
|
}
|
|
8080
|
-
async function resolveFolder(fetchImpl, accessToken, cfg) {
|
|
8081
|
-
if (cfg.folderId) {
|
|
8082
|
-
const folder = await getFolderById(fetchImpl, accessToken, cfg.folderId);
|
|
8083
|
-
if (!folder) {
|
|
8084
|
-
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.`);
|
|
8085
|
-
}
|
|
8086
|
-
return folder;
|
|
8087
|
-
}
|
|
8088
|
-
return ensureFolder(fetchImpl, accessToken, cfg.folder || DEFAULT_FOLDER_NAME);
|
|
8089
|
-
}
|
|
8090
|
-
function folderUrl(id) {
|
|
8091
|
-
return `https://drive.google.com/drive/folders/${id}`;
|
|
8092
|
-
}
|
|
8093
|
-
function toDestination(folder) {
|
|
8094
|
-
return { id: folder.id, title: folder.name, url: folderUrl(folder.id) };
|
|
8095
|
-
}
|
|
8096
8192
|
var ZIP_CHUNK_BYTES = 64 * 1024;
|
|
8097
8193
|
function yieldToEventLoop() {
|
|
8098
8194
|
return new Promise((resolve5) => setImmediate(resolve5));
|
|
@@ -8219,9 +8315,12 @@ var gdriveProvider = {
|
|
|
8219
8315
|
const folder = await createFolder(req.deps.fetch ?? globalThis.fetch, accessToken, name);
|
|
8220
8316
|
return toDestination(folder);
|
|
8221
8317
|
},
|
|
8318
|
+
async destinationStatus(req) {
|
|
8319
|
+
const { accessToken } = await getAccessToken(req);
|
|
8320
|
+
return resolveFolder(req, accessToken);
|
|
8321
|
+
},
|
|
8222
8322
|
async upload(req) {
|
|
8223
8323
|
const fetchImpl = req.deps.fetch ?? globalThis.fetch;
|
|
8224
|
-
const cfg = readConfig(req);
|
|
8225
8324
|
const { accessToken } = await getAccessToken(req);
|
|
8226
8325
|
const isHtml = req.artifact.format === "html";
|
|
8227
8326
|
const source = isHtml ? await zipHtmlExport(req.artifact.path, req.project.title, (msg) => req.deps.onProgress?.(msg)) : {
|
|
@@ -8239,10 +8338,11 @@ var gdriveProvider = {
|
|
|
8239
8338
|
}
|
|
8240
8339
|
}
|
|
8241
8340
|
req.deps.onProgress?.("Resolving the Drive folder…");
|
|
8242
|
-
const
|
|
8341
|
+
const where = await resolveFolder(req, accessToken);
|
|
8342
|
+
const folder = await uploadFolder(where, fetchImpl, accessToken);
|
|
8243
8343
|
const fileName = source.fileName;
|
|
8244
8344
|
const existing = await findFileInFolder(fetchImpl, accessToken, folder.id, fileName);
|
|
8245
|
-
req.deps.onProgress?.(existing ? `Updating "${fileName}" in "${folder.
|
|
8345
|
+
req.deps.onProgress?.(existing ? `Updating "${fileName}" in "${folder.title}"…` : `Uploading "${fileName}" to "${folder.title}"…`);
|
|
8246
8346
|
let lastReported = -1;
|
|
8247
8347
|
const file = await resumableUpload(fetchImpl, accessToken, {
|
|
8248
8348
|
...existing ? { fileId: existing.id } : {},
|
|
@@ -8262,11 +8362,11 @@ var gdriveProvider = {
|
|
|
8262
8362
|
return {
|
|
8263
8363
|
kind: "published",
|
|
8264
8364
|
url: file.webViewLink,
|
|
8265
|
-
detail: `Uploaded "${fileName}" to the "${folder.
|
|
8365
|
+
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}` : ""),
|
|
8266
8366
|
followUp: [
|
|
8267
8367
|
"To share it, open it in Drive and use the Share button — Gutterpress never changes who can see your files.",
|
|
8268
8368
|
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,
|
|
8269
|
-
|
|
8369
|
+
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
|
|
8270
8370
|
].filter((s) => !!s)
|
|
8271
8371
|
};
|
|
8272
8372
|
} finally {
|
|
@@ -8878,7 +8978,7 @@ async function resolvePublishProvider(id, book) {
|
|
|
8878
8978
|
const ext = await bookExtensions(book);
|
|
8879
8979
|
const npmEntry = ext.extensions.some((c) => !c.path && c.name === id);
|
|
8880
8980
|
if (npmEntry) {
|
|
8881
|
-
const { restoreForCommand: restoreForCommand2 } = await import("./extension-restore-
|
|
8981
|
+
const { restoreForCommand: restoreForCommand2 } = await import("./extension-restore-pd87p8r2.js");
|
|
8882
8982
|
await restoreForCommand2(book.projectDir, { manifestPath: book.manifestPath, failFast: true });
|
|
8883
8983
|
}
|
|
8884
8984
|
const publishers = await discover(ext);
|
|
@@ -8916,7 +9016,7 @@ function infoFor(p) {
|
|
|
8916
9016
|
}
|
|
8917
9017
|
function pluginProvider(p) {
|
|
8918
9018
|
let loading;
|
|
8919
|
-
const load = () => loading ??= import("./plugins-
|
|
9019
|
+
const load = () => loading ??= import("./plugins-e0n46s6m.js").then((m) => m.loadPublishFunction(p));
|
|
8920
9020
|
return {
|
|
8921
9021
|
info: infoFor(p),
|
|
8922
9022
|
async authenticate() {
|
|
@@ -8987,7 +9087,8 @@ async function requestFor(provider, options, deps) {
|
|
|
8987
9087
|
const publishSettings = manifest.publish ?? {};
|
|
8988
9088
|
const providerConfig = {
|
|
8989
9089
|
...publishSettings[provider.info.id] ?? {},
|
|
8990
|
-
...(await deps.selections?.settings(options.projectDir))?.[provider.info.id] ?? {}
|
|
9090
|
+
...(await deps.selections?.settings(options.projectDir))?.[provider.info.id] ?? {},
|
|
9091
|
+
...options.settings
|
|
8991
9092
|
};
|
|
8992
9093
|
const bookAccount = typeof providerConfig.credential === "string" ? providerConfig.credential.trim() : "";
|
|
8993
9094
|
const effectiveAccount = bookAccount || deps.credentialAccount;
|
|
@@ -9205,7 +9306,7 @@ async function disconnectPublishCredential(key, deps, options = {}) {
|
|
|
9205
9306
|
import { isSeq as isSeq2, isMap as isMap3, YAMLSeq, Scalar } from "yaml";
|
|
9206
9307
|
// src/lib/version-changes.ts
|
|
9207
9308
|
import git3 from "isomorphic-git";
|
|
9208
|
-
import
|
|
9309
|
+
import postcss6 from "postcss";
|
|
9209
9310
|
|
|
9210
9311
|
// src/lib/remote-auth/transport.ts
|
|
9211
9312
|
import git2 from "isomorphic-git";
|
|
@@ -9303,6 +9404,7 @@ var defaultGitHttp = withIdleTimeout(httpNode);
|
|
|
9303
9404
|
|
|
9304
9405
|
// src/lib/version-changes.ts
|
|
9305
9406
|
var decoder = new TextDecoder;
|
|
9407
|
+
var CLOCK_SKEW_SECONDS = 10 * 60;
|
|
9306
9408
|
// src/lib/host-policy.ts
|
|
9307
9409
|
var AUTO_SYNC_MAX_MINUTES = 24 * 60;
|
|
9308
9410
|
// src/lib/remote-auth/github-repos.ts
|
|
@@ -9435,4 +9537,6 @@ function normalizeProjectKey(projectDir) {
|
|
|
9435
9537
|
}
|
|
9436
9538
|
// src/lib/publish/manifest-publish.ts
|
|
9437
9539
|
import { isMap as isMap4 } from "yaml";
|
|
9540
|
+
// src/lib/root-tokens.ts
|
|
9541
|
+
import postcss7 from "postcss";
|
|
9438
9542
|
export { reportMissingTools, executeValidation, executeAndReport, splitOutPath, runBuild, openPath, startPreviewServer, scaffoldProject, EXTENSION_KINDS, scaffoldExtension, BUILT_IN_TEMPLATE_IDS, importExtensionFromFile, importExtensionFromUrl, searchNpmExtensions, publishCredentialKey, publishConnectionStatus, listPublishAccounts, connectGoogleDrive, listBookPublishProviders, resolvePublishProvider, resolvePublishFormat, runPublish, connectPublishProvider, disconnectPublishCredential };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
PACKAGE_VERSION,
|
|
3
3
|
debug
|
|
4
|
-
} from "./cli-
|
|
4
|
+
} from "./cli-9n9kg58f.js";
|
|
5
5
|
import {
|
|
6
6
|
isExactNpmVersion,
|
|
7
7
|
isValidNpmPackageName,
|
|
@@ -1950,8 +1950,9 @@ img.gp-shape {
|
|
|
1950
1950
|
|
|
1951
1951
|
/* Math (the bundled gutterpress-math feature, math.ts): MathJax's own rules
|
|
1952
1952
|
for the <mjx-container> SVG output it emits, from its SVG output jax's
|
|
1953
|
-
stylesheet, less the ones for its interactive menu and tooltips
|
|
1954
|
-
|
|
1953
|
+
stylesheet, less the ones for its interactive menu and tooltips, plus one
|
|
1954
|
+
bound of ours on the hidden MathML copy (#469, below). Inert in a book
|
|
1955
|
+
without formulas. */
|
|
1955
1956
|
mjx-container[jax="SVG"] { direction: ltr; }
|
|
1956
1957
|
mjx-container[jax="SVG"] > svg { overflow: visible; min-height: 1px; min-width: 1px; }
|
|
1957
1958
|
mjx-container[jax="SVG"] > svg a { fill: blue; stroke: blue; }
|
|
@@ -1968,6 +1969,15 @@ mjx-assistive-mml {
|
|
|
1968
1969
|
border: 0px !important;
|
|
1969
1970
|
display: block !important;
|
|
1970
1971
|
width: auto !important;
|
|
1972
|
+
/* Ours (#469). The browser lays the copy out in whatever math font it has,
|
|
1973
|
+
so it can be wider than the formula's SVG; ending a line, it crossed the
|
|
1974
|
+
column edge and Chromium shrank the whole print to fit. MathJax makes the
|
|
1975
|
+
container position: relative with the copy at its top left, so 100% is
|
|
1976
|
+
the formula's width. Clip and overflow still hide the copy and its MathML
|
|
1977
|
+
still reaches screen readers; only its box changes. Not the 1px
|
|
1978
|
+
visually-hidden box MathJax 2 used: its docs note VoiceOver on iOS could
|
|
1979
|
+
not reach a formula by touch in it. */
|
|
1980
|
+
max-width: 100% !important;
|
|
1971
1981
|
overflow: hidden !important;
|
|
1972
1982
|
user-select: none;
|
|
1973
1983
|
}
|
|
@@ -3575,9 +3585,9 @@ async function loadNpmPackage(packageName, baseDir, version) {
|
|
|
3575
3585
|
const looksLikeJsFilename = /\.(m?js|cjs)$/i.test(packageName);
|
|
3576
3586
|
const suggestedPath = looksLikeJsFilename ? `./${packageName}` : `./plugins/${packageName}.js`;
|
|
3577
3587
|
if (!looksLikeJsFilename && (!version || !isExactNpmVersion(version))) {
|
|
3578
|
-
throw new Error(`Extension "${packageName}${version ? `@${version}` : ""}" is not pinned to an exact version, so it can't be downloaded automatically. Run \`gutterpress ext add ${packageName}\` (or
|
|
3588
|
+
throw new Error(`Extension "${packageName}${version ? `@${version}` : ""}" is not pinned to an exact version, so it can't be downloaded automatically. Run \`gutterpress ext add ${packageName}\` (or add it in Book setup) to download it and pin its version in your manifest.`);
|
|
3579
3589
|
}
|
|
3580
|
-
throw new Error(`Extension "${packageName}" not found. Install it with \`gutterpress ext add ${version ? `${packageName}@${version}` : packageName}\` (or
|
|
3590
|
+
throw new Error(`Extension "${packageName}" not found. Install it with \`gutterpress ext add ${version ? `${packageName}@${version}` : packageName}\` (or add it in Book setup),
|
|
3581
3591
|
or reference a local file under \`extensions:\`:
|
|
3582
3592
|
extensions:
|
|
3583
3593
|
- ${suggestedPath}`);
|