gutterpress 0.11.21 → 0.11.22-alpha.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 +11 -0
- package/dist/api/index.d.ts +5 -1
- package/dist/api/index.js +68 -47
- package/dist/{build-0neyk5h6.js → build-84retk4k.js} +16 -10
- package/dist/{index-sth219v1.js → cli-2ppw6q9v.js} +26 -6
- package/dist/cli-3twpesca.js +103 -0
- package/dist/cli-5et23z83.js +2089 -0
- package/dist/{cli-j79451n6.js → cli-5qhjwne5.js} +5 -76
- package/dist/cli-80t93x2r.js +75 -0
- package/dist/{cli-j0drzb6f.js → cli-885pcze8.js} +885 -5481
- package/dist/{cli-b57adna7.js → cli-9pk65fqf.js} +9 -201
- package/dist/{cli-sqkccnm7.js → cli-d8xjns66.js} +1 -102
- package/dist/cli-h3phdstf.js +200 -0
- package/dist/{index-qf7y4d85.js → cli-habkc5ng.js} +12 -258
- package/dist/cli-hndkg7bn.js +196 -0
- package/dist/cli-pn3z0y9p.js +3073 -0
- package/dist/cli.js +15 -13
- package/dist/{doctor-fptq8tvn.js → doctor-fmzpg7ag.js} +7 -4
- package/dist/engine/shared/print-area.d.ts +77 -1
- package/dist/{engine-x07q927h.js → engine-5p8tn9b4.js} +4 -3
- package/dist/{engine-0b8bt05n.js → engine-9710cd7x.js} +3 -2
- package/dist/{ext-gp624t5c.js → ext-hsdnad5c.js} +21 -14
- package/dist/extension-restore-05pae3cp.js +16 -0
- package/dist/extension-restore-3r7phztr.js +20 -0
- package/dist/{gutterpress-viewer-w7njnkj7.js → gutterpress-viewer-w9jzx6sb.js} +56 -52
- package/dist/{index-t7r8g75c.js → index-2d8j0enc.js} +4 -2
- package/dist/{cli-sth219v1.js → index-2ppw6q9v.js} +26 -6
- package/dist/{index-mr7zs8mv.js → index-3wcr69ba.js} +5579 -10055
- package/dist/{cli-5qr3z0qa.js → index-93pqkvty.js} +63 -207
- package/dist/{index-mr72vt8n.js → index-apc8w9w8.js} +55 -267
- package/dist/index-ew7cyk7c.js +2208 -0
- package/dist/index-jsz0s3dy.js +213 -0
- package/dist/index-kx03e4m4.js +3244 -0
- package/dist/index-r7jcsk6h.js +200 -0
- package/dist/index.js +71 -50
- package/dist/lib/extension-manifest.d.ts +22 -1
- package/dist/lib/markdown/assemble.d.ts +3 -2
- package/dist/lib/markdown/plugins.d.ts +20 -0
- package/dist/lib/markdown/two-versions.d.ts +32 -0
- package/dist/lib/page-size.d.ts +3 -4
- package/dist/lib/pdf-inspect.d.ts +12 -0
- package/dist/lib/project-scaffold.d.ts +3 -3
- package/dist/lib/publish/plugin-provider.d.ts +16 -0
- package/dist/lib/publish/run-publish.d.ts +13 -5
- package/dist/lib/publish/types.d.ts +34 -2
- package/dist/lib/text-diff.d.ts +43 -0
- package/dist/lib/two-versions-markers.d.ts +26 -0
- package/dist/lib/version-changes.d.ts +87 -0
- package/dist/{manifest.schema-n292sb77.json → manifest.schema-nvawq0xv.json} +2 -2
- package/dist/{new-dre6aw05.js → new-fqtt022k.js} +23 -16
- package/dist/{pdf-inspect-zdmy7qca.js → pdf-inspect-wnw4za71.js} +1 -1
- package/dist/plugins-gfvsgnxb.js +24 -0
- package/dist/plugins-nfxr831f.js +26 -0
- package/dist/{preflight-1k1zkg1p.js → preflight-gr9mscjw.js} +18 -11
- package/dist/{preview-dtrksvxf.js → preview-52w9pdps.js} +19 -13
- package/dist/{publish-g1ytnrmr.js → publish-esmcyhpb.js} +40 -23
- package/dist/render.js +706 -0
- package/dist/schema/manifest.types.d.ts +8 -3
- package/dist/{source-provider-pzmz0br9.js → source-provider-2r74a7wp.js} +2 -1
- package/dist/{source-provider-qbthnmqw.js → source-provider-qbfknhyy.js} +2 -1
- package/dist/{validate-yrrq8639.js → validate-vt1d7h6k.js} +16 -10
- package/package.json +1 -1
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
// src/lib/plugin-vendor.ts
|
|
2
|
+
import { lstat, readFile, realpath } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { exports as resolveExports } from "resolve.exports";
|
|
5
|
+
var PLUGINS_DIR = "plugins";
|
|
6
|
+
var VENDORED_NPM_DIR = "npm";
|
|
7
|
+
var NPM_SEGMENT = /^[a-z0-9][a-z0-9._~-]*$/;
|
|
8
|
+
var EXACT_VERSION = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
|
|
9
|
+
var WINDOWS_RESERVED = /^(con|prn|aux|nul|clock\$|conin\$|conout\$|com[1-9¹²³]|lpt[1-9¹²³])(?:\..*)?$/i;
|
|
10
|
+
function isValidNpmPackageName(name) {
|
|
11
|
+
if (!name || name.length > 214 || name !== name.toLowerCase())
|
|
12
|
+
return false;
|
|
13
|
+
if (name.startsWith("@")) {
|
|
14
|
+
const parts = name.slice(1).split("/");
|
|
15
|
+
return parts.length === 2 && parts.every((part) => NPM_SEGMENT.test(part));
|
|
16
|
+
}
|
|
17
|
+
return !name.includes("/") && NPM_SEGMENT.test(name);
|
|
18
|
+
}
|
|
19
|
+
function parseNpmPluginSpec(input) {
|
|
20
|
+
const spec = input.trim();
|
|
21
|
+
if (!spec)
|
|
22
|
+
throw new Error("An npm package name is required.");
|
|
23
|
+
let name = spec;
|
|
24
|
+
let selector;
|
|
25
|
+
if (spec.startsWith("@")) {
|
|
26
|
+
const slash = spec.indexOf("/");
|
|
27
|
+
const versionAt = spec.lastIndexOf("@");
|
|
28
|
+
if (slash > 1 && versionAt > slash) {
|
|
29
|
+
name = spec.slice(0, versionAt);
|
|
30
|
+
selector = spec.slice(versionAt + 1);
|
|
31
|
+
}
|
|
32
|
+
} else {
|
|
33
|
+
const versionAt = spec.lastIndexOf("@");
|
|
34
|
+
if (versionAt > 0) {
|
|
35
|
+
name = spec.slice(0, versionAt);
|
|
36
|
+
selector = spec.slice(versionAt + 1);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (!isValidNpmPackageName(name)) {
|
|
40
|
+
throw new Error(`"${name}" is not a valid npm package name. Use a name like ` + "markdown-it-highlightjs or @scope/markdown-it-plugin.");
|
|
41
|
+
}
|
|
42
|
+
if (selector !== undefined && !selector) {
|
|
43
|
+
throw new Error(`The package spec "${spec}" is missing a selector after @.`);
|
|
44
|
+
}
|
|
45
|
+
return selector === undefined ? { name } : { name, selector };
|
|
46
|
+
}
|
|
47
|
+
function isExactNpmVersion(version) {
|
|
48
|
+
return EXACT_VERSION.test(version);
|
|
49
|
+
}
|
|
50
|
+
function encodePathPart(value) {
|
|
51
|
+
return encodeURIComponent(value).replace(/[!'()*]/g, (char) => `%${char.charCodeAt(0).toString(16).toUpperCase()}`);
|
|
52
|
+
}
|
|
53
|
+
function vendoredNpmPluginRoot(projectDir, name, version) {
|
|
54
|
+
return path.join(projectDir, PLUGINS_DIR, VENDORED_NPM_DIR, encodePathPart(name), encodePathPart(version));
|
|
55
|
+
}
|
|
56
|
+
function vendoredNpmPluginPackageDir(installRoot, name) {
|
|
57
|
+
return path.join(installRoot, "node_modules", ...name.split("/"));
|
|
58
|
+
}
|
|
59
|
+
function toPosixPath(value) {
|
|
60
|
+
return value.split(path.sep).join("/");
|
|
61
|
+
}
|
|
62
|
+
function assertWindowsSafeRelativePath(relative) {
|
|
63
|
+
if (!relative || relative.includes("\\") || relative.startsWith("/") || /^[a-zA-Z]:/.test(relative)) {
|
|
64
|
+
throw new Error(`Unsafe package path: ${relative || "(empty)"}`);
|
|
65
|
+
}
|
|
66
|
+
const normalized = relative.normalize("NFKC");
|
|
67
|
+
const parts = normalized.split("/");
|
|
68
|
+
if (parts.some((part) => !part || part === "." || part === "..")) {
|
|
69
|
+
throw new Error(`Unsafe package path: ${relative}`);
|
|
70
|
+
}
|
|
71
|
+
for (const part of parts) {
|
|
72
|
+
if (part.length > 255 || /[\u0000-\u001f<>:"|?*]/.test(part) || part.endsWith(".") || part.endsWith(" ") || WINDOWS_RESERVED.test(part)) {
|
|
73
|
+
throw new Error(`Package path is invalid on Windows: ${relative}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function windowsPathKey(relative) {
|
|
78
|
+
return relative.normalize("NFKC").toLowerCase();
|
|
79
|
+
}
|
|
80
|
+
function isContained(root, candidate) {
|
|
81
|
+
const relative = path.relative(root, candidate);
|
|
82
|
+
return relative === "" || !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
83
|
+
}
|
|
84
|
+
function object(value) {
|
|
85
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
86
|
+
}
|
|
87
|
+
async function readPackageJson(packageDir) {
|
|
88
|
+
const packageJsonPath = path.join(packageDir, "package.json");
|
|
89
|
+
const info = await lstat(packageJsonPath);
|
|
90
|
+
if (!info.isFile() || info.isSymbolicLink()) {
|
|
91
|
+
throw new Error(`Package metadata is not a regular file: ${packageJsonPath}`);
|
|
92
|
+
}
|
|
93
|
+
const parsed = object(JSON.parse(await readFile(packageJsonPath, "utf8")));
|
|
94
|
+
if (!parsed)
|
|
95
|
+
throw new Error(`Package metadata is not an object: ${packageJsonPath}`);
|
|
96
|
+
return parsed;
|
|
97
|
+
}
|
|
98
|
+
function packageResolutionTargets(manifest, subpath, condition) {
|
|
99
|
+
if (manifest.exports !== undefined) {
|
|
100
|
+
try {
|
|
101
|
+
const targets2 = resolveExports(manifest, subpath ? `./${subpath}` : ".", { require: condition === "require" }) ?? [];
|
|
102
|
+
return targets2.map((target) => ({ target, exact: true }));
|
|
103
|
+
} catch {
|
|
104
|
+
return [];
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (subpath)
|
|
108
|
+
return [{ target: subpath, exact: false }];
|
|
109
|
+
const targets = [
|
|
110
|
+
...condition === "import" && typeof manifest.module === "string" ? [manifest.module] : [],
|
|
111
|
+
...typeof manifest.main === "string" ? [manifest.main] : [],
|
|
112
|
+
"index.mjs",
|
|
113
|
+
"index.js",
|
|
114
|
+
"index.cjs"
|
|
115
|
+
];
|
|
116
|
+
return [...new Set(targets)].map((target) => ({ target, exact: false }));
|
|
117
|
+
}
|
|
118
|
+
function safePackageTarget(target) {
|
|
119
|
+
if (!target || target.includes("\\") || target.includes("*") || target.includes("?") || target.includes("#")) {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
const relative = target.startsWith("./") ? target.slice(2) : target;
|
|
123
|
+
if (!relative || path.isAbsolute(relative))
|
|
124
|
+
return null;
|
|
125
|
+
assertWindowsSafeRelativePath(relative);
|
|
126
|
+
if (relative.normalize("NFKC").split("/").some((part) => part.toLowerCase() === "node_modules")) {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
return relative;
|
|
130
|
+
}
|
|
131
|
+
async function resolveEntryCandidate(packageDir, resolution) {
|
|
132
|
+
const relative = safePackageTarget(resolution.target);
|
|
133
|
+
if (!relative)
|
|
134
|
+
return null;
|
|
135
|
+
const base = path.resolve(packageDir, ...relative.split("/"));
|
|
136
|
+
if (!isContained(packageDir, base))
|
|
137
|
+
return null;
|
|
138
|
+
const candidates = resolution.exact ? [base] : [
|
|
139
|
+
base,
|
|
140
|
+
`${base}.mjs`,
|
|
141
|
+
`${base}.js`,
|
|
142
|
+
`${base}.cjs`,
|
|
143
|
+
`${base}.json`,
|
|
144
|
+
path.join(base, "index.mjs"),
|
|
145
|
+
path.join(base, "index.js"),
|
|
146
|
+
path.join(base, "index.cjs"),
|
|
147
|
+
path.join(base, "index.json")
|
|
148
|
+
];
|
|
149
|
+
for (const candidate of candidates) {
|
|
150
|
+
try {
|
|
151
|
+
const info = await lstat(candidate);
|
|
152
|
+
if (!info.isFile() || info.isSymbolicLink())
|
|
153
|
+
continue;
|
|
154
|
+
const extension = path.extname(candidate);
|
|
155
|
+
if (extension && ![".js", ".mjs", ".cjs", ".json"].includes(extension))
|
|
156
|
+
continue;
|
|
157
|
+
const [realRoot, realCandidate] = await Promise.all([realpath(packageDir), realpath(candidate)]);
|
|
158
|
+
if (!isContained(realRoot, realCandidate))
|
|
159
|
+
continue;
|
|
160
|
+
return toPosixPath(path.relative(packageDir, realCandidate));
|
|
161
|
+
} catch {}
|
|
162
|
+
}
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
async function resolvePackageEntry(packageDir, packageJson) {
|
|
166
|
+
const manifest = packageJson ?? await readPackageJson(packageDir);
|
|
167
|
+
for (const condition of ["import", "require"]) {
|
|
168
|
+
for (const target of packageResolutionTargets(manifest, "", condition)) {
|
|
169
|
+
const resolved = await resolveEntryCandidate(packageDir, target);
|
|
170
|
+
if (resolved)
|
|
171
|
+
return resolved;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
throw new Error("Package has no contained JavaScript entry point.");
|
|
175
|
+
}
|
|
176
|
+
async function resolveVendoredPluginInstallRoot(projectDir, expectedName, expectedVersion) {
|
|
177
|
+
const requestedProjectRoot = path.resolve(projectDir);
|
|
178
|
+
const requestedInstallRoot = vendoredNpmPluginRoot(requestedProjectRoot, expectedName, expectedVersion);
|
|
179
|
+
let installInfo;
|
|
180
|
+
try {
|
|
181
|
+
installInfo = await lstat(requestedInstallRoot);
|
|
182
|
+
} catch (error) {
|
|
183
|
+
if (error.code === "ENOENT")
|
|
184
|
+
return null;
|
|
185
|
+
throw error;
|
|
186
|
+
}
|
|
187
|
+
if (!installInfo.isDirectory() || installInfo.isSymbolicLink()) {
|
|
188
|
+
throw new Error("Vendor install root is not a normal directory.");
|
|
189
|
+
}
|
|
190
|
+
const [realProjectRoot, installRoot] = await Promise.all([
|
|
191
|
+
realpath(requestedProjectRoot),
|
|
192
|
+
realpath(requestedInstallRoot)
|
|
193
|
+
]);
|
|
194
|
+
if (!isContained(realProjectRoot, installRoot)) {
|
|
195
|
+
throw new Error("Vendor install root resolves outside the book folder.");
|
|
196
|
+
}
|
|
197
|
+
return installRoot;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export { PLUGINS_DIR, VENDORED_NPM_DIR, isValidNpmPackageName, parseNpmPluginSpec, isExactNpmVersion, vendoredNpmPluginRoot, vendoredNpmPluginPackageDir, toPosixPath, assertWindowsSafeRelativePath, windowsPathKey, packageResolutionTargets, safePackageTarget, resolvePackageEntry, resolveVendoredPluginInstallRoot };
|
package/dist/index.js
CHANGED
|
@@ -4,58 +4,42 @@ import {
|
|
|
4
4
|
AUTO_SYNC_MAX_MINUTES,
|
|
5
5
|
AUTO_SYNC_MIN_MINUTES,
|
|
6
6
|
AUTO_SYNC_PUSH_INTERVAL_MINUTES,
|
|
7
|
-
BUILT_IN_STYLE_SET_IDS,
|
|
8
7
|
BUILT_IN_TEMPLATE_IDS,
|
|
9
|
-
BUNDLED_EXTENSIONS,
|
|
10
|
-
DEFAULT_NPM_REGISTRY,
|
|
11
|
-
EXTENSIONS_DIR,
|
|
12
8
|
EXTENSION_KINDS,
|
|
13
|
-
EXTENSION_MANIFEST_FILENAME,
|
|
14
9
|
FileTokenStore,
|
|
15
10
|
GDRIVE_HOST,
|
|
16
11
|
GITHUB_HOST,
|
|
17
12
|
GOOGLE_NOT_CONFIGURED_MESSAGE,
|
|
18
13
|
GitHubAuthProvider,
|
|
19
14
|
GoogleAuthProvider,
|
|
20
|
-
MANIFEST_FILENAMES,
|
|
21
15
|
MAX_SEARCH_BYTES,
|
|
22
|
-
PRESETS,
|
|
23
|
-
PRESET_IDS,
|
|
24
16
|
PublishSelectionsStore,
|
|
25
|
-
RECOMMENDED_EXTENSIONS,
|
|
26
17
|
REPAIR_SNAPSHOT_MESSAGE,
|
|
27
18
|
RESERVED_PREFIX,
|
|
28
19
|
SEARCH_KEYWORDS,
|
|
29
20
|
SNIPPETS_DIR,
|
|
30
21
|
SYNC_SNAPSHOT_MESSAGE,
|
|
31
|
-
|
|
32
|
-
TARGET_IDS,
|
|
33
|
-
addBuiltInStyleSet,
|
|
34
|
-
addExtension,
|
|
22
|
+
VERSION_CHANGES_SHOWN,
|
|
35
23
|
adoptFolder,
|
|
36
|
-
assertExtensionContained,
|
|
37
24
|
autoSnapshotDelayMs,
|
|
38
25
|
autoSyncDelayMs,
|
|
39
26
|
checkCss,
|
|
40
|
-
checkExtensionUpdates,
|
|
41
27
|
checkRemoteUpdates,
|
|
42
28
|
checkToolAvailability,
|
|
43
29
|
cloneRepository,
|
|
30
|
+
compareVersionFile,
|
|
44
31
|
connectGenericHost,
|
|
45
32
|
connectGoogleDrive,
|
|
46
33
|
connectPublishProvider,
|
|
47
34
|
defaultConfigDir,
|
|
48
35
|
deleteSnippet,
|
|
49
|
-
|
|
36
|
+
describeVersions,
|
|
50
37
|
diagnoseProjectRemote,
|
|
51
38
|
disconnectPublishCredential,
|
|
52
|
-
ensureProjectGitignore,
|
|
53
39
|
escapeYamlScalar,
|
|
54
40
|
executeAndReport,
|
|
55
41
|
executeValidation,
|
|
56
|
-
|
|
57
|
-
extensionEntry,
|
|
58
|
-
extensionStyleList,
|
|
42
|
+
exportVersionTree,
|
|
59
43
|
extractUrlCredential,
|
|
60
44
|
extractVariables,
|
|
61
45
|
forgeKindForHost,
|
|
@@ -63,18 +47,15 @@ import {
|
|
|
63
47
|
getCheckById,
|
|
64
48
|
getChecks,
|
|
65
49
|
getSystemDiagnostics,
|
|
66
|
-
hasProjectManifest,
|
|
67
50
|
importExtensionFromFile,
|
|
68
51
|
importExtensionFromUrl,
|
|
69
52
|
importTemplateFromFolder,
|
|
70
53
|
inspectImage,
|
|
71
|
-
isBundledExtension,
|
|
72
54
|
isGitInternalPath,
|
|
73
|
-
isPathSpecifier,
|
|
74
55
|
isSshRemoteUrl,
|
|
75
56
|
isValidRepositoryName,
|
|
76
57
|
knownForgeTokenUrl,
|
|
77
|
-
|
|
58
|
+
listBookPublishProviders,
|
|
78
59
|
listBuiltInTemplates,
|
|
79
60
|
listCustomTemplates,
|
|
80
61
|
listGitHubBranches,
|
|
@@ -82,49 +63,34 @@ import {
|
|
|
82
63
|
listLocationVariants,
|
|
83
64
|
listMarkerComponents,
|
|
84
65
|
listMergedSnippets,
|
|
85
|
-
|
|
86
|
-
listProjectExtensions,
|
|
66
|
+
listOnlineVersions,
|
|
87
67
|
listProjectStyles,
|
|
88
68
|
listPublishAccounts,
|
|
89
69
|
listPublishProviders,
|
|
90
70
|
listRepoBooks,
|
|
91
71
|
listSnippets,
|
|
92
|
-
loadManifest,
|
|
93
|
-
loadManifestWithPath,
|
|
94
|
-
log,
|
|
95
|
-
npmRegistryUrl,
|
|
96
72
|
openPath,
|
|
97
|
-
parseExtensionSpecifier,
|
|
98
73
|
parseRemoteOrigin,
|
|
99
|
-
pathEscapesFolder,
|
|
100
74
|
pkceChallengeFromVerifier,
|
|
101
75
|
publishConnectionStatus,
|
|
102
76
|
publishCredentialKey,
|
|
103
77
|
publishProviderFor,
|
|
104
|
-
publishTargetFor,
|
|
105
|
-
readExtensionCss,
|
|
106
|
-
readExtensionMeta,
|
|
107
78
|
readManifestFields,
|
|
108
79
|
readPageSetup,
|
|
109
80
|
readPublishSettings,
|
|
110
81
|
refreshRemoteCopies,
|
|
111
|
-
removeExtension,
|
|
112
|
-
reorderExtensions,
|
|
113
82
|
repairOnlineBackup,
|
|
114
83
|
reportMissingTools,
|
|
115
84
|
requireGoogleClientCredentials,
|
|
116
85
|
resolveActiveStyles,
|
|
117
86
|
resolveCheckSelectors,
|
|
118
|
-
resolveConfig,
|
|
119
|
-
resolveExtension,
|
|
120
87
|
resolveExtensionPrefix,
|
|
121
88
|
resolveGitHubClientId,
|
|
122
89
|
resolveGoogleClientId,
|
|
123
90
|
resolveGoogleClientSecret,
|
|
124
91
|
resolvePublishFormat,
|
|
92
|
+
resolvePublishProvider,
|
|
125
93
|
resolvePublishRequest,
|
|
126
|
-
restoreFailureMessage,
|
|
127
|
-
restorePinnedExtensions,
|
|
128
94
|
revokeGoogleCredential,
|
|
129
95
|
ruleRemoteUrls,
|
|
130
96
|
ruleRiskyProps,
|
|
@@ -132,7 +98,6 @@ import {
|
|
|
132
98
|
runBuild,
|
|
133
99
|
runChecks,
|
|
134
100
|
runPublish,
|
|
135
|
-
sameExtension,
|
|
136
101
|
sanitizeCloneFolderName,
|
|
137
102
|
saveProjectAsTemplate,
|
|
138
103
|
saveSnippet,
|
|
@@ -141,7 +106,6 @@ import {
|
|
|
141
106
|
scorchedEarth,
|
|
142
107
|
searchNpmExtensions,
|
|
143
108
|
setActiveStyles,
|
|
144
|
-
setExtensionEnabled,
|
|
145
109
|
setManifestFields,
|
|
146
110
|
setPageSetup,
|
|
147
111
|
setPublishProviderConfig,
|
|
@@ -151,18 +115,66 @@ import {
|
|
|
151
115
|
startPreviewServer,
|
|
152
116
|
substituteVariables,
|
|
153
117
|
syncProject,
|
|
154
|
-
testRemoteAccess
|
|
118
|
+
testRemoteAccess
|
|
119
|
+
} from "./index-3wcr69ba.js";
|
|
120
|
+
import {
|
|
121
|
+
BUILT_IN_STYLE_SET_IDS,
|
|
122
|
+
BUNDLED_EXTENSIONS,
|
|
123
|
+
DEFAULT_NPM_REGISTRY,
|
|
124
|
+
EXTENSIONS_DIR,
|
|
125
|
+
MANIFEST_FILENAMES,
|
|
126
|
+
PRESETS,
|
|
127
|
+
PRESET_IDS,
|
|
128
|
+
RECOMMENDED_EXTENSIONS,
|
|
129
|
+
TARGETS,
|
|
130
|
+
TARGET_IDS,
|
|
131
|
+
addBuiltInStyleSet,
|
|
132
|
+
addExtension,
|
|
133
|
+
checkExtensionUpdates,
|
|
134
|
+
describeExtension,
|
|
135
|
+
ensureProjectGitignore,
|
|
136
|
+
hasProjectManifest,
|
|
137
|
+
isBundledExtension,
|
|
138
|
+
isPathSpecifier,
|
|
139
|
+
listBuiltInStyleSets,
|
|
140
|
+
listNpmVersions,
|
|
141
|
+
listProjectExtensions,
|
|
142
|
+
loadManifest,
|
|
143
|
+
loadManifestWithPath,
|
|
144
|
+
npmRegistryUrl,
|
|
145
|
+
parseExtensionSpecifier,
|
|
146
|
+
publishTargetFor,
|
|
147
|
+
readExtensionCss,
|
|
148
|
+
removeExtension,
|
|
149
|
+
reorderExtensions,
|
|
150
|
+
resolveConfig,
|
|
151
|
+
restoreFailureMessage,
|
|
152
|
+
restorePinnedExtensions,
|
|
153
|
+
sameExtension,
|
|
154
|
+
setExtensionEnabled,
|
|
155
155
|
updateExtensions,
|
|
156
156
|
validateProjectExtensions
|
|
157
|
-
} from "./index-
|
|
157
|
+
} from "./index-ew7cyk7c.js";
|
|
158
|
+
import {
|
|
159
|
+
EXTENSION_MANIFEST_FILENAME,
|
|
160
|
+
assertExtensionContained,
|
|
161
|
+
extensionCarries,
|
|
162
|
+
extensionEntry,
|
|
163
|
+
extensionStyleList,
|
|
164
|
+
log,
|
|
165
|
+
pathEscapesFolder,
|
|
166
|
+
readExtensionMeta,
|
|
167
|
+
resolveExtension
|
|
168
|
+
} from "./index-kx03e4m4.js";
|
|
158
169
|
import"./index-ht1bcqdd.js";
|
|
159
170
|
import {
|
|
160
171
|
BUILD_DIAGNOSTIC_CODES
|
|
161
|
-
} from "./index-
|
|
172
|
+
} from "./index-2d8j0enc.js";
|
|
173
|
+
import"./index-apc8w9w8.js";
|
|
162
174
|
import {
|
|
163
175
|
BuildError
|
|
164
|
-
} from "./index-
|
|
165
|
-
import"./index-
|
|
176
|
+
} from "./index-jsz0s3dy.js";
|
|
177
|
+
import"./index-2ppw6q9v.js";
|
|
166
178
|
import {
|
|
167
179
|
DEFAULT_PRINT_OPTS,
|
|
168
180
|
assertMilestone,
|
|
@@ -171,7 +183,6 @@ import {
|
|
|
171
183
|
import {
|
|
172
184
|
AUTO_SNAPSHOT_MESSAGE,
|
|
173
185
|
HISTORY_PAGE_LIMIT,
|
|
174
|
-
PLUGINS_DIR,
|
|
175
186
|
RESTORE_BACKUP_MESSAGE,
|
|
176
187
|
SWITCH_BRANCH_SNAPSHOT_MESSAGE,
|
|
177
188
|
countUnversionedChanges,
|
|
@@ -182,7 +193,10 @@ import {
|
|
|
182
193
|
restoreVersionWithBackup,
|
|
183
194
|
switchBranch,
|
|
184
195
|
whenGitIdle
|
|
185
|
-
} from "./index-
|
|
196
|
+
} from "./index-93pqkvty.js";
|
|
197
|
+
import {
|
|
198
|
+
PLUGINS_DIR
|
|
199
|
+
} from "./index-r7jcsk6h.js";
|
|
186
200
|
import {
|
|
187
201
|
capabilitiesFor,
|
|
188
202
|
detectProjectSource,
|
|
@@ -227,6 +241,7 @@ export {
|
|
|
227
241
|
restorePinnedExtensions,
|
|
228
242
|
restoreFailureMessage,
|
|
229
243
|
resolvePublishRequest,
|
|
244
|
+
resolvePublishProvider,
|
|
230
245
|
resolvePublishFormat,
|
|
231
246
|
resolveLogger,
|
|
232
247
|
resolveGoogleClientSecret,
|
|
@@ -271,6 +286,7 @@ export {
|
|
|
271
286
|
listPublishAccounts,
|
|
272
287
|
listProjectStyles,
|
|
273
288
|
listProjectExtensions,
|
|
289
|
+
listOnlineVersions,
|
|
274
290
|
listNpmVersions,
|
|
275
291
|
listMergedSnippets,
|
|
276
292
|
listMarkerComponents,
|
|
@@ -281,6 +297,7 @@ export {
|
|
|
281
297
|
listCustomTemplates,
|
|
282
298
|
listBuiltInTemplates,
|
|
283
299
|
listBuiltInStyleSets,
|
|
300
|
+
listBookPublishProviders,
|
|
284
301
|
knownForgeTokenUrl,
|
|
285
302
|
isValidRepositoryName,
|
|
286
303
|
isSshRemoteUrl,
|
|
@@ -304,6 +321,7 @@ export {
|
|
|
304
321
|
extensionStyleList,
|
|
305
322
|
extensionEntry,
|
|
306
323
|
extensionCarries,
|
|
324
|
+
exportVersionTree,
|
|
307
325
|
executeValidation,
|
|
308
326
|
executeAndReport,
|
|
309
327
|
escapeYamlScalar,
|
|
@@ -311,6 +329,7 @@ export {
|
|
|
311
329
|
disconnectPublishCredential,
|
|
312
330
|
diagnoseProjectRemote,
|
|
313
331
|
detectProjectSource,
|
|
332
|
+
describeVersions,
|
|
314
333
|
describeExtension,
|
|
315
334
|
deleteSnippet,
|
|
316
335
|
defaultConfigDir,
|
|
@@ -318,6 +337,7 @@ export {
|
|
|
318
337
|
connectPublishProvider,
|
|
319
338
|
connectGoogleDrive,
|
|
320
339
|
connectGenericHost,
|
|
340
|
+
compareVersionFile,
|
|
321
341
|
cloneRepository,
|
|
322
342
|
checkToolAvailability,
|
|
323
343
|
checkRemoteUpdates,
|
|
@@ -331,6 +351,7 @@ export {
|
|
|
331
351
|
adoptFolder,
|
|
332
352
|
addExtension,
|
|
333
353
|
addBuiltInStyleSet,
|
|
354
|
+
VERSION_CHANGES_SHOWN,
|
|
334
355
|
TARGET_IDS,
|
|
335
356
|
TARGETS,
|
|
336
357
|
SYNC_SNAPSHOT_MESSAGE,
|
|
@@ -70,6 +70,15 @@ export interface ExtensionMetadata {
|
|
|
70
70
|
* does the merge.
|
|
71
71
|
*/
|
|
72
72
|
snippets?: string;
|
|
73
|
+
/**
|
|
74
|
+
* `gutterpress.publish: true` — EXPERIMENTAL (#381): the package is a
|
|
75
|
+
* publishing plugin. Its entry (npm `main`/`exports`, or a folder's `main`)
|
|
76
|
+
* exports a named `publish` function and contributes NO markdown-it plugin,
|
|
77
|
+
* so the markdown loader skips it without importing it. A boolean, not a
|
|
78
|
+
* path: it lets core recognise a publisher from package.json alone, without
|
|
79
|
+
* executing its code. Anything other than literal `true` reads as absent.
|
|
80
|
+
*/
|
|
81
|
+
publish?: boolean;
|
|
73
82
|
/**
|
|
74
83
|
* npm `engines.gutterpress` — the Gutterpress versions the extension works
|
|
75
84
|
* with, as a semver range (e.g. `">=0.11.20-alpha.3"`). Checked when the
|
|
@@ -98,7 +107,8 @@ export declare function extensionStyleList(meta: ExtensionMetadata): string[];
|
|
|
98
107
|
* The markdown-it entry of a FOLDER extension: an explicit
|
|
99
108
|
* `gutterpress.markdown` when the package's `main` is not the plugin,
|
|
100
109
|
* otherwise npm's own `main`. `undefined` for a folder that carries no
|
|
101
|
-
* markdown behaviour at all (a look
|
|
110
|
+
* markdown behaviour at all (a look, or a publishing plugin — whose `main` is
|
|
111
|
+
* its publish module, not a markdown-it plugin).
|
|
102
112
|
*/
|
|
103
113
|
export declare function extensionEntry(meta: ExtensionMetadata): string | undefined;
|
|
104
114
|
/** What an extension declares, by field — the desktop's one-list filter. */
|
|
@@ -107,8 +117,19 @@ export interface ExtensionCarries {
|
|
|
107
117
|
styles: boolean;
|
|
108
118
|
snippets: boolean;
|
|
109
119
|
components: boolean;
|
|
120
|
+
/** A publishing plugin (experimental, #381). */
|
|
121
|
+
publish: boolean;
|
|
110
122
|
}
|
|
111
123
|
export declare function extensionCarries(meta: ExtensionMetadata): ExtensionCarries;
|
|
124
|
+
/**
|
|
125
|
+
* A publishing plugin (experimental, #381) is a publisher and nothing else:
|
|
126
|
+
* its entry is never imported while a book renders, so a markdown entry,
|
|
127
|
+
* styles, components or snippets it also declared would either load (a
|
|
128
|
+
* folder) or be dropped without a word (a vendored copy). One rule, checked
|
|
129
|
+
* here, keeps both load paths and the publish path agreeing. Not a listing
|
|
130
|
+
* guard — `readExtensionMeta` stays tolerant.
|
|
131
|
+
*/
|
|
132
|
+
export declare function assertPublishOnly(meta: ExtensionMetadata, ref: string): void;
|
|
112
133
|
/**
|
|
113
134
|
* True when a declared relative path escapes its own folder (absolute, or a
|
|
114
135
|
* `..` segment) — the traversal shape every containment check in this
|
|
@@ -132,8 +132,9 @@ export interface AssembleBookHtmlOptions {
|
|
|
132
132
|
* preset id and printer spec — written as `<meta name="gp-print-area">`
|
|
133
133
|
* (engine/shared/print-area.ts) into EVERY assembled book, preview, build
|
|
134
134
|
* and publish alike: the preview's print overlays judge the ink against it,
|
|
135
|
-
* and both engines place pinned art on its art-safe line. Metadata only
|
|
136
|
-
*
|
|
135
|
+
* and both engines place pinned art on its art-safe line. Metadata only,
|
|
136
|
+
* with one exception: its `width` x `height` is also the page size the book
|
|
137
|
+
* prints at when no stylesheet sets one — see {@link defaultPageSizeCss}.
|
|
137
138
|
*/
|
|
138
139
|
printArea?: PrintAreaSource;
|
|
139
140
|
plugins?: LoadedPlugin[];
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ResolvedExtensionConfig } from "../../schema/manifest.types";
|
|
2
|
+
import type { PublishPluginFunction } from "../publish/types";
|
|
2
3
|
import type { LoadedPlugin } from "./renderer";
|
|
3
4
|
export type { GutterpressComponent, GutterpressComponentBlock, GutterpressComponentProblem, GutterpressMarkerDeclaration, GutterpressMarkerLabel, GutterpressMarkerTable, GutterpressPlugin, GutterpressPluginMetadata, GutterpressPluginExport, LoadedPlugin, } from "./renderer";
|
|
4
5
|
export { applyPlugins, collectPluginCss, collectPluginStylePaths, collectPluginStyleGroups } from "./renderer";
|
|
@@ -7,6 +8,25 @@ import { type PluginStyleGroup } from "./renderer";
|
|
|
7
8
|
/** Test-only: reset the path-plugin cache between test cases. */
|
|
8
9
|
export declare function __resetPathPluginCacheForTests(): void;
|
|
9
10
|
export declare function loadPlugin(config: ResolvedExtensionConfig, baseDir: string): Promise<LoadedPlugin>;
|
|
11
|
+
/** Where a publishing plugin's package sits, as discovery found it. */
|
|
12
|
+
export interface PublishPluginLocation {
|
|
13
|
+
/** The package folder: a `path:` folder, or the vendored copy's package dir. */
|
|
14
|
+
dir: string;
|
|
15
|
+
/** The vendored install root of an npm entry; `null` for a folder. */
|
|
16
|
+
installRoot: string | null;
|
|
17
|
+
/** The manifest spelling, for messages. */
|
|
18
|
+
ref: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* EXPERIMENTAL (#381): import a publishing plugin's entry and return its
|
|
22
|
+
* named `publish` export. Only the publish path calls this — never a build or
|
|
23
|
+
* preview (see the skip in {@link loadPlugin}). The package is the one
|
|
24
|
+
* discovery located, so there is no second lookup and no fall-through to a
|
|
25
|
+
* same-named package elsewhere: a vendored copy loads through
|
|
26
|
+
* {@link importVendoredEntry}, a folder's `main` through the mtime cache, so
|
|
27
|
+
* the long-lived desktop host sees edits.
|
|
28
|
+
*/
|
|
29
|
+
export declare function loadPublishFunction({ dir, installRoot, ref }: PublishPluginLocation): Promise<PublishPluginFunction>;
|
|
10
30
|
/**
|
|
11
31
|
* Load all plugins from the resolved configuration.
|
|
12
32
|
*
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `two_versions` — renders a passage the converge merge left with TWO
|
|
3
|
+
* versions as two labelled boxes instead of broken markdown.
|
|
4
|
+
*
|
|
5
|
+
* After a sync that found a passage edited both here and online, the file
|
|
6
|
+
* holds both versions inside the marker family `two-versions-markers.ts`
|
|
7
|
+
* spells out. Those lines are valid markdown — `=======` is a setext
|
|
8
|
+
* underline, `>>>>>>>` seven nested blockquotes — so until this rule the
|
|
9
|
+
* preview showed the author's paragraph as a chapter-sized heading, listed
|
|
10
|
+
* `<<<<<<< your version` in the outline, and gave no way to read either
|
|
11
|
+
* version as it would print. The `source.sync.merge-markers` check still
|
|
12
|
+
* reports every block as an error, so a build never ships one; this rule
|
|
13
|
+
* only decides what the LIVE PREVIEW shows while the author chooses.
|
|
14
|
+
*
|
|
15
|
+
* The output is plain HTML + CSS: a `div.gp-two-versions` holding two
|
|
16
|
+
* `div.gp-version`s (`-yours`, `-online`), each labelled through
|
|
17
|
+
* `data-label` and each parsed as ordinary block markdown, so a heading or
|
|
18
|
+
* a list inside a version renders as one. No viewer or print code reads
|
|
19
|
+
* these classes; `TWO_VERSIONS_CSS` is the whole styling. Matching is as
|
|
20
|
+
* exact as the check's: the three fixed lines, at the start of a line, in
|
|
21
|
+
* order; anything else (a bare `=======`, a half-deleted family) is left
|
|
22
|
+
* to markdown as before.
|
|
23
|
+
*/
|
|
24
|
+
import type MarkdownIt from "markdown-it";
|
|
25
|
+
/** The styling for the block above — injected by assemble.ts with MARKER_CSS. */
|
|
26
|
+
export declare const TWO_VERSIONS_CSS = "\n.gp-two-versions {\n margin: 1em 0;\n border: 2px dashed #b7791f;\n border-radius: 6px;\n break-inside: avoid;\n}\n.gp-two-versions > .gp-version {\n padding: 0.5em 0.9em;\n}\n.gp-two-versions > .gp-version + .gp-version {\n border-top: 2px dashed #b7791f;\n}\n.gp-two-versions > .gp-version > .gp-version-text {\n margin: 0;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n font-size: 0.85em;\n}\n.gp-two-versions > .gp-version::before {\n content: attr(data-label);\n display: block;\n margin-bottom: 0.35em;\n font-family: system-ui, sans-serif;\n font-size: 0.7em;\n font-weight: 700;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n color: #b7791f;\n}\n";
|
|
27
|
+
/**
|
|
28
|
+
* markdown-it plugin. Before `html_block` so the `<` opener is ours first;
|
|
29
|
+
* listed as a paragraph terminator so a block that starts right under a
|
|
30
|
+
* line of prose (as the merge writes it) still opens.
|
|
31
|
+
*/
|
|
32
|
+
export default function gpTwoVersions(md: MarkdownIt): void;
|
package/dist/lib/page-size.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { Document } from "yaml";
|
|
2
2
|
import { type PresetId } from "./presets.ts";
|
|
3
|
+
import { formatPageSize, isPositivePoints } from "../engine/shared/print-area.ts";
|
|
4
|
+
export { formatPageSize, isPositivePoints };
|
|
3
5
|
/** Page bounds written to the manifest's `page:` block (points; 72pt = 1in). */
|
|
4
6
|
export interface CustomPageOptions {
|
|
5
7
|
/** Trim width in points (72pt = 1in). */
|
|
@@ -28,12 +30,11 @@ export interface PageSetup {
|
|
|
28
30
|
bounds: (PageSizePoints & {
|
|
29
31
|
tolerance: number;
|
|
30
32
|
}) | null;
|
|
31
|
-
/** What the book's stylesheets print at, or null when no plain `@page` sets a size. */
|
|
33
|
+
/** What the book's stylesheets print at, or null when no plain `@page` sets a size (the book then prints at `bounds`). */
|
|
32
34
|
css: (PageSizePoints & {
|
|
33
35
|
file: string;
|
|
34
36
|
}) | null;
|
|
35
37
|
}
|
|
36
|
-
export declare function isPositivePoints(value: unknown): value is number;
|
|
37
38
|
/**
|
|
38
39
|
* Write the manifest's `page:` bounds. `tolerance` defaults to whatever the
|
|
39
40
|
* block already carries, so re-sizing a book never silently resets a
|
|
@@ -43,8 +44,6 @@ export declare function isPositivePoints(value: unknown): value is number;
|
|
|
43
44
|
export declare function writePageBounds(doc: Document, page: CustomPageOptions): void;
|
|
44
45
|
/** The size (points) a choice means: `custom` brings its own, the others are the preset's. */
|
|
45
46
|
export declare function pageSizeForChoice(choice: PageSizeChoice): PageSizePoints;
|
|
46
|
-
/** The `size` value written for a page: `8.5in 11in`, `595pt 842pt`. */
|
|
47
|
-
export declare function formatPageSize(page: PageSizePoints): string;
|
|
48
47
|
/** The size the LAST plain `@page { size }` in the stylesheet sets (cascade: last wins), or null. */
|
|
49
48
|
export declare function readPageSizeFromCss(css: string): PageSizePoints | null;
|
|
50
49
|
/**
|
|
@@ -122,6 +122,18 @@ export interface ImageRef {
|
|
|
122
122
|
*/
|
|
123
123
|
x: number;
|
|
124
124
|
y: number;
|
|
125
|
+
/**
|
|
126
|
+
* The drawn rect in points, y up from the sheet's bottom: the unit square
|
|
127
|
+
* under the CTM as its axis-aligned bounds, so it holds for an image drawn
|
|
128
|
+
* flipped or rotated where `x`/`y`/`placedW`/`placedH` do not. The
|
|
129
|
+
* `pdf.print.safe-margins` check judges it against the art rule.
|
|
130
|
+
*/
|
|
131
|
+
bounds: {
|
|
132
|
+
x: number;
|
|
133
|
+
y: number;
|
|
134
|
+
w: number;
|
|
135
|
+
h: number;
|
|
136
|
+
};
|
|
125
137
|
/** 1-based page number. */
|
|
126
138
|
page: number;
|
|
127
139
|
}
|
|
@@ -64,9 +64,9 @@ export interface CreateProjectOptions {
|
|
|
64
64
|
/**
|
|
65
65
|
* Page geometry written into the generated manifest (points; 72pt = 1in).
|
|
66
66
|
* REQUIRED when `preset` is `"custom"` (it has no built-in trim); allowed
|
|
67
|
-
* with any preset to override its trim.
|
|
68
|
-
*
|
|
69
|
-
*
|
|
67
|
+
* with any preset to override its trim. This is the size the book prints
|
|
68
|
+
* at, unless a stylesheet sets its own plain `@page { size }` (#415), and
|
|
69
|
+
* the size the built PDF is checked against — so the two should match.
|
|
70
70
|
*/
|
|
71
71
|
customPage?: CustomPageOptions;
|
|
72
72
|
/** Version-history mode for the new project. Defaults to `"local-git"`. */
|