@vivliostyle/cli 9.9.0 → 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.
Files changed (55) hide show
  1. package/README.md +74 -30
  2. package/dist/{chunk-QWX5MAON.js → chunk-2M2KXPDN.js} +16 -17
  3. package/dist/chunk-2M2KXPDN.js.map +1 -0
  4. package/dist/{chunk-OZ4XTSAH.js → chunk-5DB6XVJN.js} +2 -2
  5. package/dist/chunk-5DB6XVJN.js.map +1 -0
  6. package/dist/{chunk-3O3N2V7D.js → chunk-5K3NGLBV.js} +6 -7
  7. package/dist/chunk-5K3NGLBV.js.map +1 -0
  8. package/dist/{chunk-UYKCTF6F.js → chunk-IIKRNYAM.js} +445 -228
  9. package/dist/chunk-IIKRNYAM.js.map +1 -0
  10. package/dist/{chunk-G3GROLBN.js → chunk-MQYXBSRJ.js} +397 -88
  11. package/dist/chunk-MQYXBSRJ.js.map +1 -0
  12. package/dist/chunk-RPMMYPTR.js +1076 -0
  13. package/dist/chunk-RPMMYPTR.js.map +1 -0
  14. package/dist/{chunk-WELNNHOB.js → chunk-YN3JNBNT.js} +415 -384
  15. package/dist/chunk-YN3JNBNT.js.map +1 -0
  16. package/dist/{chunk-6UU7DEUR.js → chunk-YVNDJXMI.js} +32 -33
  17. package/dist/chunk-YVNDJXMI.js.map +1 -0
  18. package/dist/{chunk-FXUEYQRY.js → chunk-ZIK6DINS.js} +3 -3
  19. package/dist/chunk-ZIK6DINS.js.map +1 -0
  20. package/dist/chunk-ZKEIYNLT.js +331 -0
  21. package/dist/chunk-ZKEIYNLT.js.map +1 -0
  22. package/dist/cli.js +7 -8
  23. package/dist/cli.js.map +1 -1
  24. package/dist/commands/build.js +29 -17
  25. package/dist/commands/build.js.map +1 -1
  26. package/dist/commands/create.d.ts +2 -0
  27. package/dist/commands/create.js +64 -0
  28. package/dist/commands/create.js.map +1 -0
  29. package/dist/commands/init.js +23 -14
  30. package/dist/commands/init.js.map +1 -1
  31. package/dist/commands/preview.js +26 -20
  32. package/dist/commands/preview.js.map +1 -1
  33. package/dist/config/schema.d.ts +7815 -4012
  34. package/dist/config/schema.js +16 -4
  35. package/dist/index.d.ts +46 -7
  36. package/dist/index.js +24 -16
  37. package/dist/index.js.map +1 -1
  38. package/dist/node-modules.d.ts +5 -5
  39. package/dist/node-modules.js +1 -1
  40. package/dist/vite-adapter.d.ts +1 -0
  41. package/dist/vite-adapter.js +6 -6
  42. package/package.json +37 -26
  43. package/dist/chunk-3O3N2V7D.js.map +0 -1
  44. package/dist/chunk-4IIM6RSG.js +0 -71
  45. package/dist/chunk-4IIM6RSG.js.map +0 -1
  46. package/dist/chunk-6KEOMYDZ.js +0 -89
  47. package/dist/chunk-6KEOMYDZ.js.map +0 -1
  48. package/dist/chunk-6UU7DEUR.js.map +0 -1
  49. package/dist/chunk-FXUEYQRY.js.map +0 -1
  50. package/dist/chunk-G3GROLBN.js.map +0 -1
  51. package/dist/chunk-OZ4XTSAH.js.map +0 -1
  52. package/dist/chunk-QWX5MAON.js.map +0 -1
  53. package/dist/chunk-UYKCTF6F.js.map +0 -1
  54. package/dist/chunk-WELNNHOB.js.map +0 -1
  55. 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-G3GROLBN.js";
