@ng-doc/builder 22.1.0 → 22.2.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 (32) hide show
  1. package/LICENSE +21 -0
  2. package/generator/bootstrap/bin.js +150 -107
  3. package/generator/bootstrap/cli.js +150 -107
  4. package/generator/bootstrap/index.js +125 -99
  5. package/generator/bootstrap/process-tree.d.ts +5 -4
  6. package/generator/build-metafile.json +177 -78
  7. package/generator/build-provenance.json +3 -3
  8. package/generator/compiler/index.js +689 -484
  9. package/generator/content/html-worker.js +8 -0
  10. package/generator/contracts.d.ts +20 -2
  11. package/generator/kernel/flags.d.ts +3 -0
  12. package/generator/outputs/index.d.ts +22 -6
  13. package/generator/templates/demo-routes.ts.nunj +21 -1
  14. package/generator/templates/page.ts.nunj +5 -1
  15. package/generator/vite/angular/analog-provenance.json +1 -1
  16. package/generator/vite/angular-composition.d.ts +25 -1
  17. package/generator/vite/content-updates.d.ts +62 -0
  18. package/generator/vite/host-updates.d.ts +85 -5
  19. package/generator/vite/index.js +621 -243
  20. package/generator/vite/lifecycle.d.ts +39 -2
  21. package/helpers/playground/get-playground-inputs.js +6 -3
  22. package/helpers/playground/get-playground-inputs.js.map +1 -1
  23. package/helpers/playground/playground-options.d.ts +28 -0
  24. package/helpers/playground/playground-options.js +122 -0
  25. package/helpers/playground/playground-options.js.map +1 -0
  26. package/helpers/playground/written-union-order.d.ts +33 -0
  27. package/helpers/playground/written-union-order.js +106 -0
  28. package/helpers/playground/written-union-order.js.map +1 -0
  29. package/interfaces/configuration.d.ts +11 -3
  30. package/package.json +4 -4
  31. package/templates/demo-routes.ts.nunj +21 -1
  32. package/templates/page.ts.nunj +5 -1
@@ -1,5 +1,5 @@
1
1
  // libs/builder/generator/vite/plugin.ts
2
- import path20 from "node:path";
2
+ import path21 from "node:path";
3
3
 
4
4
  // libs/builder/generator/artifacts/index.ts
5
5
  import { randomUUID } from "node:crypto";
