@vivliostyle/cli 9.9.0 → 10.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +74 -30
- package/dist/{chunk-WELNNHOB.js → chunk-CKAJY2BE.js} +415 -384
- package/dist/chunk-CKAJY2BE.js.map +1 -0
- package/dist/{chunk-UYKCTF6F.js → chunk-CKXFRCPH.js} +445 -228
- package/dist/chunk-CKXFRCPH.js.map +1 -0
- package/dist/{chunk-3O3N2V7D.js → chunk-IOFOZNLZ.js} +6 -7
- package/dist/chunk-IOFOZNLZ.js.map +1 -0
- package/dist/{chunk-OZ4XTSAH.js → chunk-LVS2NLYC.js} +2 -2
- package/dist/chunk-LVS2NLYC.js.map +1 -0
- package/dist/{chunk-6UU7DEUR.js → chunk-RJO22WHX.js} +32 -33
- package/dist/chunk-RJO22WHX.js.map +1 -0
- package/dist/chunk-RKU7H2GS.js +1076 -0
- package/dist/chunk-RKU7H2GS.js.map +1 -0
- package/dist/{chunk-QWX5MAON.js → chunk-SPTG2DFV.js} +16 -17
- package/dist/chunk-SPTG2DFV.js.map +1 -0
- package/dist/{chunk-G3GROLBN.js → chunk-T2VWLU2I.js} +397 -88
- package/dist/chunk-T2VWLU2I.js.map +1 -0
- package/dist/chunk-ZEBXHUJX.js +334 -0
- package/dist/chunk-ZEBXHUJX.js.map +1 -0
- package/dist/{chunk-FXUEYQRY.js → chunk-ZIK6DINS.js} +3 -3
- package/dist/chunk-ZIK6DINS.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 +8370 -4567
- package/dist/config/schema.js +16 -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 +37 -26
- package/dist/chunk-3O3N2V7D.js.map +0 -1
- package/dist/chunk-4IIM6RSG.js +0 -71
- package/dist/chunk-4IIM6RSG.js.map +0 -1
- package/dist/chunk-6KEOMYDZ.js +0 -89
- package/dist/chunk-6KEOMYDZ.js.map +0 -1
- package/dist/chunk-6UU7DEUR.js.map +0 -1
- package/dist/chunk-FXUEYQRY.js.map +0 -1
- package/dist/chunk-G3GROLBN.js.map +0 -1
- package/dist/chunk-OZ4XTSAH.js.map +0 -1
- package/dist/chunk-QWX5MAON.js.map +0 -1
- package/dist/chunk-UYKCTF6F.js.map +0 -1
- package/dist/chunk-WELNNHOB.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-T2VWLU2I.js";
|
|
30
34
|
import {
|
|
31
35
|
VivliostyleConfigSchema
|
|
32
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-CKXFRCPH.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-ZEBXHUJX.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) => ({
|
|
@@ -265,7 +273,10 @@ function readMarkdownMetadata(filepath, documentMetadataReader) {
|
|
|
265
273
|
var manuscriptMediaTypes = [
|
|
266
274
|
"text/markdown",
|
|
267
275
|
"text/html",
|
|
268
|
-
"
|
|
276
|
+
"text/plain",
|
|
277
|
+
"application/xhtml+xml",
|
|
278
|
+
// a special MIME type indicates that a custom processor is used
|
|
279
|
+
"text/x-vivliostyle-custom"
|
|
269
280
|
];
|
|
270
281
|
var UseTemporaryServerRoot = Symbol("UseTemporaryServerRoot");
|
|
271
282
|
var DEFAULT_ASSET_EXTENSIONS = [
|
|
@@ -286,6 +297,17 @@ var DEFAULT_ASSET_EXTENSIONS = [
|
|
|
286
297
|
function isManuscriptMediaType(mediaType) {
|
|
287
298
|
return !!(mediaType && manuscriptMediaTypes.includes(mediaType));
|
|
288
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
|
+
}
|
|
289
311
|
function isWebPubConfig(config) {
|
|
290
312
|
return config.viewerInput.type === "webpub";
|
|
291
313
|
}
|
|
@@ -381,7 +403,7 @@ function parseFileMetadata({
|
|
|
381
403
|
const sourceDir = upath2.dirname(sourcePath);
|
|
382
404
|
let title;
|
|
383
405
|
let themes;
|
|
384
|
-
if (
|
|
406
|
+
if (documentMetadataReader) {
|
|
385
407
|
const metadata = readMarkdownMetadata(sourcePath, documentMetadataReader);
|
|
386
408
|
title = metadata.title;
|
|
387
409
|
if (metadata.vfm?.theme && themesDir) {
|
|
@@ -396,7 +418,7 @@ function parseFileMetadata({
|
|
|
396
418
|
})
|
|
397
419
|
);
|
|
398
420
|
}
|
|
399
|
-
} else {
|
|
421
|
+
} else if (contentType === "text/html" || contentType === "application/xhtml+xml") {
|
|
400
422
|
const content = fs3.readFileSync(sourcePath, "utf8");
|
|
401
423
|
title = content.match(/<title>([^<]*)<\/title>/)?.[1] || void 0;
|
|
402
424
|
}
|
|
@@ -436,8 +458,6 @@ function resolveTaskConfig(config, options) {
|
|
|
436
458
|
const singleDoc = options.singleDoc ?? false;
|
|
437
459
|
const quick = options.quick ?? false;
|
|
438
460
|
const temporaryFilePrefix = config.temporaryFilePrefix ?? `.vs-${Date.now()}.`;
|
|
439
|
-
const documentProcessorFactory = config?.documentProcessor ?? VFM;
|
|
440
|
-
const documentMetadataReader = config?.documentMetadataReader ?? readMetadata;
|
|
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,
|
|
@@ -558,9 +583,7 @@ function resolveTaskConfig(config, options) {
|
|
|
558
583
|
context,
|
|
559
584
|
temporaryFilePrefix,
|
|
560
585
|
themeIndexes,
|
|
561
|
-
base
|
|
562
|
-
documentProcessorFactory,
|
|
563
|
-
documentMetadataReader
|
|
586
|
+
base
|
|
564
587
|
}) : resolveComposedProjectConfig({
|
|
565
588
|
config,
|
|
566
589
|
context,
|
|
@@ -568,9 +591,7 @@ function resolveTaskConfig(config, options) {
|
|
|
568
591
|
outputs,
|
|
569
592
|
temporaryFilePrefix,
|
|
570
593
|
themeIndexes,
|
|
571
|
-
cover
|
|
572
|
-
documentProcessorFactory,
|
|
573
|
-
documentMetadataReader
|
|
594
|
+
cover
|
|
574
595
|
});
|
|
575
596
|
for (const output of outputs) {
|
|
576
597
|
const relPath = upath2.relative(context, output.path);
|
|
@@ -615,8 +636,6 @@ function resolveTaskConfig(config, options) {
|
|
|
615
636
|
quick,
|
|
616
637
|
language,
|
|
617
638
|
readingProgression,
|
|
618
|
-
documentProcessorFactory,
|
|
619
|
-
documentMetadataReader,
|
|
620
639
|
vfmOptions,
|
|
621
640
|
cover,
|
|
622
641
|
timeout,
|
|
@@ -643,9 +662,7 @@ function resolveSingleInputConfig({
|
|
|
643
662
|
context,
|
|
644
663
|
temporaryFilePrefix,
|
|
645
664
|
themeIndexes,
|
|
646
|
-
base
|
|
647
|
-
documentProcessorFactory,
|
|
648
|
-
documentMetadataReader
|
|
665
|
+
base
|
|
649
666
|
}) {
|
|
650
667
|
Logger.debug("entering single entry config mode");
|
|
651
668
|
let serverRootDir;
|
|
@@ -698,16 +715,22 @@ function resolveSingleInputConfig({
|
|
|
698
715
|
const themesDir = upath2.resolve(workspaceDir, "themes");
|
|
699
716
|
if (input.format === "markdown") {
|
|
700
717
|
const contentType = "text/markdown";
|
|
718
|
+
const documentProcessor = {
|
|
719
|
+
processorFactory: config.documentProcessor ?? VFM,
|
|
720
|
+
metadataReader: config.documentMetadataReader ?? readMetadata
|
|
721
|
+
};
|
|
701
722
|
const metadata = parseFileMetadata({
|
|
702
723
|
contentType,
|
|
703
724
|
sourcePath,
|
|
704
725
|
workspaceDir,
|
|
705
|
-
documentMetadataReader
|
|
726
|
+
documentMetadataReader: documentProcessor.metadataReader
|
|
706
727
|
});
|
|
707
|
-
const target =
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
728
|
+
const target = toHtmlExtension(
|
|
729
|
+
upath2.resolve(
|
|
730
|
+
workspaceDir,
|
|
731
|
+
`${temporaryFilePrefix}${upath2.basename(sourcePath)}`
|
|
732
|
+
)
|
|
733
|
+
);
|
|
711
734
|
touchTmpFile(target);
|
|
712
735
|
const themes = metadata.themes ?? config.theme?.map(
|
|
713
736
|
(theme) => parseTheme({
|
|
@@ -723,19 +746,18 @@ function resolveSingleInputConfig({
|
|
|
723
746
|
source: {
|
|
724
747
|
type: "file",
|
|
725
748
|
pathname: sourcePath,
|
|
726
|
-
contentType
|
|
749
|
+
contentType,
|
|
750
|
+
documentProcessor
|
|
727
751
|
},
|
|
728
752
|
target,
|
|
729
753
|
title: metadata.title,
|
|
730
|
-
themes
|
|
731
|
-
documentProcessorFactory,
|
|
732
|
-
documentMetadataReader
|
|
754
|
+
themes
|
|
733
755
|
});
|
|
734
756
|
exportAliases.push({
|
|
735
757
|
source: target,
|
|
736
758
|
target: upath2.resolve(
|
|
737
759
|
upath2.dirname(target),
|
|
738
|
-
upath2.basename(sourcePath)
|
|
760
|
+
toHtmlExtension(upath2.basename(sourcePath))
|
|
739
761
|
)
|
|
740
762
|
});
|
|
741
763
|
}
|
|
@@ -812,9 +834,7 @@ function resolveComposedProjectConfig({
|
|
|
812
834
|
outputs,
|
|
813
835
|
temporaryFilePrefix,
|
|
814
836
|
themeIndexes,
|
|
815
|
-
cover
|
|
816
|
-
documentProcessorFactory,
|
|
817
|
-
documentMetadataReader
|
|
837
|
+
cover
|
|
818
838
|
}) {
|
|
819
839
|
Logger.debug("entering composed project config mode");
|
|
820
840
|
const workspaceDir = upath2.resolve(
|
|
@@ -861,11 +881,15 @@ function resolveComposedProjectConfig({
|
|
|
861
881
|
};
|
|
862
882
|
const projectTitle = config?.title ?? pkgJson?.name;
|
|
863
883
|
const projectAuthor = config?.author ?? pkgJson?.author;
|
|
884
|
+
const rootDocumentProcessor = {
|
|
885
|
+
processorFactory: config.documentProcessor ?? VFM,
|
|
886
|
+
metadataReader: config.documentMetadataReader ?? readMetadata
|
|
887
|
+
};
|
|
864
888
|
const isContentsEntry = (entry) => entry.rel === "contents";
|
|
865
889
|
const isCoverEntry = (entry) => entry.rel === "cover";
|
|
866
890
|
const isArticleEntry = (entry) => !isContentsEntry(entry) && !isCoverEntry(entry);
|
|
867
891
|
function parseEntry(entry) {
|
|
868
|
-
const getInputInfo = (entryPath
|
|
892
|
+
const getInputInfo = (entryPath) => {
|
|
869
893
|
if (/^https?:/.test(entryPath)) {
|
|
870
894
|
return {
|
|
871
895
|
type: "uri",
|
|
@@ -881,13 +905,19 @@ function resolveComposedProjectConfig({
|
|
|
881
905
|
}
|
|
882
906
|
const pathname = upath2.resolve(entryContextDir, entryPath);
|
|
883
907
|
statFileSync(pathname);
|
|
884
|
-
const
|
|
885
|
-
|
|
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") {
|
|
886
916
|
throw new Error(
|
|
887
|
-
`Invalid manuscript type ${
|
|
917
|
+
`Invalid manuscript type ${rawContentType} detected: ${entry}`
|
|
888
918
|
);
|
|
889
919
|
}
|
|
890
|
-
const
|
|
920
|
+
const useDocumentProcessor = contentType === "text/markdown" || contentType === "text/x-vivliostyle-custom";
|
|
891
921
|
return {
|
|
892
922
|
type: "file",
|
|
893
923
|
pathname,
|
|
@@ -897,8 +927,9 @@ function resolveComposedProjectConfig({
|
|
|
897
927
|
sourcePath: pathname,
|
|
898
928
|
workspaceDir,
|
|
899
929
|
themesDir,
|
|
900
|
-
documentMetadataReader:
|
|
901
|
-
})
|
|
930
|
+
documentMetadataReader: useDocumentProcessor ? documentProcessor.metadataReader : void 0
|
|
931
|
+
}),
|
|
932
|
+
...useDocumentProcessor && { documentProcessor }
|
|
902
933
|
};
|
|
903
934
|
};
|
|
904
935
|
const getTargetPath = (source) => {
|
|
@@ -906,7 +937,7 @@ function resolveComposedProjectConfig({
|
|
|
906
937
|
case "file":
|
|
907
938
|
return upath2.resolve(
|
|
908
939
|
workspaceDir,
|
|
909
|
-
upath2.relative(entryContextDir, source.pathname)
|
|
940
|
+
toHtmlExtension(upath2.relative(entryContextDir, source.pathname))
|
|
910
941
|
);
|
|
911
942
|
case "uri": {
|
|
912
943
|
const url = new URL(source.href, "a://dummy");
|
|
@@ -1013,9 +1044,7 @@ Maybe you want to set the "output" field instead.`
|
|
|
1013
1044
|
return parsedEntry;
|
|
1014
1045
|
}
|
|
1015
1046
|
if (isArticleEntry(entry)) {
|
|
1016
|
-
const inputInfo = getInputInfo(entry.path
|
|
1017
|
-
entryDocumentMetadataReader: entry.documentMetadataReader
|
|
1018
|
-
});
|
|
1047
|
+
const inputInfo = getInputInfo(entry.path);
|
|
1019
1048
|
const { metadata, ...source } = inputInfo;
|
|
1020
1049
|
const target = entry.output ? upath2.resolve(workspaceDir, entry.output) : getTargetPath(inputInfo);
|
|
1021
1050
|
const themes = entry.theme ? [entry.theme].flat().map(
|
|
@@ -1028,10 +1057,7 @@ Maybe you want to set the "output" field instead.`
|
|
|
1028
1057
|
target,
|
|
1029
1058
|
title: entry.title ?? metadata?.title ?? projectTitle,
|
|
1030
1059
|
themes,
|
|
1031
|
-
...entry.rel && { rel: entry.rel }
|
|
1032
|
-
// Use per-entry settings if specified, otherwise fall back to global settings
|
|
1033
|
-
documentProcessorFactory: entry.documentProcessor ?? documentProcessorFactory,
|
|
1034
|
-
documentMetadataReader: entry.documentMetadataReader ?? documentMetadataReader
|
|
1060
|
+
...entry.rel && { rel: entry.rel }
|
|
1035
1061
|
};
|
|
1036
1062
|
return parsedEntry;
|
|
1037
1063
|
}
|
|
@@ -1084,77 +1110,211 @@ Maybe you want to set the "output" field instead.`
|
|
|
1084
1110
|
};
|
|
1085
1111
|
}
|
|
1086
1112
|
|
|
1113
|
+
// src/vite/vite-plugin-browser.ts
|
|
1114
|
+
import "vite";
|
|
1115
|
+
|
|
1087
1116
|
// src/browser.ts
|
|
1088
1117
|
import fs4 from "node:fs";
|
|
1118
|
+
import upath3 from "upath";
|
|
1119
|
+
var browserEnumMap = {
|
|
1120
|
+
chrome: "chrome",
|
|
1121
|
+
chromium: "chromium",
|
|
1122
|
+
firefox: "firefox"
|
|
1123
|
+
};
|
|
1089
1124
|
async function launchBrowser({
|
|
1090
1125
|
browserType,
|
|
1091
1126
|
proxy,
|
|
1092
1127
|
executablePath,
|
|
1093
1128
|
headless,
|
|
1094
1129
|
noSandbox,
|
|
1095
|
-
disableDevShmUsage
|
|
1130
|
+
disableDevShmUsage,
|
|
1131
|
+
ignoreHttpsErrors
|
|
1096
1132
|
}) {
|
|
1097
|
-
const
|
|
1098
|
-
|
|
1099
|
-
|
|
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 = {
|
|
1100
1195
|
executablePath,
|
|
1101
|
-
|
|
1196
|
+
args,
|
|
1197
|
+
browser: browserType === "chromium" ? "chrome" : browserType,
|
|
1102
1198
|
headless,
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
// set Chromium language to English to avoid locale-dependent issues
|
|
1112
|
-
"--lang=en",
|
|
1113
|
-
...!headless && process.platform === "darwin" ? ["", "-AppleLanguages", "(en)"] : []
|
|
1114
|
-
],
|
|
1115
|
-
env: { ...process.env, LANG: "en.UTF-8" },
|
|
1116
|
-
proxy
|
|
1117
|
-
} : (
|
|
1118
|
-
// TODO: Investigate appropriate settings on Firefox & Webkit
|
|
1119
|
-
{ executablePath, headless }
|
|
1120
|
-
);
|
|
1121
|
-
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
|
+
});
|
|
1122
1207
|
registerExitHandler("Closing browser", () => {
|
|
1123
1208
|
browser.close();
|
|
1124
1209
|
});
|
|
1125
|
-
|
|
1210
|
+
const [browserContext] = browser.browserContexts();
|
|
1211
|
+
return { browser, browserContext };
|
|
1126
1212
|
}
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1213
|
+
function getPuppeteerCacheDir() {
|
|
1214
|
+
if (isInContainer()) {
|
|
1215
|
+
return "/opt/puppeteer";
|
|
1216
|
+
}
|
|
1217
|
+
return upath3.join(getCacheDir(), "browsers");
|
|
1130
1218
|
}
|
|
1131
|
-
function
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
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
|
+
});
|
|
1137
1282
|
}
|
|
1138
1283
|
function checkBrowserAvailability(path) {
|
|
1139
1284
|
return fs4.existsSync(path);
|
|
1140
1285
|
}
|
|
1141
|
-
async function downloadBrowser(
|
|
1142
|
-
|
|
1143
|
-
|
|
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
|
+
}
|
|
1144
1299
|
{
|
|
1145
1300
|
var _stack = [];
|
|
1146
1301
|
try {
|
|
1147
1302
|
const _2 = __using(_stack, Logger.suspendLogging(
|
|
1148
1303
|
"Rendering browser is not installed yet. Downloading now."
|
|
1149
1304
|
));
|
|
1150
|
-
await
|
|
1305
|
+
installedBrowser = await browsers.install({
|
|
1306
|
+
cacheDir: getPuppeteerCacheDir(),
|
|
1307
|
+
browser: browserEnumMap[type],
|
|
1308
|
+
buildId,
|
|
1309
|
+
downloadProgressCallback: "default"
|
|
1310
|
+
});
|
|
1151
1311
|
} catch (_) {
|
|
1152
1312
|
var _error = _, _hasError = true;
|
|
1153
1313
|
} finally {
|
|
1154
1314
|
__callDispose(_stack, _error, _hasError);
|
|
1155
1315
|
}
|
|
1156
1316
|
}
|
|
1157
|
-
return
|
|
1317
|
+
return installedBrowser.executablePath;
|
|
1158
1318
|
}
|
|
1159
1319
|
async function launchPreview({
|
|
1160
1320
|
mode,
|
|
@@ -1164,48 +1324,59 @@ async function launchPreview({
|
|
|
1164
1324
|
config: { browser: browserConfig, proxy, sandbox, ignoreHttpsErrors }
|
|
1165
1325
|
}) {
|
|
1166
1326
|
let executableBrowser = browserConfig.executablePath;
|
|
1327
|
+
Logger.debug(`Specified browser path: ${executableBrowser}`);
|
|
1167
1328
|
if (executableBrowser) {
|
|
1168
1329
|
if (!checkBrowserAvailability(executableBrowser)) {
|
|
1169
1330
|
throw new Error(
|
|
1170
1331
|
`Cannot find the browser. Please check the executable browser path: ${executableBrowser}`
|
|
1171
1332
|
);
|
|
1172
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";
|
|
1173
1339
|
} else {
|
|
1174
|
-
executableBrowser = await getExecutableBrowserPath(browserConfig
|
|
1340
|
+
executableBrowser = await getExecutableBrowserPath(browserConfig);
|
|
1341
|
+
Logger.debug(`Using default browser: ${executableBrowser}`);
|
|
1175
1342
|
if (!checkBrowserAvailability(executableBrowser)) {
|
|
1176
|
-
await
|
|
1343
|
+
await cleanupOutdatedBrowsers();
|
|
1344
|
+
await downloadBrowser(browserConfig);
|
|
1177
1345
|
}
|
|
1178
1346
|
}
|
|
1179
|
-
|
|
1180
|
-
const browser = await launchBrowser({
|
|
1347
|
+
const { browser, browserContext } = await launchBrowser({
|
|
1181
1348
|
browserType: browserConfig.type,
|
|
1182
1349
|
proxy,
|
|
1183
1350
|
executablePath: executableBrowser,
|
|
1184
1351
|
headless: mode === "build",
|
|
1185
1352
|
noSandbox: !sandbox,
|
|
1186
|
-
disableDevShmUsage: isInContainer()
|
|
1353
|
+
disableDevShmUsage: isInContainer(),
|
|
1354
|
+
ignoreHttpsErrors
|
|
1187
1355
|
});
|
|
1188
1356
|
await onBrowserOpen?.(browser);
|
|
1189
|
-
const page = await
|
|
1190
|
-
|
|
1191
|
-
|
|
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
|
|
1192
1361
|
// https://github.com/vivliostyle/vivliostyle.js/blob/73bcf323adcad80126b0175630609451ccd09d8a/packages/core/src/vivliostyle/vgen.ts#L2489-L2500
|
|
1193
|
-
{
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
}
|
|
1197
|
-
) : null,
|
|
1198
|
-
ignoreHTTPSErrors: ignoreHttpsErrors
|
|
1199
|
-
});
|
|
1362
|
+
{ width: 800, height: 600 }
|
|
1363
|
+
) : null
|
|
1364
|
+
);
|
|
1200
1365
|
await onPageOpen?.(page);
|
|
1201
1366
|
page.on("dialog", () => {
|
|
1202
1367
|
});
|
|
1368
|
+
if (proxy?.username && proxy?.password) {
|
|
1369
|
+
await page.authenticate({
|
|
1370
|
+
username: proxy.username,
|
|
1371
|
+
password: proxy.password
|
|
1372
|
+
});
|
|
1373
|
+
}
|
|
1203
1374
|
await page.goto(url);
|
|
1204
1375
|
return { browser, page };
|
|
1205
1376
|
}
|
|
1206
1377
|
|
|
1207
1378
|
// src/server.ts
|
|
1208
|
-
import
|
|
1379
|
+
import fs10 from "node:fs";
|
|
1209
1380
|
import { URL as URL2 } from "node:url";
|
|
1210
1381
|
import upath11 from "upath";
|
|
1211
1382
|
import {
|
|
@@ -1218,170 +1389,22 @@ import escapeRe from "escape-string-regexp";
|
|
|
1218
1389
|
import { pathToFileURL as pathToFileURL6 } from "node:url";
|
|
1219
1390
|
import sirv from "sirv";
|
|
1220
1391
|
import upath8 from "upath";
|
|
1221
|
-
|
|
1222
|
-
// src/processor/asset.ts
|
|
1223
|
-
import { copy } from "fs-extra/esm";
|
|
1224
|
-
import fs5 from "node:fs";
|
|
1225
|
-
import picomatch from "picomatch";
|
|
1226
|
-
import { glob } from "tinyglobby";
|
|
1227
|
-
import upath3 from "upath";
|
|
1228
|
-
var GlobMatcher = class {
|
|
1229
|
-
constructor(matcherConfig) {
|
|
1230
|
-
this.matcherConfig = matcherConfig;
|
|
1231
|
-
this.#_matchers = matcherConfig.map(
|
|
1232
|
-
({ patterns, ...options }) => picomatch(patterns, options)
|
|
1233
|
-
);
|
|
1234
|
-
}
|
|
1235
|
-
#_matchers;
|
|
1236
|
-
match(test) {
|
|
1237
|
-
return this.#_matchers.some((matcher) => matcher(test));
|
|
1238
|
-
}
|
|
1239
|
-
async glob(globOptions = {}) {
|
|
1240
|
-
return new Set(
|
|
1241
|
-
(await Promise.all(
|
|
1242
|
-
this.matcherConfig.map(
|
|
1243
|
-
(config) => glob({ ...config, ...globOptions })
|
|
1244
|
-
)
|
|
1245
|
-
)).flat()
|
|
1246
|
-
);
|
|
1247
|
-
}
|
|
1248
|
-
};
|
|
1249
|
-
function getIgnoreThemeDirectoryPatterns({
|
|
1250
|
-
themesDir,
|
|
1251
|
-
cwd: cwd2
|
|
1252
|
-
}) {
|
|
1253
|
-
return pathContains(cwd2, themesDir) ? [
|
|
1254
|
-
`${upath3.relative(cwd2, themesDir)}/node_modules/*/example`,
|
|
1255
|
-
`${upath3.relative(cwd2, themesDir)}/node_modules/*/*/example`
|
|
1256
|
-
] : [];
|
|
1257
|
-
}
|
|
1258
|
-
function getIgnoreAssetPatterns({
|
|
1259
|
-
outputs,
|
|
1260
|
-
entries,
|
|
1261
|
-
cwd: cwd2
|
|
1262
|
-
}) {
|
|
1263
|
-
return [
|
|
1264
|
-
...outputs.flatMap(
|
|
1265
|
-
({ format, path: p }) => !pathContains(cwd2, p) ? [] : format === "webpub" ? upath3.join(upath3.relative(cwd2, p), "**") : upath3.relative(cwd2, p)
|
|
1266
|
-
),
|
|
1267
|
-
...entries.flatMap(({ template }) => {
|
|
1268
|
-
return template?.type === "file" && pathContains(cwd2, template.pathname) ? upath3.relative(cwd2, template.pathname) : [];
|
|
1269
|
-
})
|
|
1270
|
-
];
|
|
1271
|
-
}
|
|
1272
|
-
function getWebPubResourceMatcher({
|
|
1273
|
-
outputs,
|
|
1274
|
-
themesDir,
|
|
1275
|
-
entries,
|
|
1276
|
-
cwd: cwd2,
|
|
1277
|
-
manifestPath,
|
|
1278
|
-
copyAsset: { fileExtensions }
|
|
1279
|
-
}) {
|
|
1280
|
-
return new GlobMatcher([
|
|
1281
|
-
{
|
|
1282
|
-
patterns: [
|
|
1283
|
-
`**/${upath3.relative(cwd2, manifestPath)}`,
|
|
1284
|
-
"**/*.{html,htm,xhtml,xht}",
|
|
1285
|
-
`**/*.{${fileExtensions.join(",")}}`
|
|
1286
|
-
],
|
|
1287
|
-
ignore: [
|
|
1288
|
-
...getIgnoreAssetPatterns({
|
|
1289
|
-
cwd: cwd2,
|
|
1290
|
-
outputs,
|
|
1291
|
-
entries
|
|
1292
|
-
}),
|
|
1293
|
-
...getIgnoreThemeDirectoryPatterns({
|
|
1294
|
-
cwd: cwd2,
|
|
1295
|
-
themesDir
|
|
1296
|
-
}),
|
|
1297
|
-
// Ignore node_modules in the root directory
|
|
1298
|
-
"node_modules/**",
|
|
1299
|
-
// only include dotfiles starting with `.vs-`
|
|
1300
|
-
"**/.!(vs-*)/**"
|
|
1301
|
-
],
|
|
1302
|
-
dot: true,
|
|
1303
|
-
cwd: cwd2
|
|
1304
|
-
}
|
|
1305
|
-
]);
|
|
1306
|
-
}
|
|
1307
|
-
function getAssetMatcher({
|
|
1308
|
-
copyAsset: { fileExtensions, includes, excludes },
|
|
1309
|
-
outputs,
|
|
1310
|
-
themesDir,
|
|
1311
|
-
entries,
|
|
1312
|
-
cwd: cwd2,
|
|
1313
|
-
ignore = []
|
|
1314
|
-
}) {
|
|
1315
|
-
const ignorePatterns = [
|
|
1316
|
-
...ignore,
|
|
1317
|
-
...excludes,
|
|
1318
|
-
...getIgnoreAssetPatterns({ outputs, entries, cwd: cwd2 })
|
|
1319
|
-
];
|
|
1320
|
-
return new GlobMatcher([
|
|
1321
|
-
// Step 1: Glob files with an extension in `fileExtension`
|
|
1322
|
-
// Ignore files in node_modules directory, theme example files and files matched `excludes`
|
|
1323
|
-
{
|
|
1324
|
-
patterns: fileExtensions.map((ext) => `**/*.${ext}`),
|
|
1325
|
-
ignore: [
|
|
1326
|
-
"**/node_modules/**",
|
|
1327
|
-
...ignorePatterns,
|
|
1328
|
-
...getIgnoreThemeDirectoryPatterns({ themesDir, cwd: cwd2 })
|
|
1329
|
-
],
|
|
1330
|
-
cwd: cwd2
|
|
1331
|
-
},
|
|
1332
|
-
// Step 2: Glob files matched with `includes`
|
|
1333
|
-
// Ignore only files matched `excludes`
|
|
1334
|
-
{
|
|
1335
|
-
patterns: includes,
|
|
1336
|
-
ignore: ignorePatterns,
|
|
1337
|
-
cwd: cwd2
|
|
1338
|
-
}
|
|
1339
|
-
]);
|
|
1340
|
-
}
|
|
1341
|
-
async function copyAssets({
|
|
1342
|
-
entryContextDir,
|
|
1343
|
-
workspaceDir,
|
|
1344
|
-
copyAsset,
|
|
1345
|
-
outputs,
|
|
1346
|
-
themesDir,
|
|
1347
|
-
entries
|
|
1348
|
-
}) {
|
|
1349
|
-
if (pathEquals(entryContextDir, workspaceDir)) {
|
|
1350
|
-
return;
|
|
1351
|
-
}
|
|
1352
|
-
const relWorkspaceDir = upath3.relative(entryContextDir, workspaceDir);
|
|
1353
|
-
const assets = await getAssetMatcher({
|
|
1354
|
-
copyAsset,
|
|
1355
|
-
cwd: entryContextDir,
|
|
1356
|
-
outputs,
|
|
1357
|
-
themesDir,
|
|
1358
|
-
entries,
|
|
1359
|
-
ignore: [
|
|
1360
|
-
// don't copy workspace itself
|
|
1361
|
-
...relWorkspaceDir ? [upath3.join(relWorkspaceDir, "**")] : []
|
|
1362
|
-
]
|
|
1363
|
-
}).glob({ followSymbolicLinks: true });
|
|
1364
|
-
Logger.debug("assets", assets);
|
|
1365
|
-
for (const asset of assets) {
|
|
1366
|
-
const target = upath3.join(workspaceDir, asset);
|
|
1367
|
-
fs5.mkdirSync(upath3.dirname(target), { recursive: true });
|
|
1368
|
-
await copy(upath3.resolve(entryContextDir, asset), target);
|
|
1369
|
-
}
|
|
1370
|
-
}
|
|
1392
|
+
import "vite";
|
|
1371
1393
|
|
|
1372
1394
|
// src/processor/compile.ts
|
|
1373
|
-
import
|
|
1374
|
-
import
|
|
1395
|
+
import "@vivliostyle/jsdom";
|
|
1396
|
+
import { copy as copy3, move } from "fs-extra/esm";
|
|
1397
|
+
import fs8 from "node:fs";
|
|
1375
1398
|
import upath7 from "upath";
|
|
1376
1399
|
import serializeToXml2 from "w3c-xmlserializer";
|
|
1377
1400
|
import MIMEType2 from "whatwg-mimetype";
|
|
1378
1401
|
|
|
1379
1402
|
// src/output/webbook.ts
|
|
1380
|
-
import { copy as
|
|
1403
|
+
import { copy as copy2 } from "fs-extra/esm";
|
|
1381
1404
|
import { lookup as mime3 } from "mime-types";
|
|
1382
|
-
import
|
|
1405
|
+
import fs6 from "node:fs";
|
|
1383
1406
|
import { pathToFileURL as pathToFileURL5 } from "node:url";
|
|
1384
|
-
import { glob
|
|
1407
|
+
import { glob } from "tinyglobby";
|
|
1385
1408
|
import upath6 from "upath";
|
|
1386
1409
|
|
|
1387
1410
|
// src/processor/html.tsx
|
|
@@ -1548,8 +1571,8 @@ function getJsdomFromString({
|
|
|
1548
1571
|
}
|
|
1549
1572
|
async function getStructuredSectionFromHtml(htmlPath, href) {
|
|
1550
1573
|
const dom = await getJsdomFromUrlOrFile({ src: htmlPath });
|
|
1551
|
-
const { document } = dom.window;
|
|
1552
|
-
const allHeadings = [...
|
|
1574
|
+
const { document: document2 } = dom.window;
|
|
1575
|
+
const allHeadings = [...document2.querySelectorAll("h1, h2, h3, h4, h5, h6")].filter((el) => {
|
|
1553
1576
|
return !el.matches("blockquote *");
|
|
1554
1577
|
}).sort((a, b) => {
|
|
1555
1578
|
const position = a.compareDocumentPosition(b);
|
|
@@ -1714,17 +1737,17 @@ async function processTocHtml(dom, {
|
|
|
1714
1737
|
sectionDepth,
|
|
1715
1738
|
transform
|
|
1716
1739
|
}) {
|
|
1717
|
-
const { document } = dom.window;
|
|
1718
|
-
if (!
|
|
1740
|
+
const { document: document2 } = dom.window;
|
|
1741
|
+
if (!document2.querySelector(
|
|
1719
1742
|
'link[rel="publication"][type="application/ld+json"]'
|
|
1720
1743
|
)) {
|
|
1721
|
-
const l =
|
|
1744
|
+
const l = document2.createElement("link");
|
|
1722
1745
|
l.setAttribute("rel", "publication");
|
|
1723
1746
|
l.setAttribute("type", "application/ld+json");
|
|
1724
1747
|
l.setAttribute("href", encodeURI(upath4.relative(distDir, manifestPath)));
|
|
1725
|
-
|
|
1748
|
+
document2.head.appendChild(l);
|
|
1726
1749
|
}
|
|
1727
|
-
const style =
|
|
1750
|
+
const style = document2.querySelector("style[data-vv-style]");
|
|
1728
1751
|
if (style) {
|
|
1729
1752
|
const textContent = getTocHtmlStyle(styleOptions);
|
|
1730
1753
|
if (textContent) {
|
|
@@ -1733,9 +1756,9 @@ async function processTocHtml(dom, {
|
|
|
1733
1756
|
style.remove();
|
|
1734
1757
|
}
|
|
1735
1758
|
}
|
|
1736
|
-
const nav =
|
|
1759
|
+
const nav = document2.querySelector('nav, [role="doc-toc"]');
|
|
1737
1760
|
if (nav && !nav.hasChildNodes()) {
|
|
1738
|
-
const h2 =
|
|
1761
|
+
const h2 = document2.createElement("h2");
|
|
1739
1762
|
h2.textContent = tocTitle;
|
|
1740
1763
|
nav.appendChild(h2);
|
|
1741
1764
|
nav.innerHTML += await generateTocListSection({
|
|
@@ -1788,8 +1811,8 @@ async function processCoverHtml(dom, {
|
|
|
1788
1811
|
imageAlt,
|
|
1789
1812
|
styleOptions = {}
|
|
1790
1813
|
}) {
|
|
1791
|
-
const { document } = dom.window;
|
|
1792
|
-
const style =
|
|
1814
|
+
const { document: document2 } = dom.window;
|
|
1815
|
+
const style = document2.querySelector("style[data-vv-style]");
|
|
1793
1816
|
if (style) {
|
|
1794
1817
|
const textContent = getCoverHtmlStyle(styleOptions);
|
|
1795
1818
|
if (textContent) {
|
|
@@ -1798,7 +1821,7 @@ async function processCoverHtml(dom, {
|
|
|
1798
1821
|
style.remove();
|
|
1799
1822
|
}
|
|
1800
1823
|
}
|
|
1801
|
-
const cover =
|
|
1824
|
+
const cover = document2.querySelector('img[role="doc-cover"]');
|
|
1802
1825
|
if (cover && !cover.hasAttribute("src")) {
|
|
1803
1826
|
cover.setAttribute("src", encodeURI(imageSrc));
|
|
1804
1827
|
}
|
|
@@ -1813,30 +1836,30 @@ async function processManuscriptHtml(dom, {
|
|
|
1813
1836
|
contentType,
|
|
1814
1837
|
language
|
|
1815
1838
|
}) {
|
|
1816
|
-
const { document } = dom.window;
|
|
1839
|
+
const { document: document2 } = dom.window;
|
|
1817
1840
|
if (title) {
|
|
1818
|
-
if (!
|
|
1819
|
-
const t =
|
|
1820
|
-
|
|
1841
|
+
if (!document2.querySelector("title")) {
|
|
1842
|
+
const t = document2.createElement("title");
|
|
1843
|
+
document2.head.appendChild(t);
|
|
1821
1844
|
}
|
|
1822
|
-
|
|
1845
|
+
document2.title = title;
|
|
1823
1846
|
}
|
|
1824
1847
|
for (const s of style ?? []) {
|
|
1825
|
-
const l =
|
|
1848
|
+
const l = document2.createElement("link");
|
|
1826
1849
|
l.setAttribute("rel", "stylesheet");
|
|
1827
1850
|
l.setAttribute("type", "text/css");
|
|
1828
1851
|
l.setAttribute("href", encodeURI(s));
|
|
1829
|
-
|
|
1852
|
+
document2.head.appendChild(l);
|
|
1830
1853
|
}
|
|
1831
1854
|
if (language) {
|
|
1832
1855
|
if (contentType === "application/xhtml+xml") {
|
|
1833
|
-
if (!
|
|
1834
|
-
|
|
1835
|
-
|
|
1856
|
+
if (!document2.documentElement.getAttribute("xml:lang")) {
|
|
1857
|
+
document2.documentElement.setAttribute("lang", language);
|
|
1858
|
+
document2.documentElement.setAttribute("xml:lang", language);
|
|
1836
1859
|
}
|
|
1837
1860
|
} else {
|
|
1838
|
-
if (!
|
|
1839
|
-
|
|
1861
|
+
if (!document2.documentElement.getAttribute("lang")) {
|
|
1862
|
+
document2.documentElement.setAttribute("lang", language);
|
|
1840
1863
|
}
|
|
1841
1864
|
}
|
|
1842
1865
|
}
|
|
@@ -1847,8 +1870,8 @@ async function fetchLinkedPublicationManifest({
|
|
|
1847
1870
|
resourceLoader,
|
|
1848
1871
|
baseUrl
|
|
1849
1872
|
}) {
|
|
1850
|
-
const { document } = dom.window;
|
|
1851
|
-
const linkEl =
|
|
1873
|
+
const { document: document2 } = dom.window;
|
|
1874
|
+
const linkEl = document2.querySelector('link[href][rel="publication"]');
|
|
1852
1875
|
if (!linkEl) {
|
|
1853
1876
|
return null;
|
|
1854
1877
|
}
|
|
@@ -1856,7 +1879,7 @@ async function fetchLinkedPublicationManifest({
|
|
|
1856
1879
|
let manifest;
|
|
1857
1880
|
let manifestUrl = baseUrl;
|
|
1858
1881
|
if (href.startsWith("#")) {
|
|
1859
|
-
const scriptEl =
|
|
1882
|
+
const scriptEl = document2.getElementById(href.slice(1));
|
|
1860
1883
|
if (scriptEl?.getAttribute("type") !== "application/ld+json") {
|
|
1861
1884
|
return null;
|
|
1862
1885
|
}
|
|
@@ -1903,8 +1926,8 @@ ${error}`
|
|
|
1903
1926
|
};
|
|
1904
1927
|
}
|
|
1905
1928
|
function parseTocDocument(dom) {
|
|
1906
|
-
const { document } = dom.window;
|
|
1907
|
-
const docTocEl =
|
|
1929
|
+
const { document: document2 } = dom.window;
|
|
1930
|
+
const docTocEl = document2.querySelectorAll('[role="doc-toc"]');
|
|
1908
1931
|
if (docTocEl.length === 0) {
|
|
1909
1932
|
return null;
|
|
1910
1933
|
}
|
|
@@ -1954,8 +1977,8 @@ function parseTocDocument(dom) {
|
|
|
1954
1977
|
return null;
|
|
1955
1978
|
}
|
|
1956
1979
|
function parsePageListDocument(dom) {
|
|
1957
|
-
const { document } = dom.window;
|
|
1958
|
-
const docPageListEl =
|
|
1980
|
+
const { document: document2 } = dom.window;
|
|
1981
|
+
const docPageListEl = document2.querySelectorAll('[role="doc-pagelist"]');
|
|
1959
1982
|
if (docPageListEl.length === 0) {
|
|
1960
1983
|
return null;
|
|
1961
1984
|
}
|
|
@@ -1980,10 +2003,10 @@ function parsePageListDocument(dom) {
|
|
|
1980
2003
|
import archiver from "archiver";
|
|
1981
2004
|
import { lookup as lookupLanguage } from "bcp-47-match";
|
|
1982
2005
|
import { XMLBuilder } from "fast-xml-parser";
|
|
1983
|
-
import { copy
|
|
2006
|
+
import { copy } from "fs-extra/esm";
|
|
1984
2007
|
import GithubSlugger from "github-slugger";
|
|
1985
2008
|
import { lookup as mime2 } from "mime-types";
|
|
1986
|
-
import
|
|
2009
|
+
import fs5 from "node:fs";
|
|
1987
2010
|
import { pathToFileURL as pathToFileURL4 } from "node:url";
|
|
1988
2011
|
import upath5 from "upath";
|
|
1989
2012
|
import { v4 as uuid } from "uuid";
|
|
@@ -2056,8 +2079,8 @@ async function exportEpub({
|
|
|
2056
2079
|
epubVersion
|
|
2057
2080
|
});
|
|
2058
2081
|
const [tmpDir] = await useTmpDirectory();
|
|
2059
|
-
|
|
2060
|
-
await
|
|
2082
|
+
fs5.mkdirSync(upath5.join(tmpDir, "META-INF"), { recursive: true });
|
|
2083
|
+
await copy(webpubDir, upath5.join(tmpDir, "EPUB"));
|
|
2061
2084
|
const uid = `urn:uuid:${uuid()}`;
|
|
2062
2085
|
const entryHtmlRelPath = entryHtmlFile && upath5.relative(webpubDir, upath5.resolve(webpubDir, entryHtmlFile));
|
|
2063
2086
|
const findPublicationLink = (relType, list, filter) => [list].flat().find(
|
|
@@ -2096,7 +2119,7 @@ async function exportEpub({
|
|
|
2096
2119
|
return acc;
|
|
2097
2120
|
} catch (e) {
|
|
2098
2121
|
}
|
|
2099
|
-
if (!
|
|
2122
|
+
if (!fs5.existsSync(upath5.join(tmpDir, "EPUB", url))) {
|
|
2100
2123
|
return acc;
|
|
2101
2124
|
}
|
|
2102
2125
|
const mediaType = encodingFormat || mime2(url) || "text/plain";
|
|
@@ -2212,19 +2235,19 @@ async function exportEpub({
|
|
|
2212
2235
|
});
|
|
2213
2236
|
}
|
|
2214
2237
|
if (relManifestPath) {
|
|
2215
|
-
await
|
|
2238
|
+
await fs5.promises.rm(upath5.join(tmpDir, "EPUB", relManifestPath), {
|
|
2216
2239
|
force: true,
|
|
2217
2240
|
recursive: true
|
|
2218
2241
|
});
|
|
2219
2242
|
delete manifestItem[relManifestPath];
|
|
2220
2243
|
}
|
|
2221
|
-
|
|
2244
|
+
fs5.writeFileSync(
|
|
2222
2245
|
upath5.join(tmpDir, "META-INF/container.xml"),
|
|
2223
2246
|
EPUB_CONTAINER_XML,
|
|
2224
2247
|
"utf8"
|
|
2225
2248
|
);
|
|
2226
2249
|
Logger.debug(`Generating content.opf`);
|
|
2227
|
-
|
|
2250
|
+
fs5.writeFileSync(
|
|
2228
2251
|
upath5.join(tmpDir, "EPUB/content.opf"),
|
|
2229
2252
|
buildEpubPackageDocument({
|
|
2230
2253
|
epubVersion,
|
|
@@ -2242,7 +2265,7 @@ async function exportEpub({
|
|
|
2242
2265
|
async function writeAsXhtml(dom, absPath) {
|
|
2243
2266
|
const xhtml = `${XML_DECLARATION}
|
|
2244
2267
|
${serializeToXml(dom.window.document)}`;
|
|
2245
|
-
await
|
|
2268
|
+
await fs5.promises.writeFile(changeExtname(absPath, ".xhtml"), xhtml, "utf8");
|
|
2246
2269
|
}
|
|
2247
2270
|
async function transpileHtmlToXhtml({
|
|
2248
2271
|
target,
|
|
@@ -2250,24 +2273,24 @@ async function transpileHtmlToXhtml({
|
|
|
2250
2273
|
}) {
|
|
2251
2274
|
const absPath = upath5.join(contextDir, target);
|
|
2252
2275
|
const dom = await getJsdomFromUrlOrFile({ src: absPath });
|
|
2253
|
-
const { document } = dom.window;
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
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) => {
|
|
2257
2280
|
const href = decodeURI(el.getAttribute("href"));
|
|
2258
2281
|
el.setAttribute("href", getRelativeHref(href, target, target));
|
|
2259
2282
|
});
|
|
2260
2283
|
await writeAsXhtml(dom, absPath);
|
|
2261
|
-
await
|
|
2284
|
+
await fs5.promises.unlink(absPath);
|
|
2262
2285
|
return {
|
|
2263
2286
|
dom,
|
|
2264
2287
|
// FIXME: Yes, I recognize this implementation is inadequate.
|
|
2265
|
-
hasMathmlContent: !!
|
|
2266
|
-
hasRemoteResources: !!
|
|
2288
|
+
hasMathmlContent: !!document2.querySelector("math"),
|
|
2289
|
+
hasRemoteResources: !!document2.querySelector(
|
|
2267
2290
|
'[src^="http://"], [src^="https://"]'
|
|
2268
2291
|
),
|
|
2269
|
-
hasScriptedContent: !!
|
|
2270
|
-
hasSvgContent: !!
|
|
2292
|
+
hasScriptedContent: !!document2.querySelector("script, form"),
|
|
2293
|
+
hasSvgContent: !!document2.querySelector("svg")
|
|
2271
2294
|
};
|
|
2272
2295
|
}
|
|
2273
2296
|
function replaceWithNavElement(dom, el) {
|
|
@@ -2289,9 +2312,9 @@ async function processTocDocument({
|
|
|
2289
2312
|
docLanguages,
|
|
2290
2313
|
landmarks
|
|
2291
2314
|
}) {
|
|
2292
|
-
const { document } = dom.window;
|
|
2315
|
+
const { document: document2 } = dom.window;
|
|
2293
2316
|
let tocResourceTree = null;
|
|
2294
|
-
if (!
|
|
2317
|
+
if (!document2.querySelector("nav[epub:type]")) {
|
|
2295
2318
|
tocResourceTree = parseTocDocument(dom);
|
|
2296
2319
|
if (tocResourceTree) {
|
|
2297
2320
|
const nav = replaceWithNavElement(dom, tocResourceTree.element);
|
|
@@ -2299,15 +2322,15 @@ async function processTocDocument({
|
|
|
2299
2322
|
nav.setAttribute("epub:type", "toc");
|
|
2300
2323
|
} else {
|
|
2301
2324
|
Logger.debug(`Generating toc nav element: ${target}`);
|
|
2302
|
-
const nav =
|
|
2325
|
+
const nav = document2.createElement("nav");
|
|
2303
2326
|
nav.setAttribute("id", TOC_ID);
|
|
2304
2327
|
nav.setAttribute("role", "doc-toc");
|
|
2305
2328
|
nav.setAttribute("epub:type", "toc");
|
|
2306
2329
|
nav.setAttribute("hidden", "");
|
|
2307
|
-
const h2 =
|
|
2330
|
+
const h2 = document2.createElement("h2");
|
|
2308
2331
|
h2.textContent = TOC_TITLE;
|
|
2309
2332
|
nav.appendChild(h2);
|
|
2310
|
-
const ol =
|
|
2333
|
+
const ol = document2.createElement("ol");
|
|
2311
2334
|
tocResourceTree = {
|
|
2312
2335
|
element: nav,
|
|
2313
2336
|
children: []
|
|
@@ -2320,8 +2343,8 @@ async function processTocDocument({
|
|
|
2320
2343
|
});
|
|
2321
2344
|
name = dom2.window.document.title;
|
|
2322
2345
|
}
|
|
2323
|
-
const li =
|
|
2324
|
-
const a =
|
|
2346
|
+
const li = document2.createElement("li");
|
|
2347
|
+
const a = document2.createElement("a");
|
|
2325
2348
|
a.textContent = name;
|
|
2326
2349
|
a.href = getRelativeHref(content.url, "", target);
|
|
2327
2350
|
li.appendChild(a);
|
|
@@ -2329,22 +2352,22 @@ async function processTocDocument({
|
|
|
2329
2352
|
tocResourceTree.children.push({ element: li, label: a });
|
|
2330
2353
|
}
|
|
2331
2354
|
nav.appendChild(ol);
|
|
2332
|
-
|
|
2355
|
+
document2.body.appendChild(nav);
|
|
2333
2356
|
Logger.debug("Generated toc nav element", nav.outerHTML);
|
|
2334
2357
|
}
|
|
2335
2358
|
if (landmarks.length > 0) {
|
|
2336
2359
|
Logger.debug(`Generating landmark nav element: ${target}`);
|
|
2337
|
-
const nav =
|
|
2360
|
+
const nav = document2.createElement("nav");
|
|
2338
2361
|
nav.setAttribute("epub:type", "landmarks");
|
|
2339
2362
|
nav.setAttribute("id", LANDMARKS_ID);
|
|
2340
2363
|
nav.setAttribute("hidden", "");
|
|
2341
|
-
const h2 =
|
|
2364
|
+
const h2 = document2.createElement("h2");
|
|
2342
2365
|
h2.textContent = EPUB_LANDMARKS_TITLE;
|
|
2343
2366
|
nav.appendChild(h2);
|
|
2344
|
-
const ol =
|
|
2367
|
+
const ol = document2.createElement("ol");
|
|
2345
2368
|
for (const { type, href, text } of landmarks) {
|
|
2346
|
-
const li =
|
|
2347
|
-
const a =
|
|
2369
|
+
const li = document2.createElement("li");
|
|
2370
|
+
const a = document2.createElement("a");
|
|
2348
2371
|
a.setAttribute("epub:type", type);
|
|
2349
2372
|
a.setAttribute("href", getRelativeHref(href, "", target));
|
|
2350
2373
|
a.text = text;
|
|
@@ -2352,17 +2375,17 @@ async function processTocDocument({
|
|
|
2352
2375
|
ol.appendChild(li);
|
|
2353
2376
|
}
|
|
2354
2377
|
nav.appendChild(ol);
|
|
2355
|
-
|
|
2378
|
+
document2.body.appendChild(nav);
|
|
2356
2379
|
Logger.debug("Generated landmark nav element", nav.outerHTML);
|
|
2357
2380
|
}
|
|
2358
2381
|
}
|
|
2359
|
-
const publicationLinkEl =
|
|
2382
|
+
const publicationLinkEl = document2.querySelector(
|
|
2360
2383
|
'link[href][rel="publication"]'
|
|
2361
2384
|
);
|
|
2362
2385
|
if (publicationLinkEl) {
|
|
2363
2386
|
const href = publicationLinkEl.getAttribute("href").trim();
|
|
2364
2387
|
if (href.startsWith("#")) {
|
|
2365
|
-
const scriptEl =
|
|
2388
|
+
const scriptEl = document2.getElementById(href.slice(1));
|
|
2366
2389
|
if (scriptEl?.getAttribute("type") === "application/ld+json") {
|
|
2367
2390
|
scriptEl.parentNode?.removeChild(scriptEl);
|
|
2368
2391
|
}
|
|
@@ -2503,7 +2526,7 @@ async function compressEpub({
|
|
|
2503
2526
|
sourceDir
|
|
2504
2527
|
}) {
|
|
2505
2528
|
Logger.debug(`Compressing EPUB: ${target}`);
|
|
2506
|
-
const output =
|
|
2529
|
+
const output = fs5.createWriteStream(target);
|
|
2507
2530
|
const archive = archiver("zip", {
|
|
2508
2531
|
zlib: { level: 9 }
|
|
2509
2532
|
// Compression level
|
|
@@ -2541,11 +2564,11 @@ function sortManifestResources(manifest) {
|
|
|
2541
2564
|
async function prepareWebPublicationDirectory({
|
|
2542
2565
|
outputDir
|
|
2543
2566
|
}) {
|
|
2544
|
-
if (
|
|
2567
|
+
if (fs6.existsSync(outputDir)) {
|
|
2545
2568
|
Logger.debug("going to remove existing webpub", outputDir);
|
|
2546
|
-
await
|
|
2569
|
+
await fs6.promises.rm(outputDir, { force: true, recursive: true });
|
|
2547
2570
|
}
|
|
2548
|
-
|
|
2571
|
+
fs6.mkdirSync(outputDir, { recursive: true });
|
|
2549
2572
|
}
|
|
2550
2573
|
function transformPublicationManifest(entity, transformer) {
|
|
2551
2574
|
const { url: transformUrl } = transformer;
|
|
@@ -2642,8 +2665,8 @@ function writePublicationManifest(output, options) {
|
|
|
2642
2665
|
typeof thrownError === "string" ? thrownError : thrownError.stack ?? thrownError.message
|
|
2643
2666
|
);
|
|
2644
2667
|
}
|
|
2645
|
-
|
|
2646
|
-
|
|
2668
|
+
fs6.mkdirSync(upath6.dirname(output), { recursive: true });
|
|
2669
|
+
fs6.writeFileSync(output, JSON.stringify(encodedManifest, null, 2));
|
|
2647
2670
|
return publication;
|
|
2648
2671
|
}
|
|
2649
2672
|
async function retrieveWebbookEntry({
|
|
@@ -2754,12 +2777,12 @@ async function supplyWebPublicationManifestForWebbook({
|
|
|
2754
2777
|
}) {
|
|
2755
2778
|
Logger.debug(`Generating publication manifest from HTML: ${entryHtmlFile}`);
|
|
2756
2779
|
const dom = await getJsdomFromUrlOrFile({ src: entryHtmlFile });
|
|
2757
|
-
const { document } = dom.window;
|
|
2758
|
-
const language = config.language ||
|
|
2759
|
-
const title = config.title ||
|
|
2760
|
-
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") || "";
|
|
2761
2784
|
const entry = upath6.relative(outputDir, entryHtmlFile);
|
|
2762
|
-
const allFiles = await
|
|
2785
|
+
const allFiles = await glob("**", {
|
|
2763
2786
|
cwd: outputDir
|
|
2764
2787
|
});
|
|
2765
2788
|
const manifest = writePublicationManifest(
|
|
@@ -2775,7 +2798,7 @@ async function supplyWebPublicationManifestForWebbook({
|
|
|
2775
2798
|
}
|
|
2776
2799
|
);
|
|
2777
2800
|
sortManifestResources(manifest);
|
|
2778
|
-
const link =
|
|
2801
|
+
const link = document2.createElement("link");
|
|
2779
2802
|
link.setAttribute("rel", "publication");
|
|
2780
2803
|
link.setAttribute("type", "application/ld+json");
|
|
2781
2804
|
link.setAttribute(
|
|
@@ -2785,8 +2808,8 @@ async function supplyWebPublicationManifestForWebbook({
|
|
|
2785
2808
|
upath6.join(outputDir, MANIFEST_FILENAME)
|
|
2786
2809
|
)
|
|
2787
2810
|
);
|
|
2788
|
-
|
|
2789
|
-
await
|
|
2811
|
+
document2.head.appendChild(link);
|
|
2812
|
+
await fs6.promises.writeFile(entryHtmlFile, dom.serialize(), "utf8");
|
|
2790
2813
|
Logger.debug(
|
|
2791
2814
|
"Generated publication manifest from HTML",
|
|
2792
2815
|
JSON.stringify(manifest, null, 2)
|
|
@@ -2853,15 +2876,15 @@ async function copyWebPublicationAssets({
|
|
|
2853
2876
|
const relTarget = alias?.target || file;
|
|
2854
2877
|
resources.push(relTarget);
|
|
2855
2878
|
const target = upath6.join(outputDir, relTarget);
|
|
2856
|
-
|
|
2857
|
-
await
|
|
2879
|
+
fs6.mkdirSync(upath6.dirname(target), { recursive: true });
|
|
2880
|
+
await copy2(upath6.join(input, file), target);
|
|
2858
2881
|
if (alias && pathEquals(upath6.join(input, alias.source), manifestPath)) {
|
|
2859
2882
|
actualManifestPath = target;
|
|
2860
2883
|
}
|
|
2861
2884
|
}
|
|
2862
2885
|
Logger.debug("webbook publication.json", actualManifestPath);
|
|
2863
2886
|
const manifest = decodePublicationManifest(
|
|
2864
|
-
JSON.parse(
|
|
2887
|
+
JSON.parse(fs6.readFileSync(actualManifestPath, "utf8"))
|
|
2865
2888
|
);
|
|
2866
2889
|
for (const entry of relExportAliases) {
|
|
2867
2890
|
const rewriteAliasPath = (e) => {
|
|
@@ -2900,7 +2923,7 @@ async function copyWebPublicationAssets({
|
|
|
2900
2923
|
})
|
|
2901
2924
|
];
|
|
2902
2925
|
sortManifestResources(manifest);
|
|
2903
|
-
|
|
2926
|
+
fs6.writeFileSync(
|
|
2904
2927
|
actualManifestPath,
|
|
2905
2928
|
JSON.stringify(encodePublicationManifest(manifest), null, 2)
|
|
2906
2929
|
);
|
|
@@ -2967,17 +2990,18 @@ async function buildWebPublication({
|
|
|
2967
2990
|
|
|
2968
2991
|
// src/processor/theme.ts
|
|
2969
2992
|
import Arborist from "@npmcli/arborist";
|
|
2970
|
-
import
|
|
2993
|
+
import fs7 from "node:fs";
|
|
2971
2994
|
async function checkThemeInstallationNecessity({
|
|
2972
2995
|
themesDir,
|
|
2973
2996
|
themeIndexes
|
|
2974
2997
|
}) {
|
|
2975
|
-
if (!
|
|
2998
|
+
if (!fs7.existsSync(themesDir)) {
|
|
2976
2999
|
return [...themeIndexes].some((theme) => theme.type === "package");
|
|
2977
3000
|
}
|
|
2978
3001
|
const commonOpt = {
|
|
2979
3002
|
path: themesDir,
|
|
2980
|
-
lockfileVersion: 3
|
|
3003
|
+
lockfileVersion: 3,
|
|
3004
|
+
installLinks: true
|
|
2981
3005
|
};
|
|
2982
3006
|
const arb = new Arborist(commonOpt);
|
|
2983
3007
|
const tree = await arb.loadActual();
|
|
@@ -2990,11 +3014,12 @@ async function installThemeDependencies({
|
|
|
2990
3014
|
themesDir,
|
|
2991
3015
|
themeIndexes
|
|
2992
3016
|
}) {
|
|
2993
|
-
|
|
3017
|
+
fs7.mkdirSync(themesDir, { recursive: true });
|
|
2994
3018
|
try {
|
|
2995
3019
|
const commonOpt = {
|
|
2996
3020
|
path: themesDir,
|
|
2997
|
-
lockfileVersion: 3
|
|
3021
|
+
lockfileVersion: 3,
|
|
3022
|
+
installLinks: true
|
|
2998
3023
|
};
|
|
2999
3024
|
const tree = await new Arborist(commonOpt).buildIdealTree();
|
|
3000
3025
|
const existing = Array.from(tree.children.keys());
|
|
@@ -3030,7 +3055,7 @@ function locateThemePath(theme, from) {
|
|
|
3030
3055
|
if (theme.importPath) {
|
|
3031
3056
|
return [theme.importPath].flat().map((locator) => {
|
|
3032
3057
|
const resolvedPath = upath7.resolve(theme.location, locator);
|
|
3033
|
-
if (!pathContains(theme.location, resolvedPath) || !
|
|
3058
|
+
if (!pathContains(theme.location, resolvedPath) || !fs8.existsSync(resolvedPath)) {
|
|
3034
3059
|
throw new Error(
|
|
3035
3060
|
`Could not find a style path ${theme.importPath} for the theme: ${theme.name}.`
|
|
3036
3061
|
);
|
|
@@ -3039,7 +3064,7 @@ function locateThemePath(theme, from) {
|
|
|
3039
3064
|
});
|
|
3040
3065
|
} else {
|
|
3041
3066
|
const pkgJsonPath = upath7.join(theme.location, "package.json");
|
|
3042
|
-
const packageJson = JSON.parse(
|
|
3067
|
+
const packageJson = JSON.parse(fs8.readFileSync(pkgJsonPath, "utf8"));
|
|
3043
3068
|
const maybeStyle = packageJson?.vivliostyle?.theme?.style ?? packageJson.style ?? packageJson.main;
|
|
3044
3069
|
if (!maybeStyle) {
|
|
3045
3070
|
throw new DetailError(
|
|
@@ -3063,7 +3088,7 @@ async function cleanupWorkspace({
|
|
|
3063
3088
|
}
|
|
3064
3089
|
Logger.debug("cleanup workspace files", workspaceDir);
|
|
3065
3090
|
let movedWorkspacePath;
|
|
3066
|
-
if (pathContains(workspaceDir, themesDir) &&
|
|
3091
|
+
if (pathContains(workspaceDir, themesDir) && fs8.existsSync(themesDir)) {
|
|
3067
3092
|
movedWorkspacePath = upath7.join(
|
|
3068
3093
|
upath7.dirname(workspaceDir),
|
|
3069
3094
|
`.vs-${Date.now()}`
|
|
@@ -3072,18 +3097,18 @@ async function cleanupWorkspace({
|
|
|
3072
3097
|
movedWorkspacePath,
|
|
3073
3098
|
upath7.relative(workspaceDir, themesDir)
|
|
3074
3099
|
);
|
|
3075
|
-
|
|
3100
|
+
fs8.mkdirSync(upath7.dirname(movedThemePath), { recursive: true });
|
|
3076
3101
|
registerExitHandler(
|
|
3077
3102
|
`Removing the moved workspace directory: ${movedWorkspacePath}`,
|
|
3078
3103
|
() => {
|
|
3079
|
-
if (movedWorkspacePath &&
|
|
3080
|
-
|
|
3104
|
+
if (movedWorkspacePath && fs8.existsSync(movedWorkspacePath)) {
|
|
3105
|
+
fs8.rmSync(movedWorkspacePath, { recursive: true, force: true });
|
|
3081
3106
|
}
|
|
3082
3107
|
}
|
|
3083
3108
|
);
|
|
3084
3109
|
await move(themesDir, movedThemePath);
|
|
3085
3110
|
}
|
|
3086
|
-
await
|
|
3111
|
+
await fs8.promises.rm(workspaceDir, { recursive: true, force: true });
|
|
3087
3112
|
if (movedWorkspacePath) {
|
|
3088
3113
|
await move(movedWorkspacePath, workspaceDir);
|
|
3089
3114
|
}
|
|
@@ -3092,8 +3117,8 @@ async function prepareThemeDirectory({
|
|
|
3092
3117
|
themesDir,
|
|
3093
3118
|
themeIndexes
|
|
3094
3119
|
}) {
|
|
3095
|
-
if (
|
|
3096
|
-
|
|
3120
|
+
if (fs8.existsSync(upath7.join(themesDir, "packages")) && !fs8.existsSync(upath7.join(themesDir, "node_modules"))) {
|
|
3121
|
+
fs8.renameSync(
|
|
3097
3122
|
upath7.join(themesDir, "packages"),
|
|
3098
3123
|
upath7.join(themesDir, "node_modules")
|
|
3099
3124
|
);
|
|
@@ -3104,8 +3129,8 @@ async function prepareThemeDirectory({
|
|
|
3104
3129
|
}
|
|
3105
3130
|
for (const theme of themeIndexes) {
|
|
3106
3131
|
if (theme.type === "file" && !pathEquals(theme.source, theme.location)) {
|
|
3107
|
-
|
|
3108
|
-
await
|
|
3132
|
+
fs8.mkdirSync(upath7.dirname(theme.location), { recursive: true });
|
|
3133
|
+
await copy3(theme.source, theme.location);
|
|
3109
3134
|
}
|
|
3110
3135
|
}
|
|
3111
3136
|
}
|
|
@@ -3127,11 +3152,10 @@ async function transformManuscript(entry, {
|
|
|
3127
3152
|
(theme) => locateThemePath(theme, upath7.dirname(entry.target))
|
|
3128
3153
|
);
|
|
3129
3154
|
if (source?.type === "file") {
|
|
3130
|
-
if (source.
|
|
3131
|
-
const manuscriptEntry = entry;
|
|
3155
|
+
if (source.documentProcessor) {
|
|
3132
3156
|
const vfile2 = await processMarkdown(
|
|
3133
|
-
|
|
3134
|
-
|
|
3157
|
+
source.documentProcessor.processorFactory,
|
|
3158
|
+
source.documentProcessor.metadataReader,
|
|
3135
3159
|
source.pathname,
|
|
3136
3160
|
{
|
|
3137
3161
|
...vfmOptions,
|
|
@@ -3151,7 +3175,7 @@ async function transformManuscript(entry, {
|
|
|
3151
3175
|
});
|
|
3152
3176
|
} else {
|
|
3153
3177
|
if (!pathEquals(source.pathname, entry.target)) {
|
|
3154
|
-
await
|
|
3178
|
+
await copy3(source.pathname, entry.target);
|
|
3155
3179
|
}
|
|
3156
3180
|
}
|
|
3157
3181
|
} else if (source?.type === "uri") {
|
|
@@ -3285,7 +3309,7 @@ async function generateManifest({
|
|
|
3285
3309
|
const manifestEntries = entries.map((entry) => ({
|
|
3286
3310
|
title: entry.rel === "contents" && entry.tocTitle || entry.title,
|
|
3287
3311
|
path: upath7.relative(workspaceDir, entry.target),
|
|
3288
|
-
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,
|
|
3289
3313
|
rel: entry.rel
|
|
3290
3314
|
}));
|
|
3291
3315
|
writePublicationManifest(manifestPath, {
|
|
@@ -3690,6 +3714,7 @@ function vsDevServerPlugin({
|
|
|
3690
3714
|
// src/vite/vite-plugin-static-serve.ts
|
|
3691
3715
|
import sirv2 from "sirv";
|
|
3692
3716
|
import upath9 from "upath";
|
|
3717
|
+
import "vite";
|
|
3693
3718
|
function vsStaticServePlugin({
|
|
3694
3719
|
config: _config,
|
|
3695
3720
|
inlineConfig
|
|
@@ -3732,9 +3757,10 @@ function vsStaticServePlugin({
|
|
|
3732
3757
|
}
|
|
3733
3758
|
|
|
3734
3759
|
// src/vite/vite-plugin-viewer.ts
|
|
3735
|
-
import
|
|
3760
|
+
import fs9 from "node:fs";
|
|
3736
3761
|
import sirv3 from "sirv";
|
|
3737
3762
|
import upath10 from "upath";
|
|
3763
|
+
import "vite";
|
|
3738
3764
|
var viewerClientId = "@vivliostyle:viewer:client";
|
|
3739
3765
|
var viewerClientRequestPath = `/${viewerClientId}`;
|
|
3740
3766
|
var viewerClientContent = (
|
|
@@ -3753,7 +3779,7 @@ function vsViewerPlugin(_) {
|
|
|
3753
3779
|
const middleware = async function vivliostyleViewerMiddleware(req, res, next) {
|
|
3754
3780
|
if (req.url === "/" || req.url === "/index.html") {
|
|
3755
3781
|
cachedIndexHtml ??= prependToHead(
|
|
3756
|
-
|
|
3782
|
+
fs9.readFileSync(upath10.join(serveRootDir, "index.html"), "utf-8"),
|
|
3757
3783
|
`<script type="module" src="${viewerClientRequestPath}"></script>`
|
|
3758
3784
|
);
|
|
3759
3785
|
res.statusCode = 200;
|
|
@@ -3857,7 +3883,7 @@ async function getSourceUrl({
|
|
|
3857
3883
|
input = viewerInput.epubOpfPath;
|
|
3858
3884
|
break;
|
|
3859
3885
|
case "epub": {
|
|
3860
|
-
if (!
|
|
3886
|
+
if (!fs10.existsSync(viewerInput.epubTmpOutputDir)) {
|
|
3861
3887
|
await openEpub(viewerInput.epubPath, viewerInput.epubTmpOutputDir);
|
|
3862
3888
|
}
|
|
3863
3889
|
input = getDefaultEpubOpfPath(viewerInput.epubTmpOutputDir);
|
|
@@ -3919,8 +3945,8 @@ async function createViteServer({
|
|
|
3919
3945
|
if (config.serverRootDir === config.workspaceDir) {
|
|
3920
3946
|
const { cacheDir } = viteInlineConfig;
|
|
3921
3947
|
registerExitHandler("Removing the Vite cacheDir", () => {
|
|
3922
|
-
if (
|
|
3923
|
-
|
|
3948
|
+
if (fs10.existsSync(cacheDir)) {
|
|
3949
|
+
fs10.rmSync(cacheDir, { recursive: true });
|
|
3924
3950
|
}
|
|
3925
3951
|
});
|
|
3926
3952
|
}
|
|
@@ -3944,21 +3970,28 @@ function vsBrowserPlugin({
|
|
|
3944
3970
|
runExitHandlers();
|
|
3945
3971
|
}
|
|
3946
3972
|
async function openPreviewPage() {
|
|
3973
|
+
const locale = await getOsLocale();
|
|
3947
3974
|
const url = await getViewerFullUrl(config);
|
|
3948
3975
|
const { page, browser } = await launchPreview({
|
|
3949
3976
|
mode: "preview",
|
|
3950
3977
|
url,
|
|
3951
3978
|
config,
|
|
3979
|
+
/* v8 ignore next 4 */
|
|
3952
3980
|
onPageOpen: async (page2) => {
|
|
3953
3981
|
page2.on("close", handlePageClose);
|
|
3954
|
-
const locale = Intl.DateTimeFormat().resolvedOptions().locale;
|
|
3955
|
-
await page2.addInitScript(
|
|
3956
|
-
`window.localStorage.setItem('i18nextLng', '${locale}');`
|
|
3957
|
-
);
|
|
3958
3982
|
}
|
|
3959
3983
|
});
|
|
3984
|
+
if (!import.meta.env?.VITEST) {
|
|
3985
|
+
await page.evaluate((locale2) => {
|
|
3986
|
+
window.localStorage.setItem("i18nextLng", locale2);
|
|
3987
|
+
}, locale);
|
|
3988
|
+
}
|
|
3960
3989
|
await page.bringToFront();
|
|
3961
|
-
|
|
3990
|
+
if (!import.meta.env?.VITEST) {
|
|
3991
|
+
await page.evaluate(() => {
|
|
3992
|
+
document.querySelector("#vivliostyle-input-url")?.focus();
|
|
3993
|
+
});
|
|
3994
|
+
}
|
|
3962
3995
|
closeBrowser = () => {
|
|
3963
3996
|
page.off("close", handlePageClose);
|
|
3964
3997
|
browser.close();
|
|
@@ -3990,10 +4023,8 @@ export {
|
|
|
3990
4023
|
mergeInlineConfig,
|
|
3991
4024
|
isWebPubConfig,
|
|
3992
4025
|
resolveTaskConfig,
|
|
3993
|
-
getFullBrowserName,
|
|
3994
4026
|
launchPreview,
|
|
3995
4027
|
vsBrowserPlugin,
|
|
3996
|
-
copyAssets,
|
|
3997
4028
|
buildWebPublication,
|
|
3998
4029
|
cleanupWorkspace,
|
|
3999
4030
|
prepareThemeDirectory,
|
|
@@ -4005,4 +4036,4 @@ export {
|
|
|
4005
4036
|
getViewerFullUrl,
|
|
4006
4037
|
createViteServer
|
|
4007
4038
|
};
|
|
4008
|
-
//# sourceMappingURL=chunk-
|
|
4039
|
+
//# sourceMappingURL=chunk-CKAJY2BE.js.map
|