hyperbook 0.99.0 → 0.100.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -55361,6 +55361,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
55361
55361
  };
55362
55362
  Object.defineProperty(exports, "__esModule", ({ value: true }));
55363
55363
  exports.ASSETS_FOLDER = void 0;
55364
+ exports.writeSearchIndex = writeSearchIndex;
55364
55365
  exports.buildSingleBookPage = buildSingleBookPage;
55365
55366
  exports.buildSingleGlossaryPage = buildSingleGlossaryPage;
55366
55367
  exports.runBuildProject = runBuildProject;
@@ -55378,15 +55379,72 @@ const lunr_1 = __importDefault(__nccwpck_require__(12203));
55378
55379
  const markdown_1 = __nccwpck_require__(61549);
55379
55380
  const package_json_1 = __importDefault(__nccwpck_require__(8330));
55380
55381
  exports.ASSETS_FOLDER = "__hyperbook_assets";
55382
+ /**
55383
+ * Builds the lunr index and writes search.js. Extracted so the dev server can
55384
+ * regenerate it after an incremental rebuild instead of leaving it stale.
55385
+ */
55386
+ async function writeSearchIndex(hyperbookJson, baseCtx, searchDocuments, rootOut, prefix = "Hyperbook") {
55387
+ if (!hyperbookJson.search)
55388
+ return;
55389
+ const documents = {};
55390
+ console.log(`${chalk_1.default.blue(`[${prefix}]`)} Building search index`);
55391
+ let foundLanguage = false;
55392
+ if (hyperbookJson.language && hyperbookJson.language !== "en") {
55393
+ try {
55394
+ // Only register lunr language plugins once to avoid "Overwriting" warnings
55395
+ if (!lunr_1.default["_hyperbook_lang_loaded_" + hyperbookJson.language]) {
55396
+ __nccwpck_require__(30089)(lunr_1.default);
55397
+ require(`./lunr-languages/lunr.${hyperbookJson.language}.min.js`)(lunr_1.default);
55398
+ lunr_1.default["_hyperbook_lang_loaded_" + hyperbookJson.language] =
55399
+ true;
55400
+ }
55401
+ foundLanguage = true;
55402
+ }
55403
+ catch (e) {
55404
+ console.log(e);
55405
+ console.log(`${chalk_1.default.yellow(`[${prefix}]`)} ${hyperbookJson.language} is not a valid value for the language key. See https://github.com/MihaiValentin/lunr-languages for possible values. Falling back to English.`);
55406
+ }
55407
+ }
55408
+ const idx = (0, lunr_1.default)(function () {
55409
+ if (foundLanguage) {
55410
+ // @ts-ignore
55411
+ this.use(lunr_1.default[hyperbookJson.language]);
55412
+ }
55413
+ this.ref("href");
55414
+ this.field("description");
55415
+ this.field("keywords");
55416
+ this.field("heading");
55417
+ this.field("content");
55418
+ this.metadataWhitelist = ["position"];
55419
+ searchDocuments.forEach((doc) => {
55420
+ const href = baseCtx.makeUrl(doc.href, "book");
55421
+ const docWithBase = {
55422
+ ...doc,
55423
+ href,
55424
+ };
55425
+ this.add(docWithBase);
55426
+ documents[href] = docWithBase;
55427
+ });
55428
+ });
55429
+ const js = `
55430
+ const LUNR_INDEX = ${JSON.stringify(idx)};
55431
+ const SEARCH_DOCUMENTS = ${JSON.stringify(documents)};
55432
+ `;
55433
+ await promises_1.default.writeFile(path_1.default.join(rootOut, exports.ASSETS_FOLDER, "search.js"), js);
55434
+ }
55381
55435
  async function buildSingleBookPage(file, baseCtx, pageList, pagesAndSections, rootOut, assetsOut, hyperbookJson) {
55382
55436
  const n1 = await fs_1.hyperbook.getNavigationForFile(pageList, file);
55383
55437
  const navigation = {
55384
55438
  ...n1,
55385
55439
  ...pagesAndSections,
55386
55440
  };
55441
+ // Templates and snippets were inlined while the vfile was read; directive
55442
+ // `src=` files are collected as the markdown is processed.
55443
+ const dependencies = new Set((file.markdown.dependencies || []).map((d) => path_1.default.resolve(file.root, d)));
55387
55444
  const ctx = {
55388
55445
  ...baseCtx,
55389
55446
  navigation,
55447
+ dependencies,
55390
55448
  };
55391
55449
  const result = await (0, markdown_1.process)(file.markdown.content, ctx);
55392
55450
  const searchDocuments = [...(result.data.searchDocuments || [])];
@@ -55429,7 +55487,7 @@ async function buildSingleBookPage(file, baseCtx, pageList, pagesAndSections, ro
55429
55487
  await promises_1.default.writeFile(permaFileOut, redirectHtml);
55430
55488
  }
55431
55489
  await promises_1.default.writeFile(fileOut, result.value);
55432
- return { searchDocuments, directives };
55490
+ return { searchDocuments, directives, dependencies: [...dependencies] };
55433
55491
  }
55434
55492
  async function buildSingleGlossaryPage(file, baseCtx, pageList, pagesAndSections, rootOut, assetsOut, hyperbookJson) {
55435
55493
  const n1 = await fs_1.hyperbook.getNavigationForFile(pageList, file);
@@ -55452,9 +55510,13 @@ async function buildSingleGlossaryPage(file, baseCtx, pageList, pagesAndSections
55452
55510
  layout: file.markdown.data.layout,
55453
55511
  };
55454
55512
  }
55513
+ // Templates and snippets were inlined while the vfile was read; directive
55514
+ // `src=` files are collected as the markdown is processed.
55515
+ const dependencies = new Set((file.markdown.dependencies || []).map((d) => path_1.default.resolve(file.root, d)));
55455
55516
  const ctx = {
55456
55517
  ...baseCtx,
55457
55518
  navigation,
55519
+ dependencies,
55458
55520
  };
55459
55521
  const result = await (0, markdown_1.process)(file.markdown.content, ctx);
55460
55522
  const searchDocuments = [...(result.data.searchDocuments || [])];
@@ -55484,7 +55546,7 @@ async function buildSingleGlossaryPage(file, baseCtx, pageList, pagesAndSections
55484
55546
  await (0, make_dir_1.makeDir)(glossaryOut, { recursive: true });
55485
55547
  }
55486
55548
  await promises_1.default.writeFile(fileOut, result.value);
55487
- return { searchDocuments, directives };
55549
+ return { searchDocuments, directives, dependencies: [...dependencies] };
55488
55550
  }
