@vivliostyle/cli 9.8.4 → 10.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +74 -30
- package/dist/{chunk-LI2REENX.js → chunk-2M2KXPDN.js} +16 -17
- package/dist/chunk-2M2KXPDN.js.map +1 -0
- package/dist/{chunk-PBAUN5CU.js → chunk-5DB6XVJN.js} +2 -2
- package/dist/chunk-5DB6XVJN.js.map +1 -0
- package/dist/{chunk-HYY2WKJZ.js → chunk-5K3NGLBV.js} +6 -7
- package/dist/chunk-5K3NGLBV.js.map +1 -0
- package/dist/{chunk-YUYXQJDY.js → chunk-IIKRNYAM.js} +470 -238
- package/dist/chunk-IIKRNYAM.js.map +1 -0
- package/dist/{chunk-MDTA37GZ.js → chunk-MQYXBSRJ.js} +397 -88
- package/dist/chunk-MQYXBSRJ.js.map +1 -0
- package/dist/chunk-RPMMYPTR.js +1076 -0
- package/dist/chunk-RPMMYPTR.js.map +1 -0
- package/dist/{chunk-PPI5DA75.js → chunk-YN3JNBNT.js} +425 -374
- package/dist/chunk-YN3JNBNT.js.map +1 -0
- package/dist/{chunk-QOPM72CS.js → chunk-YVNDJXMI.js} +32 -33
- package/dist/chunk-YVNDJXMI.js.map +1 -0
- package/dist/{chunk-FXUEYQRY.js → chunk-ZIK6DINS.js} +3 -3
- package/dist/chunk-ZIK6DINS.js.map +1 -0
- package/dist/chunk-ZKEIYNLT.js +331 -0
- package/dist/chunk-ZKEIYNLT.js.map +1 -0
- package/dist/cli.js +7 -8
- package/dist/cli.js.map +1 -1
- package/dist/commands/build.js +29 -17
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/create.d.ts +2 -0
- package/dist/commands/create.js +64 -0
- package/dist/commands/create.js.map +1 -0
- package/dist/commands/init.js +23 -14
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/preview.js +26 -20
- package/dist/commands/preview.js.map +1 -1
- package/dist/config/schema.d.ts +9034 -4436
- package/dist/config/schema.js +20 -4
- package/dist/index.d.ts +46 -7
- package/dist/index.js +24 -16
- package/dist/index.js.map +1 -1
- package/dist/node-modules.d.ts +5 -5
- package/dist/node-modules.js +1 -1
- package/dist/vite-adapter.d.ts +1 -0
- package/dist/vite-adapter.js +6 -6
- package/package.json +38 -27
- package/dist/chunk-3VKIUKTD.js +0 -89
- package/dist/chunk-3VKIUKTD.js.map +0 -1
- package/dist/chunk-4IIM6RSG.js +0 -71
- package/dist/chunk-4IIM6RSG.js.map +0 -1
- package/dist/chunk-FXUEYQRY.js.map +0 -1
- package/dist/chunk-HYY2WKJZ.js.map +0 -1
- package/dist/chunk-LI2REENX.js.map +0 -1
- package/dist/chunk-MDTA37GZ.js.map +0 -1
- package/dist/chunk-PBAUN5CU.js.map +0 -1
- package/dist/chunk-PPI5DA75.js.map +0 -1
- package/dist/chunk-QOPM72CS.js.map +0 -1
- package/dist/chunk-YUYXQJDY.js.map +0 -1
- package/types/playwright.d.ts +0 -49
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
importNodeModule
|
|
3
|
-
} from "./chunk-FXUEYQRY.js";
|
|
4
1
|
import {
|
|
5
2
|
DetailError,
|
|
3
|
+
GlobMatcher,
|
|
6
4
|
Logger,
|
|
7
5
|
assertPubManifestSchema,
|
|
8
6
|
cwd,
|
|
9
7
|
debounce,
|
|
8
|
+
detectBrowserPlatform,
|
|
9
|
+
getAssetMatcher,
|
|
10
|
+
getCacheDir,
|
|
11
|
+
getDefaultBrowserTag,
|
|
10
12
|
getDefaultEpubOpfPath,
|
|
11
13
|
getEpubRootDir,
|
|
12
14
|
getFormattedError,
|
|
15
|
+
getOsLocale,
|
|
16
|
+
getWebPubResourceMatcher,
|
|
13
17
|
isInContainer,
|
|
14
18
|
isRunningOnWSL,
|
|
15
19
|
isValidUri,
|
|
@@ -26,15 +30,16 @@ import {
|
|
|
26
30
|
touchTmpFile,
|
|
27
31
|
useTmpDirectory,
|
|
28
32
|
writeFileIfChanged
|
|
29
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-MQYXBSRJ.js";
|
|
30
34
|
import {
|
|
31
35
|
VivliostyleConfigSchema
|
|
32
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-IIKRNYAM.js";
|
|
33
37
|
import {
|
|
34
38
|
CONTAINER_LOCAL_HOSTNAME,
|
|
35
39
|
CONTAINER_URL,
|
|
36
40
|
COVER_HTML_FILENAME,
|
|
37
41
|
COVER_HTML_IMAGE_ALT,
|
|
42
|
+
DEFAULT_BROWSER_VERSIONS,
|
|
38
43
|
EMPTY_DATA_URI,
|
|
39
44
|
EPUB_CONTAINER_XML,
|
|
40
45
|
EPUB_LANDMARKS_COVER_ENTRY,
|
|
@@ -49,7 +54,10 @@ import {
|
|
|
49
54
|
XML_DECLARATION,
|
|
50
55
|
cliVersion,
|
|
51
56
|
viewerRoot
|
|
52
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-ZKEIYNLT.js";
|
|
58
|
+
import {
|
|
59
|
+
importNodeModule
|
|
60
|
+
} from "./chunk-ZIK6DINS.js";
|
|
53
61
|
import {
|
|
54
62
|
__callDispose,
|
|
55
63
|
__using
|
|
@@ -180,7 +188,7 @@ function mergeInlineConfig({ tasks, inlineOptions }, inlineConfig) {
|
|
|
180
188
|
renderMode,
|
|
181
189
|
preflight,
|
|
182
190
|
preflightOption,
|
|
183
|
-
vite,
|
|
191
|
+
vite: vite5,
|
|
184
192
|
viteConfigFile,
|
|
185
193
|
host,
|
|
186
194
|
port,
|
|
@@ -202,7 +210,7 @@ function mergeInlineConfig({ tasks, inlineOptions }, inlineConfig) {
|
|
|
202
210
|
viewer,
|
|
203
211
|
viewerParam,
|
|
204
212
|
browser,
|
|
205
|
-
vite,
|
|
213
|
+
vite: vite5,
|
|
206
214
|
viteConfigFile
|
|
207
215
|
}),
|
|
208
216
|
output: (output?.length ? output : task.output)?.map((o) => ({
|
|
@@ -220,6 +228,11 @@ function mergeInlineConfig({ tasks, inlineOptions }, inlineConfig) {
|
|
|
220
228
|
})),
|
|
221
229
|
inlineOptions: {
|
|
222
230
|
...pruneObject(inlineOptions),
|
|
231
|
+
...pruneObject({
|
|
232
|
+
renderMode,
|
|
233
|
+
preflight,
|
|
234
|
+
preflightOption
|
|
235
|
+
}),
|
|
223
236
|
...pruneObject(
|
|
224
237
|
overrideInlineOptions
|
|
225
238
|
)
|
|
@@ -228,7 +241,10 @@ function mergeInlineConfig({ tasks, inlineOptions }, inlineConfig) {
|
|
|
228
241
|
}
|
|
229
242
|
|
|
230
243
|
// src/config/resolve.ts
|
|
231
|
-
import {
|
|
244
|
+
import {
|
|
245
|
+
readMetadata,
|
|
246
|
+
VFM
|
|
247
|
+
} from "@vivliostyle/vfm";
|
|
232
248
|
import { lookup as mime } from "mime-types";
|
|
233
249
|
import fs3 from "node:fs";
|
|
234
250
|
import { fileURLToPath, pathToFileURL as pathToFileURL2 } from "node:url";
|
|
@@ -236,38 +252,31 @@ import npa from "npm-package-arg";
|
|
|
236
252
|
import upath2 from "upath";
|
|
237
253
|
|
|
238
254
|
// src/processor/markdown.ts
|
|
239
|
-
import {
|
|
240
|
-
readMetadata
|
|
241
|
-
} from "@vivliostyle/vfm";
|
|
242
255
|
import fs2 from "node:fs";
|
|
243
256
|
import vfile from "vfile";
|
|
244
|
-
function
|
|
245
|
-
try {
|
|
246
|
-
return readMetadata(content);
|
|
247
|
-
} catch {
|
|
248
|
-
return {};
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
async function processMarkdown(documentProcessorFactory, filepath, options = {}) {
|
|
257
|
+
async function processMarkdown(documentProcessorFactory, documentMetadataReader, filepath, options = {}) {
|
|
252
258
|
const markdownString = fs2.readFileSync(filepath, "utf8");
|
|
253
259
|
const processor = documentProcessorFactory(
|
|
254
260
|
options,
|
|
255
|
-
|
|
261
|
+
documentMetadataReader(markdownString)
|
|
256
262
|
);
|
|
257
263
|
const processed = await processor.process(
|
|
258
264
|
vfile({ path: filepath, contents: markdownString })
|
|
259
265
|
);
|
|
260
266
|
return processed;
|
|
261
267
|
}
|
|
262
|
-
function readMarkdownMetadata(filepath) {
|
|
263
|
-
return
|
|
268
|
+
function readMarkdownMetadata(filepath, documentMetadataReader) {
|
|
269
|
+
return documentMetadataReader(fs2.readFileSync(filepath, "utf8"));
|
|
264
270
|
}
|
|
265
271
|
|
|
266
272
|
// src/config/resolve.ts
|
|
267
273
|
var manuscriptMediaTypes = [
|
|
268
274
|
"text/markdown",
|
|
269
275
|
"text/html",
|
|
270
|
-
"
|
|
276
|
+
"text/plain",
|
|
277
|
+
"application/xhtml+xml",
|
|
278
|
+
// a special MIME type indicates that a custom processor is used
|
|
279
|
+
"text/x-vivliostyle-custom"
|
|
271
280
|
];
|
|
272
281
|
var UseTemporaryServerRoot = Symbol("UseTemporaryServerRoot");
|
|
273
282
|
var DEFAULT_ASSET_EXTENSIONS = [
|
|
@@ -288,6 +297,17 @@ var DEFAULT_ASSET_EXTENSIONS = [
|
|
|
288
297
|
function isManuscriptMediaType(mediaType) {
|
|
289
298
|
return !!(mediaType && manuscriptMediaTypes.includes(mediaType));
|
|
290
299
|
}
|
|
300
|
+
var htmlExtensions = [".html", ".htm", ".xhtml", ".xht"];
|
|
301
|
+
function toHtmlExtension(filename) {
|
|
302
|
+
const ext = upath2.extname(filename).toLowerCase();
|
|
303
|
+
if (htmlExtensions.includes(
|
|
304
|
+
// @ts-expect-error check membership
|
|
305
|
+
ext
|
|
306
|
+
)) {
|
|
307
|
+
return filename;
|
|
308
|
+
}
|
|
309
|
+
return `${filename.slice(0, -ext.length)}.html`;
|
|
310
|
+
}
|
|
291
311
|
function isWebPubConfig(config) {
|
|
292
312
|
return config.viewerInput.type === "webpub";
|
|
293
313
|
}
|
|
@@ -377,13 +397,14 @@ function parseFileMetadata({
|
|
|
377
397
|
contentType,
|
|
378
398
|
sourcePath,
|
|
379
399
|
workspaceDir,
|
|
380
|
-
themesDir
|
|
400
|
+
themesDir,
|
|
401
|
+
documentMetadataReader
|
|
381
402
|
}) {
|
|
382
403
|
const sourceDir = upath2.dirname(sourcePath);
|
|
383
404
|
let title;
|
|
384
405
|
let themes;
|
|
385
|
-
if (
|
|
386
|
-
const metadata = readMarkdownMetadata(sourcePath);
|
|
406
|
+
if (documentMetadataReader) {
|
|
407
|
+
const metadata = readMarkdownMetadata(sourcePath, documentMetadataReader);
|
|
387
408
|
title = metadata.title;
|
|
388
409
|
if (metadata.vfm?.theme && themesDir) {
|
|
389
410
|
themes = [metadata.vfm.theme].flat().filter(
|
|
@@ -397,7 +418,7 @@ function parseFileMetadata({
|
|
|
397
418
|
})
|
|
398
419
|
);
|
|
399
420
|
}
|
|
400
|
-
} else {
|
|
421
|
+
} else if (contentType === "text/html" || contentType === "application/xhtml+xml") {
|
|
401
422
|
const content = fs3.readFileSync(sourcePath, "utf8");
|
|
402
423
|
title = content.match(/<title>([^<]*)<\/title>/)?.[1] || void 0;
|
|
403
424
|
}
|
|
@@ -437,7 +458,6 @@ function resolveTaskConfig(config, options) {
|
|
|
437
458
|
const singleDoc = options.singleDoc ?? false;
|
|
438
459
|
const quick = options.quick ?? false;
|
|
439
460
|
const temporaryFilePrefix = config.temporaryFilePrefix ?? `.vs-${Date.now()}.`;
|
|
440
|
-
const documentProcessorFactory = config?.documentProcessor ?? VFM;
|
|
441
461
|
const vfmOptions = {
|
|
442
462
|
...config?.vfm,
|
|
443
463
|
hardLineBreaks: config?.vfm?.hardLineBreaks ?? false,
|
|
@@ -445,10 +465,15 @@ function resolveTaskConfig(config, options) {
|
|
|
445
465
|
};
|
|
446
466
|
const timeout = config.timeout ?? 3e5;
|
|
447
467
|
const sandbox = options.sandbox ?? false;
|
|
448
|
-
const browser = {
|
|
449
|
-
type
|
|
450
|
-
|
|
451
|
-
|
|
468
|
+
const browser = (() => {
|
|
469
|
+
const type = config.browser?.type ?? "chrome";
|
|
470
|
+
const platform = detectBrowserPlatform();
|
|
471
|
+
return {
|
|
472
|
+
type,
|
|
473
|
+
tag: config.browser?.tag ?? (platform ? DEFAULT_BROWSER_VERSIONS[type][platform] : "latest"),
|
|
474
|
+
executablePath: options.executableBrowser
|
|
475
|
+
};
|
|
476
|
+
})();
|
|
452
477
|
const proxyServer = options.proxyServer ?? process.env.HTTP_PROXY ?? void 0;
|
|
453
478
|
const proxy = proxyServer ? {
|
|
454
479
|
server: proxyServer,
|
|
@@ -611,7 +636,6 @@ function resolveTaskConfig(config, options) {
|
|
|
611
636
|
quick,
|
|
612
637
|
language,
|
|
613
638
|
readingProgression,
|
|
614
|
-
documentProcessorFactory,
|
|
615
639
|
vfmOptions,
|
|
616
640
|
cover,
|
|
617
641
|
timeout,
|
|
@@ -691,15 +715,22 @@ function resolveSingleInputConfig({
|
|
|
691
715
|
const themesDir = upath2.resolve(workspaceDir, "themes");
|
|
692
716
|
if (input.format === "markdown") {
|
|
693
717
|
const contentType = "text/markdown";
|
|
718
|
+
const documentProcessor = {
|
|
719
|
+
processorFactory: config.documentProcessor ?? VFM,
|
|
720
|
+
metadataReader: config.documentMetadataReader ?? readMetadata
|
|
721
|
+
};
|
|
694
722
|
const metadata = parseFileMetadata({
|
|
695
723
|
contentType,
|
|
696
724
|
sourcePath,
|
|
697
|
-
workspaceDir
|
|
698
|
-
});
|
|
699
|
-
const target = upath2.resolve(
|
|
700
725
|
workspaceDir,
|
|
701
|
-
|
|
702
|
-
)
|
|
726
|
+
documentMetadataReader: documentProcessor.metadataReader
|
|
727
|
+
});
|
|
728
|
+
const target = toHtmlExtension(
|
|
729
|
+
upath2.resolve(
|
|
730
|
+
workspaceDir,
|
|
731
|
+
`${temporaryFilePrefix}${upath2.basename(sourcePath)}`
|
|
732
|
+
)
|
|
733
|
+
);
|
|
703
734
|
touchTmpFile(target);
|
|
704
735
|
const themes = metadata.themes ?? config.theme?.map(
|
|
705
736
|
(theme) => parseTheme({
|
|
@@ -715,7 +746,8 @@ function resolveSingleInputConfig({
|
|
|
715
746
|
source: {
|
|
716
747
|
type: "file",
|
|
717
748
|
pathname: sourcePath,
|
|
718
|
-
contentType
|
|
749
|
+
contentType,
|
|
750
|
+
documentProcessor
|
|
719
751
|
},
|
|
720
752
|
target,
|
|
721
753
|
title: metadata.title,
|
|
@@ -725,7 +757,7 @@ function resolveSingleInputConfig({
|
|
|
725
757
|
source: target,
|
|
726
758
|
target: upath2.resolve(
|
|
727
759
|
upath2.dirname(target),
|
|
728
|
-
upath2.basename(sourcePath)
|
|
760
|
+
toHtmlExtension(upath2.basename(sourcePath))
|
|
729
761
|
)
|
|
730
762
|
});
|
|
731
763
|
}
|
|
@@ -849,6 +881,10 @@ function resolveComposedProjectConfig({
|
|
|
849
881
|
};
|
|
850
882
|
const projectTitle = config?.title ?? pkgJson?.name;
|
|
851
883
|
const projectAuthor = config?.author ?? pkgJson?.author;
|
|
884
|
+
const rootDocumentProcessor = {
|
|
885
|
+
processorFactory: config.documentProcessor ?? VFM,
|
|
886
|
+
metadataReader: config.documentMetadataReader ?? readMetadata
|
|
887
|
+
};
|
|
852
888
|
const isContentsEntry = (entry) => entry.rel === "contents";
|
|
853
889
|
const isCoverEntry = (entry) => entry.rel === "cover";
|
|
854
890
|
const isArticleEntry = (entry) => !isContentsEntry(entry) && !isCoverEntry(entry);
|
|
@@ -869,12 +905,19 @@ function resolveComposedProjectConfig({
|
|
|
869
905
|
}
|
|
870
906
|
const pathname = upath2.resolve(entryContextDir, entryPath);
|
|
871
907
|
statFileSync(pathname);
|
|
872
|
-
const
|
|
873
|
-
|
|
908
|
+
const rawContentType = mime(pathname);
|
|
909
|
+
const documentProcessor = {
|
|
910
|
+
processorFactory: "documentProcessor" in entry && entry.documentProcessor || rootDocumentProcessor.processorFactory,
|
|
911
|
+
metadataReader: "documentMetadataReader" in entry && entry.documentMetadataReader || rootDocumentProcessor.metadataReader
|
|
912
|
+
};
|
|
913
|
+
const hasCustomProcessor = !!(documentProcessor.processorFactory !== VFM || documentProcessor.metadataReader !== readMetadata);
|
|
914
|
+
const contentType = hasCustomProcessor && rawContentType !== "text/markdown" ? "text/x-vivliostyle-custom" : rawContentType;
|
|
915
|
+
if (!isManuscriptMediaType(contentType) || contentType === "text/plain") {
|
|
874
916
|
throw new Error(
|
|
875
|
-
`Invalid manuscript type ${
|
|
917
|
+
`Invalid manuscript type ${rawContentType} detected: ${entry}`
|
|
876
918
|
);
|
|
877
919
|
}
|
|
920
|
+
const useDocumentProcessor = contentType === "text/markdown" || contentType === "text/x-vivliostyle-custom";
|
|
878
921
|
return {
|
|
879
922
|
type: "file",
|
|
880
923
|
pathname,
|
|
@@ -883,8 +926,10 @@ function resolveComposedProjectConfig({
|
|
|
883
926
|
contentType,
|
|
884
927
|
sourcePath: pathname,
|
|
885
928
|
workspaceDir,
|
|
886
|
-
themesDir
|
|
887
|
-
|
|
929
|
+
themesDir,
|
|
930
|
+
documentMetadataReader: useDocumentProcessor ? documentProcessor.metadataReader : void 0
|
|
931
|
+
}),
|
|
932
|
+
...useDocumentProcessor && { documentProcessor }
|
|
888
933
|
};
|
|
889
934
|
};
|
|
890
935
|
const getTargetPath = (source) => {
|
|
@@ -892,7 +937,7 @@ function resolveComposedProjectConfig({
|
|
|
892
937
|
case "file":
|
|
893
938
|
return upath2.resolve(
|
|
894
939
|
workspaceDir,
|
|
895
|
-
upath2.relative(entryContextDir, source.pathname)
|
|
940
|
+
toHtmlExtension(upath2.relative(entryContextDir, source.pathname))
|
|
896
941
|
);
|
|
897
942
|
case "uri": {
|
|
898
943
|
const url = new URL(source.href, "a://dummy");
|
|
@@ -1065,77 +1110,211 @@ Maybe you want to set the "output" field instead.`
|
|
|
1065
1110
|
};
|
|
1066
1111
|
}
|
|
1067
1112
|
|
|
1113
|
+
// src/vite/vite-plugin-browser.ts
|
|
1114
|
+
import "vite";
|
|
1115
|
+
|
|
1068
1116
|
// src/browser.ts
|
|
1069
1117
|
import fs4 from "node:fs";
|
|
1118
|
+
import upath3 from "upath";
|
|
1119
|
+
var browserEnumMap = {
|
|
1120
|
+
chrome: "chrome",
|
|
1121
|
+
chromium: "chromium",
|
|
1122
|
+
firefox: "firefox"
|
|
1123
|
+
};
|
|
1070
1124
|
async function launchBrowser({
|
|
1071
1125
|
browserType,
|
|
1072
1126
|
proxy,
|
|
1073
1127
|
executablePath,
|
|
1074
1128
|
headless,
|
|
1075
1129
|
noSandbox,
|
|
1076
|
-
disableDevShmUsage
|
|
1130
|
+
disableDevShmUsage,
|
|
1131
|
+
ignoreHttpsErrors
|
|
1077
1132
|
}) {
|
|
1078
|
-
const
|
|
1079
|
-
|
|
1080
|
-
|
|
1133
|
+
const puppeteer = await importNodeModule("puppeteer-core");
|
|
1134
|
+
const args = [];
|
|
1135
|
+
if (browserType === "chrome" || browserType === "chromium") {
|
|
1136
|
+
args.push(
|
|
1137
|
+
"--disable-field-trial-config",
|
|
1138
|
+
"--disable-back-forward-cache",
|
|
1139
|
+
"--disable-component-update",
|
|
1140
|
+
"--no-default-browser-check",
|
|
1141
|
+
"--disable-features=AcceptCHFrame,AvoidUnnecessaryBeforeUnloadCheckSync,DestroyProfileOnBrowserClose,DialMediaRouteProvider,GlobalMediaControls,HttpsUpgrades,LensOverlay,MediaRouter,PaintHolding,ThirdPartyStoragePartitioning,Translate,AutoDeElevate,RenderDocument",
|
|
1142
|
+
"--enable-features=CDPScreenshotNewSurface",
|
|
1143
|
+
"--no-service-autorun",
|
|
1144
|
+
"--unsafely-disable-devtools-self-xss-warnings",
|
|
1145
|
+
"--edge-skip-compat-layer-relaunch"
|
|
1146
|
+
);
|
|
1147
|
+
if (process.platform === "darwin") {
|
|
1148
|
+
args.push("--enable-unsafe-swiftshader");
|
|
1149
|
+
}
|
|
1150
|
+
if (noSandbox) {
|
|
1151
|
+
args.push("--no-sandbox");
|
|
1152
|
+
}
|
|
1153
|
+
if (headless) {
|
|
1154
|
+
args.push(
|
|
1155
|
+
"--hide-scrollbars",
|
|
1156
|
+
"--mute-audio",
|
|
1157
|
+
"--blink-settings=primaryHoverType=2,availableHoverTypes=2,primaryPointerType=4,availablePointerTypes=4"
|
|
1158
|
+
);
|
|
1159
|
+
}
|
|
1160
|
+
if (proxy?.server) {
|
|
1161
|
+
const proxyURL = new URL(proxy.server);
|
|
1162
|
+
const isSocks = proxyURL.protocol === "socks5:";
|
|
1163
|
+
if (isSocks) {
|
|
1164
|
+
args.push(
|
|
1165
|
+
`--host-resolver-rules="MAP * ~NOTFOUND , EXCLUDE ${proxyURL.hostname}"`
|
|
1166
|
+
);
|
|
1167
|
+
}
|
|
1168
|
+
args.push(`--proxy-server=${proxy.server}`);
|
|
1169
|
+
const proxyBypassRules = [];
|
|
1170
|
+
if (proxy.bypass) {
|
|
1171
|
+
proxyBypassRules.push(
|
|
1172
|
+
...proxy.bypass.split(",").map((t) => t.trim()).map((t) => t.startsWith(".") ? "*" + t : t)
|
|
1173
|
+
);
|
|
1174
|
+
}
|
|
1175
|
+
proxyBypassRules.push("<-loopback>");
|
|
1176
|
+
args.push(`--proxy-bypass-list=${proxyBypassRules.join(";")}`);
|
|
1177
|
+
}
|
|
1178
|
+
args.push("--disable-web-security");
|
|
1179
|
+
if (disableDevShmUsage) {
|
|
1180
|
+
args.push("--disable-dev-shm-usage");
|
|
1181
|
+
}
|
|
1182
|
+
if (headless) {
|
|
1183
|
+
args.push("--force-device-scale-factor=1");
|
|
1184
|
+
}
|
|
1185
|
+
if (isRunningOnWSL()) {
|
|
1186
|
+
args.push("--disable-gpu");
|
|
1187
|
+
}
|
|
1188
|
+
args.push("--lang=en");
|
|
1189
|
+
if (!headless && process.platform === "darwin") {
|
|
1190
|
+
args.push("-AppleLanguages", "(en)");
|
|
1191
|
+
}
|
|
1192
|
+
args.push("--no-startup-window");
|
|
1193
|
+
}
|
|
1194
|
+
const launchOptions = {
|
|
1081
1195
|
executablePath,
|
|
1082
|
-
|
|
1196
|
+
args,
|
|
1197
|
+
browser: browserType === "chromium" ? "chrome" : browserType,
|
|
1083
1198
|
headless,
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
// set Chromium language to English to avoid locale-dependent issues
|
|
1093
|
-
"--lang=en",
|
|
1094
|
-
...!headless && process.platform === "darwin" ? ["", "-AppleLanguages", "(en)"] : []
|
|
1095
|
-
],
|
|
1096
|
-
env: { ...process.env, LANG: "en.UTF-8" },
|
|
1097
|
-
proxy
|
|
1098
|
-
} : (
|
|
1099
|
-
// TODO: Investigate appropriate settings on Firefox & Webkit
|
|
1100
|
-
{ executablePath, headless }
|
|
1101
|
-
);
|
|
1102
|
-
const browser = await playwright[browserType].launch(options);
|
|
1199
|
+
acceptInsecureCerts: ignoreHttpsErrors,
|
|
1200
|
+
waitForInitialPage: false
|
|
1201
|
+
};
|
|
1202
|
+
Logger.debug("launchOptions %O", launchOptions);
|
|
1203
|
+
const browser = await puppeteer.launch({
|
|
1204
|
+
...launchOptions,
|
|
1205
|
+
env: { ...process.env, LANG: "en.UTF-8" }
|
|
1206
|
+
});
|
|
1103
1207
|
registerExitHandler("Closing browser", () => {
|
|
1104
1208
|
browser.close();
|
|
1105
1209
|
});
|
|
1106
|
-
|
|
1210
|
+
const [browserContext] = browser.browserContexts();
|
|
1211
|
+
return { browser, browserContext };
|
|
1107
1212
|
}
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1213
|
+
function getPuppeteerCacheDir() {
|
|
1214
|
+
if (isInContainer()) {
|
|
1215
|
+
return "/opt/puppeteer";
|
|
1216
|
+
}
|
|
1217
|
+
return upath3.join(getCacheDir(), "browsers");
|
|
1111
1218
|
}
|
|
1112
|
-
function
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1219
|
+
async function resolveBuildId({
|
|
1220
|
+
type,
|
|
1221
|
+
tag,
|
|
1222
|
+
browsers
|
|
1223
|
+
}) {
|
|
1224
|
+
const cacheDataFilename = upath3.join(
|
|
1225
|
+
getPuppeteerCacheDir(),
|
|
1226
|
+
"build-ids.json"
|
|
1227
|
+
);
|
|
1228
|
+
let cacheData;
|
|
1229
|
+
try {
|
|
1230
|
+
cacheData = JSON.parse(fs4.readFileSync(cacheDataFilename, "utf-8"));
|
|
1231
|
+
if (Date.now() - cacheData.createdAt > 24 * 60 * 60 * 1e3) {
|
|
1232
|
+
cacheData = { createdAt: Date.now(), buildIds: {} };
|
|
1233
|
+
}
|
|
1234
|
+
} catch (_) {
|
|
1235
|
+
cacheData = { createdAt: Date.now(), buildIds: {} };
|
|
1236
|
+
}
|
|
1237
|
+
if (cacheData.buildIds[type]?.[tag]) {
|
|
1238
|
+
return cacheData.buildIds[type][tag];
|
|
1239
|
+
}
|
|
1240
|
+
const platform = detectBrowserPlatform();
|
|
1241
|
+
if (!platform) {
|
|
1242
|
+
throw new Error("The current platform is not supported.");
|
|
1243
|
+
}
|
|
1244
|
+
const buildId = await browsers.resolveBuildId(
|
|
1245
|
+
browserEnumMap[type],
|
|
1246
|
+
platform,
|
|
1247
|
+
tag
|
|
1248
|
+
);
|
|
1249
|
+
(cacheData.buildIds[type] ??= {})[tag] = buildId;
|
|
1250
|
+
fs4.mkdirSync(upath3.dirname(cacheDataFilename), { recursive: true });
|
|
1251
|
+
fs4.writeFileSync(cacheDataFilename, JSON.stringify(cacheData));
|
|
1252
|
+
return buildId;
|
|
1253
|
+
}
|
|
1254
|
+
async function cleanupOutdatedBrowsers() {
|
|
1255
|
+
for (const browser of Object.values(browserEnumMap)) {
|
|
1256
|
+
const browsersDir = upath3.join(getPuppeteerCacheDir(), browser);
|
|
1257
|
+
if (!fs4.existsSync(browsersDir)) {
|
|
1258
|
+
continue;
|
|
1259
|
+
}
|
|
1260
|
+
const entries = fs4.readdirSync(browsersDir);
|
|
1261
|
+
for (const entry of entries) {
|
|
1262
|
+
const entryPath = upath3.join(browsersDir, entry);
|
|
1263
|
+
const stat = fs4.statSync(entryPath);
|
|
1264
|
+
if (!stat.isDirectory() || Date.now() - stat.mtimeMs > 7 * 24 * 60 * 60 * 1e3) {
|
|
1265
|
+
Logger.debug(`Removing outdated browser at ${entryPath}`);
|
|
1266
|
+
await fs4.promises.rm(entryPath, { recursive: true, force: true });
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
async function getExecutableBrowserPath({
|
|
1272
|
+
type,
|
|
1273
|
+
tag
|
|
1274
|
+
}) {
|
|
1275
|
+
const browsers = await importNodeModule("@puppeteer/browsers");
|
|
1276
|
+
const buildId = await resolveBuildId({ type, tag, browsers });
|
|
1277
|
+
return browsers.computeExecutablePath({
|
|
1278
|
+
cacheDir: getPuppeteerCacheDir(),
|
|
1279
|
+
browser: browserEnumMap[type],
|
|
1280
|
+
buildId
|
|
1281
|
+
});
|
|
1118
1282
|
}
|
|
1119
1283
|
function checkBrowserAvailability(path) {
|
|
1120
1284
|
return fs4.existsSync(path);
|
|
1121
1285
|
}
|
|
1122
|
-
async function downloadBrowser(
|
|
1123
|
-
|
|
1124
|
-
|
|
1286
|
+
async function downloadBrowser({
|
|
1287
|
+
type,
|
|
1288
|
+
tag
|
|
1289
|
+
}) {
|
|
1290
|
+
const browsers = await importNodeModule("@puppeteer/browsers");
|
|
1291
|
+
const buildId = await resolveBuildId({ type, tag, browsers });
|
|
1292
|
+
let installedBrowser;
|
|
1293
|
+
if (isInContainer()) {
|
|
1294
|
+
const defaultBrowserVersion = getDefaultBrowserTag("chrome");
|
|
1295
|
+
Logger.logWarn(
|
|
1296
|
+
`The container you are using already includes a browser (chrome@${defaultBrowserVersion}); however, the specified browser ${type}@${tag} was not found. Downloading the browser inside the container may take a long time. Consider using a container image that includes the required browser version.`
|
|
1297
|
+
);
|
|
1298
|
+
}
|
|
1125
1299
|
{
|
|
1126
1300
|
var _stack = [];
|
|
1127
1301
|
try {
|
|
1128
1302
|
const _2 = __using(_stack, Logger.suspendLogging(
|
|
1129
1303
|
"Rendering browser is not installed yet. Downloading now."
|
|
1130
1304
|
));
|
|
1131
|
-
await
|
|
1305
|
+
installedBrowser = await browsers.install({
|
|
1306
|
+
cacheDir: getPuppeteerCacheDir(),
|
|
1307
|
+
browser: browserEnumMap[type],
|
|
1308
|
+
buildId,
|
|
1309
|
+
downloadProgressCallback: "default"
|
|
1310
|
+
});
|
|
1132
1311
|
} catch (_) {
|
|
1133
1312
|
var _error = _, _hasError = true;
|
|
1134
1313
|
} finally {
|
|
1135
1314
|
__callDispose(_stack, _error, _hasError);
|
|
1136
1315
|
}
|
|
1137
1316
|
}
|
|
1138
|
-
return
|
|
1317
|
+
return installedBrowser.executablePath;
|
|
1139
1318
|
}
|
|
1140
1319
|
async function launchPreview({
|
|
1141
1320
|
mode,
|
|
@@ -1145,48 +1324,59 @@ async function launchPreview({
|
|
|
1145
1324
|
config: { browser: browserConfig, proxy, sandbox, ignoreHttpsErrors }
|
|
1146
1325
|
}) {
|
|
1147
1326
|
let executableBrowser = browserConfig.executablePath;
|
|
1327
|
+
Logger.debug(`Specified browser path: ${executableBrowser}`);
|
|
1148
1328
|
if (executableBrowser) {
|
|
1149
1329
|
if (!checkBrowserAvailability(executableBrowser)) {
|
|
1150
1330
|
throw new Error(
|
|
1151
1331
|
`Cannot find the browser. Please check the executable browser path: ${executableBrowser}`
|
|
1152
1332
|
);
|
|
1153
1333
|
}
|
|
1334
|
+
} else if (detectBrowserPlatform() === "linux_arm" && (browserConfig.type === "chrome" || browserConfig.type === "chromium")) {
|
|
1335
|
+
Logger.logInfo(
|
|
1336
|
+
"The official Chrome/Chromium binaries are not available for ARM64 Linux. Using the system-installed Chromium browser instead."
|
|
1337
|
+
);
|
|
1338
|
+
executableBrowser = "/usr/bin/chromium";
|
|
1154
1339
|
} else {
|
|
1155
|
-
executableBrowser = await getExecutableBrowserPath(browserConfig
|
|
1340
|
+
executableBrowser = await getExecutableBrowserPath(browserConfig);
|
|
1341
|
+
Logger.debug(`Using default browser: ${executableBrowser}`);
|
|
1156
1342
|
if (!checkBrowserAvailability(executableBrowser)) {
|
|
1157
|
-
await
|
|
1343
|
+
await cleanupOutdatedBrowsers();
|
|
1344
|
+
await downloadBrowser(browserConfig);
|
|
1158
1345
|
}
|
|
1159
1346
|
}
|
|
1160
|
-
|
|
1161
|
-
const browser = await launchBrowser({
|
|
1347
|
+
const { browser, browserContext } = await launchBrowser({
|
|
1162
1348
|
browserType: browserConfig.type,
|
|
1163
1349
|
proxy,
|
|
1164
1350
|
executablePath: executableBrowser,
|
|
1165
1351
|
headless: mode === "build",
|
|
1166
1352
|
noSandbox: !sandbox,
|
|
1167
|
-
disableDevShmUsage: isInContainer()
|
|
1353
|
+
disableDevShmUsage: isInContainer(),
|
|
1354
|
+
ignoreHttpsErrors
|
|
1168
1355
|
});
|
|
1169
1356
|
await onBrowserOpen?.(browser);
|
|
1170
|
-
const page = await
|
|
1171
|
-
|
|
1172
|
-
|
|
1357
|
+
const page = (await browserContext.pages())[0] ?? await browserContext.newPage();
|
|
1358
|
+
await page.setViewport(
|
|
1359
|
+
mode === "build" ? (
|
|
1360
|
+
// This viewport size is important to detect headless environment in Vivliostyle viewer
|
|
1173
1361
|
// https://github.com/vivliostyle/vivliostyle.js/blob/73bcf323adcad80126b0175630609451ccd09d8a/packages/core/src/vivliostyle/vgen.ts#L2489-L2500
|
|
1174
|
-
{
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
}
|
|
1178
|
-
) : null,
|
|
1179
|
-
ignoreHTTPSErrors: ignoreHttpsErrors
|
|
1180
|
-
});
|
|
1362
|
+
{ width: 800, height: 600 }
|
|
1363
|
+
) : null
|
|
1364
|
+
);
|
|
1181
1365
|
await onPageOpen?.(page);
|
|
1182
1366
|
page.on("dialog", () => {
|
|
1183
1367
|
});
|
|
1368
|
+
if (proxy?.username && proxy?.password) {
|
|
1369
|
+
await page.authenticate({
|
|
1370
|
+
username: proxy.username,
|
|
1371
|
+
password: proxy.password
|
|
1372
|
+
});
|
|
1373
|
+
}
|
|
1184
1374
|
await page.goto(url);
|
|
1185
1375
|
return { browser, page };
|
|
1186
1376
|
}
|
|
1187
1377
|
|
|
1188
1378
|
// src/server.ts
|
|
1189
|
-
import
|
|
1379
|
+
import fs10 from "node:fs";
|
|
1190
1380
|
import { URL as URL2 } from "node:url";
|
|
1191
1381
|
import upath11 from "upath";
|
|
1192
1382
|
import {
|
|
@@ -1199,170 +1389,22 @@ import escapeRe from "escape-string-regexp";
|
|
|
1199
1389
|
import { pathToFileURL as pathToFileURL6 } from "node:url";
|
|
1200
1390
|
import sirv from "sirv";
|
|
1201
1391
|
import upath8 from "upath";
|
|
1202
|
-
|
|
1203
|
-
// src/processor/asset.ts
|
|
1204
|
-
import { copy } from "fs-extra/esm";
|
|
1205
|
-
import fs5 from "node:fs";
|
|
1206
|
-
import picomatch from "picomatch";
|
|
1207
|
-
import { glob } from "tinyglobby";
|
|
1208
|
-
import upath3 from "upath";
|
|
1209
|
-
var GlobMatcher = class {
|
|
1210
|
-
constructor(matcherConfig) {
|
|
1211
|
-
this.matcherConfig = matcherConfig;
|
|
1212
|
-
this.#_matchers = matcherConfig.map(
|
|
1213
|
-
({ patterns, ...options }) => picomatch(patterns, options)
|
|
1214
|
-
);
|
|
1215
|
-
}
|
|
1216
|
-
#_matchers;
|
|
1217
|
-
match(test) {
|
|
1218
|
-
return this.#_matchers.some((matcher) => matcher(test));
|
|
1219
|
-
}
|
|
1220
|
-
async glob(globOptions = {}) {
|
|
1221
|
-
return new Set(
|
|
1222
|
-
(await Promise.all(
|
|
1223
|
-
this.matcherConfig.map(
|
|
1224
|
-
(config) => glob({ ...config, ...globOptions })
|
|
1225
|
-
)
|
|
1226
|
-
)).flat()
|
|
1227
|
-
);
|
|
1228
|
-
}
|
|
1229
|
-
};
|
|
1230
|
-
function getIgnoreThemeDirectoryPatterns({
|
|
1231
|
-
themesDir,
|
|
1232
|
-
cwd: cwd2
|
|
1233
|
-
}) {
|
|
1234
|
-
return pathContains(cwd2, themesDir) ? [
|
|
1235
|
-
`${upath3.relative(cwd2, themesDir)}/node_modules/*/example`,
|
|
1236
|
-
`${upath3.relative(cwd2, themesDir)}/node_modules/*/*/example`
|
|
1237
|
-
] : [];
|
|
1238
|
-
}
|
|
1239
|
-
function getIgnoreAssetPatterns({
|
|
1240
|
-
outputs,
|
|
1241
|
-
entries,
|
|
1242
|
-
cwd: cwd2
|
|
1243
|
-
}) {
|
|
1244
|
-
return [
|
|
1245
|
-
...outputs.flatMap(
|
|
1246
|
-
({ format, path: p }) => !pathContains(cwd2, p) ? [] : format === "webpub" ? upath3.join(upath3.relative(cwd2, p), "**") : upath3.relative(cwd2, p)
|
|
1247
|
-
),
|
|
1248
|
-
...entries.flatMap(({ template }) => {
|
|
1249
|
-
return template?.type === "file" && pathContains(cwd2, template.pathname) ? upath3.relative(cwd2, template.pathname) : [];
|
|
1250
|
-
})
|
|
1251
|
-
];
|
|
1252
|
-
}
|
|
1253
|
-
function getWebPubResourceMatcher({
|
|
1254
|
-
outputs,
|
|
1255
|
-
themesDir,
|
|
1256
|
-
entries,
|
|
1257
|
-
cwd: cwd2,
|
|
1258
|
-
manifestPath,
|
|
1259
|
-
copyAsset: { fileExtensions }
|
|
1260
|
-
}) {
|
|
1261
|
-
return new GlobMatcher([
|
|
1262
|
-
{
|
|
1263
|
-
patterns: [
|
|
1264
|
-
`**/${upath3.relative(cwd2, manifestPath)}`,
|
|
1265
|
-
"**/*.{html,htm,xhtml,xht}",
|
|
1266
|
-
`**/*.{${fileExtensions.join(",")}}`
|
|
1267
|
-
],
|
|
1268
|
-
ignore: [
|
|
1269
|
-
...getIgnoreAssetPatterns({
|
|
1270
|
-
cwd: cwd2,
|
|
1271
|
-
outputs,
|
|
1272
|
-
entries
|
|
1273
|
-
}),
|
|
1274
|
-
...getIgnoreThemeDirectoryPatterns({
|
|
1275
|
-
cwd: cwd2,
|
|
1276
|
-
themesDir
|
|
1277
|
-
}),
|
|
1278
|
-
// Ignore node_modules in the root directory
|
|
1279
|
-
"node_modules/**",
|
|
1280
|
-
// only include dotfiles starting with `.vs-`
|
|
1281
|
-
"**/.!(vs-*)/**"
|
|
1282
|
-
],
|
|
1283
|
-
dot: true,
|
|
1284
|
-
cwd: cwd2
|
|
1285
|
-
}
|
|
1286
|
-
]);
|
|
1287
|
-
}
|
|
1288
|
-
function getAssetMatcher({
|
|
1289
|
-
copyAsset: { fileExtensions, includes, excludes },
|
|
1290
|
-
outputs,
|
|
1291
|
-
themesDir,
|
|
1292
|
-
entries,
|
|
1293
|
-
cwd: cwd2,
|
|
1294
|
-
ignore = []
|
|
1295
|
-
}) {
|
|
1296
|
-
const ignorePatterns = [
|
|
1297
|
-
...ignore,
|
|
1298
|
-
...excludes,
|
|
1299
|
-
...getIgnoreAssetPatterns({ outputs, entries, cwd: cwd2 })
|
|
1300
|
-
];
|
|
1301
|
-
return new GlobMatcher([
|
|
1302
|
-
// Step 1: Glob files with an extension in `fileExtension`
|
|
1303
|
-
// Ignore files in node_modules directory, theme example files and files matched `excludes`
|
|
1304
|
-
{
|
|
1305
|
-
patterns: fileExtensions.map((ext) => `**/*.${ext}`),
|
|
1306
|
-
ignore: [
|
|
1307
|
-
"**/node_modules/**",
|
|
1308
|
-
...ignorePatterns,
|
|
1309
|
-
...getIgnoreThemeDirectoryPatterns({ themesDir, cwd: cwd2 })
|
|
1310
|
-
],
|
|
1311
|
-
cwd: cwd2
|
|
1312
|
-
},
|
|
1313
|
-
// Step 2: Glob files matched with `includes`
|
|
1314
|
-
// Ignore only files matched `excludes`
|
|
1315
|
-
{
|
|
1316
|
-
patterns: includes,
|
|
1317
|
-
ignore: ignorePatterns,
|
|
1318
|
-
cwd: cwd2
|
|
1319
|
-
}
|
|
1320
|
-
]);
|
|
1321
|
-
}
|
|
1322
|
-
async function copyAssets({
|
|
1323
|
-
entryContextDir,
|
|
1324
|
-
workspaceDir,
|
|
1325
|
-
copyAsset,
|
|
1326
|
-
outputs,
|
|
1327
|
-
themesDir,
|
|
1328
|
-
entries
|
|
1329
|
-
}) {
|
|
1330
|
-
if (pathEquals(entryContextDir, workspaceDir)) {
|
|
1331
|
-
return;
|
|
1332
|
-
}
|
|
1333
|
-
const relWorkspaceDir = upath3.relative(entryContextDir, workspaceDir);
|
|
1334
|
-
const assets = await getAssetMatcher({
|
|
1335
|
-
copyAsset,
|
|
1336
|
-
cwd: entryContextDir,
|
|
1337
|
-
outputs,
|
|
1338
|
-
themesDir,
|
|
1339
|
-
entries,
|
|
1340
|
-
ignore: [
|
|
1341
|
-
// don't copy workspace itself
|
|
1342
|
-
...relWorkspaceDir ? [upath3.join(relWorkspaceDir, "**")] : []
|
|
1343
|
-
]
|
|
1344
|
-
}).glob({ followSymbolicLinks: true });
|
|
1345
|
-
Logger.debug("assets", assets);
|
|
1346
|
-
for (const asset of assets) {
|
|
1347
|
-
const target = upath3.join(workspaceDir, asset);
|
|
1348
|
-
fs5.mkdirSync(upath3.dirname(target), { recursive: true });
|
|
1349
|
-
await copy(upath3.resolve(entryContextDir, asset), target);
|
|
1350
|
-
}
|
|
1351
|
-
}
|
|
1392
|
+
import "vite";
|
|
1352
1393
|
|
|
1353
1394
|
// src/processor/compile.ts
|
|
1354
|
-
import
|
|
1355
|
-
import
|
|
1395
|
+
import "@vivliostyle/jsdom";
|
|
1396
|
+
import { copy as copy3, move } from "fs-extra/esm";
|
|
1397
|
+
import fs8 from "node:fs";
|
|
1356
1398
|
import upath7 from "upath";
|
|
1357
1399
|
import serializeToXml2 from "w3c-xmlserializer";
|
|
1358
1400
|
import MIMEType2 from "whatwg-mimetype";
|
|
1359
1401
|
|
|
1360
1402
|
// src/output/webbook.ts
|
|
1361
|
-
import { copy as
|
|
1403
|
+
import { copy as copy2 } from "fs-extra/esm";
|
|
1362
1404
|
import { lookup as mime3 } from "mime-types";
|
|
1363
|
-
import
|
|
1405
|
+
import fs6 from "node:fs";
|
|
1364
1406
|
import { pathToFileURL as pathToFileURL5 } from "node:url";
|
|
1365
|
-
import { glob
|
|
1407
|
+
import { glob } from "tinyglobby";
|
|
1366
1408
|
import upath6 from "upath";
|
|
1367
1409
|
|
|
1368
1410
|
// src/processor/html.tsx
|
|
@@ -1529,8 +1571,8 @@ function getJsdomFromString({
|
|
|
1529
1571
|
}
|
|
1530
1572
|
async function getStructuredSectionFromHtml(htmlPath, href) {
|
|
1531
1573
|
const dom = await getJsdomFromUrlOrFile({ src: htmlPath });
|
|
1532
|
-
const { document } = dom.window;
|
|
1533
|
-
const allHeadings = [...
|
|
1574
|
+
const { document: document2 } = dom.window;
|
|
1575
|
+
const allHeadings = [...document2.querySelectorAll("h1, h2, h3, h4, h5, h6")].filter((el) => {
|
|
1534
1576
|
return !el.matches("blockquote *");
|
|
1535
1577
|
}).sort((a, b) => {
|
|
1536
1578
|
const position = a.compareDocumentPosition(b);
|
|
@@ -1695,17 +1737,17 @@ async function processTocHtml(dom, {
|
|
|
1695
1737
|
sectionDepth,
|
|
1696
1738
|
transform
|
|
1697
1739
|
}) {
|
|
1698
|
-
const { document } = dom.window;
|
|
1699
|
-
if (!
|
|
1740
|
+
const { document: document2 } = dom.window;
|
|
1741
|
+
if (!document2.querySelector(
|
|
1700
1742
|
'link[rel="publication"][type="application/ld+json"]'
|
|
1701
1743
|
)) {
|
|
1702
|
-
const l =
|
|
1744
|
+
const l = document2.createElement("link");
|
|
1703
1745
|
l.setAttribute("rel", "publication");
|
|
1704
1746
|
l.setAttribute("type", "application/ld+json");
|
|
1705
1747
|
l.setAttribute("href", encodeURI(upath4.relative(distDir, manifestPath)));
|
|
1706
|
-
|
|
1748
|
+
document2.head.appendChild(l);
|
|
1707
1749
|
}
|
|
1708
|
-
const style =
|
|
1750
|
+
const style = document2.querySelector("style[data-vv-style]");
|
|
1709
1751
|
if (style) {
|
|
1710
1752
|
const textContent = getTocHtmlStyle(styleOptions);
|
|
1711
1753
|
if (textContent) {
|
|
@@ -1714,9 +1756,9 @@ async function processTocHtml(dom, {
|
|
|
1714
1756
|
style.remove();
|
|
1715
1757
|
}
|
|
1716
1758
|
}
|
|
1717
|
-
const nav =
|
|
1759
|
+
const nav = document2.querySelector('nav, [role="doc-toc"]');
|
|
1718
1760
|
if (nav && !nav.hasChildNodes()) {
|
|
1719
|
-
const h2 =
|
|
1761
|
+
const h2 = document2.createElement("h2");
|
|
1720
1762
|
h2.textContent = tocTitle;
|
|
1721
1763
|
nav.appendChild(h2);
|
|
1722
1764
|
nav.innerHTML += await generateTocListSection({
|
|
@@ -1769,8 +1811,8 @@ async function processCoverHtml(dom, {
|
|
|
1769
1811
|
imageAlt,
|
|
1770
1812
|
styleOptions = {}
|
|
1771
1813
|
}) {
|
|
1772
|
-
const { document } = dom.window;
|
|
1773
|
-
const style =
|
|
1814
|
+
const { document: document2 } = dom.window;
|
|
1815
|
+
const style = document2.querySelector("style[data-vv-style]");
|
|
1774
1816
|
if (style) {
|
|
1775
1817
|
const textContent = getCoverHtmlStyle(styleOptions);
|
|
1776
1818
|
if (textContent) {
|
|
@@ -1779,7 +1821,7 @@ async function processCoverHtml(dom, {
|
|
|
1779
1821
|
style.remove();
|
|
1780
1822
|
}
|
|
1781
1823
|
}
|
|
1782
|
-
const cover =
|
|
1824
|
+
const cover = document2.querySelector('img[role="doc-cover"]');
|
|
1783
1825
|
if (cover && !cover.hasAttribute("src")) {
|
|
1784
1826
|
cover.setAttribute("src", encodeURI(imageSrc));
|
|
1785
1827
|
}
|
|
@@ -1794,30 +1836,30 @@ async function processManuscriptHtml(dom, {
|
|
|
1794
1836
|
contentType,
|
|
1795
1837
|
language
|
|
1796
1838
|
}) {
|
|
1797
|
-
const { document } = dom.window;
|
|
1839
|
+
const { document: document2 } = dom.window;
|
|
1798
1840
|
if (title) {
|
|
1799
|
-
if (!
|
|
1800
|
-
const t =
|
|
1801
|
-
|
|
1841
|
+
if (!document2.querySelector("title")) {
|
|
1842
|
+
const t = document2.createElement("title");
|
|
1843
|
+
document2.head.appendChild(t);
|
|
1802
1844
|
}
|
|
1803
|
-
|
|
1845
|
+
document2.title = title;
|
|
1804
1846
|
}
|
|
1805
1847
|
for (const s of style ?? []) {
|
|
1806
|
-
const l =
|
|
1848
|
+
const l = document2.createElement("link");
|
|
1807
1849
|
l.setAttribute("rel", "stylesheet");
|
|
1808
1850
|
l.setAttribute("type", "text/css");
|
|
1809
1851
|
l.setAttribute("href", encodeURI(s));
|
|
1810
|
-
|
|
1852
|
+
document2.head.appendChild(l);
|
|
1811
1853
|
}
|
|
1812
1854
|
if (language) {
|
|
1813
1855
|
if (contentType === "application/xhtml+xml") {
|
|
1814
|
-
if (!
|
|
1815
|
-
|
|
1816
|
-
|
|
1856
|
+
if (!document2.documentElement.getAttribute("xml:lang")) {
|
|
1857
|
+
document2.documentElement.setAttribute("lang", language);
|
|
1858
|
+
document2.documentElement.setAttribute("xml:lang", language);
|
|
1817
1859
|
}
|
|
1818
1860
|
} else {
|
|
1819
|
-
if (!
|
|
1820
|
-
|
|
1861
|
+
if (!document2.documentElement.getAttribute("lang")) {
|
|
1862
|
+
document2.documentElement.setAttribute("lang", language);
|
|
1821
1863
|
}
|
|
1822
1864
|
}
|
|
1823
1865
|
}
|
|
@@ -1828,8 +1870,8 @@ async function fetchLinkedPublicationManifest({
|
|
|
1828
1870
|
resourceLoader,
|
|
1829
1871
|
baseUrl
|
|
1830
1872
|
}) {
|
|
1831
|
-
const { document } = dom.window;
|
|
1832
|
-
const linkEl =
|
|
1873
|
+
const { document: document2 } = dom.window;
|
|
1874
|
+
const linkEl = document2.querySelector('link[href][rel="publication"]');
|
|
1833
1875
|
if (!linkEl) {
|
|
1834
1876
|
return null;
|
|
1835
1877
|
}
|
|
@@ -1837,7 +1879,7 @@ async function fetchLinkedPublicationManifest({
|
|
|
1837
1879
|
let manifest;
|
|
1838
1880
|
let manifestUrl = baseUrl;
|
|
1839
1881
|
if (href.startsWith("#")) {
|
|
1840
|
-
const scriptEl =
|
|
1882
|
+
const scriptEl = document2.getElementById(href.slice(1));
|
|
1841
1883
|
if (scriptEl?.getAttribute("type") !== "application/ld+json") {
|
|
1842
1884
|
return null;
|
|
1843
1885
|
}
|
|
@@ -1884,8 +1926,8 @@ ${error}`
|
|
|
1884
1926
|
};
|
|
1885
1927
|
}
|
|
1886
1928
|
function parseTocDocument(dom) {
|
|
1887
|
-
const { document } = dom.window;
|
|
1888
|
-
const docTocEl =
|
|
1929
|
+
const { document: document2 } = dom.window;
|
|
1930
|
+
const docTocEl = document2.querySelectorAll('[role="doc-toc"]');
|
|
1889
1931
|
if (docTocEl.length === 0) {
|
|
1890
1932
|
return null;
|
|
1891
1933
|
}
|
|
@@ -1935,8 +1977,8 @@ function parseTocDocument(dom) {
|
|
|
1935
1977
|
return null;
|
|
1936
1978
|
}
|
|
1937
1979
|
function parsePageListDocument(dom) {
|
|
1938
|
-
const { document } = dom.window;
|
|
1939
|
-
const docPageListEl =
|
|
1980
|
+
const { document: document2 } = dom.window;
|
|
1981
|
+
const docPageListEl = document2.querySelectorAll('[role="doc-pagelist"]');
|
|
1940
1982
|
if (docPageListEl.length === 0) {
|
|
1941
1983
|
return null;
|
|
1942
1984
|
}
|
|
@@ -1961,10 +2003,10 @@ function parsePageListDocument(dom) {
|
|
|
1961
2003
|
import archiver from "archiver";
|
|
1962
2004
|
import { lookup as lookupLanguage } from "bcp-47-match";
|
|
1963
2005
|
import { XMLBuilder } from "fast-xml-parser";
|
|
1964
|
-
import { copy
|
|
2006
|
+
import { copy } from "fs-extra/esm";
|
|
1965
2007
|
import GithubSlugger from "github-slugger";
|
|
1966
2008
|
import { lookup as mime2 } from "mime-types";
|
|
1967
|
-
import
|
|
2009
|
+
import fs5 from "node:fs";
|
|
1968
2010
|
import { pathToFileURL as pathToFileURL4 } from "node:url";
|
|
1969
2011
|
import upath5 from "upath";
|
|
1970
2012
|
import { v4 as uuid } from "uuid";
|
|
@@ -2037,8 +2079,8 @@ async function exportEpub({
|
|
|
2037
2079
|
epubVersion
|
|
2038
2080
|
});
|
|
2039
2081
|
const [tmpDir] = await useTmpDirectory();
|
|
2040
|
-
|
|
2041
|
-
await
|
|
2082
|
+
fs5.mkdirSync(upath5.join(tmpDir, "META-INF"), { recursive: true });
|
|
2083
|
+
await copy(webpubDir, upath5.join(tmpDir, "EPUB"));
|
|
2042
2084
|
const uid = `urn:uuid:${uuid()}`;
|
|
2043
2085
|
const entryHtmlRelPath = entryHtmlFile && upath5.relative(webpubDir, upath5.resolve(webpubDir, entryHtmlFile));
|
|
2044
2086
|
const findPublicationLink = (relType, list, filter) => [list].flat().find(
|
|
@@ -2077,7 +2119,7 @@ async function exportEpub({
|
|
|
2077
2119
|
return acc;
|
|
2078
2120
|
} catch (e) {
|
|
2079
2121
|
}
|
|
2080
|
-
if (!
|
|
2122
|
+
if (!fs5.existsSync(upath5.join(tmpDir, "EPUB", url))) {
|
|
2081
2123
|
return acc;
|
|
2082
2124
|
}
|
|
2083
2125
|
const mediaType = encodingFormat || mime2(url) || "text/plain";
|
|
@@ -2193,19 +2235,19 @@ async function exportEpub({
|
|
|
2193
2235
|
});
|
|
2194
2236
|
}
|
|
2195
2237
|
if (relManifestPath) {
|
|
2196
|
-
await
|
|
2238
|
+
await fs5.promises.rm(upath5.join(tmpDir, "EPUB", relManifestPath), {
|
|
2197
2239
|
force: true,
|
|
2198
2240
|
recursive: true
|
|
2199
2241
|
});
|
|
2200
2242
|
delete manifestItem[relManifestPath];
|
|
2201
2243
|
}
|
|
2202
|
-
|
|
2244
|
+
fs5.writeFileSync(
|
|
2203
2245
|
upath5.join(tmpDir, "META-INF/container.xml"),
|
|
2204
2246
|
EPUB_CONTAINER_XML,
|
|
2205
2247
|
"utf8"
|
|
2206
2248
|
);
|
|
2207
2249
|
Logger.debug(`Generating content.opf`);
|
|
2208
|
-
|
|
2250
|
+
fs5.writeFileSync(
|
|
2209
2251
|
upath5.join(tmpDir, "EPUB/content.opf"),
|
|
2210
2252
|
buildEpubPackageDocument({
|
|
2211
2253
|
epubVersion,
|
|
@@ -2223,7 +2265,7 @@ async function exportEpub({
|
|
|
2223
2265
|
async function writeAsXhtml(dom, absPath) {
|
|
2224
2266
|
const xhtml = `${XML_DECLARATION}
|
|
2225
2267
|
${serializeToXml(dom.window.document)}`;
|
|
2226
|
-
await
|
|
2268
|
+
await fs5.promises.writeFile(changeExtname(absPath, ".xhtml"), xhtml, "utf8");
|
|
2227
2269
|
}
|
|
2228
2270
|
async function transpileHtmlToXhtml({
|
|
2229
2271
|
target,
|
|
@@ -2231,24 +2273,24 @@ async function transpileHtmlToXhtml({
|
|
|
2231
2273
|
}) {
|
|
2232
2274
|
const absPath = upath5.join(contextDir, target);
|
|
2233
2275
|
const dom = await getJsdomFromUrlOrFile({ src: absPath });
|
|
2234
|
-
const { document } = dom.window;
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2276
|
+
const { document: document2 } = dom.window;
|
|
2277
|
+
document2.documentElement.removeAttribute("xmlns");
|
|
2278
|
+
document2.documentElement.setAttribute("xmlns:epub", EPUB_NS);
|
|
2279
|
+
document2.querySelectorAll("a[href]").forEach((el) => {
|
|
2238
2280
|
const href = decodeURI(el.getAttribute("href"));
|
|
2239
2281
|
el.setAttribute("href", getRelativeHref(href, target, target));
|
|
2240
2282
|
});
|
|
2241
2283
|
await writeAsXhtml(dom, absPath);
|
|
2242
|
-
await
|
|
2284
|
+
await fs5.promises.unlink(absPath);
|
|
2243
2285
|
return {
|
|
2244
2286
|
dom,
|
|
2245
2287
|
// FIXME: Yes, I recognize this implementation is inadequate.
|
|
2246
|
-
hasMathmlContent: !!
|
|
2247
|
-
hasRemoteResources: !!
|
|
2288
|
+
hasMathmlContent: !!document2.querySelector("math"),
|
|
2289
|
+
hasRemoteResources: !!document2.querySelector(
|
|
2248
2290
|
'[src^="http://"], [src^="https://"]'
|
|
2249
2291
|
),
|
|
2250
|
-
hasScriptedContent: !!
|
|
2251
|
-
hasSvgContent: !!
|
|
2292
|
+
hasScriptedContent: !!document2.querySelector("script, form"),
|
|
2293
|
+
hasSvgContent: !!document2.querySelector("svg")
|
|
2252
2294
|
};
|
|
2253
2295
|
}
|
|
2254
2296
|
function replaceWithNavElement(dom, el) {
|
|
@@ -2270,9 +2312,9 @@ async function processTocDocument({
|
|
|
2270
2312
|
docLanguages,
|
|
2271
2313
|
landmarks
|
|
2272
2314
|
}) {
|
|
2273
|
-
const { document } = dom.window;
|
|
2315
|
+
const { document: document2 } = dom.window;
|
|
2274
2316
|
let tocResourceTree = null;
|
|
2275
|
-
if (!
|
|
2317
|
+
if (!document2.querySelector("nav[epub:type]")) {
|
|
2276
2318
|
tocResourceTree = parseTocDocument(dom);
|
|
2277
2319
|
if (tocResourceTree) {
|
|
2278
2320
|
const nav = replaceWithNavElement(dom, tocResourceTree.element);
|
|
@@ -2280,15 +2322,15 @@ async function processTocDocument({
|
|
|
2280
2322
|
nav.setAttribute("epub:type", "toc");
|
|
2281
2323
|
} else {
|
|
2282
2324
|
Logger.debug(`Generating toc nav element: ${target}`);
|
|
2283
|
-
const nav =
|
|
2325
|
+
const nav = document2.createElement("nav");
|
|
2284
2326
|
nav.setAttribute("id", TOC_ID);
|
|
2285
2327
|
nav.setAttribute("role", "doc-toc");
|
|
2286
2328
|
nav.setAttribute("epub:type", "toc");
|
|
2287
2329
|
nav.setAttribute("hidden", "");
|
|
2288
|
-
const h2 =
|
|
2330
|
+
const h2 = document2.createElement("h2");
|
|
2289
2331
|
h2.textContent = TOC_TITLE;
|
|
2290
2332
|
nav.appendChild(h2);
|
|
2291
|
-
const ol =
|
|
2333
|
+
const ol = document2.createElement("ol");
|
|
2292
2334
|
tocResourceTree = {
|
|
2293
2335
|
element: nav,
|
|
2294
2336
|
children: []
|
|
@@ -2301,8 +2343,8 @@ async function processTocDocument({
|
|
|
2301
2343
|
});
|
|
2302
2344
|
name = dom2.window.document.title;
|
|
2303
2345
|
}
|
|
2304
|
-
const li =
|
|
2305
|
-
const a =
|
|
2346
|
+
const li = document2.createElement("li");
|
|
2347
|
+
const a = document2.createElement("a");
|
|
2306
2348
|
a.textContent = name;
|
|
2307
2349
|
a.href = getRelativeHref(content.url, "", target);
|
|
2308
2350
|
li.appendChild(a);
|
|
@@ -2310,22 +2352,22 @@ async function processTocDocument({
|
|
|
2310
2352
|
tocResourceTree.children.push({ element: li, label: a });
|
|
2311
2353
|
}
|
|
2312
2354
|
nav.appendChild(ol);
|
|
2313
|
-
|
|
2355
|
+
document2.body.appendChild(nav);
|
|
2314
2356
|
Logger.debug("Generated toc nav element", nav.outerHTML);
|
|
2315
2357
|
}
|
|
2316
2358
|
if (landmarks.length > 0) {
|
|
2317
2359
|
Logger.debug(`Generating landmark nav element: ${target}`);
|
|
2318
|
-
const nav =
|
|
2360
|
+
const nav = document2.createElement("nav");
|
|
2319
2361
|
nav.setAttribute("epub:type", "landmarks");
|
|
2320
2362
|
nav.setAttribute("id", LANDMARKS_ID);
|
|
2321
2363
|
nav.setAttribute("hidden", "");
|
|
2322
|
-
const h2 =
|
|
2364
|
+
const h2 = document2.createElement("h2");
|
|
2323
2365
|
h2.textContent = EPUB_LANDMARKS_TITLE;
|
|
2324
2366
|
nav.appendChild(h2);
|
|
2325
|
-
const ol =
|
|
2367
|
+
const ol = document2.createElement("ol");
|
|
2326
2368
|
for (const { type, href, text } of landmarks) {
|
|
2327
|
-
const li =
|
|
2328
|
-
const a =
|
|
2369
|
+
const li = document2.createElement("li");
|
|
2370
|
+
const a = document2.createElement("a");
|
|
2329
2371
|
a.setAttribute("epub:type", type);
|
|
2330
2372
|
a.setAttribute("href", getRelativeHref(href, "", target));
|
|
2331
2373
|
a.text = text;
|
|
@@ -2333,17 +2375,17 @@ async function processTocDocument({
|
|
|
2333
2375
|
ol.appendChild(li);
|
|
2334
2376
|
}
|
|
2335
2377
|
nav.appendChild(ol);
|
|
2336
|
-
|
|
2378
|
+
document2.body.appendChild(nav);
|
|
2337
2379
|
Logger.debug("Generated landmark nav element", nav.outerHTML);
|
|
2338
2380
|
}
|
|
2339
2381
|
}
|
|
2340
|
-
const publicationLinkEl =
|
|
2382
|
+
const publicationLinkEl = document2.querySelector(
|
|
2341
2383
|
'link[href][rel="publication"]'
|
|
2342
2384
|
);
|
|
2343
2385
|
if (publicationLinkEl) {
|
|
2344
2386
|
const href = publicationLinkEl.getAttribute("href").trim();
|
|
2345
2387
|
if (href.startsWith("#")) {
|
|
2346
|
-
const scriptEl =
|
|
2388
|
+
const scriptEl = document2.getElementById(href.slice(1));
|
|
2347
2389
|
if (scriptEl?.getAttribute("type") === "application/ld+json") {
|
|
2348
2390
|
scriptEl.parentNode?.removeChild(scriptEl);
|
|
2349
2391
|
}
|
|
@@ -2484,7 +2526,7 @@ async function compressEpub({
|
|
|
2484
2526
|
sourceDir
|
|
2485
2527
|
}) {
|
|
2486
2528
|
Logger.debug(`Compressing EPUB: ${target}`);
|
|
2487
|
-
const output =
|
|
2529
|
+
const output = fs5.createWriteStream(target);
|
|
2488
2530
|
const archive = archiver("zip", {
|
|
2489
2531
|
zlib: { level: 9 }
|
|
2490
2532
|
// Compression level
|
|
@@ -2522,11 +2564,11 @@ function sortManifestResources(manifest) {
|
|
|
2522
2564
|
async function prepareWebPublicationDirectory({
|
|
2523
2565
|
outputDir
|
|
2524
2566
|
}) {
|
|
2525
|
-
if (
|
|
2567
|
+
if (fs6.existsSync(outputDir)) {
|
|
2526
2568
|
Logger.debug("going to remove existing webpub", outputDir);
|
|
2527
|
-
await
|
|
2569
|
+
await fs6.promises.rm(outputDir, { force: true, recursive: true });
|
|
2528
2570
|
}
|
|
2529
|
-
|
|
2571
|
+
fs6.mkdirSync(outputDir, { recursive: true });
|
|
2530
2572
|
}
|
|
2531
2573
|
function transformPublicationManifest(entity, transformer) {
|
|
2532
2574
|
const { url: transformUrl } = transformer;
|
|
@@ -2623,8 +2665,8 @@ function writePublicationManifest(output, options) {
|
|
|
2623
2665
|
typeof thrownError === "string" ? thrownError : thrownError.stack ?? thrownError.message
|
|
2624
2666
|
);
|
|
2625
2667
|
}
|
|
2626
|
-
|
|
2627
|
-
|
|
2668
|
+
fs6.mkdirSync(upath6.dirname(output), { recursive: true });
|
|
2669
|
+
fs6.writeFileSync(output, JSON.stringify(encodedManifest, null, 2));
|
|
2628
2670
|
return publication;
|
|
2629
2671
|
}
|
|
2630
2672
|
async function retrieveWebbookEntry({
|
|
@@ -2735,12 +2777,12 @@ async function supplyWebPublicationManifestForWebbook({
|
|
|
2735
2777
|
}) {
|
|
2736
2778
|
Logger.debug(`Generating publication manifest from HTML: ${entryHtmlFile}`);
|
|
2737
2779
|
const dom = await getJsdomFromUrlOrFile({ src: entryHtmlFile });
|
|
2738
|
-
const { document } = dom.window;
|
|
2739
|
-
const language = config.language ||
|
|
2740
|
-
const title = config.title ||
|
|
2741
|
-
const author = config.author ||
|
|
2780
|
+
const { document: document2 } = dom.window;
|
|
2781
|
+
const language = config.language || document2.documentElement.lang || void 0;
|
|
2782
|
+
const title = config.title || document2.title || "";
|
|
2783
|
+
const author = config.author || document2.querySelector('meta[name="author"]')?.getAttribute("content") || "";
|
|
2742
2784
|
const entry = upath6.relative(outputDir, entryHtmlFile);
|
|
2743
|
-
const allFiles = await
|
|
2785
|
+
const allFiles = await glob("**", {
|
|
2744
2786
|
cwd: outputDir
|
|
2745
2787
|
});
|
|
2746
2788
|
const manifest = writePublicationManifest(
|
|
@@ -2756,7 +2798,7 @@ async function supplyWebPublicationManifestForWebbook({
|
|
|
2756
2798
|
}
|
|
2757
2799
|
);
|
|
2758
2800
|
sortManifestResources(manifest);
|
|
2759
|
-
const link =
|
|
2801
|
+
const link = document2.createElement("link");
|
|
2760
2802
|
link.setAttribute("rel", "publication");
|
|
2761
2803
|
link.setAttribute("type", "application/ld+json");
|
|
2762
2804
|
link.setAttribute(
|
|
@@ -2766,8 +2808,8 @@ async function supplyWebPublicationManifestForWebbook({
|
|
|
2766
2808
|
upath6.join(outputDir, MANIFEST_FILENAME)
|
|
2767
2809
|
)
|
|
2768
2810
|
);
|
|
2769
|
-
|
|
2770
|
-
await
|
|
2811
|
+
document2.head.appendChild(link);
|
|
2812
|
+
await fs6.promises.writeFile(entryHtmlFile, dom.serialize(), "utf8");
|
|
2771
2813
|
Logger.debug(
|
|
2772
2814
|
"Generated publication manifest from HTML",
|
|
2773
2815
|
JSON.stringify(manifest, null, 2)
|
|
@@ -2834,15 +2876,15 @@ async function copyWebPublicationAssets({
|
|
|
2834
2876
|
const relTarget = alias?.target || file;
|
|
2835
2877
|
resources.push(relTarget);
|
|
2836
2878
|
const target = upath6.join(outputDir, relTarget);
|
|
2837
|
-
|
|
2838
|
-
await
|
|
2879
|
+
fs6.mkdirSync(upath6.dirname(target), { recursive: true });
|
|
2880
|
+
await copy2(upath6.join(input, file), target);
|
|
2839
2881
|
if (alias && pathEquals(upath6.join(input, alias.source), manifestPath)) {
|
|
2840
2882
|
actualManifestPath = target;
|
|
2841
2883
|
}
|
|
2842
2884
|
}
|
|
2843
2885
|
Logger.debug("webbook publication.json", actualManifestPath);
|
|
2844
2886
|
const manifest = decodePublicationManifest(
|
|
2845
|
-
JSON.parse(
|
|
2887
|
+
JSON.parse(fs6.readFileSync(actualManifestPath, "utf8"))
|
|
2846
2888
|
);
|
|
2847
2889
|
for (const entry of relExportAliases) {
|
|
2848
2890
|
const rewriteAliasPath = (e) => {
|
|
@@ -2881,7 +2923,7 @@ async function copyWebPublicationAssets({
|
|
|
2881
2923
|
})
|
|
2882
2924
|
];
|
|
2883
2925
|
sortManifestResources(manifest);
|
|
2884
|
-
|
|
2926
|
+
fs6.writeFileSync(
|
|
2885
2927
|
actualManifestPath,
|
|
2886
2928
|
JSON.stringify(encodePublicationManifest(manifest), null, 2)
|
|
2887
2929
|
);
|
|
@@ -2948,17 +2990,18 @@ async function buildWebPublication({
|
|
|
2948
2990
|
|
|
2949
2991
|
// src/processor/theme.ts
|
|
2950
2992
|
import Arborist from "@npmcli/arborist";
|
|
2951
|
-
import
|
|
2993
|
+
import fs7 from "node:fs";
|
|
2952
2994
|
async function checkThemeInstallationNecessity({
|
|
2953
2995
|
themesDir,
|
|
2954
2996
|
themeIndexes
|
|
2955
2997
|
}) {
|
|
2956
|
-
if (!
|
|
2998
|
+
if (!fs7.existsSync(themesDir)) {
|
|
2957
2999
|
return [...themeIndexes].some((theme) => theme.type === "package");
|
|
2958
3000
|
}
|
|
2959
3001
|
const commonOpt = {
|
|
2960
3002
|
path: themesDir,
|
|
2961
|
-
lockfileVersion: 3
|
|
3003
|
+
lockfileVersion: 3,
|
|
3004
|
+
installLinks: true
|
|
2962
3005
|
};
|
|
2963
3006
|
const arb = new Arborist(commonOpt);
|
|
2964
3007
|
const tree = await arb.loadActual();
|
|
@@ -2971,11 +3014,12 @@ async function installThemeDependencies({
|
|
|
2971
3014
|
themesDir,
|
|
2972
3015
|
themeIndexes
|
|
2973
3016
|
}) {
|
|
2974
|
-
|
|
3017
|
+
fs7.mkdirSync(themesDir, { recursive: true });
|
|
2975
3018
|
try {
|
|
2976
3019
|
const commonOpt = {
|
|
2977
3020
|
path: themesDir,
|
|
2978
|
-
lockfileVersion: 3
|
|
3021
|
+
lockfileVersion: 3,
|
|
3022
|
+
installLinks: true
|
|
2979
3023
|
};
|
|
2980
3024
|
const tree = await new Arborist(commonOpt).buildIdealTree();
|
|
2981
3025
|
const existing = Array.from(tree.children.keys());
|
|
@@ -3011,7 +3055,7 @@ function locateThemePath(theme, from) {
|
|
|
3011
3055
|
if (theme.importPath) {
|
|
3012
3056
|
return [theme.importPath].flat().map((locator) => {
|
|
3013
3057
|
const resolvedPath = upath7.resolve(theme.location, locator);
|
|
3014
|
-
if (!pathContains(theme.location, resolvedPath) || !
|
|
3058
|
+
if (!pathContains(theme.location, resolvedPath) || !fs8.existsSync(resolvedPath)) {
|
|
3015
3059
|
throw new Error(
|
|
3016
3060
|
`Could not find a style path ${theme.importPath} for the theme: ${theme.name}.`
|
|
3017
3061
|
);
|
|
@@ -3020,7 +3064,7 @@ function locateThemePath(theme, from) {
|
|
|
3020
3064
|
});
|
|
3021
3065
|
} else {
|
|
3022
3066
|
const pkgJsonPath = upath7.join(theme.location, "package.json");
|
|
3023
|
-
const packageJson = JSON.parse(
|
|
3067
|
+
const packageJson = JSON.parse(fs8.readFileSync(pkgJsonPath, "utf8"));
|
|
3024
3068
|
const maybeStyle = packageJson?.vivliostyle?.theme?.style ?? packageJson.style ?? packageJson.main;
|
|
3025
3069
|
if (!maybeStyle) {
|
|
3026
3070
|
throw new DetailError(
|
|
@@ -3044,7 +3088,7 @@ async function cleanupWorkspace({
|
|
|
3044
3088
|
}
|
|
3045
3089
|
Logger.debug("cleanup workspace files", workspaceDir);
|
|
3046
3090
|
let movedWorkspacePath;
|
|
3047
|
-
if (pathContains(workspaceDir, themesDir) &&
|
|
3091
|
+
if (pathContains(workspaceDir, themesDir) && fs8.existsSync(themesDir)) {
|
|
3048
3092
|
movedWorkspacePath = upath7.join(
|
|
3049
3093
|
upath7.dirname(workspaceDir),
|
|
3050
3094
|
`.vs-${Date.now()}`
|
|
@@ -3053,18 +3097,18 @@ async function cleanupWorkspace({
|
|
|
3053
3097
|
movedWorkspacePath,
|
|
3054
3098
|
upath7.relative(workspaceDir, themesDir)
|
|
3055
3099
|
);
|
|
3056
|
-
|
|
3100
|
+
fs8.mkdirSync(upath7.dirname(movedThemePath), { recursive: true });
|
|
3057
3101
|
registerExitHandler(
|
|
3058
3102
|
`Removing the moved workspace directory: ${movedWorkspacePath}`,
|
|
3059
3103
|
() => {
|
|
3060
|
-
if (movedWorkspacePath &&
|
|
3061
|
-
|
|
3104
|
+
if (movedWorkspacePath && fs8.existsSync(movedWorkspacePath)) {
|
|
3105
|
+
fs8.rmSync(movedWorkspacePath, { recursive: true, force: true });
|
|
3062
3106
|
}
|
|
3063
3107
|
}
|
|
3064
3108
|
);
|
|
3065
3109
|
await move(themesDir, movedThemePath);
|
|
3066
3110
|
}
|
|
3067
|
-
await
|
|
3111
|
+
await fs8.promises.rm(workspaceDir, { recursive: true, force: true });
|
|
3068
3112
|
if (movedWorkspacePath) {
|
|
3069
3113
|
await move(movedWorkspacePath, workspaceDir);
|
|
3070
3114
|
}
|
|
@@ -3073,8 +3117,8 @@ async function prepareThemeDirectory({
|
|
|
3073
3117
|
themesDir,
|
|
3074
3118
|
themeIndexes
|
|
3075
3119
|
}) {
|
|
3076
|
-
if (
|
|
3077
|
-
|
|
3120
|
+
if (fs8.existsSync(upath7.join(themesDir, "packages")) && !fs8.existsSync(upath7.join(themesDir, "node_modules"))) {
|
|
3121
|
+
fs8.renameSync(
|
|
3078
3122
|
upath7.join(themesDir, "packages"),
|
|
3079
3123
|
upath7.join(themesDir, "node_modules")
|
|
3080
3124
|
);
|
|
@@ -3085,8 +3129,8 @@ async function prepareThemeDirectory({
|
|
|
3085
3129
|
}
|
|
3086
3130
|
for (const theme of themeIndexes) {
|
|
3087
3131
|
if (theme.type === "file" && !pathEquals(theme.source, theme.location)) {
|
|
3088
|
-
|
|
3089
|
-
await
|
|
3132
|
+
fs8.mkdirSync(upath7.dirname(theme.location), { recursive: true });
|
|
3133
|
+
await copy3(theme.source, theme.location);
|
|
3090
3134
|
}
|
|
3091
3135
|
}
|
|
3092
3136
|
}
|
|
@@ -3097,7 +3141,6 @@ async function transformManuscript(entry, {
|
|
|
3097
3141
|
title,
|
|
3098
3142
|
entries,
|
|
3099
3143
|
language,
|
|
3100
|
-
documentProcessorFactory,
|
|
3101
3144
|
vfmOptions,
|
|
3102
3145
|
rootUrl
|
|
3103
3146
|
}) {
|
|
@@ -3109,9 +3152,10 @@ async function transformManuscript(entry, {
|
|
|
3109
3152
|
(theme) => locateThemePath(theme, upath7.dirname(entry.target))
|
|
3110
3153
|
);
|
|
3111
3154
|
if (source?.type === "file") {
|
|
3112
|
-
if (source.
|
|
3155
|
+
if (source.documentProcessor) {
|
|
3113
3156
|
const vfile2 = await processMarkdown(
|
|
3114
|
-
|
|
3157
|
+
source.documentProcessor.processorFactory,
|
|
3158
|
+
source.documentProcessor.metadataReader,
|
|
3115
3159
|
source.pathname,
|
|
3116
3160
|
{
|
|
3117
3161
|
...vfmOptions,
|
|
@@ -3131,7 +3175,7 @@ async function transformManuscript(entry, {
|
|
|
3131
3175
|
});
|
|
3132
3176
|
} else {
|
|
3133
3177
|
if (!pathEquals(source.pathname, entry.target)) {
|
|
3134
|
-
await
|
|
3178
|
+
await copy3(source.pathname, entry.target);
|
|
3135
3179
|
}
|
|
3136
3180
|
}
|
|
3137
3181
|
} else if (source?.type === "uri") {
|
|
@@ -3265,7 +3309,7 @@ async function generateManifest({
|
|
|
3265
3309
|
const manifestEntries = entries.map((entry) => ({
|
|
3266
3310
|
title: entry.rel === "contents" && entry.tocTitle || entry.title,
|
|
3267
3311
|
path: upath7.relative(workspaceDir, entry.target),
|
|
3268
|
-
encodingFormat: !("contentType" in entry) || entry.contentType === "text/markdown" || entry.contentType === "text/html" ? void 0 : entry.contentType,
|
|
3312
|
+
encodingFormat: !("contentType" in entry) || entry.contentType === "text/markdown" || entry.contentType === "text/x-vivliostyle-custom" || entry.contentType === "text/html" ? void 0 : entry.contentType,
|
|
3269
3313
|
rel: entry.rel
|
|
3270
3314
|
}));
|
|
3271
3315
|
writePublicationManifest(manifestPath, {
|
|
@@ -3670,6 +3714,7 @@ function vsDevServerPlugin({
|
|
|
3670
3714
|
// src/vite/vite-plugin-static-serve.ts
|
|
3671
3715
|
import sirv2 from "sirv";
|
|
3672
3716
|
import upath9 from "upath";
|
|
3717
|
+
import "vite";
|
|
3673
3718
|
function vsStaticServePlugin({
|
|
3674
3719
|
config: _config,
|
|
3675
3720
|
inlineConfig
|
|
@@ -3712,9 +3757,10 @@ function vsStaticServePlugin({
|
|
|
3712
3757
|
}
|
|
3713
3758
|
|
|
3714
3759
|
// src/vite/vite-plugin-viewer.ts
|
|
3715
|
-
import
|
|
3760
|
+
import fs9 from "node:fs";
|
|
3716
3761
|
import sirv3 from "sirv";
|
|
3717
3762
|
import upath10 from "upath";
|
|
3763
|
+
import "vite";
|
|
3718
3764
|
var viewerClientId = "@vivliostyle:viewer:client";
|
|
3719
3765
|
var viewerClientRequestPath = `/${viewerClientId}`;
|
|
3720
3766
|
var viewerClientContent = (
|
|
@@ -3733,7 +3779,7 @@ function vsViewerPlugin(_) {
|
|
|
3733
3779
|
const middleware = async function vivliostyleViewerMiddleware(req, res, next) {
|
|
3734
3780
|
if (req.url === "/" || req.url === "/index.html") {
|
|
3735
3781
|
cachedIndexHtml ??= prependToHead(
|
|
3736
|
-
|
|
3782
|
+
fs9.readFileSync(upath10.join(serveRootDir, "index.html"), "utf-8"),
|
|
3737
3783
|
`<script type="module" src="${viewerClientRequestPath}"></script>`
|
|
3738
3784
|
);
|
|
3739
3785
|
res.statusCode = 200;
|
|
@@ -3837,7 +3883,7 @@ async function getSourceUrl({
|
|
|
3837
3883
|
input = viewerInput.epubOpfPath;
|
|
3838
3884
|
break;
|
|
3839
3885
|
case "epub": {
|
|
3840
|
-
if (!
|
|
3886
|
+
if (!fs10.existsSync(viewerInput.epubTmpOutputDir)) {
|
|
3841
3887
|
await openEpub(viewerInput.epubPath, viewerInput.epubTmpOutputDir);
|
|
3842
3888
|
}
|
|
3843
3889
|
input = getDefaultEpubOpfPath(viewerInput.epubTmpOutputDir);
|
|
@@ -3899,8 +3945,8 @@ async function createViteServer({
|
|
|
3899
3945
|
if (config.serverRootDir === config.workspaceDir) {
|
|
3900
3946
|
const { cacheDir } = viteInlineConfig;
|
|
3901
3947
|
registerExitHandler("Removing the Vite cacheDir", () => {
|
|
3902
|
-
if (
|
|
3903
|
-
|
|
3948
|
+
if (fs10.existsSync(cacheDir)) {
|
|
3949
|
+
fs10.rmSync(cacheDir, { recursive: true });
|
|
3904
3950
|
}
|
|
3905
3951
|
});
|
|
3906
3952
|
}
|
|
@@ -3924,21 +3970,28 @@ function vsBrowserPlugin({
|
|
|
3924
3970
|
runExitHandlers();
|
|
3925
3971
|
}
|
|
3926
3972
|
async function openPreviewPage() {
|
|
3973
|
+
const locale = await getOsLocale();
|
|
3927
3974
|
const url = await getViewerFullUrl(config);
|
|
3928
3975
|
const { page, browser } = await launchPreview({
|
|
3929
3976
|
mode: "preview",
|
|
3930
3977
|
url,
|
|
3931
3978
|
config,
|
|
3979
|
+
/* v8 ignore next 4 */
|
|
3932
3980
|
onPageOpen: async (page2) => {
|
|
3933
3981
|
page2.on("close", handlePageClose);
|
|
3934
|
-
const locale = Intl.DateTimeFormat().resolvedOptions().locale;
|
|
3935
|
-
await page2.addInitScript(
|
|
3936
|
-
`window.localStorage.setItem('i18nextLng', '${locale}');`
|
|
3937
|
-
);
|
|
3938
3982
|
}
|
|
3939
3983
|
});
|
|
3984
|
+
if (!import.meta.env?.VITEST) {
|
|
3985
|
+
await page.evaluate((locale2) => {
|
|
3986
|
+
window.localStorage.setItem("i18nextLng", locale2);
|
|
3987
|
+
}, locale);
|
|
3988
|
+
}
|
|
3940
3989
|
await page.bringToFront();
|
|
3941
|
-
|
|
3990
|
+
if (!import.meta.env?.VITEST) {
|
|
3991
|
+
await page.evaluate(() => {
|
|
3992
|
+
document.querySelector("#vivliostyle-input-url")?.focus();
|
|
3993
|
+
});
|
|
3994
|
+
}
|
|
3942
3995
|
closeBrowser = () => {
|
|
3943
3996
|
page.off("close", handlePageClose);
|
|
3944
3997
|
browser.close();
|
|
@@ -3970,10 +4023,8 @@ export {
|
|
|
3970
4023
|
mergeInlineConfig,
|
|
3971
4024
|
isWebPubConfig,
|
|
3972
4025
|
resolveTaskConfig,
|
|
3973
|
-
getFullBrowserName,
|
|
3974
4026
|
launchPreview,
|
|
3975
4027
|
vsBrowserPlugin,
|
|
3976
|
-
copyAssets,
|
|
3977
4028
|
buildWebPublication,
|
|
3978
4029
|
cleanupWorkspace,
|
|
3979
4030
|
prepareThemeDirectory,
|
|
@@ -3985,4 +4036,4 @@ export {
|
|
|
3985
4036
|
getViewerFullUrl,
|
|
3986
4037
|
createViteServer
|
|
3987
4038
|
};
|
|
3988
|
-
//# sourceMappingURL=chunk-
|
|
4039
|
+
//# sourceMappingURL=chunk-YN3JNBNT.js.map
|