@@ -49,24 +49,24 @@ function sha256Hex(value) {
49
49
  function canonicalJson(value) {
50
50
  return canonical(value, /* @__PURE__ */ new Set()) ?? "null";
51
51
  }
52
- function canonical(value, path25) {
52
+ function canonical(value, path26) {
53
53
  if (value !== null && typeof value === "object" && typeof value.toJSON === "function")
54
54
  value = value.toJSON();
55
55
  if (value === null || typeof value !== "object") return JSON.stringify(value);
56
- if (path25.has(value)) throw new TypeError("Converting circular structure to canonical JSON");
57
- path25.add(value);
56
+ if (path26.has(value)) throw new TypeError("Converting circular structure to canonical JSON");
57
+ path26.add(value);
58
58
  let text5;
59
59
  if (Array.isArray(value)) {
60
- text5 = `[${Array.from(value, (item) => canonical(item, path25) ?? "null").join(",")}]`;
60
+ text5 = `[${Array.from(value, (item) => canonical(item, path26) ?? "null").join(",")}]`;
61
61
  } else {
62
62
  const fields = [];
63
63
  for (const key of Object.keys(value).sort(compareCodeUnits)) {
64
- const item = canonical(value[key], path25);
64
+ const item = canonical(value[key], path26);
65
65
  if (item !== void 0) fields.push(`${JSON.stringify(key)}:${item}`);
66
66
  }
67
67
  text5 = `{${fields.join(",")}}`;
68
68
  }
69
- path25.delete(value);
69
+ path26.delete(value);
70
70
  return text5;
71
71
  }
72
72
  function digestOf(value) {
@@ -1608,7 +1608,7 @@ function normalizeRelative(value) {
1608
1608
  return normalized;
1609
1609
  }
1610
1610
  function trustedBase(last, request) {
1611
- const published = (manifest) => isRecord(manifest) && manifest.projectId === last.projectId && manifest.revision === last.revision && manifest.generation === last.generation;
1611
+ const published = (manifest) => isRecord(manifest) && manifest["projectId"] === last.projectId && manifest["revision"] === last.revision && manifest["generation"] === last.generation;
1612
1612
  const base = request.base;
1613
1613
  return isRecord(base) && published(base.manifest) && published(request.previous) && isRecord(base.snapshot) && base.snapshot.projectId === last.projectId && base.snapshot.revision === last.revision;
1614
1614
  }
@@ -1622,17 +1622,17 @@ function sameManifestStamp(left, right) {
1622
1622
  return left.dev === right.dev && left.ino === right.ino && left.size === right.size && left.mtimeNs === right.mtimeNs && left.ctimeNs === right.ctimeNs;
1623
1623
  }
1624
1624
  function configurationDigest(candidate) {
1625
- return isRecord(candidate) && isRecord(candidate.configuration) ? candidate.configuration.digest : void 0;
1625
+ return isRecord(candidate) && isRecord(candidate["configuration"]) ? candidate["configuration"]["digest"] : void 0;
1626
1626
  }
1627
1627
  function unchangedArtifact(artifact, last) {
1628
- const id = artifact.id;
1629
- const outputs = artifact.outputs;
1630
- if (!string(artifact.revision) || last.revisions.get(id) !== artifact.revision || !Array.isArray(outputs) || outputs.length !== (last.counts.get(id) ?? 0))
1628
+ const id = artifact["id"];
1629
+ const outputs = artifact["outputs"];
1630
+ if (!string(artifact["revision"]) || last.revisions.get(id) !== artifact["revision"] || !Array.isArray(outputs) || outputs.length !== (last.counts.get(id) ?? 0))
1631
1631
  return false;
1632
1632
  return outputs.every((output) => {
1633
- if (!isRecord(output) || !string(output.path)) return false;
1634
- const entry = last.files.get(output.path);
1635
- return entry?.ownerId === id && entry.digest === output.digest && entry.role === output.role;
1633
+ if (!isRecord(output) || !string(output["path"])) return false;
1634
+ const entry = last.files.get(output["path"]);
1635
+ return entry?.ownerId === id && entry.digest === output["digest"] && entry.role === output["role"];
1636
1636
  });
1637
1637
  }
1638
1638
  var EMPTY_SCOPE_FACTS = canonicalJson({ definitions: [], references: [] });
@@ -1815,7 +1815,7 @@ function stringArray(value) {
1815
1815
  function isIdentity(value) {
1816
1816
  if (!isRecord(value) || !exact(value, ["projectId", "entryId", "role"], ["declarationId", "part"]))
1817
1817
  return false;
1818
- return string(value.projectId) && string(value.entryId) && [
1818
+ return string(value["projectId"]) && string(value["entryId"]) && [
1819
1819
  "page-shell",
1820
1820
  "content",
1821
1821
  "demo-assets",
@@ -1823,7 +1823,7 @@ function isIdentity(value) {
1823
1823
  "category",
1824
1824
  "api-list",
1825
1825
  "aggregate"
1826
- ].includes(String(value.role)) && (value.declarationId === void 0 || string(value.declarationId)) && (value.part === void 0 || string(value.part));
1826
+ ].includes(String(value["role"])) && (value["declarationId"] === void 0 || string(value["declarationId"])) && (value["part"] === void 0 || string(value["part"]));
1827
1827
  }
1828
1828
  function isFingerprint(value) {
1829
1829
  return isRecord(value) && exact(value, [
@@ -1833,40 +1833,40 @@ function isFingerprint(value) {
1833
1833
  "configurationDigest",
1834
1834
  "inputDigest",
1835
1835
  "keywordDigest"
1836
- ]) && value.schemaVersion === SCHEMA_VERSION && [
1837
- value.compilerVersion,
1838
- value.toolchainDigest,
1839
- value.configurationDigest,
1840
- value.inputDigest,
1841
- value.keywordDigest
1836
+ ]) && value["schemaVersion"] === SCHEMA_VERSION && [
1837
+ value["compilerVersion"],
1838
+ value["toolchainDigest"],
1839
+ value["configurationDigest"],
1840
+ value["inputDigest"],
1841
+ value["keywordDigest"]
1842
1842
  ].every(string);
1843
1843
  }
1844
1844
  function isDependency(value) {
1845
- if (!isRecord(value) || !string(value.kind)) return false;
1846
- if (value.kind === "content")
1847
- return exact(value, ["kind", "path", "digest"]) && string(value.path) && string(value.digest);
1848
- if (value.kind === "existence")
1849
- return exact(value, ["kind", "path", "exists"]) && string(value.path) && typeof value.exists === "boolean";
1850
- if (value.kind === "glob")
1851
- return exact(value, ["kind", "root", "include", "exclude", "members"]) && string(value.root) && stringArray(value.include) && stringArray(value.exclude) && stringArray(value.members);
1852
- if (value.kind === "semantic")
1853
- return exact(value, ["kind", "scopeId", "digest", "files", "reason"]) && string(value.scopeId) && string(value.digest) && stringArray(value.files) && string(value.reason);
1854
- if (value.kind === "semantic-reference")
1855
- return exact(value, ["kind", "scopeId", "digest", "reason"]) && string(value.scopeId) && string(value.digest) && string(value.reason);
1856
- if (value.kind === "semantic-closure")
1857
- return exact(value, ["kind", "scopeId", "key", "digest"]) && string(value.scopeId) && string(value.key) && string(value.digest);
1858
- if (value.kind === "evaluated")
1859
- return exact(value, ["kind", "entryId", "digest"]) && string(value.entryId) && string(value.digest);
1860
- return value.kind === "keyword" && exact(value, ["kind", "key", "digest"]) && string(value.key) && string(value.digest);
1845
+ if (!isRecord(value) || !string(value["kind"])) return false;
1846
+ if (value["kind"] === "content")
1847
+ return exact(value, ["kind", "path", "digest"]) && string(value["path"]) && string(value["digest"]);
1848
+ if (value["kind"] === "existence")
1849
+ return exact(value, ["kind", "path", "exists"]) && string(value["path"]) && typeof value["exists"] === "boolean";
1850
+ if (value["kind"] === "glob")
1851
+ return exact(value, ["kind", "root", "include", "exclude", "members"]) && string(value["root"]) && stringArray(value["include"]) && stringArray(value["exclude"]) && stringArray(value["members"]);
1852
+ if (value["kind"] === "semantic")
1853
+ return exact(value, ["kind", "scopeId", "digest", "files", "reason"]) && string(value["scopeId"]) && string(value["digest"]) && stringArray(value["files"]) && string(value["reason"]);
1854
+ if (value["kind"] === "semantic-reference")
1855
+ return exact(value, ["kind", "scopeId", "digest", "reason"]) && string(value["scopeId"]) && string(value["digest"]) && string(value["reason"]);
1856
+ if (value["kind"] === "semantic-closure")
1857
+ return exact(value, ["kind", "scopeId", "key", "digest"]) && string(value["scopeId"]) && string(value["key"]) && string(value["digest"]);
1858
+ if (value["kind"] === "evaluated")
1859
+ return exact(value, ["kind", "entryId", "digest"]) && string(value["entryId"]) && string(value["digest"]);
1860
+ return value["kind"] === "keyword" && exact(value, ["kind", "key", "digest"]) && string(value["key"]) && string(value["digest"]);
1861
1861
  }
1862
1862
  function isKeyword(value) {
1863
- return isRecord(value) && exact(value, ["key", "title", "path"], ["type", "languages", "description"]) && string(value.key) && string(value.title) && string(value.path) && (value.type === void 0 || value.type === "link") && (value.languages === void 0 || stringArray(value.languages)) && [value.description, value.signature].every((item) => item === void 0 || string(item));
1863
+ return isRecord(value) && exact(value, ["key", "title", "path"], ["type", "languages", "description"]) && string(value["key"]) && string(value["title"]) && string(value["path"]) && (value["type"] === void 0 || value["type"] === "link") && (value["languages"] === void 0 || stringArray(value["languages"])) && [value["description"], value["signature"]].every((item) => item === void 0 || string(item));
1864
1864
  }
1865
1865
  function isSource(value) {
1866
- return isRecord(value) && exact(value, ["path"], ["line", "column"]) && string(value.path) && (value.line === void 0 || finite(value.line)) && (value.column === void 0 || finite(value.column));
1866
+ return isRecord(value) && exact(value, ["path"], ["line", "column"]) && string(value["path"]) && (value["line"] === void 0 || finite(value["line"])) && (value["column"] === void 0 || finite(value["column"]));
1867
1867
  }
1868
1868
  function isDiagnostic(value) {
1869
- return isRecord(value) && exact(value, ["code", "severity", "message", "stage"], ["source", "ownerId", "related"]) && string(value.code) && ["error", "warning", "info"].includes(String(value.severity)) && string(value.message) && [
1869
+ return isRecord(value) && exact(value, ["code", "severity", "message", "stage"], ["source", "ownerId", "related"]) && string(value["code"]) && ["error", "warning", "info"].includes(String(value["severity"])) && string(value["message"]) && [
1870
1870
  "discovery",
1871
1871
  "evaluation",
1872
1872
  "semantic",
@@ -1875,8 +1875,8 @@ function isDiagnostic(value) {
1875
1875
  "cache",
1876
1876
  "commit",
1877
1877
  "host"
1878
- ].includes(String(value.stage)) && (value.source === void 0 || isSource(value.source)) && (value.ownerId === void 0 || string(value.ownerId)) && (value.related === void 0 || Array.isArray(value.related) && value.related.every(
1879
- (item) => isRecord(item) && exact(item, ["message", "source"]) && string(item.message) && isSource(item.source)
1878
+ ].includes(String(value["stage"])) && (value["source"] === void 0 || isSource(value["source"])) && (value["ownerId"] === void 0 || string(value["ownerId"])) && (value["related"] === void 0 || Array.isArray(value["related"]) && value["related"].every(
1879
+ (item) => isRecord(item) && exact(item, ["message", "source"]) && string(item["message"]) && isSource(item["source"])
1880
1880
  ));
1881
1881
  }
1882
1882
  function isSearch(value) {
@@ -1884,17 +1884,17 @@ function isSearch(value) {
1884
1884
  value,
1885
1885
  ["breadcrumbs", "pageType", "title", "section", "route", "content"],
1886
1886
  ["fragment", "kind", "signature", "description"]
1887
- ) && stringArray(value.breadcrumbs) && ["guide", "api"].includes(String(value.pageType)) && [value.title, value.section, value.route, value.content].every(string) && [value.fragment, value.kind, value.signature, value.description].every(
1887
+ ) && stringArray(value["breadcrumbs"]) && ["guide", "api"].includes(String(value["pageType"])) && [value["title"], value["section"], value["route"], value["content"]].every(string) && [value["fragment"], value["kind"], value["signature"], value["description"]].every(
1888
1888
  (item) => item === void 0 || string(item)
1889
1889
  );
1890
1890
  }
1891
1891
  function isAnchor(value) {
1892
- return isRecord(value) && exact(value, ["anchorId", "anchor", "title", "type"], ["scope"]) && [value.anchorId, value.anchor, value.title].every(string) && ["heading", "member"].includes(String(value.type)) && (value.scope === void 0 || isRecord(value.scope) && exact(value.scope, ["key", "title"]) && string(value.scope.key) && string(value.scope.title));
1892
+ return isRecord(value) && exact(value, ["anchorId", "anchor", "title", "type"], ["scope"]) && [value["anchorId"], value["anchor"], value["title"]].every(string) && ["heading", "member"].includes(String(value["type"])) && (value["scope"] === void 0 || isRecord(value["scope"]) && exact(value["scope"], ["key", "title"]) && string(value["scope"]["key"]) && string(value["scope"]["title"]));
1893
1893
  }
1894
1894
  function isLinkedContent(value) {
1895
- if (!isRecord(value) || !exact(value, ["ir", "html", "searchRecords", "keywordDigest"]) || !string(value.html) || !string(value.keywordDigest) || !Array.isArray(value.searchRecords) || !value.searchRecords.every(isSearch) || !isRecord(value.ir))
1895
+ if (!isRecord(value) || !exact(value, ["ir", "html", "searchRecords", "keywordDigest"]) || !string(value["html"]) || !string(value["keywordDigest"]) || !Array.isArray(value["searchRecords"]) || !value["searchRecords"].every(isSearch) || !isRecord(value["ir"]))
1896
1896
  return false;
1897
- const ir = value.ir;
1897
+ const ir = value["ir"];
1898
1898
  return exact(
1899
1899
  ir,
1900
1900
  [
@@ -1913,7 +1913,9 @@ function isLinkedContent(value) {
1913
1913
  "diagnostics"
1914
1914
  ],
1915
1915
  ["icon", "searchBreadcrumbs"]
1916
- ) && ir.schemaVersion === SCHEMA_VERSION && [ir.id, ir.entryId, ir.title, ir.route, ir.absoluteRoute, ir.html].every(string) && ["guide-tab", "api-tab", "header", "demo-assets"].includes(String(ir.role)) && (ir.searchBreadcrumbs === void 0 || stringArray(ir.searchBreadcrumbs)) && (ir.icon === void 0 || string(ir.icon)) && Array.isArray(ir.anchors) && ir.anchors.every(isAnchor) && Array.isArray(ir.exportedKeywords) && ir.exportedKeywords.every(isKeyword) && stringArray(ir.usedKeywords) && Array.isArray(ir.dependencies) && ir.dependencies.every(isDependency) && Array.isArray(ir.diagnostics) && ir.diagnostics.every(isDiagnostic);
1916
+ ) && ir["schemaVersion"] === SCHEMA_VERSION && [ir["id"], ir["entryId"], ir["title"], ir["route"], ir["absoluteRoute"], ir["html"]].every(
1917
+ string
1918
+ ) && ["guide-tab", "api-tab", "header", "demo-assets"].includes(String(ir["role"])) && (ir["searchBreadcrumbs"] === void 0 || stringArray(ir["searchBreadcrumbs"])) && (ir["icon"] === void 0 || string(ir["icon"])) && Array.isArray(ir["anchors"]) && ir["anchors"].every(isAnchor) && Array.isArray(ir["exportedKeywords"]) && ir["exportedKeywords"].every(isKeyword) && stringArray(ir["usedKeywords"]) && Array.isArray(ir["dependencies"]) && ir["dependencies"].every(isDependency) && Array.isArray(ir["diagnostics"]) && ir["diagnostics"].every(isDiagnostic);
1917
1919
  }
1918
1920
  function isRoute(value) {
1919
1921
  return isRecord(value) && exact(
@@ -1929,23 +1931,29 @@ function isRoute(value) {
1929
1931
  "modulePath",
1930
1932
  "apiListSegment",
1931
1933
  "demoModulePath",
1932
- "demoNames"
1934
+ "demoNames",
1935
+ "playgroundPages"
1933
1936
  ]
1934
- ) && [value.id, value.path, value.title].every(string) && (value.parentId === void 0 || string(value.parentId)) && (value.order === void 0 || finite(value.order)) && (value.hidden === void 0 || typeof value.hidden === "boolean") && (value.icon === void 0 || string(value.icon)) && (value.modulePath === void 0 || string(value.modulePath)) && (value.apiListSegment === void 0 || string(value.apiListSegment)) && (value.demoModulePath === void 0 || string(value.demoModulePath)) && (value.demoNames === void 0 || stringArray(value.demoNames)) && (value.metadata === void 0 || isRecord(value.metadata) && exact(value.metadata, ["description", "tags"]) && string(value.metadata.description) && isRecord(value.metadata.tags) && Object.values(value.metadata.tags).every(stringArray)) && (value.category === void 0 || isRecord(value.category) && exact(value.category, ["runtimeImport"], ["expandable", "expanded"]) && isRecord(value.category.runtimeImport) && exact(value.category.runtimeImport, ["source", "exportName"]) && string(value.category.runtimeImport.source) && string(value.category.runtimeImport.exportName) && (value.category.expandable === void 0 || typeof value.category.expandable === "boolean") && (value.category.expanded === void 0 || typeof value.category.expanded === "boolean"));
1937
+ ) && [value["id"], value["path"], value["title"]].every(string) && (value["parentId"] === void 0 || string(value["parentId"])) && (value["order"] === void 0 || finite(value["order"])) && (value["hidden"] === void 0 || typeof value["hidden"] === "boolean") && (value["icon"] === void 0 || string(value["icon"])) && (value["modulePath"] === void 0 || string(value["modulePath"])) && (value["apiListSegment"] === void 0 || string(value["apiListSegment"])) && (value["demoModulePath"] === void 0 || string(value["demoModulePath"])) && (value["demoNames"] === void 0 || stringArray(value["demoNames"])) && (value["playgroundPages"] === void 0 || stringArray(value["playgroundPages"])) && (value["metadata"] === void 0 || isRecord(value["metadata"]) && exact(value["metadata"], ["description", "tags"]) && string(value["metadata"]["description"]) && isRecord(value["metadata"]["tags"]) && Object.values(value["metadata"]["tags"]).every(stringArray)) && (value["category"] === void 0 || isRecord(value["category"]) && exact(value["category"], ["runtimeImport"], ["expandable", "expanded"]) && isRecord(value["category"]["runtimeImport"]) && exact(value["category"]["runtimeImport"], ["source", "exportName"]) && string(value["category"]["runtimeImport"]["source"]) && string(value["category"]["runtimeImport"]["exportName"]) && (value["category"]["expandable"] === void 0 || typeof value["category"]["expandable"] === "boolean") && (value["category"]["expanded"] === void 0 || typeof value["category"]["expanded"] === "boolean"));
1935
1938
  }
1936
1939
  function isApiList(value) {
1937
1940
  return isRecord(value) && exact(
1938
1941
  value,
1939
1942
  ["apiEntryId", "scopeId", "scopeTitle", "name", "type", "route"],
1940
1943
  ["description", "signature"]
1941
- ) && [value.apiEntryId, value.scopeId, value.scopeTitle, value.name, value.type, value.route].every(
1942
- string
1943
- ) && [value.description, value.signature].every((item) => item === void 0 || string(item));
1944
+ ) && [
1945
+ value["apiEntryId"],
1946
+ value["scopeId"],
1947
+ value["scopeTitle"],
1948
+ value["name"],
1949
+ value["type"],
1950
+ value["route"]
1951
+ ].every(string) && [value["description"], value["signature"]].every((item) => item === void 0 || string(item));
1944
1952
  }
1945
1953
  function isFileOutput(value) {
1946
- return isRecord(value) && exact(value, ["path", "role", "encoding", "content", "digest"]) && string(value.path) && ["angular", "content", "asset", "routes", "context", "search", "api-list"].includes(
1947
- String(value.role)
1948
- ) && ["utf8", "base64"].includes(String(value.encoding)) && string(value.content) && string(value.digest);
1954
+ return isRecord(value) && exact(value, ["path", "role", "encoding", "content", "digest"]) && string(value["path"]) && ["angular", "content", "asset", "routes", "context", "search", "api-list"].includes(
1955
+ String(value["role"])
1956
+ ) && ["utf8", "base64"].includes(String(value["encoding"])) && string(value["content"]) && string(value["digest"]);
1949
1957
  }
1950
1958
  function isContentDescriptor(value) {
1951
1959
  if (!isRecord(value) || !exact(
@@ -1969,23 +1977,23 @@ function isContentDescriptor(value) {
1969
1977
  ["icon", "keyword"]
1970
1978
  ))
1971
1979
  return false;
1972
- if (value.schemaVersion !== SCHEMA_VERSION || ![
1973
- value.id,
1974
- value.ownerId,
1975
- value.title,
1976
- value.route,
1977
- value.absoluteRoute,
1978
- value.inputDigest,
1979
- value.requestDigest
1980
- ].every(string) || ![value.id, value.ownerId, value.inputDigest, value.requestDigest].every(
1980
+ if (value["schemaVersion"] !== SCHEMA_VERSION || ![
1981
+ value["id"],
1982
+ value["ownerId"],
1983
+ value["title"],
1984
+ value["route"],
1985
+ value["absoluteRoute"],
1986
+ value["inputDigest"],
1987
+ value["requestDigest"]
1988
+ ].every(string) || ![value["id"], value["ownerId"], value["inputDigest"], value["requestDigest"]].every(
1981
1989
  (item) => string(item) && item.length > 0 && !item.includes("\0")
1982
- ) || !finite(value.ordinal) || value.ordinal < 0 || !Number.isInteger(value.ordinal) || !["guide-tab", "api-tab", "header"].includes(String(value.role)) || !stringArray(value.searchBreadcrumbs) || !Array.isArray(value.dependencies) || !value.dependencies.every((dependency) => isPhysicalDescriptorDependency(dependency)) || new Set(value.dependencies.map((dependency) => canonicalJson(dependency))).size !== value.dependencies.length || !stringArray(value.closureIds) || value.icon !== void 0 && !string(value.icon) || value.keyword !== void 0 && !string(value.keyword) || !isRecord(value.locator))
1990
+ ) || !finite(value["ordinal"]) || value["ordinal"] < 0 || !Number.isInteger(value["ordinal"]) || !["guide-tab", "api-tab", "header"].includes(String(value["role"])) || !stringArray(value["searchBreadcrumbs"]) || !Array.isArray(value["dependencies"]) || !value["dependencies"].every((dependency) => isPhysicalDescriptorDependency(dependency)) || new Set(value["dependencies"].map((dependency) => canonicalJson(dependency))).size !== value["dependencies"].length || !stringArray(value["closureIds"]) || value["icon"] !== void 0 && !string(value["icon"]) || value["keyword"] !== void 0 && !string(value["keyword"]) || !isRecord(value["locator"]))
1983
1991
  return false;
1984
- const locator = value.locator;
1985
- return value.role === "header" ? exact(locator, ["kind"]) && locator.kind === "header" : value.role === "guide-tab" ? exact(locator, ["kind", "markdown"]) && locator.kind === "guide-tab" && string(locator.markdown) : exact(locator, ["kind", "declarationId"]) && locator.kind === "api-tab" && string(locator.declarationId);
1992
+ const locator = value["locator"];
1993
+ return value["role"] === "header" ? exact(locator, ["kind"]) && locator["kind"] === "header" : value["role"] === "guide-tab" ? exact(locator, ["kind", "markdown"]) && locator["kind"] === "guide-tab" && string(locator["markdown"]) : exact(locator, ["kind", "declarationId"]) && locator["kind"] === "api-tab" && string(locator["declarationId"]);
1986
1994
  }
1987
1995
  function isPhysicalDescriptorDependency(value) {
1988
- return isRecord(value) && (value.kind === "content" && exact(value, ["kind", "path", "digest"]) && absoluteNormalizedPath(value.path) && string(value.digest) || value.kind === "existence" && exact(value, ["kind", "path", "exists"]) && absoluteNormalizedPath(value.path) && typeof value.exists === "boolean");
1996
+ return isRecord(value) && (value["kind"] === "content" && exact(value, ["kind", "path", "digest"]) && absoluteNormalizedPath(value["path"]) && string(value["digest"]) || value["kind"] === "existence" && exact(value, ["kind", "path", "exists"]) && absoluteNormalizedPath(value["path"]) && typeof value["exists"] === "boolean");
1989
1997
  }
1990
1998
  function validDescriptorPlan(artifact) {
1991
1999
  const descriptors = artifact.contentDescriptors;
@@ -2070,7 +2078,7 @@ function isPageArtifact(value) {
2070
2078
  "diagnostics"
2071
2079
  ],
2072
2080
  ["contentDescriptors"]
2073
- ) && string(value.id) && isIdentity(value.identity) && string(value.revision) && isFingerprint(value.fingerprint) && Array.isArray(value.dependencies) && value.dependencies.every(isDependency) && Array.isArray(value.content) && value.content.every(isLinkedContent) && Array.isArray(value.exportedKeywords) && value.exportedKeywords.every(isKeyword) && stringArray(value.usedKeywords) && Array.isArray(value.searchRecords) && value.searchRecords.every(isSearch) && Array.isArray(value.routes) && value.routes.every(isRoute) && Array.isArray(value.apiList) && value.apiList.every(isApiList) && Array.isArray(value.outputs) && value.outputs.every((output) => isFileOutput(output) && validOutputDigest(output)) && Array.isArray(value.diagnostics) && value.diagnostics.every(isDiagnostic) && validDescriptorPlan(value);
2081
+ ) && string(value["id"]) && isIdentity(value["identity"]) && string(value["revision"]) && isFingerprint(value["fingerprint"]) && Array.isArray(value["dependencies"]) && value["dependencies"].every(isDependency) && Array.isArray(value["content"]) && value["content"].every(isLinkedContent) && Array.isArray(value["exportedKeywords"]) && value["exportedKeywords"].every(isKeyword) && stringArray(value["usedKeywords"]) && Array.isArray(value["searchRecords"]) && value["searchRecords"].every(isSearch) && Array.isArray(value["routes"]) && value["routes"].every(isRoute) && Array.isArray(value["apiList"]) && value["apiList"].every(isApiList) && Array.isArray(value["outputs"]) && value["outputs"].every((output) => isFileOutput(output) && validOutputDigest(output)) && Array.isArray(value["diagnostics"]) && value["diagnostics"].every(isDiagnostic) && validDescriptorPlan(value);
2074
2082
  }
2075
2083
  function isJsonTree(value, ancestors = /* @__PURE__ */ new WeakSet()) {
2076
2084
  if (value === null || string(value) || typeof value === "boolean") return true;
@@ -2105,19 +2113,19 @@ function validOutputDigest(output) {
2105
2113
  }
2106
2114
  }
2107
2115
  function isPublishedGeneratorConfiguration(value) {
2108
- return isJsonTree(value) && isRecord(value) && exact(value, ["outputRoot", "cacheRoot", "assetDirectory", "themes", "digest"]) && [value.outputRoot, value.cacheRoot].every(
2116
+ return isJsonTree(value) && isRecord(value) && exact(value, ["outputRoot", "cacheRoot", "assetDirectory", "themes", "digest"]) && [value["outputRoot"], value["cacheRoot"]].every(
2109
2117
  (item) => string(item) && path2.isAbsolute(item) && path2.resolve(item).replace(/\\/g, "/") === item && !item.includes("\0")
2110
- ) && string(value.assetDirectory) && !path2.win32.parse(value.assetDirectory).root && safeRelative(value.assetDirectory) && isRecord(value.themes) && exact(value.themes, ["light", "dark"]) && string(value.themes.light) && string(value.themes.dark) && string(value.digest);
2118
+ ) && string(value["assetDirectory"]) && !path2.win32.parse(value["assetDirectory"]).root && safeRelative(value["assetDirectory"]) && isRecord(value["themes"]) && exact(value["themes"], ["light", "dark"]) && string(value["themes"]["light"]) && string(value["themes"]["dark"]) && string(value["digest"]);
2111
2119
  }
2112
2120
  function isArtifactSnapshotShape(value) {
2113
2121
  return isJsonTree(value) && isRecord(value) && exact(
2114
2122
  value,
2115
2123
  ["projectId", "revision", "artifacts", "globalKeywords", "remoteKeywords"],
2116
2124
  ["configuration"]
2117
- ) && (value.configuration === void 0 || isPublishedGeneratorConfiguration(value.configuration)) && string(value.projectId) && string(value.revision) && Array.isArray(value.artifacts) && value.artifacts.every(isPageArtifact) && Array.isArray(value.globalKeywords) && value.globalKeywords.every(isKeyword) && Array.isArray(value.remoteKeywords) && value.remoteKeywords.every(isRemoteKeywords);
2125
+ ) && (value["configuration"] === void 0 || isPublishedGeneratorConfiguration(value["configuration"])) && string(value["projectId"]) && string(value["revision"]) && Array.isArray(value["artifacts"]) && value["artifacts"].every(isPageArtifact) && Array.isArray(value["globalKeywords"]) && value["globalKeywords"].every(isKeyword) && Array.isArray(value["remoteKeywords"]) && value["remoteKeywords"].every(isRemoteKeywords);
2118
2126
  }
2119
2127
  function isRemoteKeywords(remote) {
2120
- return isRecord(remote) && exact(remote, ["loaderId", "digest", "keywords"], ["validator"]) && string(remote.loaderId) && string(remote.digest) && Array.isArray(remote.keywords) && remote.keywords.every(isKeyword) && (remote.validator === void 0 || string(remote.validator));
2128
+ return isRecord(remote) && exact(remote, ["loaderId", "digest", "keywords"], ["validator"]) && string(remote["loaderId"]) && string(remote["digest"]) && Array.isArray(remote["keywords"]) && remote["keywords"].every(isKeyword) && (remote["validator"] === void 0 || string(remote["validator"]));
2121
2129
  }
2122
2130
  function isSnapshotEnvelope(value) {
2123
2131
  if (!isRecord(value) || Object.getPrototypeOf(value) !== Object.prototype) return false;
@@ -2128,7 +2136,7 @@ function isSnapshotEnvelope(value) {
2128
2136
  return descriptor?.enumerable === true && "value" in descriptor;
2129
2137
  }))
2130
2138
  return false;
2131
- const artifacts = value.artifacts;
2139
+ const artifacts = value["artifacts"];
2132
2140
  if (!Array.isArray(artifacts) || Object.getPrototypeOf(artifacts) !== Array.prototype || Reflect.ownKeys(artifacts).length !== artifacts.length + 1)
2133
2141
  return false;
2134
2142
  for (let index = 0; index < artifacts.length; index += 1)
@@ -2137,14 +2145,14 @@ function isSnapshotEnvelope(value) {
2137
2145
  value,
2138
2146
  ["projectId", "revision", "artifacts", "globalKeywords", "remoteKeywords"],
2139
2147
  ["configuration"]
2140
- ) && (value.configuration === void 0 || isPublishedGeneratorConfiguration(value.configuration)) && string(value.projectId) && string(value.revision) && isJsonTree(value.globalKeywords) && Array.isArray(value.globalKeywords) && value.globalKeywords.every(isKeyword) && isJsonTree(value.remoteKeywords) && Array.isArray(value.remoteKeywords) && value.remoteKeywords.every(isRemoteKeywords);
2148
+ ) && (value["configuration"] === void 0 || isPublishedGeneratorConfiguration(value["configuration"])) && string(value["projectId"]) && string(value["revision"]) && isJsonTree(value["globalKeywords"]) && Array.isArray(value["globalKeywords"]) && value["globalKeywords"].every(isKeyword) && isJsonTree(value["remoteKeywords"]) && Array.isArray(value["remoteKeywords"]) && value["remoteKeywords"].every(isRemoteKeywords);
2141
2149
  }
2142
2150
  function isOutputManifest(value) {
2143
- return isJsonTree(value) && isRecord(value) && exact(value, ["schemaVersion", "projectId", "generation", "revision", "files"]) && value.schemaVersion === OUTPUT_SCHEMA_VERSION && string(value.projectId) && finite(value.generation) && string(value.revision) && Array.isArray(value.files) && value.files.every(
2144
- (file) => isRecord(file) && exact(file, ["path", "ownerId", "digest", "role"]) && string(file.path) && string(file.ownerId) && string(file.digest) && safeRelative(file.path) && ["angular", "content", "asset", "routes", "context", "search", "api-list"].includes(
2145
- String(file.role)
2151
+ return isJsonTree(value) && isRecord(value) && exact(value, ["schemaVersion", "projectId", "generation", "revision", "files"]) && value["schemaVersion"] === OUTPUT_SCHEMA_VERSION && string(value["projectId"]) && finite(value["generation"]) && string(value["revision"]) && Array.isArray(value["files"]) && value["files"].every(
2152
+ (file) => isRecord(file) && exact(file, ["path", "ownerId", "digest", "role"]) && string(file["path"]) && string(file["ownerId"]) && string(file["digest"]) && safeRelative(file["path"]) && ["angular", "content", "asset", "routes", "context", "search", "api-list"].includes(
2153
+ String(file["role"])
2146
2154
  )
2147
- ) && new Set(value.files.map((file) => file.path)).size === value.files.length;
2155
+ ) && new Set(value["files"].map((file) => file.path)).size === value["files"].length;
2148
2156
  }
2149
2157
  function safeRelative(value) {
2150
2158
  try {
@@ -2171,7 +2179,10 @@ var INCREMENTAL_PROGRAM_FLAG = "NGDOC_INCREMENTAL_PROGRAM";
2171
2179
  var SHAPE_CLOSURE_FLAG = "NGDOC_SHAPE_CLOSURE";
2172
2180
  var ANGULAR_SHARED_PASS_FLAG = "NGDOC_ANGULAR_SHARED_PASS";
2173
2181
  var ANGULAR_STRUCTURAL_PASS_FLAG = "NGDOC_ANGULAR_STRUCTURAL_PASS";
2182
+ var ANGULAR_DESCRIPTION_PASS_FLAG = "NGDOC_ANGULAR_DESCRIPTION_PASS";
2183
+ var VITE_CONTENT_UPDATE_FLAG = "NGDOC_VITE_CONTENT_UPDATE";
2174
2184
  var VITE_BUILD_HANDOFF_FLAG = "NGDOC_VITE_BUILD_HANDOFF";
2185
+ var VITE_MODULELESS_SETTLE_FLAG = "NGDOC_VITE_MODULELESS_SETTLE";
2175
2186
  var TRACKED_PROGRAM_REUSE_FLAG = "NGDOC_TRACKED_PROGRAM_REUSE";
2176
2187
  var FAST_START_FLAG = "NGDOC_FAST_START";
2177
2188
  var PARALLEL_WRITES_FLAG = "NGDOC_PARALLEL_WRITES";
@@ -2246,6 +2257,21 @@ var FLAGS = Object.freeze(
2246
2257
  description: "In the Vite host, the generated modules and description modules a generation creates or deletes join that generation's Angular compiler pass instead of starting a pass of their own.",
2247
2258
  verify: false
2248
2259
  },
2260
+ {
2261
+ name: ANGULAR_DESCRIPTION_PASS_FLAG,
2262
+ description: "In the Vite host, an edited description module joins the Angular compiler pass of the generation it starts, when that generation rewrites generated TypeScript modules, instead of taking a pass of its own first.",
2263
+ verify: false
2264
+ },
2265
+ {
2266
+ name: VITE_CONTENT_UPDATE_FLAG,
2267
+ description: "In the Vite host, a generation that changes only content modules and the search index updates the open pages in place instead of reloading them.",
2268
+ verify: false
2269
+ },
2270
+ {
2271
+ name: VITE_MODULELESS_SETTLE_FLAG,
2272
+ description: "In the Vite host, a hot update that hands Vite no module to update settles once it is acknowledged, instead of waiting for the newest generation to be published.",
2273
+ verify: false
2274
+ },
2249
2275
  {
2250
2276
  name: VITE_BUILD_HANDOFF_FLAG,
2251
2277
  description: "The server build of the Vite production pipeline publishes the browser build's generation instead of generating again.",
@@ -2347,11 +2373,11 @@ async function changedInputs(inputs, ownedRoots) {
2347
2373
  const refresher = createDependencyRefresher();
2348
2374
  const changes = /* @__PURE__ */ new Map();
2349
2375
  const add = (kind, file) => {
2350
- const path25 = normalize(file);
2351
- if (owned(path25, roots)) return;
2352
- const existing = changes.get(path25);
2376
+ const path26 = normalize(file);
2377
+ if (owned(path26, roots)) return;
2378
+ const existing = changes.get(path26);
2353
2379
  if (!existing || CHANGE_RANK[kind] > CHANGE_RANK[existing.kind])
2354
- changes.set(path25, { kind, path: path25 });
2380
+ changes.set(path26, { kind, path: path26 });
2355
2381
  };
2356
2382
  for (let offset = 0; offset < inputs.length; offset += CONCURRENCY) {
2357
2383
  await Promise.all(
@@ -2849,29 +2875,29 @@ function projectWatchInputs(dependencies) {
2849
2875
  const scopes = /* @__PURE__ */ new Map();
2850
2876
  const references = [];
2851
2877
  for (const dependency of dependencies) {
2852
- if (!isRecord2(dependency) || typeof dependency.kind !== "string")
2878
+ if (!isRecord2(dependency) || typeof dependency["kind"] !== "string")
2853
2879
  throw new Error("Invalid dependency");
2854
- switch (dependency.kind) {
2880
+ switch (dependency["kind"]) {
2855
2881
  case "content": {
2856
2882
  if (!hasExactKeys(dependency, ["digest", "kind", "path"]))
2857
2883
  throw new Error("Invalid content dependency");
2858
- files.add(path5(dependency.path, "content path"));
2859
- string2(dependency.digest, "content digest");
2884
+ files.add(path5(dependency["path"], "content path"));
2885
+ string2(dependency["digest"], "content digest");
2860
2886
  break;
2861
2887
  }
2862
2888
  case "existence": {
2863
- if (!hasExactKeys(dependency, ["exists", "kind", "path"]) || typeof dependency.exists !== "boolean")
2889
+ if (!hasExactKeys(dependency, ["exists", "kind", "path"]) || typeof dependency["exists"] !== "boolean")
2864
2890
  throw new Error("Invalid existence dependency");
2865
- files.add(path5(dependency.path, "existence path"));
2891
+ files.add(path5(dependency["path"], "existence path"));
2866
2892
  break;
2867
2893
  }
2868
2894
  case "glob": {
2869
2895
  if (!hasExactKeys(dependency, ["exclude", "include", "kind", "members", "root"]))
2870
2896
  throw new Error("Invalid glob dependency");
2871
- const root = path5(dependency.root, "glob root");
2872
- const include = strings(dependency.include, "glob include");
2873
- const exclude = strings(dependency.exclude, "glob exclude");
2874
- paths(dependency.members, "glob members").forEach((member) => files.add(member));
2897
+ const root = path5(dependency["root"], "glob root");
2898
+ const include = strings(dependency["include"], "glob include");
2899
+ const exclude = strings(dependency["exclude"], "glob exclude");
2900
+ paths(dependency["members"], "glob members").forEach((member) => files.add(member));
2875
2901
  const glob2 = { root, include, exclude };
2876
2902
  globs.set(JSON.stringify(glob2), glob2);
2877
2903
  break;
@@ -2879,10 +2905,10 @@ function projectWatchInputs(dependencies) {
2879
2905
  case "semantic": {
2880
2906
  if (!hasExactKeys(dependency, ["digest", "files", "kind", "reason", "scopeId"]))
2881
2907
  throw new Error("Invalid semantic dependency");
2882
- const scopeId = string2(dependency.scopeId, "semantic scope ID");
2883
- const digest = string2(dependency.digest, "semantic digest");
2884
- string2(dependency.reason, "semantic reason");
2885
- const scopeFiles = paths(dependency.files, "semantic files");
2908
+ const scopeId = string2(dependency["scopeId"], "semantic scope ID");
2909
+ const digest = string2(dependency["digest"], "semantic digest");
2910
+ string2(dependency["reason"], "semantic reason");
2911
+ const scopeFiles = paths(dependency["files"], "semantic files");
2886
2912
  scopeFiles.forEach((file) => files.add(file));
2887
2913
  const registered = scopes.get(scopeId) ?? [];
2888
2914
  registered.push({ digest });
@@ -2893,17 +2919,17 @@ function projectWatchInputs(dependencies) {
2893
2919
  if (!hasExactKeys(dependency, ["digest", "kind", "reason", "scopeId"]))
2894
2920
  throw new Error("Invalid semantic-reference dependency");
2895
2921
  references.push({
2896
- scopeId: string2(dependency.scopeId, "semantic-reference scope ID"),
2897
- digest: string2(dependency.digest, "semantic-reference digest")
2922
+ scopeId: string2(dependency["scopeId"], "semantic-reference scope ID"),
2923
+ digest: string2(dependency["digest"], "semantic-reference digest")
2898
2924
  });
2899
- string2(dependency.reason, "semantic-reference reason");
2925
+ string2(dependency["reason"], "semantic-reference reason");
2900
2926
  break;
2901
2927
  }
2902
2928
  case "keyword": {
2903
2929
  if (!hasExactKeys(dependency, ["digest", "key", "kind"]))
2904
2930
  throw new Error("Invalid keyword dependency");
2905
- string2(dependency.key, "keyword key");
2906
- string2(dependency.digest, "keyword digest");
2931
+ string2(dependency["key"], "keyword key");
2932
+ string2(dependency["digest"], "keyword digest");
2907
2933
  break;
2908
2934
  }
2909
2935
  // The non-physical kinds are validated but are never watch inputs: they name no path, and
@@ -2911,16 +2937,16 @@ function projectWatchInputs(dependencies) {
2911
2937
  case "semantic-closure": {
2912
2938
  if (!hasExactKeys(dependency, ["digest", "key", "kind", "scopeId"]))
2913
2939
  throw new Error("Invalid semantic-closure dependency");
2914
- string2(dependency.scopeId, "semantic-closure scope ID");
2915
- string2(dependency.key, "semantic-closure key");
2916
- string2(dependency.digest, "semantic-closure digest");
2940
+ string2(dependency["scopeId"], "semantic-closure scope ID");
2941
+ string2(dependency["key"], "semantic-closure key");
2942
+ string2(dependency["digest"], "semantic-closure digest");
2917
2943
  break;
2918
2944
  }
2919
2945
  case "evaluated": {
2920
2946
  if (!hasExactKeys(dependency, ["digest", "entryId", "kind"]))
2921
2947
  throw new Error("Invalid evaluated dependency");
2922
- string2(dependency.entryId, "evaluated entry ID");
2923
- string2(dependency.digest, "evaluated digest");
2948
+ string2(dependency["entryId"], "evaluated entry ID");
2949
+ string2(dependency["digest"], "evaluated digest");
2924
2950
  break;
2925
2951
  }
2926
2952
  default:
@@ -3284,7 +3310,7 @@ var GeneratorBuildSession = class {
3284
3310
  const pending = state.pending;
3285
3311
  if (queued) {
3286
3312
  const changes = new Map(queued.changes.map((change) => [change.path, change]));
3287
- pending.changes.forEach((change, path25) => changes.set(path25, change));
3313
+ pending.changes.forEach((change, path26) => changes.set(path26, change));
3288
3314
  queued.changes = [...changes.values()];
3289
3315
  queued.origin = queued.changes.length ? "filesystem" : "reconcile";
3290
3316
  queued.waiters.push(...pending.waiters);
@@ -4925,7 +4951,7 @@ function createCandidateOutputCommitter(options = {}, host = {}) {
4925
4951
 
4926
4952
  // libs/builder/generator/bootstrap/constants.ts
4927
4953
  var GENERATOR_COMPILER_VERSION = "0.0.1";
4928
- var GENERATOR_TOOLCHAIN_DIGEST = "d3b66d41f47865fb003a881897f703f6b49568eefa8f301d410768b97f5647e2";
4954
+ var GENERATOR_TOOLCHAIN_DIGEST = "495b74972f5c2d99ad311bd24b03e2560f77343e401abd7c4d8185e4fee96764";
4929
4955
 
4930
4956
  // libs/builder/generator/bootstrap/index.ts
4931
4957
  var PERSISTENT_WORKER_ENV = PERSISTENT_WORKER_FLAG;
@@ -5147,6 +5173,13 @@ function observePhysicalVersion(file) {
5147
5173
  }
5148
5174
  }
5149
5175
  var HostUpdateCoordinator = class {
5176
+ /**
5177
+ * @param notify Announces the newest settled publication to the browser. `changes` lists the
5178
+ * generated files that differ from the last announcement, when nothing else asks for a full
5179
+ * reload; without it, or when the host cannot apply the changes in place, the page reloads.
5180
+ * @param fail Reports a host error.
5181
+ * @param recovery What the host does after a burst.
5182
+ */
5150
5183
  constructor(notify, fail, recovery) {
5151
5184
  this.notify = notify;
5152
5185
  this.fail = fail;
@@ -5167,6 +5200,13 @@ var HostUpdateCoordinator = class {
5167
5200
  this.disposed = false;
5168
5201
  /** The start and the hot updates of the current burst-detection window. */
5169
5202
  this.window = { start: 0, events: 0 };
5203
+ /** Whether a module-less host update settles without waiting for the current publication. */
5204
+ this.modulelessSettle = !flagOff(VITE_MODULELESS_SETTLE_FLAG);
5205
+ /**
5206
+ * Whether the pending reload must reload the page whatever its outputs: an Angular source was
5207
+ * compiled for it, or it repairs an earlier failure (the browser shows the error overlay).
5208
+ */
5209
+ this.pendingFull = false;
5170
5210
  }
5171
5211
  seed(outputRoot, manifest) {
5172
5212
  this.outputRoot = normalize3(outputRoot);
@@ -5341,7 +5381,8 @@ var HostUpdateCoordinator = class {
5341
5381
  * generated output that a generation claimed. Its host hooks settle only once the newest
5342
5382
  * generation is published and every host obligation is drained, and by then `flush()` has sent
5343
5383
  * that generation's reload (or its outputs equal the last announced ones). A native reload for
5344
- * the same output would be a second one.
5384
+ * the same output would be a second one. A module-less one settles earlier (see
5385
+ * {@link settle}), but Vite has nothing of it to reload either way.
5345
5386
  */
5346
5387
  announces(read) {
5347
5388
  const token = this.tokensByEvent.get(read);
@@ -5366,6 +5407,25 @@ var HostUpdateCoordinator = class {
5366
5407
  )
5367
5408
  ).map((expected) => expected.path).sort();
5368
5409
  }
5410
+ /**
5411
+ * Whether the generation that claimed this TypeScript source update committed and still has a
5412
+ * generated TypeScript module update whose Angular pass has not completed: that pass is still to
5413
+ * come, and the source can join it (`ngDocCompanionFiles`) instead of taking a pass of its own.
5414
+ * False for anything else: a generated output, a source no generation claimed, a generation
5415
+ * that failed, was cancelled or rewrote no TypeScript module, or whose passes all completed.
5416
+ * Call it after `committed(ticket)`, which waits for the generation's result.
5417
+ * @param ticket The source's hot update ticket.
5418
+ */
5419
+ generationPass(ticket) {
5420
+ const token = ticket.token;
5421
+ const attempt = token?.attempt;
5422
+ if (this.disposed || !token || token.generated || !token.isClaimed || token.sourceKind !== "typescript" || token.type !== "update" || !attempt?.resultSeen || attempt.resultStatus !== "success") {
5423
+ return false;
5424
+ }
5425
+ return [...attempt.expected.values()].some(
5426
+ (expected) => expected.kind === "update" && !expected.completed && COMPILER_TYPESCRIPT.test(expected.path) && !JAVASCRIPT_MODULE.test(expected.path)
5427
+ );
5428
+ }
5369
5429
  /**
5370
5430
  * Whether `file` is a generated output: a path below the output root of the published
5371
5431
  * generation. Nothing is generated before the first publication or after disposal.
@@ -5407,10 +5467,28 @@ var HostUpdateCoordinator = class {
5407
5467
  this.diagnosticChanged = deferred2();
5408
5468
  }
5409
5469
  }
5410
- /** Waits for the current accepted publication and all peer host acknowledgments. */
5411
- async settle(ticket) {
5470
+ /**
5471
+ * Waits for the current accepted publication and all peer host acknowledgments.
5472
+ *
5473
+ * A module-less hot update does not wait: once its hooks return, Vite has no module to update
5474
+ * and sends nothing, and its acknowledgment has already settled what it obliged (the reload,
5475
+ * sent by `flush()` once every obligation is settled, is this coordinator's own). Waiting made
5476
+ * it follow every generation that started meanwhile, so under sustained churn it settled only
5477
+ * when the churn stopped, and each wait for the host obligations to drain could time out
5478
+ * (`NGDOC_VITE_HOST_TIMEOUT`) while every single obligation was completed in time. Nothing
5479
+ * else changes: obligations, the reload and what is published are the same, so the switch off
5480
+ * (`NGDOC_VITE_MODULELESS_SETTLE=0`) only makes it wait as before.
5481
+ * @param ticket The hot update's ticket, after its acknowledgment.
5482
+ * @param modules Whether its hooks hand Vite any module to update (or a page reload Vite sends
5483
+ * itself, for an HTML file without modules). Only the caller, which sees Vite's context, knows.
5484
+ */
5485
+ async settle(ticket, modules = true) {
5412
5486
  const token = ticket.token;
5413
5487
  if (!token || this.disposed) return;
5488
+ if (!modules && this.modulelessSettle) {
5489
+ this.settleModuleless(token);
5490
+ return;
5491
+ }
5414
5492
  if (!token.generated && token.isClaimed && token.sourceKind === "typescript" && token.type === "update") {
5415
5493
  await this.awaitWithoutDiagnostic(token.attempt.publication.promise);
5416
5494
  if (token.attempt.publicationStatus === "skipped" || token.attempt.publicationStatus === "cancelled") {
@@ -5426,9 +5504,14 @@ var HostUpdateCoordinator = class {
5426
5504
  if (!token?.attempt || this.disposed) return;
5427
5505
  await token.attempt.result.promise;
5428
5506
  }
5429
- async complete(ticket) {
5507
+ /**
5508
+ * Acknowledges a hot update that takes no compiler pass, then settles it.
5509
+ * @param ticket The hot update's ticket.
5510
+ * @param modules See {@link settle}.
5511
+ */
5512
+ async complete(ticket, modules = true) {
5430
5513
  await this.acknowledge(ticket);
5431
- await this.settle(ticket);
5514
+ await this.settle(ticket, modules);
5432
5515
  }
5433
5516
  published(result, recovered) {
5434
5517
  const attempt = this.attempts.get(result.generation);
@@ -5440,6 +5523,7 @@ var HostUpdateCoordinator = class {
5440
5523
  this.publishedGeneration = result.generation;
5441
5524
  this.publication(result.generation, "success");
5442
5525
  if (recovered || delta.changed || compilerSource || this.pendingGeneration !== void 0) {
5526
+ if (recovered || compilerSource) this.pendingFull = true;
5443
5527
  this.pendingGeneration = result.generation;
5444
5528
  this.pendingManifest = structuredClone(result.manifest);
5445
5529
  this.flush();
@@ -5452,6 +5536,7 @@ var HostUpdateCoordinator = class {
5452
5536
  this.burst = void 0;
5453
5537
  this.pendingGeneration = void 0;
5454
5538
  this.pendingManifest = void 0;
5539
+ this.pendingFull = false;
5455
5540
  for (const attempt of this.attempts.values()) {
5456
5541
  attempt.result.resolve();
5457
5542
  attempt.shapes.resolve();
@@ -5645,8 +5730,10 @@ var HostUpdateCoordinator = class {
5645
5730
  return;
5646
5731
  if (this.latestAttempt && this.pendingGeneration < this.latestAttempt.generation) return;
5647
5732
  this.pendingGeneration = void 0;
5733
+ const changes = this.pendingFull || !this.pendingManifest || !this.outputRoot ? void 0 : this.changes(this.outputRoot, this.announcedManifest, this.pendingManifest);
5734
+ this.pendingFull = false;
5648
5735
  try {
5649
- this.notify();
5736
+ this.notify(changes?.length ? changes : void 0);
5650
5737
  if (this.pendingManifest) this.announcedManifest = this.pendingManifest;
5651
5738
  this.pendingManifest = void 0;
5652
5739
  } catch (error2) {
@@ -5654,10 +5741,29 @@ var HostUpdateCoordinator = class {
5654
5741
  }
5655
5742
  }
5656
5743
  queueCurrentReload() {
5744
+ this.pendingFull = true;
5657
5745
  this.pendingGeneration = this.publishedGeneration ?? this.manifest?.generation ?? this.pendingGeneration ?? 0;
5658
5746
  this.pendingManifest = structuredClone(this.manifest ?? this.announcedManifest);
5659
5747
  this.flush();
5660
5748
  }
5749
+ /**
5750
+ * Settles a module-less hot update without waiting (see {@link settle}).
5751
+ * @param token The acknowledged hot update.
5752
+ */
5753
+ settleModuleless(token) {
5754
+ const failure3 = this.diagnosticError();
5755
+ if (failure3) throw failure3;
5756
+ const attempt = token.attempt;
5757
+ if (!attempt || token.generated || !token.isClaimed || token.sourceKind !== "typescript" || token.type !== "update") {
5758
+ return;
5759
+ }
5760
+ void attempt.publication.promise.then(() => {
5761
+ if (this.disposed || this.diagnosticError()) return;
5762
+ if (attempt.publicationStatus === "skipped" || attempt.publicationStatus === "cancelled") {
5763
+ this.queueCurrentReload();
5764
+ }
5765
+ });
5766
+ }
5661
5767
  async awaitCurrentPublication(initial) {
5662
5768
  if (this.diagnosticError()) throw this.diagnosticError();
5663
5769
  let attempt = initial ?? this.latestAttempt;
@@ -5714,6 +5820,28 @@ var HostUpdateCoordinator = class {
5714
5820
  }
5715
5821
  return { changed };
5716
5822
  }
5823
+ /**
5824
+ * The generated files that differ between two manifests, in path order.
5825
+ * @param previousManifest The outputs the browser was last told about.
5826
+ * @param nextManifest The outputs announced now.
5827
+ */
5828
+ changes(root, previousManifest, nextManifest) {
5829
+ const previous = manifestMap(previousManifest);
5830
+ const next2 = manifestMap(nextManifest);
5831
+ const changes = [];
5832
+ for (const relative of [.../* @__PURE__ */ new Set([...previous.keys(), ...next2.keys()])].sort()) {
5833
+ const before = previous.get(relative);
5834
+ const after = next2.get(relative);
5835
+ if (sameFile(before, after)) continue;
5836
+ changes.push({
5837
+ path: relative,
5838
+ file: normalize3(path8.join(root, relative)),
5839
+ ...before ? { before: { digest: before.digest, role: before.role } } : {},
5840
+ ...after ? { after: { digest: after.digest, role: after.role } } : {}
5841
+ });
5842
+ }
5843
+ return changes;
5844
+ }
5717
5845
  prune(generation) {
5718
5846
  for (const [candidate, attempt] of this.attempts) {
5719
5847
  if (candidate < generation && ![...attempt.expected.values()].some((item) => !item.completed)) {
@@ -5865,10 +5993,23 @@ function globalStyleSheet(context) {
5865
5993
  };
5866
5994
  return context.modules.every(global) && virtual;
5867
5995
  }
5996
+ function handsViteModules(file, modules) {
5997
+ return modules.length > 0 || file.endsWith(".html");
5998
+ }
5999
+ function handedModules(context, result) {
6000
+ return Array.isArray(result) ? result : context.modules;
6001
+ }
5868
6002
  function analogHostHooks(compiler) {
5869
6003
  const hooks = compiler?.api?.ngDocHost;
5870
6004
  return hooks && typeof hooks === "object" && typeof hooks.passes === "number" ? hooks : void 0;
5871
6005
  }
6006
+ function released() {
6007
+ let resolve;
6008
+ const promise = new Promise((done) => {
6009
+ resolve = done;
6010
+ });
6011
+ return { promise, resolve };
6012
+ }
5872
6013
  function error(code, message4, cause) {
5873
6014
  return Object.assign(
5874
6015
  new Error(`[${code}] ${message4}`, cause === void 0 ? void 0 : { cause }),
@@ -5950,10 +6091,10 @@ var CompilerAdmission = class {
5950
6091
  this.drained = new Promise((resolve) => {
5951
6092
  this.drainedResolve = resolve;
5952
6093
  });
5953
- let released = false;
6094
+ let released2 = false;
5954
6095
  waiter.resolve(() => {
5955
- if (released) return;
5956
- released = true;
6096
+ if (released2) return;
6097
+ released2 = true;
5957
6098
  this.locked = false;
5958
6099
  this.drainedResolve?.();
5959
6100
  this.drainedResolve = void 0;
@@ -6018,6 +6159,9 @@ function composeAngularPlugins(angularPlugins, componentProbe, bridge) {
6018
6159
  const sharedPasses = !flagOff(ANGULAR_SHARED_PASS_FLAG);
6019
6160
  const compiledStates = /* @__PURE__ */ new Map();
6020
6161
  const hooks = flagOff(ANGULAR_STRUCTURAL_PASS_FLAG) ? void 0 : analogHostHooks(compiler);
6162
+ const descriptionPasses = sharedPasses && !flagOff(ANGULAR_DESCRIPTION_PASS_FLAG);
6163
+ const waitingSources = /* @__PURE__ */ new Map();
6164
+ let admissionReleased = released();
6021
6165
  if (hooks)
6022
6166
  hooks.claimFilesystemChange = (file) => !disposed && bridge.claimsFilesystemChange?.(file) === true;
6023
6167
  const captureInitialCompilation = async () => {
@@ -6157,20 +6301,26 @@ function composeAngularPlugins(angularPlugins, componentProbe, bridge) {
6157
6301
  if (!compilerTrigger) {
6158
6302
  const result2 = await Reflect.apply(originalHot, this, [context]);
6159
6303
  await bridge.acknowledge(ticket, false);
6160
- await bridge.settle(ticket);
6304
+ await bridge.settle(ticket, handsViteModules(context.file, handedModules(context, result2)));
6161
6305
  return result2;
6162
6306
  }
6163
6307
  await preflight();
6164
6308
  const resource = COMPILER_RESOURCE2.test(context.file);
6165
6309
  if (resource) await bridge.committed(ticket);
6166
6310
  else await ticket.ready;
6311
+ if (!resource && descriptionPasses && bridge.descriptionModule?.(context.file)) {
6312
+ await joinGenerationPass(context, ticket);
6313
+ }
6167
6314
  const release = await admission.acquire();
6168
6315
  let result;
6169
6316
  try {
6170
6317
  if (!resource && (await coveredByInitialCompilation(context) || await coveredByCompanionPass(context))) {
6171
6318
  await bridge.acknowledge(ticket, false);
6172
6319
  } else {
6173
- const companions = sharedPasses && !resource ? await captureCompanions(bridge.companions?.(ticket) ?? []) : /* @__PURE__ */ new Map();
6320
+ const companions = sharedPasses && !resource ? await captureCompanions([
6321
+ ...bridge.companions?.(ticket) ?? [],
6322
+ ...takeWaitingSources(context.file)
6323
+ ]) : /* @__PURE__ */ new Map();
6174
6324
  const hotContext = companions.size > 0 ? { ...context, ngDocCompanionFiles: [...companions.keys()].map(analogFileId) } : context;
6175
6325
  const own = companions.size > 0 ? await observePhysicalState(path9.resolve(context.file)).catch(() => void 0) : void 0;
6176
6326
  const mark = companions.size > 0 ? bridge.diagnosticMark?.() : void 0;
@@ -6197,10 +6347,47 @@ function composeAngularPlugins(angularPlugins, componentProbe, bridge) {
6197
6347
  throw cause;
6198
6348
  } finally {
6199
6349
  release();
6350
+ const ended = admissionReleased;
6351
+ admissionReleased = released();
6352
+ ended.resolve();
6200
6353
  }
6201
- await bridge.settle(ticket);
6354
+ await bridge.settle(ticket, handsViteModules(context.file, handedModules(context, result)));
6202
6355
  return result;
6203
6356
  };
6357
+ const joinGenerationPass = async (context, ticket) => {
6358
+ await bridge.committed(ticket);
6359
+ if (disposed || !bridge.generationPass?.(ticket)) return;
6360
+ const file = path9.resolve(context.file);
6361
+ const entry = { taken: false };
6362
+ waitingSources.set(file, entry);
6363
+ const deadline = Date.now() + HOST_COMPLETION_TIMEOUT_MS;
6364
+ try {
6365
+ while (!entry.taken && !disposed && bridge.generationPass(ticket)) {
6366
+ const remaining = deadline - Date.now();
6367
+ if (remaining <= 0) return;
6368
+ let timer2;
6369
+ await Promise.race([
6370
+ admissionReleased.promise,
6371
+ new Promise((resolve) => {
6372
+ timer2 = setTimeout(resolve, remaining);
6373
+ timer2.unref?.();
6374
+ })
6375
+ ]);
6376
+ clearTimeout(timer2);
6377
+ }
6378
+ } finally {
6379
+ if (waitingSources.get(file) === entry) waitingSources.delete(file);
6380
+ }
6381
+ };
6382
+ const takeWaitingSources = (file) => {
6383
+ if (!bridge.generated?.(file)) return [];
6384
+ const taken = [];
6385
+ for (const [source, entry] of waitingSources) {
6386
+ entry.taken = true;
6387
+ taken.push(source);
6388
+ }
6389
+ return taken;
6390
+ };
6204
6391
  const wrappedCompiler = {
6205
6392
  ...compiler,
6206
6393
  buildStart: replaceHandler(
@@ -6454,14 +6641,101 @@ function sameRuntimeConfiguration(left, right) {
6454
6641
  return left.outputRoot === right.outputRoot && left.cacheRoot === right.cacheRoot && left.assetDirectory === right.assetDirectory;
6455
6642
  }
6456
6643
 
6644
+ // libs/builder/generator/vite/content-updates.ts
6645
+ import path11 from "node:path";
6646
+ var CONTENT_UPDATE_EVENT = "ng-doc:content-update";
6647
+ var CONTENT_CLIENT_EVENT = "ng-doc:content-client";
6648
+ var CONTENT_UPDATE_VERSION = 1;
6649
+ var CONTENT_UPDATE_CLIENT = `
6650
+ const hot = import.meta.hot;
6651
+ if (hot) {
6652
+ let queue = Promise.resolve();
6653
+ hot.on(${JSON.stringify(CONTENT_UPDATE_EVENT)}, (update) => {
6654
+ queue = queue.then(async () => {
6655
+ try {
6656
+ const payloads = await Promise.all(
6657
+ update.modules.map(async (url) => (await import(/* @vite-ignore */ url)).default),
6658
+ );
6659
+ const event = new CustomEvent(${JSON.stringify(CONTENT_UPDATE_EVENT)}, {
6660
+ cancelable: true,
6661
+ detail: { payloads, search: update.search },
6662
+ });
6663
+ if (window.dispatchEvent(event)) location.reload();
6664
+ } catch (error) {
6665
+ console.error('[ng-doc] The content update failed; reloading the page.', error);
6666
+ location.reload();
6667
+ }
6668
+ });
6669
+ });
6670
+ hot.send(${JSON.stringify(CONTENT_CLIENT_EVENT)}, { version: ${CONTENT_UPDATE_VERSION} });
6671
+ }
6672
+ `;
6673
+ var CLIENT_MARKER = "data-ng-doc-content-updates";
6674
+ function contentUpdateClientTags(html) {
6675
+ if (!contentUpdatesEnabled() || html.includes(CLIENT_MARKER)) return [];
6676
+ return [
6677
+ {
6678
+ tag: "script",
6679
+ attrs: { type: "module", [CLIENT_MARKER]: "" },
6680
+ children: CONTENT_UPDATE_CLIENT,
6681
+ injectTo: "head"
6682
+ }
6683
+ ];
6684
+ }
6685
+ function contentUpdatesEnabled() {
6686
+ return !flagOff(VITE_CONTENT_UPDATE_FLAG);
6687
+ }
6688
+ function contentOnly(changes, assetDirectory) {
6689
+ if (!changes?.length) return void 0;
6690
+ const keywords = path11.posix.join(assetDirectory.replace(/\\/g, "/"), "keywords.json");
6691
+ const modules = [];
6692
+ let search = false;
6693
+ for (const change of changes) {
6694
+ const { before, after } = change;
6695
+ if (!before || !after || before.role !== after.role) return void 0;
6696
+ if (after.role === "content" && change.path.endsWith(".content.mjs")) {
6697
+ modules.push(change.file);
6698
+ } else if (after.role === "search") {
6699
+ search = true;
6700
+ } else if (!(after.role === "asset" && change.path === keywords)) {
6701
+ return void 0;
6702
+ }
6703
+ }
6704
+ return { modules, search };
6705
+ }
6706
+ function sendContentUpdate(server, clients, changes, timestamp) {
6707
+ const connected = [...server.ws.clients ?? []];
6708
+ if (connected.length === 0) {
6709
+ server.ws.send({ type: "full-reload" });
6710
+ return;
6711
+ }
6712
+ const graph = server.environments["client"]?.moduleGraph;
6713
+ const urls = /* @__PURE__ */ new Set();
6714
+ for (const file of changes.modules) {
6715
+ for (const module of graph?.getModulesByFile(file) ?? []) urls.add(module.url);
6716
+ }
6717
+ const base = server.config.base.endsWith("/") ? server.config.base : `${server.config.base}/`;
6718
+ const message4 = {
6719
+ version: CONTENT_UPDATE_VERSION,
6720
+ modules: [...urls].sort().map(
6721
+ (url) => `${base}${url.replace(/^\//, "")}${url.includes("?") ? "&" : "?"}t=${timestamp}`
6722
+ ),
6723
+ search: changes.search
6724
+ };
6725
+ for (const client of connected) {
6726
+ if (clients.has(client)) client.send(CONTENT_UPDATE_EVENT, message4);
6727
+ else client.send({ type: "full-reload" });
6728
+ }
6729
+ }
6730
+
6457
6731
  // libs/builder/generator/vite/demo-application.ts
6458
6732
  import { readFile as readFile5 } from "node:fs/promises";
6459
- import path11 from "node:path";
6733
+ import path12 from "node:path";
6460
6734
  var DEMO_APPLICATION_MODULE = "demo-app.ts";
6461
6735
  var DEMO_PATH = /^export const NG_DOC_DEMO_PATH = '([^'\\\n]*)';$/m;
6462
6736
  var DEMO_PAGES = /^export const NG_DOC_DEMO_PAGES: string\[\] = (.*);$/m;
6463
6737
  async function readDemoApplication(outputRoot) {
6464
- const module = path11.join(outputRoot, DEMO_APPLICATION_MODULE);
6738
+ const module = path12.join(outputRoot, DEMO_APPLICATION_MODULE);
6465
6739
  const source = await readFile5(module, "utf8").catch(() => void 0);
6466
6740
  const demoPath = source === void 0 ? void 0 : DEMO_PATH.exec(source)?.[1];
6467
6741
  const pages2 = source === void 0 ? void 0 : demoPages(DEMO_PAGES.exec(source)?.[1]);
@@ -6491,7 +6765,7 @@ function hostDiagnostic(code, message4) {
6491
6765
  }
6492
6766
 
6493
6767
  // libs/builder/generator/vite/lease.ts
6494
- import path12 from "node:path";
6768
+ import path13 from "node:path";
6495
6769
  var identities = /* @__PURE__ */ new Map();
6496
6770
  var outputRoots = /* @__PURE__ */ new Map();
6497
6771
  function acquireOutputLease(identity2, defaultOutputRoot) {
@@ -6499,7 +6773,7 @@ function acquireOutputLease(identity2, defaultOutputRoot) {
6499
6773
  throw new Error(`[NGDOC_VITE_OUTPUT_LEASE] Output owner is already active for ${identity2}.`);
6500
6774
  }
6501
6775
  const token = Symbol(identity2);
6502
- const initialRoot = canonicalDrive(path12.resolve(defaultOutputRoot).replace(/\\/g, "/"));
6776
+ const initialRoot = canonicalDrive(path13.resolve(defaultOutputRoot).replace(/\\/g, "/"));
6503
6777
  if (outputRoots.has(initialRoot)) {
6504
6778
  throw new Error(
6505
6779
  `[NGDOC_VITE_OUTPUT_LEASE] Default output root is already active: ${initialRoot}.`
@@ -6513,7 +6787,7 @@ function acquireOutputLease(identity2, defaultOutputRoot) {
6513
6787
  return {
6514
6788
  admit(value) {
6515
6789
  if (disposed) throw new Error("[NGDOC_VITE_OUTPUT_LEASE] Output lease is disposed.");
6516
- const normalized = canonicalDrive(path12.resolve(value).replace(/\\/g, "/"));
6790
+ const normalized = canonicalDrive(path13.resolve(value).replace(/\\/g, "/"));
6517
6791
  const owner = outputRoots.get(normalized);
6518
6792
  if (owner && owner !== token) {
6519
6793
  throw new Error(
@@ -6544,11 +6818,11 @@ function acquireOutputLease(identity2, defaultOutputRoot) {
6544
6818
 
6545
6819
  // libs/builder/generator/vite/lifecycle.ts
6546
6820
  import { existsSync as existsSync5 } from "node:fs";
6547
- import path17 from "node:path";
6821
+ import path18 from "node:path";
6548
6822
 
6549
6823
  // libs/builder/generator/vite/assets.ts
6550
6824
  import { readFile as readFile6 } from "node:fs/promises";
6551
- import path13 from "node:path";
6825
+ import path14 from "node:path";
6552
6826
  var GENERATED_ASSET_PATH = "assets/ng-doc";
6553
6827
  var MIME = /* @__PURE__ */ new Map([
6554
6828
  [".css", "text/css; charset=utf-8"],
@@ -6570,7 +6844,7 @@ function normalizedBase(base) {
6570
6844
  return value.endsWith("/") ? value : `${value}/`;
6571
6845
  }
6572
6846
  function safeRelative2(value) {
6573
- return !!value && !value.includes("\0") && !value.includes("\\") && !path13.posix.isAbsolute(value) && !value.split("/").some((segment) => segment === ".." || segment === "");
6847
+ return !!value && !value.includes("\0") && !value.includes("\\") && !path14.posix.isAbsolute(value) && !value.split("/").some((segment) => segment === ".." || segment === "");
6574
6848
  }
6575
6849
  function inventory(configuration, manifest) {
6576
6850
  const prefix = `${configuration.assetDirectory.replace(/\\/g, "/").replace(/\/$/, "")}/`;
@@ -6587,7 +6861,7 @@ function inventory(configuration, manifest) {
6587
6861
  throw new Error(`[NGDOC_VITE_ASSET_COLLISION] Duplicate generated asset: ${relative}.`);
6588
6862
  }
6589
6863
  result.set(relative, {
6590
- file: path13.join(configuration.outputRoot, output),
6864
+ file: path14.join(configuration.outputRoot, output),
6591
6865
  outputName: outputName2
6592
6866
  });
6593
6867
  }
@@ -6631,7 +6905,7 @@ var GeneratedAssetInventory = class {
6631
6905
  response.statusCode = 200;
6632
6906
  response.setHeader(
6633
6907
  "Content-Type",
6634
- MIME.get(path13.extname(relative).toLowerCase()) ?? "application/octet-stream"
6908
+ MIME.get(path14.extname(relative).toLowerCase()) ?? "application/octet-stream"
6635
6909
  );
6636
6910
  response.end(source);
6637
6911
  },
@@ -6665,7 +6939,7 @@ var GeneratedAssetInventory = class {
6665
6939
 
6666
6940
  // libs/builder/generator/vite/vite-event-source.ts
6667
6941
  import { existsSync as existsSync4, realpathSync as realpathSync2, statSync as statSync6 } from "node:fs";
6668
- import path16 from "node:path";
6942
+ import path17 from "node:path";
6669
6943
 
6670
6944
  // libs/builder/generator/vite/external-probes.ts
6671
6945
  import { statSync as statSync5 } from "node:fs";
@@ -6746,7 +7020,7 @@ var ExternalProbeWatcher = class {
6746
7020
 
6747
7021
  // libs/builder/generator/vite/missing-paths.ts
6748
7022
  import { existsSync as existsSync3, watch as watchDirectory } from "node:fs";
6749
- import path14 from "node:path";
7023
+ import path15 from "node:path";
6750
7024
  var MAX_MISSING_PATH_DIRECTORIES = 1024;
6751
7025
  var defaultWatch = (directory, listener) => watchDirectory(
6752
7026
  directory,
@@ -6754,9 +7028,9 @@ var defaultWatch = (directory, listener) => watchDirectory(
6754
7028
  (event, name) => listener(event, typeof name === "string" ? name : null)
6755
7029
  );
6756
7030
  function anchorOf(target) {
6757
- let cursor = path14.dirname(target);
7031
+ let cursor = path15.dirname(target);
6758
7032
  while (!existsSync3(cursor)) {
6759
- const parent = path14.dirname(cursor);
7033
+ const parent = path15.dirname(cursor);
6760
7034
  if (parent === cursor) break;
6761
7035
  cursor = parent;
6762
7036
  }
@@ -6843,7 +7117,7 @@ var MissingPathWatcher = class {
6843
7117
  const members2 = [...this.members.get(anchor) ?? []];
6844
7118
  const gone = !existsSync3(anchor);
6845
7119
  for (const target of members2) {
6846
- const entry = path14.relative(anchor, target).split(path14.sep)[0];
7120
+ const entry = path15.relative(anchor, target).split(path15.sep)[0];
6847
7121
  if (!gone && name !== null && name !== entry) continue;
6848
7122
  this.refresh(target);
6849
7123
  }
@@ -6866,9 +7140,9 @@ var MissingPathWatcher = class {
6866
7140
  // libs/builder/generator/vite/watch-inputs.ts
6867
7141
  import { Minimatch } from "minimatch";
6868
7142
  import { access } from "node:fs/promises";
6869
- import path15 from "node:path";
7143
+ import path16 from "node:path";
6870
7144
  function normalize4(value) {
6871
- return path15.resolve(value).replace(/\\/g, "/");
7145
+ return path16.resolve(value).replace(/\\/g, "/");
6872
7146
  }
6873
7147
  function union(left, right) {
6874
7148
  const files = new Set([...left?.files ?? [], ...right?.files ?? []].map(normalize4));
@@ -6890,14 +7164,14 @@ function inputKey(inputs) {
6890
7164
  return JSON.stringify(inputs);
6891
7165
  }
6892
7166
  function absolutePattern(root, pattern) {
6893
- return normalize4(path15.isAbsolute(pattern) ? pattern : path15.join(root, pattern));
7167
+ return normalize4(path16.isAbsolute(pattern) ? pattern : path16.join(root, pattern));
6894
7168
  }
6895
7169
  function patternBase(root, pattern) {
6896
7170
  const absolute2 = absolutePattern(root, pattern);
6897
7171
  const magic = absolute2.search(/[*?{}[\]()!]/);
6898
- if (magic < 0) return path15.dirname(absolute2).replace(/\\/g, "/");
7172
+ if (magic < 0) return path16.dirname(absolute2).replace(/\\/g, "/");
6899
7173
  const slash2 = absolute2.lastIndexOf("/", magic);
6900
- return (slash2 > 0 ? absolute2.slice(0, slash2) : path15.parse(absolute2).root).replace(/\\/g, "/");
7174
+ return (slash2 > 0 ? absolute2.slice(0, slash2) : path16.parse(absolute2).root).replace(/\\/g, "/");
6901
7175
  }
6902
7176
  async function nearestExisting(value) {
6903
7177
  let cursor = normalize4(value);
@@ -6906,7 +7180,7 @@ async function nearestExisting(value) {
6906
7180
  await access(cursor);
6907
7181
  return cursor;
6908
7182
  } catch {
6909
- const parent = path15.dirname(cursor).replace(/\\/g, "/");
7183
+ const parent = path16.dirname(cursor).replace(/\\/g, "/");
6910
7184
  if (parent === cursor) return cursor;
6911
7185
  cursor = parent;
6912
7186
  }
@@ -6916,16 +7190,16 @@ function ancestorOf(target, candidate) {
6916
7190
  return target === candidate || target.startsWith(`${candidate}/`);
6917
7191
  }
6918
7192
  function globPattern(pattern) {
6919
- return path15.sep === "\\" ? pattern.replace(/\\/g, "/") : pattern;
7193
+ return path16.sep === "\\" ? pattern.replace(/\\/g, "/") : pattern;
6920
7194
  }
6921
7195
  function compilePattern(pattern) {
6922
7196
  return {
6923
- absolute: path15.isAbsolute(pattern),
7197
+ absolute: path16.isAbsolute(pattern),
6924
7198
  matcher: new Minimatch(globPattern(pattern), { dot: true })
6925
7199
  };
6926
7200
  }
6927
7201
  function patternMatches(glob2, pattern, changed) {
6928
- const subject = pattern.absolute ? changed : path15.relative(glob2.root, changed).replace(/\\/g, "/");
7202
+ const subject = pattern.absolute ? changed : path16.relative(glob2.root, changed).replace(/\\/g, "/");
6929
7203
  return pattern.matcher.match(subject);
6930
7204
  }
6931
7205
  function globMatches(glob2, changed) {
@@ -7012,7 +7286,7 @@ var WatchInputRegistry = class {
7012
7286
  const directories = /* @__PURE__ */ new Set();
7013
7287
  for (const target of globBases) {
7014
7288
  const existing = await nearestExisting(target);
7015
- if (existing === path15.parse(existing).root.replace(/\\/g, "/")) {
7289
+ if (existing === path16.parse(existing).root.replace(/\\/g, "/")) {
7016
7290
  throw new Error(
7017
7291
  `[NGDOC_VITE_WATCH_ROOT] Refusing an unbounded filesystem-root glob watch for ${target}.`
7018
7292
  );
@@ -7023,7 +7297,7 @@ var WatchInputRegistry = class {
7023
7297
  }
7024
7298
  }
7025
7299
  for (const target of desired) {
7026
- if (target === path15.parse(target).root.replace(/\\/g, "/")) {
7300
+ if (target === path16.parse(target).root.replace(/\\/g, "/")) {
7027
7301
  throw new Error(
7028
7302
  `[NGDOC_VITE_WATCH_ROOT] Refusing an unbounded filesystem-root file watch for ${target}.`
7029
7303
  );
@@ -7082,7 +7356,7 @@ var WatchInputRegistry = class {
7082
7356
 
7083
7357
  // libs/builder/generator/vite/vite-event-source.ts
7084
7358
  function normalize5(value) {
7085
- return canonicalDrive(path16.resolve(value).replace(/\\/g, "/"));
7359
+ return canonicalDrive(path17.resolve(value).replace(/\\/g, "/"));
7086
7360
  }
7087
7361
  function within2(target, root) {
7088
7362
  return target === root || target.startsWith(`${root}/`);
@@ -7103,12 +7377,12 @@ function statVersion(file) {
7103
7377
  }
7104
7378
  }
7105
7379
  function listed(watched, target) {
7106
- return watched.has(target) || (watched.get(path16.dirname(target))?.includes(path16.basename(target)) ?? false);
7380
+ return watched.has(target) || (watched.get(path17.dirname(target))?.includes(path17.basename(target)) ?? false);
7107
7381
  }
7108
7382
  function nearestExistingPath(target) {
7109
7383
  let cursor = target;
7110
7384
  while (!existsSync4(cursor)) {
7111
- const parent = path16.dirname(cursor);
7385
+ const parent = path17.dirname(cursor);
7112
7386
  if (parent === cursor) return cursor;
7113
7387
  cursor = parent;
7114
7388
  }
@@ -7133,7 +7407,7 @@ function workspaceRoots(root) {
7133
7407
  roots.add(normalize5(realpathSync2.native(root)));
7134
7408
  } catch {
7135
7409
  }
7136
- return [...roots].filter((value) => value !== normalize5(path16.parse(value).root));
7410
+ return [...roots].filter((value) => value !== normalize5(path17.parse(value).root));
7137
7411
  }
7138
7412
  function watchesMissingPaths(watcher) {
7139
7413
  const options = watcher.options;
@@ -7585,8 +7859,20 @@ var ViteAdapterLifecycle = class {
7585
7859
  this.registration = Promise.resolve();
7586
7860
  this.disposed = false;
7587
7861
  this.latestStarted = -1;
7862
+ /** Whether a content-only reload updates the open pages in place (`NGDOC_VITE_CONTENT_UPDATE`). */
7863
+ this.contentUpdates = contentUpdatesEnabled();
7864
+ /** The browser clients whose NgDoc client listens for content updates. */
7865
+ this.contentClients = /* @__PURE__ */ new WeakSet();
7866
+ /** The timestamp of the last content update: each one imports the modules anew. */
7867
+ this.contentStamp = 0;
7868
+ /** Records the clients that announce the NgDoc client. */
7869
+ this.contentClient = (data, client) => {
7870
+ if (data?.version === CONTENT_UPDATE_VERSION) {
7871
+ this.contentClients.add(client);
7872
+ }
7873
+ };
7588
7874
  this.hostUpdates = new HostUpdateCoordinator(
7589
- () => this.server?.ws.send({ type: "full-reload" }),
7875
+ (changes) => this.announce(changes),
7590
7876
  (error2) => this.fail(error2),
7591
7877
  {
7592
7878
  warn: (message4) => this.warn(message4),
@@ -7616,9 +7902,40 @@ var ViteAdapterLifecycle = class {
7616
7902
  }
7617
7903
  attachServer(server, source) {
7618
7904
  if (this.disposed) throw new Error("Vite adapter is disposed.");
7905
+ if (this.contentUpdates && this.server !== server) {
7906
+ this.stopContentClients();
7907
+ if (typeof server.ws?.on === "function")
7908
+ server.ws.on(CONTENT_CLIENT_EVENT, this.contentClient);
7909
+ }
7619
7910
  this.server = server;
7620
7911
  this.source = source;
7621
7912
  }
7913
+ /** Stops recording the clients that announce the NgDoc client. */
7914
+ stopContentClients() {
7915
+ try {
7916
+ if (typeof this.server?.ws?.off === "function") {
7917
+ this.server.ws.off(CONTENT_CLIENT_EVENT, this.contentClient);
7918
+ }
7919
+ } catch {
7920
+ }
7921
+ }
7922
+ /**
7923
+ * Tells the browser about the newest settled publication: a content update when it changed only
7924
+ * content (see `contentOnly`), else a full reload.
7925
+ * @param changes The generated files that differ from the last announcement, if the reload may
7926
+ * be applied in place.
7927
+ */
7928
+ announce(changes) {
7929
+ const server = this.server;
7930
+ if (!server) return;
7931
+ const content = this.contentUpdates && this.configuration ? contentOnly(changes, this.configuration.assetDirectory) : void 0;
7932
+ if (!content) {
7933
+ server.ws.send({ type: "full-reload" });
7934
+ return;
7935
+ }
7936
+ this.contentStamp = Math.max(Date.now(), this.contentStamp + 1);
7937
+ sendContentUpdate(server, this.contentClients, content, this.contentStamp);
7938
+ }
7622
7939
  attachWatch(watch) {
7623
7940
  if (this.disposed) throw new Error("Vite adapter is disposed.");
7624
7941
  this.watch = watch;
@@ -7669,13 +7986,13 @@ var ViteAdapterLifecycle = class {
7669
7986
  const read = /* @__PURE__ */ new Set();
7670
7987
  for (const artifact of committed.snapshot.artifacts) {
7671
7988
  for (const dependency of artifact.dependencies) {
7672
- if (dependency.kind === "content" && DESCRIPTION_MODULE.test(path17.basename(dependency.path)))
7673
- read.add(canonicalDrive(path17.resolve(dependency.path)));
7989
+ if (dependency.kind === "content" && DESCRIPTION_MODULE.test(path18.basename(dependency.path)))
7990
+ read.add(canonicalDrive(path18.resolve(dependency.path)));
7674
7991
  }
7675
7992
  }
7676
7993
  committed.read = read;
7677
7994
  }
7678
- return committed.read.has(canonicalDrive(path17.resolve(file)));
7995
+ return committed.read.has(canonicalDrive(path18.resolve(file)));
7679
7996
  }
7680
7997
  hostUpdateStarted(file, type, read) {
7681
7998
  const change = { kind: type, path: file };
@@ -7684,13 +8001,34 @@ var ViteAdapterLifecycle = class {
7684
8001
  if (relevant) this.source.forward(change);
7685
8002
  return ticket;
7686
8003
  }
7687
- hostUpdateCompleted(ticket) {
7688
- return this.hostUpdates.complete(ticket);
8004
+ /**
8005
+ * See {@link HostUpdateCoordinator.complete}.
8006
+ * @param ticket The hot update's ticket.
8007
+ * @param modules Whether its hooks hand Vite any module to update.
8008
+ */
8009
+ hostUpdateCompleted(ticket, modules = true) {
8010
+ return this.hostUpdates.complete(ticket, modules);
7689
8011
  }
7690
8012
  /** The adapter reloads for this settled hot update itself. */
7691
8013
  hostUpdateAnnounced(read) {
7692
8014
  return !this.disposed && this.hostUpdates.announces(read);
7693
8015
  }
8016
+ /** See {@link HostUpdateCoordinator.generationPass}. */
8017
+ hostGenerationPass(ticket) {
8018
+ return !this.disposed && this.hostUpdates.generationPass(ticket);
8019
+ }
8020
+ /**
8021
+ * Whether `file` is a description module (`ng-doc.page.ts`, `ng-doc.category.ts`,
8022
+ * `ng-doc.api.ts`) the generator watches: its edit starts a generation that reads it.
8023
+ * @param file An absolute path.
8024
+ */
8025
+ hostDescriptionModule(file) {
8026
+ return !this.disposed && DESCRIPTION_MODULE.test(path18.basename(file)) && (this.source?.matches({ kind: "update", path: file }) ?? false);
8027
+ }
8028
+ /** Whether `file` is a generated output (see {@link HostUpdateCoordinator.generated}). */
8029
+ hostGenerated(file) {
8030
+ return !this.disposed && this.hostUpdates.generated(file);
8031
+ }
7694
8032
  /** See {@link HostUpdateCoordinator.compilerCompanions}. */
7695
8033
  hostUpdateCompanions(ticket) {
7696
8034
  return this.disposed ? [] : this.hostUpdates.compilerCompanions(ticket);
@@ -7720,7 +8058,7 @@ var ViteAdapterLifecycle = class {
7720
8058
  hostClaimsFilesystemChange(file) {
7721
8059
  if (this.disposed) return false;
7722
8060
  if (this.hostUpdates.generated(file)) return true;
7723
- if (!DESCRIPTION_MODULE.test(path17.basename(file)) || !(this.source?.matches({ kind: "update", path: file }) ?? false))
8061
+ if (!DESCRIPTION_MODULE.test(path18.basename(file)) || !(this.source?.matches({ kind: "update", path: file }) ?? false))
7724
8062
  return false;
7725
8063
  return !(this.committedDescriptionModule(file) && existsSync5(file));
7726
8064
  }
@@ -7738,8 +8076,13 @@ var ViteAdapterLifecycle = class {
7738
8076
  this.hostUpdates.diagnostic(ticket, error2);
7739
8077
  this.report(error2);
7740
8078
  }
7741
- hostUpdateSettled(ticket) {
7742
- return this.hostUpdates.settle(ticket);
8079
+ /**
8080
+ * See {@link HostUpdateCoordinator.settle}.
8081
+ * @param ticket The hot update's ticket.
8082
+ * @param modules Whether its hooks hand Vite any module to update.
8083
+ */
8084
+ hostUpdateSettled(ticket, modules = true) {
8085
+ return this.hostUpdates.settle(ticket, modules);
7743
8086
  }
7744
8087
  hostUpdateCommitted(ticket) {
7745
8088
  return this.hostUpdates.committed(ticket);
@@ -7908,6 +8251,7 @@ var ViteAdapterLifecycle = class {
7908
8251
  }
7909
8252
  async disposeAll() {
7910
8253
  this.hostUpdates.dispose();
8254
+ this.stopContentClients();
7911
8255
  const results = await Promise.allSettled([
7912
8256
  this.registration,
7913
8257
  this.watch?.dispose(),
@@ -7924,7 +8268,7 @@ var ViteAdapterLifecycle = class {
7924
8268
  var NG_DOC_SYNTAX_THEME_NAME = "css-variables";
7925
8269
 
7926
8270
  // libs/builder/generator/vite/options.ts
7927
- import path18 from "node:path";
8271
+ import path19 from "node:path";
7928
8272
 
7929
8273
  // libs/builder/generator/progress/settings.ts
7930
8274
  var PROGRESS_SETTINGS = Object.freeze([
@@ -8043,6 +8387,21 @@ var ENGINE_SWITCHES = Object.freeze([
8043
8387
  values: /^(0|false|off|no)$/i,
8044
8388
  effect: "adding or removing a page compiles the application twice"
8045
8389
  },
8390
+ {
8391
+ name: "NGDOC_ANGULAR_DESCRIPTION_PASS",
8392
+ values: /^(0|false|off|no)$/i,
8393
+ effect: "a page title edit compiles the application twice"
8394
+ },
8395
+ {
8396
+ name: "NGDOC_VITE_CONTENT_UPDATE",
8397
+ values: /^(0|false|off|no)$/i,
8398
+ effect: "guide text edits reload the page"
8399
+ },
8400
+ {
8401
+ name: "NGDOC_VITE_MODULELESS_SETTLE",
8402
+ values: /^(0|false|off|no)$/i,
8403
+ effect: "hot updates of files the browser never loaded wait for the newest generation"
8404
+ },
8046
8405
  {
8047
8406
  name: "NGDOC_VITE_BUILD_HANDOFF",
8048
8407
  values: /^(0|false|off|no)$/i,
@@ -8118,7 +8477,7 @@ function resolveOptions(options) {
8118
8477
  );
8119
8478
  }
8120
8479
  const angularComponentProbe = text2(options.angularComponentProbe, "angularComponentProbe");
8121
- if (!path18.isAbsolute(angularComponentProbe) || !/\.ts$/.test(angularComponentProbe) || /\.d\.ts$/.test(angularComponentProbe) || angularComponentProbe.includes("?")) {
8480
+ if (!path19.isAbsolute(angularComponentProbe) || !/\.ts$/.test(angularComponentProbe) || /\.d\.ts$/.test(angularComponentProbe) || angularComponentProbe.includes("?")) {
8122
8481
  throw new TypeError(
8123
8482
  "angularComponentProbe must be an absolute application .ts component path."
8124
8483
  );
@@ -8137,8 +8496,8 @@ function resolveOptions(options) {
8137
8496
  if (options.progress !== void 0 && (!isProgressSetting(options.progress) || options.progress === "json")) {
8138
8497
  throw new TypeError("progress must be auto, live, plain, verbose, summary or off.");
8139
8498
  }
8140
- const workspace = path18.resolve(text2(options.generator.workspaceRoot, "workspaceRoot"));
8141
- const defaultRoot = path18.resolve(
8499
+ const workspace = path19.resolve(text2(options.generator.workspaceRoot, "workspaceRoot"));
8500
+ const defaultRoot = path19.resolve(
8142
8501
  text2(options.generator.defaults.outputRoot, "defaults.outputRoot")
8143
8502
  );
8144
8503
  return {
@@ -8148,7 +8507,7 @@ function resolveOptions(options) {
8148
8507
  themeModules,
8149
8508
  leaseIdentity: `${text2(options.generator.projectId, "projectId")}\0${workspace}\0${defaultRoot}`,
8150
8509
  angularPlugins: [...options.angularPlugins],
8151
- angularComponentProbe: path18.normalize(angularComponentProbe),
8510
+ angularComponentProbe: path19.normalize(angularComponentProbe),
8152
8511
  ...options.progress ? { progress: options.progress } : {}
8153
8512
  };
8154
8513
  }
@@ -8165,14 +8524,14 @@ function themeImports(options, configuration) {
8165
8524
  ].sort();
8166
8525
  }
8167
8526
  function within3(root, file) {
8168
- const relative = path18.relative(root, file);
8169
- return relative === "" || !relative.startsWith("..") && !path18.isAbsolute(relative);
8527
+ const relative = path19.relative(root, file);
8528
+ return relative === "" || !relative.startsWith("..") && !path19.isAbsolute(relative);
8170
8529
  }
8171
8530
  var CacheRootWatchIgnore = class {
8172
8531
  constructor(options) {
8173
8532
  this.options = options;
8174
8533
  const cacheRoot = options.generator.defaults.cacheRoot;
8175
- this.cacheRoot = typeof cacheRoot === "string" && path18.isAbsolute(cacheRoot) ? canonicalDrive(path18.resolve(cacheRoot)) : void 0;
8534
+ this.cacheRoot = typeof cacheRoot === "string" && path19.isAbsolute(cacheRoot) ? canonicalDrive(path19.resolve(cacheRoot)) : void 0;
8176
8535
  this.active = this.cacheRoot !== void 0;
8177
8536
  }
8178
8537
  get ignoring() {
@@ -8186,11 +8545,11 @@ var CacheRootWatchIgnore = class {
8186
8545
  workspaceRoot,
8187
8546
  defaults.outputRoot,
8188
8547
  defaults.docsRoot,
8189
- typeof defaults.tsConfig === "string" ? path18.dirname(defaults.tsConfig) : void 0
8548
+ typeof defaults.tsConfig === "string" ? path19.dirname(defaults.tsConfig) : void 0
8190
8549
  ]);
8191
8550
  const cacheRoot = this.cacheRoot;
8192
8551
  if (!this.active || !cacheRoot) return void 0;
8193
- return (file) => this.active && typeof file === "string" && within3(cacheRoot, path18.resolve(file));
8552
+ return (file) => this.active && typeof file === "string" && within3(cacheRoot, path19.resolve(file));
8194
8553
  }
8195
8554
  /** Re-checks the finally resolved Vite root (a later plugin can change `root`). */
8196
8555
  confirmRoot(viteRoot) {
@@ -8203,7 +8562,7 @@ var CacheRootWatchIgnore = class {
8203
8562
  admit(configuration) {
8204
8563
  const cacheRoot = this.cacheRoot;
8205
8564
  if (!this.active || !cacheRoot) return false;
8206
- const publishedCache = typeof configuration.cacheRoot === "string" ? canonicalDrive(path18.resolve(configuration.cacheRoot)) : void 0;
8565
+ const publishedCache = typeof configuration.cacheRoot === "string" ? canonicalDrive(path19.resolve(configuration.cacheRoot)) : void 0;
8207
8566
  if (publishedCache === cacheRoot && this.guard([configuration.outputRoot])) return false;
8208
8567
  this.active = false;
8209
8568
  return true;
@@ -8211,7 +8570,7 @@ var CacheRootWatchIgnore = class {
8211
8570
  guard(roots) {
8212
8571
  const cacheRoot = this.cacheRoot;
8213
8572
  if (!this.active || !cacheRoot || // Unvalidated roots are rejected by bootstrap later; never ignore when one is missing.
8214
- roots.some((value) => typeof value !== "string" || !value) || roots.some((value) => within3(cacheRoot, path18.resolve(value)))) {
8573
+ roots.some((value) => typeof value !== "string" || !value) || roots.some((value) => within3(cacheRoot, path19.resolve(value)))) {
8215
8574
  this.active = false;
8216
8575
  }
8217
8576
  return this.active;
@@ -8219,26 +8578,26 @@ var CacheRootWatchIgnore = class {
8219
8578
  };
8220
8579
  function metadataWatchIgnore(options, viteRoot) {
8221
8580
  const { workspaceRoot, defaults } = options.generator;
8222
- if (typeof workspaceRoot !== "string" || !path18.isAbsolute(workspaceRoot)) return void 0;
8223
- const idea = path18.resolve(workspaceRoot, ".idea");
8581
+ if (typeof workspaceRoot !== "string" || !path19.isAbsolute(workspaceRoot)) return void 0;
8582
+ const idea = path19.resolve(workspaceRoot, ".idea");
8224
8583
  const roots = [
8225
8584
  viteRoot,
8226
8585
  defaults.outputRoot,
8227
8586
  defaults.docsRoot,
8228
- typeof defaults.tsConfig === "string" ? path18.dirname(defaults.tsConfig) : void 0
8587
+ typeof defaults.tsConfig === "string" ? path19.dirname(defaults.tsConfig) : void 0
8229
8588
  ];
8230
8589
  const ignoreIdea = !roots.some(
8231
- (value) => typeof value === "string" && value && within3(idea, path18.resolve(value))
8590
+ (value) => typeof value === "string" && value && within3(idea, path19.resolve(value))
8232
8591
  );
8233
8592
  return (file) => {
8234
8593
  if (typeof file !== "string") return false;
8235
- const target = path18.resolve(file);
8236
- return path18.basename(target) === ".DS_Store" || ignoreIdea && within3(idea, target);
8594
+ const target = path19.resolve(file);
8595
+ return path19.basename(target) === ".DS_Store" || ignoreIdea && within3(idea, target);
8237
8596
  };
8238
8597
  }
8239
8598
  function staticViteConfig(options, viteRoot = process.cwd(), cacheWatch = new CacheRootWatchIgnore(options)) {
8240
- const cacheIgnore = cacheWatch.matcher(path18.resolve(viteRoot));
8241
- const metadataIgnore = metadataWatchIgnore(options, path18.resolve(viteRoot));
8599
+ const cacheIgnore = cacheWatch.matcher(path19.resolve(viteRoot));
8600
+ const metadataIgnore = metadataWatchIgnore(options, path19.resolve(viteRoot));
8242
8601
  const ignored = [GENERATED_STAGE_IGNORE];
8243
8602
  if (cacheIgnore) ignored.push(cacheIgnore);
8244
8603
  if (metadataIgnore) ignored.push(metadataIgnore);
@@ -8274,10 +8633,10 @@ function assertThemeModules(options, configuration) {
8274
8633
 
8275
8634
  // libs/builder/generator/vite/output-watch.ts
8276
8635
  import { realpathSync as realpathSync3 } from "node:fs";
8277
- import path19 from "node:path";
8636
+ import path20 from "node:path";
8278
8637
  var OUTPUT_WATCH_ATTACH_TIMEOUT_MS = 1e4;
8279
8638
  function normalize6(value) {
8280
- return canonicalDrive(path19.resolve(value).replace(/\\/g, "/"));
8639
+ return canonicalDrive(path20.resolve(value).replace(/\\/g, "/"));
8281
8640
  }
8282
8641
  function within4(target, root) {
8283
8642
  return target === root || target.startsWith(`${root}/`);
@@ -8309,9 +8668,9 @@ async function watchOutputRoot(watcher, viteRoot, outputRoot, files, options = {
8309
8668
  for (const file of files) {
8310
8669
  let target = `${root}/${file.replace(/\\/g, "/")}`;
8311
8670
  while (target !== root && within4(target, root)) {
8312
- const parent = path19.posix.dirname(target);
8671
+ const parent = path20.posix.dirname(target);
8313
8672
  const listed2 = entries.get(parent) ?? /* @__PURE__ */ new Set();
8314
- listed2.add(path19.posix.basename(target));
8673
+ listed2.add(path20.posix.basename(target));
8315
8674
  entries.set(parent, listed2);
8316
8675
  target = parent;
8317
8676
  }
@@ -9727,7 +10086,7 @@ function hotPayload(value, childToServer = false) {
9727
10086
  case "full-reload":
9728
10087
  return (value.path === void 0 || typeof value.path === "string") && (value.triggeredBy === void 0 || typeof value.triggeredBy === "string");
9729
10088
  case "prune":
9730
- return Array.isArray(value.paths) && value.paths.every((path25) => typeof path25 === "string");
10089
+ return Array.isArray(value.paths) && value.paths.every((path26) => typeof path26 === "string");
9731
10090
  case "update":
9732
10091
  return Array.isArray(value.updates) && value.updates.every(
9733
10092
  (update) => record2(update) && (update.type === "js-update" || update.type === "css-update") && typeof update.path === "string" && typeof update.acceptedPath === "string" && Number.isFinite(update.timestamp)
@@ -10786,6 +11145,15 @@ function createPlugin(options) {
10786
11145
  diagnosticMark() {
10787
11146
  return (active?.lifecycle ?? pendingLifecycle)?.hostDiagnosticMark() ?? 0;
10788
11147
  },
11148
+ generationPass(ticket) {
11149
+ return (active?.lifecycle ?? pendingLifecycle)?.hostGenerationPass(ticket) ?? false;
11150
+ },
11151
+ descriptionModule(file) {
11152
+ return (active?.lifecycle ?? pendingLifecycle)?.hostDescriptionModule(file) ?? false;
11153
+ },
11154
+ generated(file) {
11155
+ return (active?.lifecycle ?? pendingLifecycle)?.hostGenerated(file) ?? false;
11156
+ },
10789
11157
  claimsFilesystemChange(file) {
10790
11158
  return (active?.lifecycle ?? pendingLifecycle)?.hostClaimsFilesystemChange(file) ?? false;
10791
11159
  },
@@ -10803,8 +11171,8 @@ function createPlugin(options) {
10803
11171
  committed(ticket) {
10804
11172
  return (active?.lifecycle ?? pendingLifecycle)?.hostUpdateCommitted(ticket) ?? Promise.resolve();
10805
11173
  },
10806
- settle(ticket) {
10807
- return (active?.lifecycle ?? pendingLifecycle)?.hostUpdateSettled(ticket) ?? Promise.resolve();
11174
+ settle(ticket, modules) {
11175
+ return (active?.lifecycle ?? pendingLifecycle)?.hostUpdateSettled(ticket, modules) ?? Promise.resolve();
10808
11176
  },
10809
11177
  fail(error2) {
10810
11178
  (active?.lifecycle ?? pendingLifecycle)?.hostUpdateFailed(error2);
@@ -10853,7 +11221,7 @@ function createPlugin(options) {
10853
11221
  "[NGDOC_VITE_BUILD_WATCH] Vite build watch is unsupported; use the development server."
10854
11222
  );
10855
11223
  }
10856
- return staticViteConfig(resolved, path20.resolve(config.root ?? process.cwd()), cacheWatch);
11224
+ return staticViteConfig(resolved, path21.resolve(config.root ?? process.cwd()), cacheWatch);
10857
11225
  },
10858
11226
  configResolved(config) {
10859
11227
  vite = config;
@@ -10984,7 +11352,14 @@ function createPlugin(options) {
10984
11352
  load(id) {
10985
11353
  return ssrRenderer.controlModule(id) ?? null;
10986
11354
  },
10987
- transformIndexHtml: { order: "pre", handler: transformNgDocIndex },
11355
+ transformIndexHtml: {
11356
+ order: "pre",
11357
+ async handler(html, context) {
11358
+ const transformed = await transformNgDocIndex(html);
11359
+ const tags = context?.server ? contentUpdateClientTags(transformed) : [];
11360
+ return tags.length > 0 ? { html: transformed, tags } : transformed;
11361
+ }
11362
+ },
10988
11363
  async generateBundle(_output, bundle) {
10989
11364
  if (vite?.command === "build" && active) await active.lifecycle.assets.emit(this, bundle);
10990
11365
  },
@@ -11012,7 +11387,10 @@ function createPlugin(options) {
11012
11387
  const ticket = hostUpdates.get(context);
11013
11388
  if (ticket) {
11014
11389
  hostUpdates.delete(context);
11015
- await (active?.lifecycle ?? pendingLifecycle)?.hostUpdateCompleted(ticket);
11390
+ const modules = handsViteModules(context.file, context.modules) || Object.values(devServer?.environments ?? {}).some(
11391
+ (environment) => environment !== this.environment && (environment.moduleGraph.getModulesByFile(context.file)?.size ?? 0) > 0
11392
+ );
11393
+ await (active?.lifecycle ?? pendingLifecycle)?.hostUpdateCompleted(ticket, modules);
11016
11394
  }
11017
11395
  if (!(active?.lifecycle ?? pendingLifecycle)?.hostUpdateAnnounced(context.read)) return;
11018
11396
  const invalidated = /* @__PURE__ */ new Set();
@@ -11036,11 +11414,11 @@ import { minimatch as minimatch2 } from "minimatch";
11036
11414
  import { existsSync as existsSync6 } from "node:fs";
11037
11415
  import { mkdir as mkdir2, readdir, readFile as readFile8, stat as stat5, writeFile as writeFile2 } from "node:fs/promises";
11038
11416
  import { createRequire as createRequire2 } from "node:module";
11039
- import path23 from "node:path";
11417
+ import path24 from "node:path";
11040
11418
  import { escapePath, glob } from "tinyglobby";
11041
11419
 
11042
11420
  // libs/builder/generator/vite/dev-styles.ts
11043
- import path21 from "node:path";
11421
+ import path22 from "node:path";
11044
11422
  var GATE_TIMINGS = { sheet: 5e3, quiet: 1500, limit: 1e4 };
11045
11423
  function ngDocDevStyleGate(timings = GATE_TIMINGS) {
11046
11424
  return `(() => {
@@ -11099,8 +11477,8 @@ async function ngDocDevStyleTags(server, styles) {
11099
11477
  { tag: "script", children: NG_DOC_DEV_STYLE_GATE, injectTo: "head-prepend" }
11100
11478
  ];
11101
11479
  for (const style of styles) {
11102
- const relative = path21.relative(root, style);
11103
- const url = relative && !relative.startsWith("..") && !path21.isAbsolute(relative) ? `/${relative.split(path21.sep).join("/")}` : `/@fs/${style.split(path21.sep).join("/").replace(/^\/+/, "")}`;
11480
+ const relative = path22.relative(root, style);
11481
+ const url = relative && !relative.startsWith("..") && !path22.isAbsolute(relative) ? `/${relative.split(path22.sep).join("/")}` : `/@fs/${style.split(path22.sep).join("/").replace(/^\/+/, "")}`;
11104
11482
  try {
11105
11483
  const sheet = cssModuleSheet((await environment.transformRequest(url))?.code ?? "");
11106
11484
  if (!sheet) continue;
@@ -11132,7 +11510,7 @@ function cssModuleSheet(code) {
11132
11510
  }
11133
11511
 
11134
11512
  // libs/builder/generator/vite/mime.ts
11135
- import path22 from "node:path";
11513
+ import path23 from "node:path";
11136
11514
  var TYPES = {
11137
11515
  ".aac": "audio/aac",
11138
11516
  ".apng": "image/apng",
@@ -11182,7 +11560,7 @@ var TYPES = {
11182
11560
  ".zip": "application/zip"
11183
11561
  };
11184
11562
  function contentType(file) {
11185
- return TYPES[path22.extname(file).toLowerCase()] ?? "application/octet-stream";
11563
+ return TYPES[path23.extname(file).toLowerCase()] ?? "application/octet-stream";
11186
11564
  }
11187
11565
 
11188
11566
  // libs/builder/generator/vite/application.ts
@@ -11288,23 +11666,23 @@ function posix(value) {
11288
11666
  return value.replace(/\\/g, "/");
11289
11667
  }
11290
11668
  function specifier(workspaceRoot, value) {
11291
- const file = path23.resolve(workspaceRoot, value);
11292
- return value.startsWith(".") || path23.isAbsolute(value) || existsSync6(file) ? posix(file) : value;
11669
+ const file = path24.resolve(workspaceRoot, value);
11670
+ return value.startsWith(".") || path24.isAbsolute(value) || existsSync6(file) ? posix(file) : value;
11293
11671
  }
11294
11672
  async function resolveAssets(assets, workspaceRoot, sourceRoot) {
11295
11673
  const resolved = [];
11296
11674
  for (const [index, asset] of assets.entries()) {
11297
11675
  if (typeof asset === "string") {
11298
- const input = path23.resolve(workspaceRoot, text4(asset, `assets[${index}]`));
11676
+ const input = path24.resolve(workspaceRoot, text4(asset, `assets[${index}]`));
11299
11677
  const file = await stat5(input).then(
11300
11678
  (value) => value.isFile(),
11301
11679
  () => {
11302
11680
  throw optionError(`assets[${index}] does not exist: ${asset}`);
11303
11681
  }
11304
11682
  );
11305
- const directory = file ? path23.dirname(input) : input;
11306
- const relative = path23.relative(sourceRoot, directory);
11307
- if (relative.startsWith("..") || path23.isAbsolute(relative)) {
11683
+ const directory = file ? path24.dirname(input) : input;
11684
+ const relative = path24.relative(sourceRoot, directory);
11685
+ if (relative.startsWith("..") || path24.isAbsolute(relative)) {
11308
11686
  throw optionError(
11309
11687
  `assets[${index}] (${asset}) is outside sourceRoot (${sourceRoot}); use a { glob, input, output } entry.`
11310
11688
  );
@@ -11312,18 +11690,18 @@ async function resolveAssets(assets, workspaceRoot, sourceRoot) {
11312
11690
  resolved.push({
11313
11691
  input: directory,
11314
11692
  output: posix(relative),
11315
- glob: file ? path23.basename(input) : "**/*",
11693
+ glob: file ? path24.basename(input) : "**/*",
11316
11694
  ignore: []
11317
11695
  });
11318
11696
  continue;
11319
11697
  }
11320
11698
  if (!asset || typeof asset !== "object") throw optionError(`assets[${index}] is invalid.`);
11321
11699
  const output = posix(asset.output ?? "").replace(/^\/+|\/+$/g, "");
11322
- if (output.split("/").includes("..") || path23.isAbsolute(output)) {
11700
+ if (output.split("/").includes("..") || path24.isAbsolute(output)) {
11323
11701
  throw optionError(`assets[${index}].output must stay inside the output directory.`);
11324
11702
  }
11325
11703
  resolved.push({
11326
- input: path23.resolve(workspaceRoot, text4(asset.input, `assets[${index}].input`)),
11704
+ input: path24.resolve(workspaceRoot, text4(asset.input, `assets[${index}].input`)),
11327
11705
  output,
11328
11706
  glob: text4(asset.glob, `assets[${index}].glob`),
11329
11707
  ignore: [...asset.ignore ?? []]
@@ -11345,7 +11723,7 @@ async function collectAssets(assets) {
11345
11723
  expandDirectories: false
11346
11724
  });
11347
11725
  for (const relative of matches.map(posix).sort()) {
11348
- files.set(outputName(asset, relative), path23.join(asset.input, relative));
11726
+ files.set(outputName(asset, relative), path24.join(asset.input, relative));
11349
11727
  }
11350
11728
  }
11351
11729
  return files;
@@ -11365,14 +11743,14 @@ function matchAssets(assets, base, url) {
11365
11743
  for (const asset of [...assets].reverse()) {
11366
11744
  const relative = asset.output ? requested.startsWith(`${asset.output}/`) ? requested.slice(asset.output.length + 1) : void 0 : requested;
11367
11745
  if (relative && minimatch2(relative, asset.glob, { dot: true }) && !asset.ignore.some((pattern) => minimatch2(relative, pattern, { dot: true }))) {
11368
- candidates.push({ file: path23.join(asset.input, relative), relative });
11746
+ candidates.push({ file: path24.join(asset.input, relative), relative });
11369
11747
  }
11370
11748
  }
11371
11749
  return candidates;
11372
11750
  }
11373
11751
  function resolvable(root, name) {
11374
11752
  try {
11375
- createRequire2(path23.join(root, "package.json")).resolve(`${name}/package.json`);
11753
+ createRequire2(path24.join(root, "package.json")).resolve(`${name}/package.json`);
11376
11754
  return true;
11377
11755
  } catch {
11378
11756
  return false;
@@ -11380,17 +11758,17 @@ function resolvable(root, name) {
11380
11758
  }
11381
11759
  async function coreImports(root) {
11382
11760
  const found = /* @__PURE__ */ new Set();
11383
- const require2 = createRequire2(path23.join(root, "package.json"));
11761
+ const require2 = createRequire2(path24.join(root, "package.json"));
11384
11762
  for (const name of ["@ng-doc/app", "@ng-doc/ui-kit"]) {
11385
11763
  let directory;
11386
11764
  try {
11387
- directory = path23.join(path23.dirname(require2.resolve(`${name}/package.json`)), "fesm2022");
11765
+ directory = path24.join(path24.dirname(require2.resolve(`${name}/package.json`)), "fesm2022");
11388
11766
  } catch {
11389
11767
  continue;
11390
11768
  }
11391
11769
  const files = await readdir(directory).catch(() => []);
11392
11770
  for (const file of files.filter((item) => item.endsWith(".mjs")).sort()) {
11393
- for (const match of (await readFile8(path23.join(directory, file), "utf8")).matchAll(
11771
+ for (const match of (await readFile8(path24.join(directory, file), "utf8")).matchAll(
11394
11772
  CORE_IMPORT
11395
11773
  )) {
11396
11774
  found.add(match[1]);
@@ -11410,8 +11788,8 @@ function demoDocument(index) {
11410
11788
  ) : `${index}${DEMO_ROOT}`;
11411
11789
  }
11412
11790
  function withDemoInput(input, key, id, next2) {
11413
- const record3 = typeof input === "string" ? { [path23.parse(input).name]: input } : Array.isArray(input) ? Object.fromEntries(input.map((item) => [path23.parse(item).name, item])) : { ...input ?? {} };
11414
- if (Object.values(record3).some((item) => item === id || posix(path23.resolve(item)) === id)) {
11791
+ const record3 = typeof input === "string" ? { [path24.parse(input).name]: input } : Array.isArray(input) ? Object.fromEntries(input.map((item) => [path24.parse(item).name, item])) : { ...input ?? {} };
11792
+ if (Object.values(record3).some((item) => item === id || posix(path24.resolve(item)) === id)) {
11415
11793
  record3[key] = next2;
11416
11794
  }
11417
11795
  return record3;
@@ -11427,15 +11805,15 @@ function withBase(html, base) {
11427
11805
  function createNgDocApplicationPlugin(options) {
11428
11806
  if (!options || typeof options !== "object") throw optionError("options must be an object.");
11429
11807
  const warnings = checkOptionKeys(options);
11430
- const workspaceRoot = path23.resolve(options.workspaceRoot ?? process.cwd());
11431
- const browser = path23.resolve(workspaceRoot, text4(options.browser, "browser"));
11432
- const server = options.server === void 0 ? void 0 : path23.resolve(workspaceRoot, text4(options.server, "server"));
11433
- const sourceRoot = path23.resolve(workspaceRoot, options.sourceRoot ?? path23.dirname(browser));
11808
+ const workspaceRoot = path24.resolve(options.workspaceRoot ?? process.cwd());
11809
+ const browser = path24.resolve(workspaceRoot, text4(options.browser, "browser"));
11810
+ const server = options.server === void 0 ? void 0 : path24.resolve(workspaceRoot, text4(options.server, "server"));
11811
+ const sourceRoot = path24.resolve(workspaceRoot, options.sourceRoot ?? path24.dirname(browser));
11434
11812
  const polyfills = (options.polyfills ?? []).map(
11435
11813
  (item, index) => specifier(workspaceRoot, text4(item, `polyfills[${index}]`))
11436
11814
  );
11437
11815
  const styles = (options.styles ?? []).map(
11438
- (item, index) => posix(path23.resolve(workspaceRoot, text4(item, `styles[${index}]`)))
11816
+ (item, index) => posix(path24.resolve(workspaceRoot, text4(item, `styles[${index}]`)))
11439
11817
  );
11440
11818
  const assetPatterns = [...options.assets ?? []];
11441
11819
  const zone = (options.polyfills ?? []).some(
@@ -11444,7 +11822,7 @@ function createNgDocApplicationPlugin(options) {
11444
11822
  let viteRoot = process.cwd();
11445
11823
  let demoApi;
11446
11824
  let demo;
11447
- const demoPage = () => posix(path23.join(viteRoot, NG_DOC_DEMO_PAGE));
11825
+ const demoPage = () => posix(path24.join(viteRoot, NG_DOC_DEMO_PAGE));
11448
11826
  const currentDemo = async () => config?.command === "build" ? demo : await demoApi?.current().catch(() => void 0);
11449
11827
  let assets;
11450
11828
  const resolvedAssets = () => assets ??= resolveAssets(assetPatterns, workspaceRoot, sourceRoot);
@@ -11453,12 +11831,12 @@ function createNgDocApplicationPlugin(options) {
11453
11831
  include: [
11454
11832
  .../* @__PURE__ */ new Set([
11455
11833
  ...await coreImports(viteRoot2),
11456
- ...polyfills.filter((item) => !path23.isAbsolute(item)),
11834
+ ...polyfills.filter((item) => !path24.isAbsolute(item)),
11457
11835
  ...resolvable(viteRoot2, "tslib") ? ["tslib"] : []
11458
11836
  ])
11459
11837
  ].sort(),
11460
- entries: [...polyfills.filter((item) => path23.isAbsolute(item)), posix(browser)].map(
11461
- (file) => escapePath(posix(path23.relative(viteRoot2, file)))
11838
+ entries: [...polyfills.filter((item) => path24.isAbsolute(item)), posix(browser)].map(
11839
+ (file) => escapePath(posix(path24.relative(viteRoot2, file)))
11462
11840
  )
11463
11841
  });
11464
11842
  const api = Object.freeze({
@@ -11470,7 +11848,7 @@ function createNgDocApplicationPlugin(options) {
11470
11848
  enforce: "pre",
11471
11849
  api: { ngDocApplication: api },
11472
11850
  async config(user, environment) {
11473
- viteRoot = path23.resolve(user.root ?? process.cwd());
11851
+ viteRoot = path24.resolve(user.root ?? process.cwd());
11474
11852
  return {
11475
11853
  resolve: { dedupe: ANGULAR_DEDUPE },
11476
11854
  // Every `vite build` is a production build of the application (the Angular CLI's
@@ -11509,9 +11887,9 @@ function createNgDocApplicationPlugin(options) {
11509
11887
  NG_DOC_SERVER_ENTRY,
11510
11888
  NG_DOC_DEMO_SERVER_ENTRY
11511
11889
  ) : withDemoInput(
11512
- input.input ?? path23.join(viteRoot, "index.html"),
11890
+ input.input ?? path24.join(viteRoot, "index.html"),
11513
11891
  "ng-doc-demo",
11514
- posix(path23.join(viteRoot, "index.html")),
11892
+ posix(path24.join(viteRoot, "index.html")),
11515
11893
  demoPage()
11516
11894
  )
11517
11895
  };
@@ -11520,7 +11898,7 @@ function createNgDocApplicationPlugin(options) {
11520
11898
  if (source === NG_DOC_BROWSER_ENTRY) return BROWSER_ID;
11521
11899
  if (source === NG_DOC_DEMO_ENTRY) return DEMO_ID;
11522
11900
  if (source === NG_DOC_DEMO_SERVER_ENTRY) return DEMO_SERVER_ID;
11523
- if (config?.command === "build" && demo && posix(path23.resolve(viteRoot, source)) === demoPage()) {
11901
+ if (config?.command === "build" && demo && posix(path24.resolve(viteRoot, source)) === demoPage()) {
11524
11902
  return demoPage();
11525
11903
  }
11526
11904
  if ((importer === BROWSER_ID || importer === DEMO_ID) && config?.command === "build") {
@@ -11539,7 +11917,7 @@ function createNgDocApplicationPlugin(options) {
11539
11917
  },
11540
11918
  load(id) {
11541
11919
  if (config?.command === "build" && demo && id === demoPage()) {
11542
- const index = path23.join(viteRoot, "index.html");
11920
+ const index = path24.join(viteRoot, "index.html");
11543
11921
  this.addWatchFile(index);
11544
11922
  return readFile8(index, "utf8").then(demoDocument);
11545
11923
  }
@@ -11622,7 +12000,7 @@ function createNgDocApplicationPlugin(options) {
11622
12000
  next2();
11623
12001
  return;
11624
12002
  }
11625
- const index = await readFile8(path23.join(viteRoot, "index.html"), "utf8");
12003
+ const index = await readFile8(path24.join(viteRoot, "index.html"), "utf8");
11626
12004
  const html = await server2.transformIndexHtml(
11627
12005
  url,
11628
12006
  demoDocument(index),
@@ -11639,11 +12017,11 @@ function createNgDocApplicationPlugin(options) {
11639
12017
  // replaces each copy with the rendered page.
11640
12018
  async writeBundle(output) {
11641
12019
  if (config?.command !== "build" || config.build.ssr || !demo || !output.dir) return;
11642
- const page = await readFile8(path23.join(output.dir, NG_DOC_DEMO_PAGE), "utf8");
12020
+ const page = await readFile8(path24.join(output.dir, NG_DOC_DEMO_PAGE), "utf8");
11643
12021
  for (const route of [...demo.pages].sort()) {
11644
12022
  if (unsafeSegment(route)) continue;
11645
- const file = path23.join(output.dir, ...route.split("/"), "index.html");
11646
- await mkdir2(path23.dirname(file), { recursive: true });
12023
+ const file = path24.join(output.dir, ...route.split("/"), "index.html");
12024
+ await mkdir2(path24.dirname(file), { recursive: true });
11647
12025
  await writeFile2(file, page);
11648
12026
  }
11649
12027
  },
@@ -11794,7 +12172,7 @@ function prerenderNgDoc(options) {
11794
12172
  // libs/builder/generator/vite/production.ts
11795
12173
  import { existsSync as existsSync7 } from "node:fs";
11796
12174
  import { rm as rm2, writeFile as writeFile3 } from "node:fs/promises";
11797
- import path24 from "node:path";
12175
+ import path25 from "node:path";
11798
12176
  import { build as viteBuild } from "vite";
11799
12177
  var defaultDependencies = {
11800
12178
  build: viteBuild,
@@ -11831,11 +12209,11 @@ function applicationProbe() {
11831
12209
  async function buildNgDocViteApplication(options, dependencies = defaultDependencies) {
11832
12210
  assertSupportedViteVersion();
11833
12211
  assertConsistentAngularBuild();
11834
- const configFile = path24.resolve(options.configFile);
11835
- const outputPath = path24.resolve(options.outputPath);
11836
- const browser = path24.join(outputPath, "browser");
11837
- const serverDirectory = path24.join(outputPath, "server");
11838
- const serverEntry = path24.join(serverDirectory, "server.mjs");
12212
+ const configFile = path25.resolve(options.configFile);
12213
+ const outputPath = path25.resolve(options.outputPath);
12214
+ const browser = path25.join(outputPath, "browser");
12215
+ const serverDirectory = path25.join(outputPath, "server");
12216
+ const serverEntry = path25.join(serverDirectory, "server.mjs");
11839
12217
  const mode = options.mode ?? "production";
11840
12218
  const log = options.log ?? (() => {
11841
12219
  });
@@ -11872,7 +12250,7 @@ async function buildNgDocViteApplication(options, dependencies = defaultDependen
11872
12250
  ssr ??= entry !== void 0;
11873
12251
  if (!ssr) {
11874
12252
  await rm2(serverDirectory, { recursive: true, force: true });
11875
- await rm2(path24.join(outputPath, "prerendered-routes.json"), { force: true });
12253
+ await rm2(path25.join(outputPath, "prerendered-routes.json"), { force: true });
11876
12254
  if (options.prerender === true) throw noServer();
11877
12255
  } else {
11878
12256
  if (!entry) {
@@ -11907,13 +12285,13 @@ async function buildNgDocViteApplication(options, dependencies = defaultDependen
11907
12285
  }
11908
12286
  const prerender = options.prerender ?? (options.skipBuild ? true : ssr === true);
11909
12287
  if (!prerender) return { browser, ...ssr ? { server: serverEntry } : {} };
11910
- const demoServerEntry = path24.join(serverDirectory, "demo-server.mjs");
12288
+ const demoServerEntry = path25.join(serverDirectory, "demo-server.mjs");
11911
12289
  const report = await timed(
11912
12290
  "Prerendered the routes",
11913
12291
  () => dependencies.prerender({
11914
12292
  browserDir: browser,
11915
12293
  serverEntry,
11916
- ...existsSync7(demoServerEntry) && existsSync7(path24.join(browser, "ng-doc-demo.html")) ? { demoServerEntry } : {},
12294
+ ...existsSync7(demoServerEntry) && existsSync7(path25.join(browser, "ng-doc-demo.html")) ? { demoServerEntry } : {},
11917
12295
  routes: options.routes ?? [],
11918
12296
  discoverRoutes: options.discoverRoutes ?? true,
11919
12297
  ...options.routeTimeoutMs === void 0 ? {} : { routeTimeoutMs: options.routeTimeoutMs },
@@ -11921,7 +12299,7 @@ async function buildNgDocViteApplication(options, dependencies = defaultDependen
11921
12299
  })
11922
12300
  );
11923
12301
  await writeFile3(
11924
- path24.join(outputPath, "prerendered-routes.json"),
12302
+ path25.join(outputPath, "prerendered-routes.json"),
11925
12303
  `${JSON.stringify({ routes: report.routes, excluded: report.excluded }, null, 2)}
11926
12304
  `
11927
12305
  );