55489
55551
  /**
55490
55552
  * Generates an llms.txt file by combining all markdown files in order
@@ -55596,11 +55658,11 @@ Also you need to use unique ids when the element supports it.
55596
55658
  const llmsTxtContent = lines.join("\n");
55597
55659
  await promises_1.default.writeFile(path_1.default.join(rootOut, "llms.txt"), llmsTxtContent);
55598
55660
  }
55599
- async function runBuildProject(project, rootProject, out, filter) {
55661
+ async function runBuildProject(project, rootProject, out, filter, onPage) {
55600
55662
  const name = fs_1.hyperproject.getName(project);
55601
55663
  if (project.type === "book") {
55602
55664
  console.log(`${chalk_1.default.cyan(`[${name}]`)} Building Book.`);
55603
- await runBuild(project.src, rootProject, project.basePath, name, out, filter);
55665
+ await runBuild(project.src, rootProject, project.basePath, name, out, filter, onPage);
55604
55666
  }
55605
55667
  else {
55606
55668
  console.log(`${chalk_1.default.cyan(`[${name}]`)} Building Library.`);
@@ -55609,7 +55671,7 @@ async function runBuildProject(project, rootProject, out, filter) {
55609
55671
  }
55610
55672
  await (0, rimraf_1.rimraf)(path_1.default.join(out, ".hyperbook", "out"));
55611
55673
  for (const p of project.projects) {
55612
- await runBuildProject(p, rootProject, out, filter);
55674
+ await runBuildProject(p, rootProject, out, filter, onPage);
55613
55675
  }
55614
55676
  }
55615
55677
  }
@@ -55688,7 +55750,7 @@ function makeBaseCtx(root, hyperbookJson, basePath, rootProject) {
55688
55750
  project: rootProject,
55689
55751
  };
55690
55752
  }
55691
- async function runBuild(root, rootProject, basePath, prefix, out, filter) {
55753
+ async function runBuild(root, rootProject, basePath, prefix, out, filter, onPage) {
55692
55754
  var _a;
55693
55755
  console.log(`${chalk_1.default.blue(`[${prefix}]`)} Reading hyperbook.json.`);
55694
55756
  const hyperbookJson = await fs_1.hyperbook.getJson(root);
@@ -55738,6 +55800,7 @@ async function runBuild(root, rootProject, basePath, prefix, out, filter) {
55738
55800
  for (let directive of pageResult.directives) {
55739
55801
  directives.add(directive);
55740
55802
  }
55803
+ onPage === null || onPage === void 0 ? void 0 : onPage(file.path.href || file.path.absolute, pageResult);
55741
55804
  if (!process.env.CI) {
55742
55805
  readline_1.default.clearLine(process.stdout, 0);
55743
55806
  readline_1.default.cursorTo(process.stdout, 0);
@@ -55759,6 +55822,7 @@ async function runBuild(root, rootProject, basePath, prefix, out, filter) {
55759
55822
  for (let directive of pageResult.directives) {
55760
55823
  directives.add(directive);
55761
55824
  }
55825
+ onPage === null || onPage === void 0 ? void 0 : onPage(file.path.href || file.path.absolute, pageResult);
55762
55826
  if (!process.env.CI) {
55763
55827
  readline_1.default.clearLine(process.stdout, 0);
55764
55828
  readline_1.default.cursorTo(process.stdout, 0);
@@ -55963,52 +56027,7 @@ async function runBuild(root, rootProject, basePath, prefix, out, filter) {
55963
56027
  }
55964
56028
  }
55965
56029
  process.stdout.write("\n");
55966
- if (hyperbookJson.search) {
55967
- const documents = {};
55968
- console.log(`${chalk_1.default.blue(`[${prefix}]`)} Building search index`);
55969
- let foundLanguage = false;
55970
- if (hyperbookJson.language && hyperbookJson.language !== "en") {
55971
- try {
55972
- // Only register lunr language plugins once to avoid "Overwriting" warnings
55973
- if (!lunr_1.default["_hyperbook_lang_loaded_" + hyperbookJson.language]) {
55974
- __nccwpck_require__(30089)(lunr_1.default);
55975
- require(`./lunr-languages/lunr.${hyperbookJson.language}.min.js`)(lunr_1.default);
55976
- lunr_1.default["_hyperbook_lang_loaded_" + hyperbookJson.language] = true;
55977
- }
55978
- foundLanguage = true;
55979
- }
55980
- catch (e) {
55981
- console.log(e);
55982
- console.log(`${chalk_1.default.yellow(`[${prefix}]`)} ${hyperbookJson.language} is not a valid value for the language key. See https://github.com/MihaiValentin/lunr-languages for possible values. Falling back to English.`);
55983
- }
55984
- }
55985
- const idx = (0, lunr_1.default)(function () {
55986
- if (foundLanguage) {
55987
- // @ts-ignore
55988
- this.use(lunr_1.default[hyperbookJson.language]);
55989
- }
55990
- this.ref("href");
55991
- this.field("description");
55992
- this.field("keywords");
55993
- this.field("heading");
55994
- this.field("content");
55995
- this.metadataWhitelist = ["position"];
55996
- searchDocuments.forEach((doc) => {
55997
- const href = baseCtx.makeUrl(doc.href, "book");
55998
- const docWithBase = {
55999
- ...doc,
56000
- href,
56001
- };
56002
- this.add(docWithBase);
56003
- documents[href] = docWithBase;
56004
- });
56005
- });
56006
- const js = `
56007
- const LUNR_INDEX = ${JSON.stringify(idx)};
56008
- const SEARCH_DOCUMENTS = ${JSON.stringify(documents)};
56009
- `;
56010
- await promises_1.default.writeFile(path_1.default.join(rootOut, exports.ASSETS_FOLDER, "search.js"), js);
56011
- }
56030
+ await writeSearchIndex(hyperbookJson, baseCtx, searchDocuments, rootOut, prefix);
56012
56031
  const supportLanguages = await promises_1.default
56013
56032
  .readdir(path_1.default.join(__dirname, "locales"))
56014
56033
  .then((files) => files.map((file) => file.split(".")[0]));
@@ -56554,17 +56573,65 @@ class IncrementalBuilder {
56554
56573
  // Track known files for structural change detection
56555
56574
  this.knownBookFiles = new Set();
56556
56575
  this.knownGlossaryFiles = new Set();
56576
+ // Reverse dependency index: inlined file -> pages that inlined it. Built from
56577
+ // what each page actually read, so a change maps to the pages it can affect
56578
+ // rather than to a guess based on the file's folder.
56579
+ this.dependents = new Map();
56580
+ // Page absolute path -> the file it was built from, to rebuild by dependency.
56581
+ this.bookFileByPath = new Map();
56582
+ this.glossaryFileByPath = new Map();
56583
+ // Nav-relevant shape of the last build, to notice when every page goes stale.
56584
+ this.navigationFingerprint = "";
56557
56585
  this.root = root;
56558
56586
  this.rootProject = rootProject;
56559
56587
  }
56560
56588
  async initialize() {
56561
56589
  console.log(`${chalk_1.default.yellow("[Incremental]")} Full initial build...`);
56562
- await (0, build_1.runBuildProject)(this.rootProject, this.rootProject);
56590
+ await this.fullRebuild();
56563
56591
  // Populate caches after full build
56564
56592
  await this.refreshCaches();
56565
56593
  this.initialized = true;
56566
56594
  console.log(`${chalk_1.default.green("[Incremental]")} Initial build complete. Incremental mode active.`);
56567
56595
  }
56596
+ /**
56597
+ * Full rebuild that also repopulates the dependency graph and the cached
56598
+ * search documents, so incremental updates afterwards start from the truth.
56599
+ */
56600
+ async fullRebuild() {
56601
+ this.dependents.clear();
56602
+ this.searchDocuments.clear();
56603
+ await (0, build_1.runBuildProject)(this.rootProject, this.rootProject, undefined, undefined, (href, result) => {
56604
+ this.recordPageResult(href, result);
56605
+ });
56606
+ }
56607
+ /** Indexes one page's dependencies and search documents. */
56608
+ recordPageResult(href, result) {
56609
+ // Drop stale edges first: a page that no longer uses a file must not keep
56610
+ // being rebuilt when that file changes.
56611
+ for (const pages of this.dependents.values()) {
56612
+ pages.delete(href);
56613
+ }
56614
+ for (const dependency of result.dependencies) {
56615
+ let pages = this.dependents.get(dependency);
56616
+ if (!pages) {
56617
+ pages = new Set();
56618
+ this.dependents.set(dependency, pages);
56619
+ }
56620
+ pages.add(href);
56621
+ }
56622
+ this.searchDocuments.set(href, result.searchDocuments);
56623
+ }
56624
+ /**
56625
+ * Everything that is baked into every page's HTML — the sidebar, page order,
56626
+ * titles. When this changes, one rebuilt page is not enough.
56627
+ */
56628
+ computeNavigationFingerprint() {
56629
+ var _a, _b, _c, _d;
56630
+ return JSON.stringify({
56631
+ sections: (_b = (_a = this.pagesAndSections) === null || _a === void 0 ? void 0 : _a.sections) !== null && _b !== void 0 ? _b : [],
56632
+ pages: (_d = (_c = this.pagesAndSections) === null || _c === void 0 ? void 0 : _c.pages) !== null && _d !== void 0 ? _d : [],
56633
+ });
56634
+ }
56568
56635
  async refreshCaches() {
56569
56636
  var _a;
56570
56637
  const project = this.rootProject;
@@ -56592,21 +56659,33 @@ class IncrementalBuilder {
56592
56659
  // Track known files
56593
56660
  this.knownBookFiles.clear();
56594
56661
  this.knownGlossaryFiles.clear();
56662
+ this.bookFileByPath.clear();
56663
+ this.glossaryFileByPath.clear();
56595
56664
  const bookFiles = await fs_1.vfile.listForFolder(this.root, "book");
56596
56665
  for (const f of bookFiles) {
56597
56666
  this.knownBookFiles.add(f.path.absolute);
56667
+ this.bookFileByPath.set(f.path.absolute, f);
56598
56668
  }
56599
56669
  const glossaryFiles = await fs_1.vfile.listForFolder(this.root, "glossary");
56600
56670
  for (const f of glossaryFiles) {
56601
56671
  this.knownGlossaryFiles.add(f.path.absolute);
56672
+ this.glossaryFileByPath.set(f.path.absolute, f);
56602
56673
  }
56674
+ this.navigationFingerprint = this.computeNavigationFingerprint();
56603
56675
  }
56604
56676
  classifyChange(filePath, eventType) {
56677
+ var _a;
56605
56678
  const absPath = path_1.default.resolve(this.root, filePath);
56606
56679
  // Config changes always trigger full rebuild
56607
56680
  if (filePath === "hyperbook.json" || filePath === "hyperlibrary.json") {
56608
56681
  return "config";
56609
56682
  }
56683
+ // A file some page inlined — rebuild those pages, whatever folder it is in.
56684
+ // Checked before the folder rules, because a `src=` target usually lives in
56685
+ // public/ or book/ and would otherwise be treated as a plain asset.
56686
+ if ((_a = this.dependents.get(absPath)) === null || _a === void 0 ? void 0 : _a.size) {
56687
+ return "dependency";
56688
+ }
56610
56689
  // Public file changes (check before structural to avoid unnecessary full rebuilds)
56611
56690
  const publicDir = path_1.default.join(this.root, "public");
56612
56691
  const bookPublicDir = path_1.default.join(this.root, "book-public");
@@ -56623,7 +56702,10 @@ class IncrementalBuilder {
56623
56702
  // Content changes to book files
56624
56703
  const bookDir = path_1.default.join(this.root, "book");
56625
56704
  if (absPath.startsWith(bookDir + path_1.default.sep) || absPath === bookDir) {
56626
- const isMarkdown = filePath.endsWith(".md") || filePath.endsWith(".md.hbs") || filePath.endsWith(".md.json") || filePath.endsWith(".md.yml");
56705
+ const isMarkdown = filePath.endsWith(".md") ||
56706
+ filePath.endsWith(".md.hbs") ||
56707
+ filePath.endsWith(".md.json") ||
56708
+ filePath.endsWith(".md.yml");
56627
56709
  if (isMarkdown) {
56628
56710
  return "content-book";
56629
56711
  }
@@ -56640,7 +56722,7 @@ class IncrementalBuilder {
56640
56722
  async handleChange(filePath, eventType) {
56641
56723
  if (!this.initialized || this.rootProject.type !== "book") {
56642
56724
  // Fall back to full rebuild for libraries or uninitialized state
56643
- await (0, build_1.runBuildProject)(this.rootProject, this.rootProject);
56725
+ await this.fullRebuild();
56644
56726
  await this.refreshCaches();
56645
56727
  return { changedPages: "*" };
56646
56728
  }
@@ -56650,10 +56732,33 @@ class IncrementalBuilder {
56650
56732
  case "structural": {
56651
56733
  console.log(`${chalk_1.default.yellow("[Incremental]")} Structural change detected, full rebuild...`);
56652
56734
  fs_1.vfile.clean(this.root);
56653
- await (0, build_1.runBuildProject)(this.rootProject, this.rootProject);
56735
+ await this.fullRebuild();
56654
56736
  await this.refreshCaches();
56655
56737
  return { changedPages: "*" };
56656
56738
  }
56739
+ case "dependency": {
56740
+ const absPath = path_1.default.resolve(this.root, filePath);
56741
+ const pages = [...(this.dependents.get(absPath) || [])];
56742
+ console.log(`${chalk_1.default.yellow("[Incremental]")} Dependency change: ${filePath} -> ${pages.length} page(s)`);
56743
+ // The file itself may also be a served asset (a `src=` script under
56744
+ // public/ is both inlined and downloadable), so copy it as well.
56745
+ await this.copyIfPublic(filePath);
56746
+ fs_1.vfile.clean(this.root);
56747
+ await this.refreshCaches();
56748
+ const rebuilt = [];
56749
+ for (const href of pages) {
56750
+ const file = [...this.bookFileByPath.values()].find((f) => (f.path.href || "/") === href) ||
56751
+ [...this.glossaryFileByPath.values()].find((f) => (f.path.href || "/glossary") === href);
56752
+ if (!file)
56753
+ continue;
56754
+ const result = await this.rebuildPage(file.path.absolute);
56755
+ if (result)
56756
+ rebuilt.push(result);
56757
+ }
56758
+ await this.refreshSearchIndex();
56759
+ console.log(`${chalk_1.default.green("[Incremental]")} Rebuilt: ${rebuilt.join(", ") || "nothing"}`);
56760
+ return { changedPages: rebuilt };
56761
+ }
56657
56762
  case "content-book": {
56658
56763
  console.log(`${chalk_1.default.yellow("[Incremental]")} Content change: ${filePath}`);
56659
56764
  // Clear vfile cache so it re-reads the changed file
@@ -56666,19 +56771,39 @@ class IncrementalBuilder {
56666
56771
  const changedFile = bookFiles.find((f) => f.path.absolute === absPath);
56667
56772
  if (!changedFile) {
56668
56773
  console.log(`${chalk_1.default.yellow("[Incremental]")} Could not find changed file, full rebuild...`);
56669
- await (0, build_1.runBuildProject)(this.rootProject, this.rootProject);
56774
+ await this.fullRebuild();
56670
56775
  await this.refreshCaches();
56671
56776
  return { changedPages: "*" };
56672
56777
  }
56673
56778
  const result = await (0, build_1.buildSingleBookPage)(changedFile, this.baseCtx, this.pageList, this.pagesAndSections, this.rootOut, this.assetsOut, this.hyperbookJson);
56674
- // Update search documents cache
56675
- this.searchDocuments.set(changedFile.path.href || changedFile.path.absolute, result.searchDocuments);
56779
+ // Reindex, so a page that dropped a `src=` or a snippet stops being
56780
+ // rebuilt when that file changes.
56781
+ this.recordPageResult(changedFile.path.href || "/", result);
56676
56782
  for (const directive of result.directives) {
56677
56783
  this.directives.add(directive);
56678
56784
  }
56679
56785
  // Copy any new directive assets
56680
56786
  await this.copyDirectiveAssets(result.directives);
56681
56787
  const changedHref = changedFile.path.href || "/";
56788
+ // The sidebar is baked into every page, so a rename or reorder makes
56789
+ // all of them stale — rebuilding just this one would leave the rest
56790
+ // showing the old title.
56791
+ const nextFingerprint = this.computeNavigationFingerprint();
56792
+ if (nextFingerprint !== this.navigationFingerprint) {
56793
+ console.log(`${chalk_1.default.yellow("[Incremental]")} Navigation changed, rebuilding all pages...`);
56794
+ this.navigationFingerprint = nextFingerprint;
56795
+ for (const absolute of this.bookFileByPath.keys()) {
56796
+ if (absolute === absPath)
56797
+ continue;
56798
+ await this.rebuildPage(absolute);
56799
+ }
56800
+ for (const absolute of this.glossaryFileByPath.keys()) {
56801
+ await this.rebuildPage(absolute);
56802
+ }
56803
+ await this.refreshSearchIndex();
56804
+ return { changedPages: "*" };
56805
+ }
56806
+ await this.refreshSearchIndex();
56682
56807
  console.log(`${chalk_1.default.green("[Incremental]")} Rebuilt: ${changedHref}`);
56683
56808
  return { changedPages: [changedHref] };
56684
56809
  }
@@ -56692,50 +56817,91 @@ class IncrementalBuilder {
56692
56817
  const changedFile = glossaryFiles.find((f) => f.path.absolute === absPath);
56693
56818
  if (!changedFile) {
56694
56819
  console.log(`${chalk_1.default.yellow("[Incremental]")} Could not find changed glossary file, full rebuild...`);
56695
- await (0, build_1.runBuildProject)(this.rootProject, this.rootProject);
56820
+ await this.fullRebuild();
56696
56821
  await this.refreshCaches();
56697
56822
  return { changedPages: "*" };
56698
56823
  }
56699
56824
  const result = await (0, build_1.buildSingleGlossaryPage)(changedFile, this.baseCtx, this.pageList, this.pagesAndSections, this.rootOut, this.assetsOut, this.hyperbookJson);
56700
- this.searchDocuments.set(changedFile.path.href || changedFile.path.absolute, result.searchDocuments);
56825
+ this.recordPageResult(changedFile.path.href || "/glossary", result);
56701
56826
  for (const directive of result.directives) {
56702
56827
  this.directives.add(directive);
56703
56828
  }
56704
56829
  await this.copyDirectiveAssets(result.directives);
56705
56830
  const changedHref = changedFile.path.href || "/glossary";
56831
+ await this.refreshSearchIndex();
56706
56832
  console.log(`${chalk_1.default.green("[Incremental]")} Rebuilt: ${changedHref}`);
56707
56833
  return { changedPages: [changedHref] };
56708
56834
  }
56709
56835
  case "public": {
56710
56836
  console.log(`${chalk_1.default.yellow("[Incremental]")} Public file change: ${filePath}`);
56711
- const absPath = path_1.default.resolve(this.root, filePath);
56712
- // Determine which public folder it belongs to and copy it
56713
- const publicDirs = [
56714
- { dir: path_1.default.join(this.root, "public"), folder: "public" },
56715
- { dir: path_1.default.join(this.root, "book-public"), folder: "book-public" },
56716
- { dir: path_1.default.join(this.root, "glossary-public"), folder: "glossary-public" },
56717
- ];
56718
- for (const { dir } of publicDirs) {
56719
- if (absPath.startsWith(dir + path_1.default.sep)) {
56720
- const relativePath = path_1.default.relative(dir, absPath);
56721
- const destPath = path_1.default.join(this.rootOut, relativePath);
56722
- const destDir = path_1.default.dirname(destPath);
56723
- try {
56724
- await promises_1.default.mkdir(destDir, { recursive: true });
56725
- await (0, promises_2.cp)(absPath, destPath);
56726
- console.log(`${chalk_1.default.green("[Incremental]")} Copied: ${relativePath}`);
56727
- }
56728
- catch (e) {
56729
- console.log(`${chalk_1.default.red("[Incremental]")} Failed to copy: ${relativePath}`);
56730
- }
56731
- break;
56732
- }
56733
- }
56734
- // Public file changes affect all pages (images could be on any page)
56837
+ await this.copyIfPublic(filePath);
56838
+ // No page inlined this file — it is a plain asset, so nothing needs
56839
+ // rebuilding, but any page could embed it, so reload everything.
56735
56840
  return { changedPages: "*" };
56736
56841
  }
56737
56842
  }
56738
56843
  }
56844
+ /** Copies a changed file to the output if it lives in a public folder. */
56845
+ async copyIfPublic(filePath) {
56846
+ const absPath = path_1.default.resolve(this.root, filePath);
56847
+ const publicDirs = [
56848
+ path_1.default.join(this.root, "public"),
56849
+ path_1.default.join(this.root, "book-public"),
56850
+ path_1.default.join(this.root, "glossary-public"),
56851
+ ];
56852
+ for (const dir of publicDirs) {
56853
+ if (!absPath.startsWith(dir + path_1.default.sep))
56854
+ continue;
56855
+ const relativePath = path_1.default.relative(dir, absPath);
56856
+ const destPath = path_1.default.join(this.rootOut, relativePath);
56857
+ try {
56858
+ await promises_1.default.mkdir(path_1.default.dirname(destPath), { recursive: true });
56859
+ await (0, promises_2.cp)(absPath, destPath);
56860
+ console.log(`${chalk_1.default.green("[Incremental]")} Copied: ${relativePath}`);
56861
+ }
56862
+ catch (e) {
56863
+ console.log(`${chalk_1.default.red("[Incremental]")} Failed to copy: ${relativePath}`);
56864
+ }
56865
+ return;
56866
+ }
56867
+ }
56868
+ /** Rebuilds one book or glossary page and reindexes what it consumed. */
56869
+ async rebuildPage(absPath) {
56870
+ const bookFile = this.bookFileByPath.get(absPath);
56871
+ if (bookFile) {
56872
+ const result = await (0, build_1.buildSingleBookPage)(bookFile, this.baseCtx, this.pageList, this.pagesAndSections, this.rootOut, this.assetsOut, this.hyperbookJson);
56873
+ const href = bookFile.path.href || "/";
56874
+ this.recordPageResult(href, result);
56875
+ for (const directive of result.directives) {
56876
+ this.directives.add(directive);
56877
+ }
56878
+ await this.copyDirectiveAssets(result.directives);
56879
+ return href;
56880
+ }
56881
+ const glossaryFile = this.glossaryFileByPath.get(absPath);
56882
+ if (glossaryFile) {
56883
+ const result = await (0, build_1.buildSingleGlossaryPage)(glossaryFile, this.baseCtx, this.pageList, this.pagesAndSections, this.rootOut, this.assetsOut, this.hyperbookJson);
56884
+ const href = glossaryFile.path.href || "/glossary";
56885
+ this.recordPageResult(href, result);
56886
+ for (const directive of result.directives) {
56887
+ this.directives.add(directive);
56888
+ }
56889
+ await this.copyDirectiveAssets(result.directives);
56890
+ return href;
56891
+ }
56892
+ return null;
56893
+ }
56894
+ /** Rewrites search.js from the cached per-page documents. */
56895
+ async refreshSearchIndex() {
56896
+ var _a;
56897
+ if (!((_a = this.hyperbookJson) === null || _a === void 0 ? void 0 : _a.search))
56898
+ return;
56899
+ const all = [];
56900
+ for (const docs of this.searchDocuments.values()) {
56901
+ all.push(...docs);
56902
+ }
56903
+ await (0, build_1.writeSearchIndex)(this.hyperbookJson, this.baseCtx, all, this.rootOut, "Incremental");
56904
+ }
56739
56905
  async copyDirectiveAssets(newDirectives) {
56740
56906
  const assetsPath = path_1.default.join(__dirname, "assets");
56741
56907
  for (const directive of newDirectives) {
@@ -94869,6 +95035,8 @@ var getMarkdown = async (file) => {
94869
95035
  );
94870
95036
  }
94871
95037
  registerHelpers(import_handlebars.default, { file });
95038
+ const dependencies = [];
95039
+ const addDependency = (absolute) => dependencies.push(external_path_.relative(file.root, absolute));
94872
95040
  let markdown = "";
94873
95041
  if (file.extension === ".md.yml") {
94874
95042
  const j = await promises_.readFile(file.path.absolute).then((f) => dist.parse(f.toString()));
@@ -94877,9 +95045,13 @@ var getMarkdown = async (file) => {
94877
95045
  `Yaml files need a template. You need to define a template property in your yaml file: ${file.path.absolute}`
94878
95046
  );
94879
95047
  } else {
94880
- const templateSource = await promises_.readFile(
94881
- external_path_.join(file.root, "templates", j.template + ".md.hbs")
95048
+ const templatePath = external_path_.join(
95049
+ file.root,
95050
+ "templates",
95051
+ j.template + ".md.hbs"
94882
95052
  );
95053
+ addDependency(templatePath);
95054
+ const templateSource = await promises_.readFile(templatePath);
94883
95055
  const template = import_handlebars.default.compile(templateSource.toString());
94884
95056
  markdown = template(j);
94885
95057
  }
@@ -94890,9 +95062,13 @@ var getMarkdown = async (file) => {
94890
95062
  `JSON files need a template. You need to define a template property in your json file: ${file.path.absolute}`
94891
95063
  );
94892
95064
  } else {
94893
- const templateSource = await promises_.readFile(
94894
- external_path_.join(file.root, "templates", j.template + ".md.hbs")
95065
+ const templatePath = external_path_.join(
95066
+ file.root,
95067
+ "templates",
95068
+ j.template + ".md.hbs"
94895
95069
  );
95070
+ addDependency(templatePath);
95071
+ const templateSource = await promises_.readFile(templatePath);
94896
95072
  const template = import_handlebars.default.compile(templateSource.toString());
94897
95073
  markdown = template(j);
94898
95074
  }
@@ -94915,10 +95091,9 @@ var getMarkdown = async (file) => {
94915
95091
  for (const snippet of snippets) {
94916
95092
  const dots = snippet[2];
94917
95093
  const snippetId = snippet[3];
94918
- const snippetFile = await promises_.readFile(
94919
- external_path_.join(file.root, "snippets", snippetId + ".md.hbs"),
94920
- { encoding: "utf8" }
94921
- );
95094
+ const snippetPath = external_path_.join(file.root, "snippets", snippetId + ".md.hbs");
95095
+ addDependency(snippetPath);
95096
+ const snippetFile = await promises_.readFile(snippetPath, { encoding: "utf8" });
94922
95097
  const template = import_handlebars.default.compile(snippetFile);
94923
95098
  const vars = {
94924
95099
  hyperbook,
@@ -94968,6 +95143,7 @@ var getMarkdown = async (file) => {
94968
95143
  }
94969
95144
  return {
94970
95145
  content,
95146
+ dependencies,
94971
95147
  data: { ...data }
94972
95148
  };
94973
95149
  };
@@ -174933,6 +175109,7 @@ var en_default = {
174933
175109
  "pyide-canvas": "Canvas",
174934
175110
  "pyide-input": "Input",
174935
175111
  "pyide-input-prompt": "Input required:",
175112
+ "pyide-input-submit": "Send",
174936
175113
  "pyide-reset": "Reset",
174937
175114
  "pyide-copy": "Copy",
174938
175115
  "pyide-download": "Download",
@@ -175076,6 +175253,7 @@ var de_default = {
175076
175253
  "pyide-canvas": "Canvas",
175077
175254
  "pyide-input": "Eingabe",
175078
175255
  "pyide-input-prompt": "Eingabe erforderlich:",
175256
+ "pyide-input-submit": "Senden",
175079
175257
  "pyide-reset": "Zur\xFCcksetzen",
175080
175258
  "pyide-copy": "Kopieren",
175081
175259
  "pyide-download": "Herunterladen",
@@ -177242,7 +177420,7 @@ var remarkDirectiveTiles_default = (ctx) => () => {
177242
177420
  if (node4.name !== "tile") {
177243
177421
  return;
177244
177422
  }
177245
- const { title, size = "M", icon, href } = node4.attributes || {};
177423
+ const { title, size = "M", icon: icon2, href } = node4.attributes || {};
177246
177424
  expectLeafDirective(node4, file, "tile");
177247
177425
  if (!title) {
177248
177426
  file.fail(
@@ -177266,11 +177444,11 @@ var remarkDirectiveTiles_default = (ctx) => () => {
177266
177444
  ]
177267
177445
  }
177268
177446
  ];
177269
- if (icon) {
177270
- const emojiMatch = icon.match(/^:([+\w-]+):$/);
177447
+ if (icon2) {
177448
+ const emojiMatch = icon2.match(/^:([+\w-]+):$/);
177271
177449
  if (emojiMatch) {
177272
177450
  const emojiName = emojiMatch[1];
177273
- const emoji = github_emojis_default[emojiName] ?? icon;
177451
+ const emoji = github_emojis_default[emojiName] ?? icon2;
177274
177452
  tileChildren.push({
177275
177453
  type: "element",
177276
177454
  tagName: "span",
@@ -177290,7 +177468,7 @@ var remarkDirectiveTiles_default = (ctx) => () => {
177290
177468
  tagName: "img",
177291
177469
  properties: {
177292
177470
  class: "tile-icon",
177293
- src: ctx.makeUrl(icon, "public")
177471
+ src: ctx.makeUrl(icon2, "public")
177294
177472
  },
177295
177473
  children: []
177296
177474
  });
@@ -179914,9 +180092,9 @@ var makeHeaderElements = (ctx) => {
179914
180092
  let submenu = [];
179915
180093
  if ("links" in link3) {
179916
180094
  const links = link3.links.map((link4) => {
179917
- let icon2 = [];
180095
+ let icon3 = [];
179918
180096
  if (link4.icon) {
179919
- icon2.push({
180097
+ icon3.push({
179920
180098
  type: "element",
179921
180099
  tagName: "div",
179922
180100
  properties: {
@@ -179944,7 +180122,7 @@ var makeHeaderElements = (ctx) => {
179944
180122
  href: "href" in link4 ? link4.href : "#"
179945
180123
  },
179946
180124
  children: [
179947
- ...icon2,
180125
+ ...icon3,
179948
180126
  {
179949
180127
  type: "element",
179950
180128
  tagName: "div",
@@ -179972,9 +180150,9 @@ var makeHeaderElements = (ctx) => {
179972
180150
  children: links
179973
180151
  });
179974
180152
  }
179975
- const icon = [];
180153
+ const icon2 = [];
179976
180154
  if (link3.icon) {
179977
- icon.push({
180155
+ icon2.push({
179978
180156
  type: "element",
179979
180157
  tagName: "div",
179980
180158
  properties: {
@@ -180004,7 +180182,7 @@ var makeHeaderElements = (ctx) => {
180004
180182
  href
180005
180183
  },
180006
180184
  children: [
180007
- ...icon,
180185
+ ...icon2,
180008
180186
  {
180009
180187
  type: "element",
180010
180188
  tagName: "div",
@@ -180431,9 +180609,9 @@ var makeCustomLinksFooter = (ctx) => {
180431
180609
  let submenu = [];
180432
180610
  if ("links" in link3) {
180433
180611
  const links = link3.links.map((link4) => {
180434
- let icon2 = [];
180612
+ let icon3 = [];
180435
180613
  if (link4.icon) {
180436
- icon2.push({
180614
+ icon3.push({
180437
180615
  type: "element",
180438
180616
  tagName: "div",
180439
180617
  properties: {
@@ -180461,7 +180639,7 @@ var makeCustomLinksFooter = (ctx) => {
180461
180639
  href: "href" in link4 ? link4.href : "#"
180462
180640
  },
180463
180641
  children: [
180464
- ...icon2,
180642
+ ...icon3,
180465
180643
  {
180466
180644
  type: "element",
180467
180645
  tagName: "div",
@@ -180489,9 +180667,9 @@ var makeCustomLinksFooter = (ctx) => {
180489
180667
  children: links
180490
180668
  });
180491
180669
  }
180492
- const icon = [];
180670
+ const icon2 = [];
180493
180671
  if (link3.icon) {
180494
- icon.push({
180672
+ icon2.push({
180495
180673
  type: "element",
180496
180674
  tagName: "div",
180497
180675
  properties: {
@@ -180524,7 +180702,7 @@ var makeCustomLinksFooter = (ctx) => {
180524
180702
  href
180525
180703
  },
180526
180704
  children: [
180527
- ...icon,
180705
+ ...icon2,
180528
180706
  {
180529
180707
  type: "element",
180530
180708
  tagName: "div",
@@ -180803,10 +180981,10 @@ var remarkDirectiveAlert_default = (ctx) => () => {
180803
180981
  const color3 = node3.attributes?.color;
180804
180982
  const content5 = node3.attributes?.label;
180805
180983
  const type = Object.keys(node3.attributes || {}).join(" ").trim();
180806
- const icon = content5 || type;
180984
+ const icon2 = content5 || type;
180807
180985
  data.hName = "div";
180808
180986
  data.hProperties = {
180809
- class: `directive-alert ${type} ${icon ? "icon" : ""}`.trim(),
180987
+ class: `directive-alert ${type} ${icon2 ? "icon" : ""}`.trim(),
180810
180988
  style: `${color3 ? `--alert-color: ${color3};` : ""} ${content5 ? `--alert-content: '${content5}';` : ""}`
180811
180989
  };
180812
180990
  }
@@ -181037,6 +181215,68 @@ var remarkDirectiveCollapsible_default = (ctx) => function() {
181037
181215
  };
181038
181216
  };
181039
181217
 
181218
+ // src/icons.ts
181219
+ var PATHS = {
181220
+ // rotate-ccw
181221
+ reset: ["M1 4v6h6", "M3.51 15a9 9 0 1 0 2.13-9.36L1 10"],
181222
+ // two offset sheets
181223
+ copy: [
181224
+ "M9 9h11a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-9a2 2 0 0 1-2-2V9z",
181225
+ "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"
181226
+ ],
181227
+ // arrow into a tray
181228
+ download: [
181229
+ "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",
181230
+ "M7 10l5 5 5-5",
181231
+ "M12 15V3"
181232
+ ],
181233
+ // four corner brackets
181234
+ fullscreen: [
181235
+ "M8 3H5a2 2 0 0 0-2 2v3",
181236
+ "M21 8V5a2 2 0 0 0-2-2h-3",
181237
+ "M16 21h3a2 2 0 0 0 2-2v-3",
181238
+ "M3 16v3a2 2 0 0 0 2 2h3"
181239
+ ],
181240
+ // closed padlock
181241
+ lock: [
181242
+ "M5 11h14a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2z",
181243
+ "M7 11V7a5 5 0 0 1 10 0v4"
181244
+ ],
181245
+ plus: ["M12 5v14", "M5 12h14"],
181246
+ // lidded box — the whole project rather than a single file
181247
+ archive: ["M21 8v13H3V8", "M1 3h22v5H1z", "M10 12h4"],
181248
+ // document with a folded corner — the rendered PDF
181249
+ pdf: [
181250
+ "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z",
181251
+ "M14 2v6h6",
181252
+ "M16 13H8",
181253
+ "M16 17H8"
181254
+ ],
181255
+ // disclosure arrow; rotated by CSS when the section is open
181256
+ chevron: ["M9 18l6-6-6-6"]
181257
+ };
181258
+ var icon = (name) => ({
181259
+ type: "element",
181260
+ tagName: "svg",
181261
+ properties: {
181262
+ className: ["icon", `icon-${name}`],
181263
+ viewBox: "0 0 24 24",
181264
+ fill: "none",
181265
+ stroke: "currentColor",
181266
+ strokeWidth: "2",
181267
+ strokeLinecap: "round",
181268
+ strokeLinejoin: "round",
181269
+ "aria-hidden": "true",
181270
+ focusable: "false"
181271
+ },
181272
+ children: PATHS[name].map((d) => ({
181273
+ type: "element",
181274
+ tagName: "path",
181275
+ properties: { d },
181276
+ children: []
181277
+ }))
181278
+ });
181279
+
181040
181280
  // src/remarkDirectiveArchive.ts
181041
181281
  var remarkDirectiveArchive_default = (ctx) => () => {
181042
181282
  const name = "archive";
@@ -181062,12 +181302,7 @@ var remarkDirectiveArchive_default = (ctx) => () => {
181062
181302
  properties: {
181063
181303
  class: "icon"
181064
181304
  },
181065
- children: [
181066
- {
181067
- type: "text",
181068
- value: "\u23EC"
181069
- }
181070
- ]
181305
+ children: [icon("download")]
181071
181306
  },
181072
181307
  {
181073
181308
  type: "element",
@@ -181112,12 +181347,7 @@ var remarkDirectiveDownload_default = (ctx) => () => {
181112
181347
  properties: {
181113
181348
  class: "icon"
181114
181349
  },
181115
- children: [
181116
- {
181117
- type: "text",
181118
- value: "\u23EC"
181119
- }
181120
- ]
181350
+ children: [icon("download")]
181121
181351
  },
181122
181352
  {
181123
181353
  type: "element",
@@ -181351,9 +181581,12 @@ var remarkDirectiveProtect_default = (ctx) => function() {
181351
181581
  type: "paragraph",
181352
181582
  data: {
181353
181583
  hName: "span",
181354
- hProperties: { class: "icon" }
181584
+ hProperties: { class: "icon" },
181585
+ // This is an mdast node, so the hast icon has to be handed
181586
+ // over as hChildren — mdast children would drop it.
181587
+ hChildren: [icon("lock")]
181355
181588
  },
181356
- children: [{ type: "text", value: "\u{1F512}" }]
181589
+ children: []
181357
181590
  },
181358
181591
  {
181359
181592
  type: "paragraph",
@@ -194338,6 +194571,8 @@ var getMarkdown = async (file) => {
194338
194571
  );
194339
194572
  }
194340
194573
  registerHelpers(import_handlebars.default, { file });
194574
+ const dependencies = [];
194575
+ const addDependency = (absolute) => dependencies.push(path__WEBPACK_IMPORTED_MODULE_4__.relative(file.root, absolute));
194341
194576
  let markdown = "";
194342
194577
  if (file.extension === ".md.yml") {
194343
194578
  const j = await fs_promises__WEBPACK_IMPORTED_MODULE_5__.readFile(file.path.absolute).then((f) => import_yaml5.default.parse(f.toString()));
@@ -194346,9 +194581,13 @@ var getMarkdown = async (file) => {
194346
194581
  `Yaml files need a template. You need to define a template property in your yaml file: ${file.path.absolute}`
194347
194582
  );
194348
194583
  } else {
194349
- const templateSource = await fs_promises__WEBPACK_IMPORTED_MODULE_5__.readFile(
194350
- path__WEBPACK_IMPORTED_MODULE_4__.join(file.root, "templates", j.template + ".md.hbs")
194584
+ const templatePath = path__WEBPACK_IMPORTED_MODULE_4__.join(
194585
+ file.root,
194586
+ "templates",
194587
+ j.template + ".md.hbs"
194351
194588
  );
194589
+ addDependency(templatePath);
194590
+ const templateSource = await fs_promises__WEBPACK_IMPORTED_MODULE_5__.readFile(templatePath);
194352
194591
  const template = import_handlebars.default.compile(templateSource.toString());
194353
194592
  markdown = template(j);
194354
194593
  }
@@ -194359,9 +194598,13 @@ var getMarkdown = async (file) => {
194359
194598
  `JSON files need a template. You need to define a template property in your json file: ${file.path.absolute}`
194360
194599
  );
194361
194600
  } else {
194362
- const templateSource = await fs_promises__WEBPACK_IMPORTED_MODULE_5__.readFile(
194363
- path__WEBPACK_IMPORTED_MODULE_4__.join(file.root, "templates", j.template + ".md.hbs")
194601
+ const templatePath = path__WEBPACK_IMPORTED_MODULE_4__.join(
194602
+ file.root,
194603
+ "templates",
194604
+ j.template + ".md.hbs"
194364
194605
  );
194606
+ addDependency(templatePath);
194607
+ const templateSource = await fs_promises__WEBPACK_IMPORTED_MODULE_5__.readFile(templatePath);
194365
194608
  const template = import_handlebars.default.compile(templateSource.toString());
194366
194609
  markdown = template(j);
194367
194610
  }
@@ -194384,10 +194627,9 @@ var getMarkdown = async (file) => {
194384
194627
  for (const snippet of snippets) {
194385
194628
  const dots = snippet[2];
194386
194629
  const snippetId = snippet[3];
194387
- const snippetFile = await fs_promises__WEBPACK_IMPORTED_MODULE_5__.readFile(
194388
- path__WEBPACK_IMPORTED_MODULE_4__.join(file.root, "snippets", snippetId + ".md.hbs"),
194389
- { encoding: "utf8" }
194390
- );
194630
+ const snippetPath = path__WEBPACK_IMPORTED_MODULE_4__.join(file.root, "snippets", snippetId + ".md.hbs");
194631
+ addDependency(snippetPath);
194632
+ const snippetFile = await fs_promises__WEBPACK_IMPORTED_MODULE_5__.readFile(snippetPath, { encoding: "utf8" });
194391
194633
  const template = import_handlebars.default.compile(snippetFile);
194392
194634
  const vars = {
194393
194635
  hyperbook,
@@ -194437,6 +194679,7 @@ var getMarkdown = async (file) => {
194437
194679
  }
194438
194680
  return {
194439
194681
  content: content5,
194682
+ dependencies,
194440
194683
  data: { ...data }
194441
194684
  };
194442
194685
  };
@@ -195172,29 +195415,24 @@ function node2(value) {
195172
195415
 
195173
195416
 
195174
195417
  var readFile = (src, ctx) => {
195175
- let srcFile = null;
195176
- try {
195177
- srcFile = fs__WEBPACK_IMPORTED_MODULE_7__.readFileSync(path__WEBPACK_IMPORTED_MODULE_4__.join(ctx.root, "public", src), "utf-8");
195178
- } catch (e) {
195418
+ const candidates = [
195419
+ path__WEBPACK_IMPORTED_MODULE_4__.join(ctx.root, "public", src),
195420
+ path__WEBPACK_IMPORTED_MODULE_4__.join(ctx.root, "book", src),
195421
+ path__WEBPACK_IMPORTED_MODULE_4__.join(
195422
+ ctx.root,
195423
+ "book",
195424
+ ctx.navigation.current?.path?.directory || "",
195425
+ src
195426
+ )
195427
+ ];
195428
+ for (const candidate of candidates) {
195429
+ ctx.dependencies?.add(candidate);
195179
195430
  try {
195180
- srcFile = fs__WEBPACK_IMPORTED_MODULE_7__.readFileSync(path__WEBPACK_IMPORTED_MODULE_4__.join(ctx.root, "book", src), "utf-8");
195181
- } catch (e2) {
195182
- try {
195183
- srcFile = fs__WEBPACK_IMPORTED_MODULE_7__.readFileSync(
195184
- path__WEBPACK_IMPORTED_MODULE_4__.join(
195185
- ctx.root,
195186
- "book",
195187
- ctx.navigation.current?.path?.directory || "",
195188
- src
195189
- ),
195190
- "utf-8"
195191
- );
195192
- } catch (e3) {
195193
- return null;
195194
- }
195431
+ return fs__WEBPACK_IMPORTED_MODULE_7__.readFileSync(candidate, "utf-8");
195432
+ } catch (e) {
195195
195433
  }
195196
195434
  }
195197
- return srcFile;
195435
+ return null;
195198
195436
  };
195199
195437
 
195200
195438
  // src/rehypeDirectiveP5.ts
@@ -195366,40 +195604,31 @@ ${(code4.scripts ? [cdnLibraryUrl, ...code4.scripts] : []).map((src) => `<script
195366
195604
  type: "element",
195367
195605
  tagName: "button",
195368
195606
  properties: {
195369
- class: "reset"
195607
+ class: "reset",
195608
+ title: i18n.get("p5-reset"),
195609
+ "aria-label": i18n.get("p5-reset")
195370
195610
  },
195371
- children: [
195372
- {
195373
- type: "text",
195374
- value: i18n.get("p5-reset")
195375
- }
195376
- ]
195611
+ children: [icon("reset")]
195377
195612
  },
195378
195613
  {
195379
195614
  type: "element",
195380
195615
  tagName: "button",
195381
195616
  properties: {
195382
- class: "copy"
195617
+ class: "copy",
195618
+ title: i18n.get("p5-copy"),
195619
+ "aria-label": i18n.get("p5-copy")
195383
195620
  },
195384
- children: [
195385
- {
195386
- type: "text",
195387
- value: i18n.get("p5-copy")
195388
- }
195389
- ]
195621
+ children: [icon("copy")]
195390
195622
  },
195391
195623
  {
195392
195624
  type: "element",
195393
195625
  tagName: "button",
195394
195626
  properties: {
195395
- class: "download"
195627
+ class: "download",
195628
+ title: i18n.get("p5-download"),
195629
+ "aria-label": i18n.get("p5-download")
195396
195630
  },
195397
- children: [
195398
- {
195399
- type: "text",
195400
- value: i18n.get("p5-download")
195401
- }
195402
- ]
195631
+ children: [icon("download")]
195403
195632
  },
195404
195633
  {
195405
195634
  type: "element",
@@ -195409,12 +195638,7 @@ ${(code4.scripts ? [cdnLibraryUrl, ...code4.scripts] : []).map((src) => `<script
195409
195638
  title: i18n.get("ide-fullscreen-enter"),
195410
195639
  "aria-label": i18n.get("ide-fullscreen-enter")
195411
195640
  },
195412
- children: [
195413
- {
195414
- type: "text",
195415
- value: "\u26F6"
195416
- }
195417
- ]
195641
+ children: [icon("fullscreen")]
195418
195642
  }
195419
195643
  ]
195420
195644
  }
@@ -195598,40 +195822,31 @@ var remarkDirectiveAbcMusic_default = (ctx) => () => {
195598
195822
  type: "element",
195599
195823
  tagName: "button",
195600
195824
  properties: {
195601
- class: "reset"
195825
+ class: "reset",
195826
+ title: i18n.get("abc-music-reset"),
195827
+ "aria-label": i18n.get("abc-music-reset")
195602
195828
  },
195603
- children: [
195604
- {
195605
- type: "text",
195606
- value: i18n.get("abc-music-reset")
195607
- }
195608
- ]
195829
+ children: [icon("reset")]
195609
195830
  },
195610
195831
  {
195611
195832
  type: "element",
195612
195833
  tagName: "button",
195613
195834
  properties: {
195614
- class: "copy"
195835
+ class: "copy",
195836
+ title: i18n.get("abc-music-copy"),
195837
+ "aria-label": i18n.get("abc-music-copy")
195615
195838
  },
195616
- children: [
195617
- {
195618
- type: "text",
195619
- value: i18n.get("abc-music-copy")
195620
- }
195621
- ]
195839
+ children: [icon("copy")]
195622
195840
  },
195623
195841
  {
195624
195842
  type: "element",
195625
195843
  tagName: "button",
195626
195844
  properties: {
195627
- class: "download"
195845
+ class: "download",
195846
+ title: i18n.get("abc-music-download"),
195847
+ "aria-label": i18n.get("abc-music-download")
195628
195848
  },
195629
- children: [
195630
- {
195631
- type: "text",
195632
- value: i18n.get("abc-music-download")
195633
- }
195634
- ]
195849
+ children: [icon("download")]
195635
195850
  }
195636
195851
  ]
195637
195852
  }
@@ -195670,11 +195885,22 @@ var remarkDirectivePyide_default = (ctx) => () => {
195670
195885
  if (isDirective(node3)) {
195671
195886
  if (node3.name !== name) return;
195672
195887
  const data = node3.data || (node3.data = {});
195673
- const { src = "", id = hash(node3), packages, height } = node3.attributes || {};
195888
+ const {
195889
+ src = "",
195890
+ id = hash(node3),
195891
+ packages,
195892
+ height
195893
+ } = node3.attributes || {};
195674
195894
  const hasCanvas = "canvas" in (node3.attributes || {});
195675
195895
  const packageList = parsePackagesAttribute(packages);
195676
195896
  expectContainerDirective(node3, file, name);
195677
- registerDirective(file, name, ["python-friendly-error-messages.js", "client.js"], ["style.css"], []);
195897
+ registerDirective(
195898
+ file,
195899
+ name,
195900
+ ["python-friendly-error-messages.js", "client.js"],
195901
+ ["style.css"],
195902
+ []
195903
+ );
195678
195904
  requestJS(file, ["codemirror", "codemirror.bundle.js"]);
195679
195905
  let srcFile = "";
195680
195906
  let tests = [];
@@ -195807,6 +196033,53 @@ var remarkDirectivePyide_default = (ctx) => () => {
195807
196033
  class: "output"
195808
196034
  },
195809
196035
  children: []
196036
+ },
196037
+ // Shown only while the running script waits on input(). Reading
196038
+ // input here keeps the main thread free, so drawings stay live.
196039
+ {
196040
+ type: "element",
196041
+ tagName: "form",
196042
+ properties: {
196043
+ class: "stdin hidden"
196044
+ },
196045
+ children: [
196046
+ // The prompt also goes to the output panel, but that panel is
196047
+ // hidden while the canvas tab is open — so repeat it here.
196048
+ {
196049
+ type: "element",
196050
+ tagName: "span",
196051
+ properties: {
196052
+ class: "stdin-prompt"
196053
+ },
196054
+ children: []
196055
+ },
196056
+ {
196057
+ type: "element",
196058
+ tagName: "input",
196059
+ properties: {
196060
+ class: "stdin-field",
196061
+ type: "text",
196062
+ autocomplete: "off",
196063
+ spellcheck: "false",
196064
+ "aria-label": i18n.get("pyide-input")
196065
+ },
196066
+ children: []
196067
+ },
196068
+ {
196069
+ type: "element",
196070
+ tagName: "button",
196071
+ properties: {
196072
+ class: "stdin-submit",
196073
+ type: "submit"
196074
+ },
196075
+ children: [
196076
+ {
196077
+ type: "text",
196078
+ value: i18n.get("pyide-input-submit")
196079
+ }
196080
+ ]
196081
+ }
196082
+ ]
195810
196083
  }
195811
196084
  ]
195812
196085
  },
@@ -195903,40 +196176,31 @@ var remarkDirectivePyide_default = (ctx) => () => {
195903
196176
  type: "element",
195904
196177
  tagName: "button",
195905
196178
  properties: {
195906
- class: "reset"
196179
+ class: "reset",
196180
+ title: i18n.get("pyide-reset"),
196181
+ "aria-label": i18n.get("pyide-reset")
195907
196182
  },
195908
- children: [
195909
- {
195910
- type: "text",
195911
- value: i18n.get("pyide-reset")
195912
- }
195913
- ]
196183
+ children: [icon("reset")]
195914
196184
  },
195915
196185
  {
195916
196186
  type: "element",
195917
196187
  tagName: "button",
195918
196188
  properties: {
195919
- class: "copy"
196189
+ class: "copy",
196190
+ title: i18n.get("pyide-copy"),
196191
+ "aria-label": i18n.get("pyide-copy")
195920
196192
  },
195921
- children: [
195922
- {
195923
- type: "text",
195924
- value: i18n.get("pyide-copy")
195925
- }
195926
- ]
196193
+ children: [icon("copy")]
195927
196194
  },
195928
196195
  {
195929
196196
  type: "element",
195930
196197
  tagName: "button",
195931
196198
  properties: {
195932
- class: "download"
196199
+ class: "download",
196200
+ title: i18n.get("pyide-download"),
196201
+ "aria-label": i18n.get("pyide-download")
195933
196202
  },
195934
- children: [
195935
- {
195936
- type: "text",
195937
- value: i18n.get("pyide-download")
195938
- }
195939
- ]
196203
+ children: [icon("download")]
195940
196204
  },
195941
196205
  {
195942
196206
  type: "element",
@@ -195946,12 +196210,7 @@ var remarkDirectivePyide_default = (ctx) => () => {
195946
196210
  title: i18n.get("ide-fullscreen-enter"),
195947
196211
  "aria-label": i18n.get("ide-fullscreen-enter")
195948
196212
  },
195949
- children: [
195950
- {
195951
- type: "text",
195952
- value: "\u26F6"
195953
- }
195954
- ]
196213
+ children: [icon("fullscreen")]
195955
196214
  }
195956
196215
  ]
195957
196216
  }
@@ -196188,27 +196447,21 @@ html, body {
196188
196447
  type: "element",
196189
196448
  tagName: "button",
196190
196449
  properties: {
196191
- class: "reset"
196450
+ class: "reset",
196451
+ title: i18n.get("webide-reset"),
196452
+ "aria-label": i18n.get("webide-reset")
196192
196453
  },
196193
- children: [
196194
- {
196195
- type: "text",
196196
- value: i18n.get("webide-reset")
196197
- }
196198
- ]
196454
+ children: [icon("reset")]
196199
196455
  },
196200
196456
  {
196201
196457
  type: "element",
196202
196458
  tagName: "button",
196203
196459
  properties: {
196204
- class: "download"
196460
+ class: "download",
196461
+ title: i18n.get("webide-download"),
196462
+ "aria-label": i18n.get("webide-download")
196205
196463
  },
196206
- children: [
196207
- {
196208
- type: "text",
196209
- value: i18n.get("webide-download")
196210
- }
196211
- ]
196464
+ children: [icon("download")]
196212
196465
  },
196213
196466
  {
196214
196467
  type: "element",
@@ -196218,12 +196471,7 @@ html, body {
196218
196471
  title: i18n.get("ide-fullscreen-enter"),
196219
196472
  "aria-label": i18n.get("ide-fullscreen-enter")
196220
196473
  },
196221
- children: [
196222
- {
196223
- type: "text",
196224
- value: "\u26F6"
196225
- }
196226
- ]
196474
+ children: [icon("fullscreen")]
196227
196475
  }
196228
196476
  ]
196229
196477
  }
@@ -201165,9 +201413,7 @@ var remarkDirectiveTypst_default = (ctx) => () => {
201165
201413
  );
201166
201414
  binaryFiles.push({ dest, url });
201167
201415
  }
201168
- const fontMatches = text9.matchAll(
201169
- /@font\s+src="([^"]+)"/g
201170
- );
201416
+ const fontMatches = text9.matchAll(/@font\s+src="([^"]+)"/g);
201171
201417
  for (const match of fontMatches) {
201172
201418
  const src = match[1];
201173
201419
  const isRemote = src.startsWith("http://") || src.startsWith("https://");
@@ -201212,9 +201458,7 @@ var remarkDirectiveTypst_default = (ctx) => () => {
201212
201458
  );
201213
201459
  binaryFiles.push({ dest, url });
201214
201460
  }
201215
- const fontMatches = text9.matchAll(
201216
- /@font\s+src="([^"]+)"/g
201217
- );
201461
+ const fontMatches = text9.matchAll(/@font\s+src="([^"]+)"/g);
201218
201462
  for (const match of fontMatches) {
201219
201463
  const src = match[1];
201220
201464
  const isRemote = src.startsWith("http://") || src.startsWith("https://");
@@ -201270,9 +201514,9 @@ var remarkDirectiveTypst_default = (ctx) => () => {
201270
201514
  "data-binary-files": Buffer.from(
201271
201515
  JSON.stringify(binaryFiles)
201272
201516
  ).toString("base64"),
201273
- "data-font-files": Buffer.from(
201274
- JSON.stringify(fontFiles)
201275
- ).toString("base64"),
201517
+ "data-font-files": Buffer.from(JSON.stringify(fontFiles)).toString(
201518
+ "base64"
201519
+ ),
201276
201520
  "data-base-path": basePath,
201277
201521
  "data-page-path": pagePath,
201278
201522
  ...height !== void 0 && !isPreviewMode ? { style: `--typst-height: ${height}` } : {}
@@ -201327,27 +201571,21 @@ var remarkDirectiveTypst_default = (ctx) => () => {
201327
201571
  type: "element",
201328
201572
  tagName: "button",
201329
201573
  properties: {
201330
- class: "download-pdf"
201574
+ class: "download-pdf",
201575
+ title: i18n.get("typst-download-pdf"),
201576
+ "aria-label": i18n.get("typst-download-pdf")
201331
201577
  },
201332
- children: [
201333
- {
201334
- type: "text",
201335
- value: i18n.get("typst-download-pdf")
201336
- }
201337
- ]
201578
+ children: [icon("pdf")]
201338
201579
  };
201339
201580
  const downloadProjectButton = {
201340
201581
  type: "element",
201341
201582
  tagName: "button",
201342
201583
  properties: {
201343
- class: "download-project"
201584
+ class: "download-project",
201585
+ title: i18n.get("typst-download-project"),
201586
+ "aria-label": i18n.get("typst-download-project")
201344
201587
  },
201345
- children: [
201346
- {
201347
- type: "text",
201348
- value: i18n.get("typst-download-project")
201349
- }
201350
- ]
201588
+ children: [icon("archive")]
201351
201589
  };
201352
201590
  const createFullscreenButton = () => ({
201353
201591
  type: "element",
@@ -201357,12 +201595,7 @@ var remarkDirectiveTypst_default = (ctx) => () => {
201357
201595
  title: i18n.get("ide-fullscreen-enter"),
201358
201596
  "aria-label": i18n.get("ide-fullscreen-enter")
201359
201597
  },
201360
- children: [
201361
- {
201362
- type: "text",
201363
- value: "\u26F6"
201364
- }
201365
- ]
201598
+ children: [icon("fullscreen")]
201366
201599
  });
201367
201600
  if (isEditMode) {
201368
201601
  data.hChildren = [
@@ -201406,12 +201639,7 @@ var remarkDirectiveTypst_default = (ctx) => () => {
201406
201639
  class: "add-source-file",
201407
201640
  title: i18n.get("typst-add-source-file")
201408
201641
  },
201409
- children: [
201410
- {
201411
- type: "text",
201412
- value: "+"
201413
- }
201414
- ]
201642
+ children: [icon("plus")]
201415
201643
  }
201416
201644
  ]
201417
201645
  },
@@ -201440,12 +201668,7 @@ var remarkDirectiveTypst_default = (ctx) => () => {
201440
201668
  properties: {
201441
201669
  class: "summary-indicator"
201442
201670
  },
201443
- children: [
201444
- {
201445
- type: "text",
201446
- value: "\u25B6"
201447
- }
201448
- ]
201671
+ children: [icon("chevron")]
201449
201672
  },
201450
201673
  {
201451
201674
  type: "text",
@@ -201513,14 +201736,11 @@ var remarkDirectiveTypst_default = (ctx) => () => {
201513
201736
  type: "element",
201514
201737
  tagName: "button",
201515
201738
  properties: {
201516
- class: "reset"
201739
+ class: "reset",
201740
+ title: i18n.get("typst-reset"),
201741
+ "aria-label": i18n.get("typst-reset")
201517
201742
  },
201518
- children: [
201519
- {
201520
- type: "text",
201521
- value: i18n.get("typst-reset")
201522
- }
201523
- ]
201743
+ children: [icon("reset")]
201524
201744
  },
201525
201745
  downloadProjectButton,
201526
201746
  downloadButton,
@@ -201571,7 +201791,12 @@ var remarkDirectiveOpenscad_default = (ctx) => () => {
201571
201791
  return (tree, file) => {
201572
201792
  visit(tree, function(node3) {
201573
201793
  if (isDirective(node3) && node3.name === name) {
201574
- const { src = "", id = hash(node3), height, library } = node3.attributes || {};
201794
+ const {
201795
+ src = "",
201796
+ id = hash(node3),
201797
+ height,
201798
+ library
201799
+ } = node3.attributes || {};
201575
201800
  const data = node3.data || (node3.data = {});
201576
201801
  const binaryFiles = [];
201577
201802
  for (const child of node3.children) {
@@ -201590,7 +201815,9 @@ var remarkDirectiveOpenscad_default = (ctx) => () => {
201590
201815
  text9 = child.children.map(reconstructText).join("");
201591
201816
  }
201592
201817
  if (!text9) continue;
201593
- const fileMatches = text9.matchAll(/@file\s+dest="([^"]+)"\s+src="([^"]+)"/g);
201818
+ const fileMatches = text9.matchAll(
201819
+ /@file\s+dest="([^"]+)"\s+src="([^"]+)"/g
201820
+ );
201594
201821
  for (const match of fileMatches) {
201595
201822
  const dest = match[1];
201596
201823
  const src2 = match[2];
@@ -201640,7 +201867,9 @@ var remarkDirectiveOpenscad_default = (ctx) => () => {
201640
201867
  type: "element",
201641
201868
  tagName: "div",
201642
201869
  properties: { class: "preview-header" },
201643
- children: [{ type: "text", value: i18n.get("openscad-preview") }]
201870
+ children: [
201871
+ { type: "text", value: i18n.get("openscad-preview") }
201872
+ ]
201644
201873
  },
201645
201874
  {
201646
201875
  type: "element",
@@ -201682,7 +201911,9 @@ var remarkDirectiveOpenscad_default = (ctx) => () => {
201682
201911
  type: "element",
201683
201912
  tagName: "div",
201684
201913
  properties: { class: "parameters-header" },
201685
- children: [{ type: "text", value: i18n.get("openscad-parameters") }]
201914
+ children: [
201915
+ { type: "text", value: i18n.get("openscad-parameters") }
201916
+ ]
201686
201917
  },
201687
201918
  {
201688
201919
  type: "element",
@@ -201718,7 +201949,9 @@ var remarkDirectiveOpenscad_default = (ctx) => () => {
201718
201949
  type: "element",
201719
201950
  tagName: "button",
201720
201951
  properties: { class: "render" },
201721
- children: [{ type: "text", value: i18n.get("openscad-render") }]
201952
+ children: [
201953
+ { type: "text", value: i18n.get("openscad-render") }
201954
+ ]
201722
201955
  }
201723
201956
  ]
201724
201957
  },
@@ -201747,12 +201980,7 @@ var remarkDirectiveOpenscad_default = (ctx) => () => {
201747
201980
  properties: {
201748
201981
  class: "summary-indicator"
201749
201982
  },
201750
- children: [
201751
- {
201752
- type: "text",
201753
- value: "\u25B6"
201754
- }
201755
- ]
201983
+ children: [icon("chevron")]
201756
201984
  },
201757
201985
  {
201758
201986
  type: "text",
@@ -201821,20 +202049,32 @@ var remarkDirectiveOpenscad_default = (ctx) => () => {
201821
202049
  {
201822
202050
  type: "element",
201823
202051
  tagName: "button",
201824
- properties: { class: "copy" },
201825
- children: [{ type: "text", value: i18n.get("openscad-copy") }]
202052
+ properties: {
202053
+ class: "copy",
202054
+ title: i18n.get("openscad-copy"),
202055
+ "aria-label": i18n.get("openscad-copy")
202056
+ },
202057
+ children: [icon("copy")]
201826
202058
  },
201827
202059
  {
201828
202060
  type: "element",
201829
202061
  tagName: "button",
201830
- properties: { class: "download-stl" },
201831
- children: [{ type: "text", value: i18n.get("openscad-download-stl") }]
202062
+ properties: {
202063
+ class: "download-stl",
202064
+ title: i18n.get("openscad-download-stl"),
202065
+ "aria-label": i18n.get("openscad-download-stl")
202066
+ },
202067
+ children: [icon("download")]
201832
202068
  },
201833
202069
  {
201834
202070
  type: "element",
201835
202071
  tagName: "button",
201836
- properties: { class: "reset" },
201837
- children: [{ type: "text", value: i18n.get("openscad-reset") }]
202072
+ properties: {
202073
+ class: "reset",
202074
+ title: i18n.get("openscad-reset"),
202075
+ "aria-label": i18n.get("openscad-reset")
202076
+ },
202077
+ children: [icon("reset")]
201838
202078
  },
201839
202079
  {
201840
202080
  type: "element",
@@ -201844,7 +202084,7 @@ var remarkDirectiveOpenscad_default = (ctx) => () => {
201844
202084
  title: i18n.get("ide-fullscreen-enter"),
201845
202085
  "aria-label": i18n.get("ide-fullscreen-enter")
201846
202086
  },
201847
- children: [{ type: "text", value: "\u26F6" }]
202087
+ children: [icon("fullscreen")]
201848
202088
  }
201849
202089
  ]
201850
202090
  }
@@ -202298,7 +202538,7 @@ module.exports = /*#__PURE__*/JSON.parse('{"application/1d-interleaved-parityfec
202298
202538
  /***/ ((module) => {
202299
202539
 
202300
202540
  "use strict";
202301
- module.exports = /*#__PURE__*/JSON.parse('{"name":"hyperbook","version":"0.99.0","author":"Mike Barkmin","homepage":"https://github.com/openpatch/hyperbook#readme","license":"MIT","bin":{"hyperbook":"./dist/index.js"},"files":["dist"],"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/openpatch/hyperbook.git","directory":"packages/hyperbook"},"bugs":{"url":"https://github.com/openpatch/hyperbook/issues"},"engines":{"node":">=18"},"scripts":{"version":"pnpm build","lint":"tsc --noEmit","dev":"ncc build ./index.ts -w -o dist/","build":"rimraf dist && ncc build ./index.ts -o ./dist/ --no-cache --no-source-map-register --external favicons --external sharp && node postbuild.mjs"},"dependencies":{"favicons":"^7.2.0"},"devDependencies":{"create-hyperbook":"workspace:*","@hyperbook/fs":"workspace:*","@hyperbook/markdown":"workspace:*","@hyperbook/types":"workspace:*","@pnpm/exportable-manifest":"1000.0.6","@types/archiver":"6.0.3","@types/async-retry":"1.4.9","@types/cross-spawn":"6.0.6","@types/lunr":"^2.3.7","@types/prompts":"2.4.9","@types/tar":"6.1.13","@types/ws":"^8.5.14","@vercel/ncc":"0.38.3","archiver":"7.0.1","async-retry":"1.3.3","chalk":"5.4.1","chokidar":"4.0.3","commander":"12.1.0","cpy":"11.1.0","cross-spawn":"7.0.6","domutils":"^3.2.2","extract-zip":"^2.0.1","got":"12.6.0","htmlparser2":"^10.0.0","lunr":"^2.3.9","lunr-languages":"^1.14.0","mime":"^4.0.6","prompts":"2.4.2","rimraf":"6.0.1","tar":"7.4.3","update-check":"1.5.4","ws":"^8.18.0"}}');
202541
+ module.exports = /*#__PURE__*/JSON.parse('{"name":"hyperbook","version":"0.100.0","author":"Mike Barkmin","homepage":"https://github.com/openpatch/hyperbook#readme","license":"MIT","bin":{"hyperbook":"./dist/index.js"},"files":["dist"],"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/openpatch/hyperbook.git","directory":"packages/hyperbook"},"bugs":{"url":"https://github.com/openpatch/hyperbook/issues"},"engines":{"node":">=18"},"scripts":{"version":"pnpm build","lint":"tsc --noEmit","test":"vitest","dev":"ncc build ./index.ts -w -o dist/","build":"rimraf dist && ncc build ./index.ts -o ./dist/ --no-cache --no-source-map-register --external favicons --external sharp && node postbuild.mjs"},"dependencies":{"favicons":"^7.2.0"},"devDependencies":{"@hyperbook/fs":"workspace:*","@hyperbook/markdown":"workspace:*","@hyperbook/types":"workspace:*","@pnpm/exportable-manifest":"1000.0.6","@types/archiver":"6.0.3","@types/async-retry":"1.4.9","@types/cross-spawn":"6.0.6","@types/lunr":"^2.3.7","@types/prompts":"2.4.9","@types/tar":"6.1.13","@types/ws":"^8.5.14","@vercel/ncc":"0.38.3","archiver":"7.0.1","async-retry":"1.3.3","chalk":"5.4.1","chokidar":"4.0.3","commander":"12.1.0","cpy":"11.1.0","create-hyperbook":"workspace:*","cross-spawn":"7.0.6","domutils":"^3.2.2","extract-zip":"^2.0.1","got":"12.6.0","htmlparser2":"^10.0.0","lunr":"^2.3.9","lunr-languages":"^1.14.0","mime":"^4.0.6","prompts":"2.4.2","rimraf":"6.0.1","tar":"7.4.3","update-check":"1.5.4","vitest":"^4.0.18","ws":"^8.18.0"}}');
202302
202542
 
202303
202543
  /***/ })
202304
202544