33
+ } from "./chunk-MQYXBSRJ.js";
30
34
  import {
31
35
  VivliostyleConfigSchema
32
- } from "./chunk-UYKCTF6F.js";
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-4IIM6RSG.js";
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) => ({
@@ -265,7 +273,10 @@ function readMarkdownMetadata(filepath, documentMetadataReader) {
265
273
  var manuscriptMediaTypes = [
266
274
  "text/markdown",
267
275
  "text/html",
268
- "application/xhtml+xml"
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 (contentType === "text/markdown") {
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: config.browser ?? "chromium",
450
- executablePath: options.executableBrowser
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 = upath2.resolve(
708
- workspaceDir,
709
- `${temporaryFilePrefix}${upath2.basename(sourcePath)}`
710
- ).replace(/\.md$/, ".html");
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).replace(/\.md$/, ".html")
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, options) => {
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 contentType = mime(pathname);
885
- if (!isManuscriptMediaType(contentType)) {
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 ${contentType} detected: ${entry}`
917
+ `Invalid manuscript type ${rawContentType} detected: ${entry}`
888
918
  );
889
919
  }
890
- const effectiveMetadataReader = options?.entryDocumentMetadataReader ?? documentMetadataReader;
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: effectiveMetadataReader
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).replace(/\.md$/, ".html")
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 playwright = await importNodeModule("playwright-core");
1098
- playwright.firefox.executablePath;
1099
- const options = browserType === "chromium" ? {
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
- chromiumSandbox: !noSandbox,
1196
+ args,
1197
+ browser: browserType === "chromium" ? "chrome" : browserType,
1102
1198
  headless,
1103
- args: [
1104
- // #579: disable web security to allow cross-origin requests
1105
- "--disable-web-security",
1106
- ...disableDevShmUsage ? ["--disable-dev-shm-usage"] : [],
1107
- // #357: Set devicePixelRatio=1 otherwise it causes layout issues in HiDPI displays
1108
- ...headless ? ["--force-device-scale-factor=1"] : [],
1109
- // #565: Add --disable-gpu option when running on WSL
1110
- ...isRunningOnWSL() ? ["--disable-gpu"] : [],
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
- return browser;
1210
+ const [browserContext] = browser.browserContexts();
1211
+ return { browser, browserContext };
1126
1212
  }
1127
- async function getExecutableBrowserPath(browserType) {
1128
- const playwright = await importNodeModule("playwright-core");
1129
- return playwright[browserType].executablePath();
1213
+ function getPuppeteerCacheDir() {
1214
+ if (isInContainer()) {
1215
+ return "/opt/puppeteer";
1216
+ }
1217
+ return upath3.join(getCacheDir(), "browsers");
1130
1218
  }
1131
- function getFullBrowserName(browserType) {
1132
- return {
1133
- chromium: "Chromium",
1134
- firefox: "Firefox",
1135
- webkit: "Webkit"
1136
- }[browserType];
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(browserType) {
1142
- const { registry } = await importNodeModule("playwright-core/lib/server");
1143
- const executable = registry.findExecutable(browserType);
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 registry.install([executable], false);
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 executable.executablePath();
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.type);
1340
+ executableBrowser = await getExecutableBrowserPath(browserConfig);
1341
+ Logger.debug(`Using default browser: ${executableBrowser}`);
1175
1342
  if (!checkBrowserAvailability(executableBrowser)) {
1176
- await downloadBrowser(browserConfig.type);
1343
+ await cleanupOutdatedBrowsers();
1344
+ await downloadBrowser(browserConfig);
1177
1345
  }
1178
1346
  }
1179
- Logger.debug(`Executing browser path: ${executableBrowser}`);
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 browser.newPage({
1190
- viewport: mode === "build" ? (
1191
- // This viewport size important to detect headless environment in Vivliostyle viewer
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
- width: 800,
1195
- height: 600
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 fs11 from "node:fs";
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 { copy as copy4, move } from "fs-extra/esm";
1374
- import fs9 from "node:fs";
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 copy3 } from "fs-extra/esm";
1403
+ import { copy as copy2 } from "fs-extra/esm";
1381
1404
  import { lookup as mime3 } from "mime-types";
1382
- import fs7 from "node:fs";
1405
+ import fs6 from "node:fs";
1383
1406
  import { pathToFileURL as pathToFileURL5 } from "node:url";
1384
- import { glob as glob2 } from "tinyglobby";
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 = [...document.querySelectorAll("h1, h2, h3, h4, h5, h6")].filter((el) => {
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 (!document.querySelector(
1740
+ const { document: document2 } = dom.window;
1741
+ if (!document2.querySelector(
1719
1742
  'link[rel="publication"][type="application/ld+json"]'
1720
1743
  )) {
1721
- const l = document.createElement("link");
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
- document.head.appendChild(l);
1748
+ document2.head.appendChild(l);
1726
1749
  }
1727
- const style = document.querySelector("style[data-vv-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 = document.querySelector('nav, [role="doc-toc"]');
1759
+ const nav = document2.querySelector('nav, [role="doc-toc"]');
1737
1760
  if (nav && !nav.hasChildNodes()) {
1738
- const h2 = document.createElement("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 = document.querySelector("style[data-vv-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 = document.querySelector('img[role="doc-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 (!document.querySelector("title")) {
1819
- const t = document.createElement("title");
1820
- document.head.appendChild(t);
1841
+ if (!document2.querySelector("title")) {
1842
+ const t = document2.createElement("title");
1843
+ document2.head.appendChild(t);
1821
1844
  }
1822
- document.title = title;
1845
+ document2.title = title;
1823
1846
  }
1824
1847
  for (const s of style ?? []) {
1825
- const l = document.createElement("link");
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
- document.head.appendChild(l);
1852
+ document2.head.appendChild(l);
1830
1853
  }
1831
1854
  if (language) {
1832
1855
  if (contentType === "application/xhtml+xml") {
1833
- if (!document.documentElement.getAttribute("xml:lang")) {
1834
- document.documentElement.setAttribute("lang", language);
1835
- document.documentElement.setAttribute("xml:lang", language);
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 (!document.documentElement.getAttribute("lang")) {
1839
- document.documentElement.setAttribute("lang", language);
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 = document.querySelector('link[href][rel="publication"]');
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 = document.getElementById(href.slice(1));
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 = document.querySelectorAll('[role="doc-toc"]');
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 = document.querySelectorAll('[role="doc-pagelist"]');
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 as copy2 } from "fs-extra/esm";
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 fs6 from "node:fs";
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
- fs6.mkdirSync(upath5.join(tmpDir, "META-INF"), { recursive: true });
2060
- await copy2(webpubDir, upath5.join(tmpDir, "EPUB"));
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 (!fs6.existsSync(upath5.join(tmpDir, "EPUB", url))) {
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 fs6.promises.rm(upath5.join(tmpDir, "EPUB", relManifestPath), {
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
- fs6.writeFileSync(
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
- fs6.writeFileSync(
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 fs6.promises.writeFile(changeExtname(absPath, ".xhtml"), xhtml, "utf8");
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
- document.documentElement.removeAttribute("xmlns");
2255
- document.documentElement.setAttribute("xmlns:epub", EPUB_NS);
2256
- document.querySelectorAll("a[href]").forEach((el) => {
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 fs6.promises.unlink(absPath);
2284
+ await fs5.promises.unlink(absPath);
2262
2285
  return {
2263
2286
  dom,
2264
2287
  // FIXME: Yes, I recognize this implementation is inadequate.
2265
- hasMathmlContent: !!document.querySelector("math"),
2266
- hasRemoteResources: !!document.querySelector(
2288
+ hasMathmlContent: !!document2.querySelector("math"),
2289
+ hasRemoteResources: !!document2.querySelector(
2267
2290
  '[src^="http://"], [src^="https://"]'
2268
2291
  ),
2269
- hasScriptedContent: !!document.querySelector("script, form"),
2270
- hasSvgContent: !!document.querySelector("svg")
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 (!document.querySelector("nav[epub:type]")) {
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 = document.createElement("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 = document.createElement("h2");
2330
+ const h2 = document2.createElement("h2");
2308
2331
  h2.textContent = TOC_TITLE;
2309
2332
  nav.appendChild(h2);
2310
- const ol = document.createElement("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 = document.createElement("li");
2324
- const a = document.createElement("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
- document.body.appendChild(nav);
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 = document.createElement("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 = document.createElement("h2");
2364
+ const h2 = document2.createElement("h2");
2342
2365
  h2.textContent = EPUB_LANDMARKS_TITLE;
2343
2366
  nav.appendChild(h2);
2344
- const ol = document.createElement("ol");
2367
+ const ol = document2.createElement("ol");
2345
2368
  for (const { type, href, text } of landmarks) {
2346
- const li = document.createElement("li");
2347
- const a = document.createElement("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
- document.body.appendChild(nav);
2378
+ document2.body.appendChild(nav);
2356
2379
  Logger.debug("Generated landmark nav element", nav.outerHTML);
2357
2380
  }
2358
2381
  }
2359
- const publicationLinkEl = document.querySelector(
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 = document.getElementById(href.slice(1));
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 = fs6.createWriteStream(target);
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 (fs7.existsSync(outputDir)) {
2567
+ if (fs6.existsSync(outputDir)) {
2545
2568
  Logger.debug("going to remove existing webpub", outputDir);
2546
- await fs7.promises.rm(outputDir, { force: true, recursive: true });
2569
+ await fs6.promises.rm(outputDir, { force: true, recursive: true });
2547
2570
  }
2548
- fs7.mkdirSync(outputDir, { recursive: true });
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
- fs7.mkdirSync(upath6.dirname(output), { recursive: true });
2646
- fs7.writeFileSync(output, JSON.stringify(encodedManifest, null, 2));
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 || document.documentElement.lang || void 0;
2759
- const title = config.title || document.title || "";
2760
- const author = config.author || document.querySelector('meta[name="author"]')?.getAttribute("content") || "";
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 glob2("**", {
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 = document.createElement("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
- document.head.appendChild(link);
2789
- await fs7.promises.writeFile(entryHtmlFile, dom.serialize(), "utf8");
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
- fs7.mkdirSync(upath6.dirname(target), { recursive: true });
2857
- await copy3(upath6.join(input, file), target);
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(fs7.readFileSync(actualManifestPath, "utf8"))
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
- fs7.writeFileSync(
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 fs8 from "node:fs";
2993
+ import fs7 from "node:fs";
2971
2994
  async function checkThemeInstallationNecessity({
2972
2995
  themesDir,
2973
2996
  themeIndexes
2974
2997
  }) {
2975
- if (!fs8.existsSync(themesDir)) {
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
- fs8.mkdirSync(themesDir, { recursive: true });
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) || !fs9.existsSync(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(fs9.readFileSync(pkgJsonPath, "utf8"));
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) && fs9.existsSync(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
- fs9.mkdirSync(upath7.dirname(movedThemePath), { recursive: true });
3100
+ fs8.mkdirSync(upath7.dirname(movedThemePath), { recursive: true });
3076
3101
  registerExitHandler(
3077
3102
  `Removing the moved workspace directory: ${movedWorkspacePath}`,
3078
3103
  () => {
3079
- if (movedWorkspacePath && fs9.existsSync(movedWorkspacePath)) {
3080
- fs9.rmSync(movedWorkspacePath, { recursive: true, force: true });
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 fs9.promises.rm(workspaceDir, { recursive: true, force: true });
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 (fs9.existsSync(upath7.join(themesDir, "packages")) && !fs9.existsSync(upath7.join(themesDir, "node_modules"))) {
3096
- fs9.renameSync(
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
- fs9.mkdirSync(upath7.dirname(theme.location), { recursive: true });
3108
- await copy4(theme.source, theme.location);
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.contentType === "text/markdown") {
3131
- const manuscriptEntry = entry;
3155
+ if (source.documentProcessor) {
3132
3156
  const vfile2 = await processMarkdown(
3133
- manuscriptEntry.documentProcessorFactory,
3134
- manuscriptEntry.documentMetadataReader,
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 copy4(source.pathname, entry.target);
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 fs10 from "node:fs";
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
- fs10.readFileSync(upath10.join(serveRootDir, "index.html"), "utf-8"),
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 (!fs11.existsSync(viewerInput.epubTmpOutputDir)) {
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 (fs11.existsSync(cacheDir)) {
3923
- fs11.rmSync(cacheDir, { recursive: true });
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
- await page.locator("#vivliostyle-input-url").focus({ timeout: 0 });
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-WELNNHOB.js.map
4039
+ //# sourceMappingURL=chunk-YN3JNBNT.js.map