vde-open 0.1.1 → 0.1.4

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.
@@ -8515,10 +8515,65 @@ function htmlText(node) {
8515
8515
  for (const child of node.childNodes) if (!HTML_SKIPPED.has(child.nodeName)) text += htmlText(child);
8516
8516
  return text;
8517
8517
  }
8518
+ const HTML_HEADING = /^h([1-6])$/;
8519
+ function htmlIdOf(element) {
8520
+ const id = element.attrs.find((attribute) => attribute.name === "id")?.value;
8521
+ return id === void 0 || id === "" ? null : id;
8522
+ }
8523
+ function fragmentOfAnchor(anchor) {
8524
+ return encodeURIComponent(anchor);
8525
+ }
8526
+ function htmlHeadings(document) {
8527
+ const used = /* @__PURE__ */ new Set();
8528
+ const all = [document];
8529
+ while (all.length > 0) {
8530
+ const node = all.pop();
8531
+ if ("tagName" in node) {
8532
+ const id = htmlIdOf(node);
8533
+ if (id !== null) used.add(id);
8534
+ if ("content" in node) all.push(node.content);
8535
+ }
8536
+ if ("childNodes" in node) for (const child of node.childNodes) all.push(child);
8537
+ }
8538
+ const found = [];
8539
+ const stack = [document];
8540
+ while (stack.length > 0) {
8541
+ const node = stack.pop();
8542
+ if ("tagName" in node) {
8543
+ if (HTML_SKIPPED.has(node.tagName)) continue;
8544
+ const match = HTML_HEADING.exec(node.tagName);
8545
+ if (match) {
8546
+ found.push({
8547
+ element: node,
8548
+ level: Number(match[1])
8549
+ });
8550
+ continue;
8551
+ }
8552
+ }
8553
+ if ("childNodes" in node) for (let index = node.childNodes.length - 1; index >= 0; index -= 1) stack.push(node.childNodes[index]);
8554
+ }
8555
+ return found.map(({ element, level }, index) => {
8556
+ let anchor = htmlIdOf(element);
8557
+ if (anchor === null) {
8558
+ const base = `h${String(index + 1)}`;
8559
+ anchor = base;
8560
+ for (let suffix = 2; used.has(anchor); suffix += 1) anchor = `${base}-${String(suffix)}`;
8561
+ used.add(anchor);
8562
+ }
8563
+ return {
8564
+ element,
8565
+ level,
8566
+ sectionId: sectionIdOf(index + 1),
8567
+ anchor
8568
+ };
8569
+ });
8570
+ }
8518
8571
  function tidy(text) {
8519
8572
  return text.split("\n").map(collapse$1).filter((line) => line !== "").join("\n");
8520
8573
  }
8521
8574
  function analyzeHtml(source) {
8575
+ const document = parse$50(source, { scriptingEnabled: false });
8576
+ const headingOf = new Map(htmlHeadings(document).map((heading) => [heading.element, heading]));
8522
8577
  const headings = [];
8523
8578
  const bodies = [""];
8524
8579
  let title = null;
@@ -8539,13 +8594,12 @@ function analyzeHtml(source) {
8539
8594
  if (text !== "") title = text;
8540
8595
  }
8541
8596
  if (HTML_SKIPPED.has(node.tagName)) return;
8542
- const match = /^h([1-6])$/.exec(node.tagName);
8543
- if (match) {
8544
- const id = node.attrs.find((attribute) => attribute.name === "id")?.value;
8597
+ const heading = headingOf.get(node);
8598
+ if (heading) {
8545
8599
  headings.push({
8546
- level: Number(match[1]),
8600
+ level: heading.level,
8547
8601
  title: collapse$1(htmlText(node)),
8548
- anchor: id ?? `h${String(headings.length + 1)}`
8602
+ anchor: heading.anchor
8549
8603
  });
8550
8604
  bodies.push("");
8551
8605
  return;
@@ -8559,7 +8613,7 @@ function analyzeHtml(source) {
8559
8613
  append(separator);
8560
8614
  }
8561
8615
  };
8562
- walk(parse$50(source, { scriptingEnabled: false }), 0);
8616
+ walk(document, 0);
8563
8617
  const outline = buildOutline(headings);
8564
8618
  const [preamble, ...texts] = bodies.map(tidy);
8565
8619
  return {
@@ -14600,6 +14654,8 @@ function transformStaticHtml(input, log = new DiagnosticLog()) {
14600
14654
  }
14601
14655
  };
14602
14656
  const document = parse$50(input.source, { scriptingEnabled: false });
14657
+ const headings = interactive ? [] : htmlHeadings(document);
14658
+ for (const heading of headings) setId(heading.element, heading.anchor);
14603
14659
  rewriteTree(document, policy);
14604
14660
  if (interactive && input.sdkScript !== void 0) insertFirstScript(document, input.sdkScript);
14605
14661
  const html = serialize(document);
@@ -14607,9 +14663,43 @@ function transformStaticHtml(input, log = new DiagnosticLog()) {
14607
14663
  return {
14608
14664
  html,
14609
14665
  links,
14610
- diagnostics: log.list()
14666
+ diagnostics: log.list(),
14667
+ headingTargets: reachable(document, headings)
14611
14668
  };
14612
14669
  }
14670
+ function setId(element, id) {
14671
+ if (htmlIdOf(element) === id) return;
14672
+ element.attrs = [...element.attrs.filter((attribute) => attribute.name !== "id"), {
14673
+ name: "id",
14674
+ value: id
14675
+ }];
14676
+ }
14677
+ function reachable(document, headings) {
14678
+ if (headings.length === 0) return [];
14679
+ const present = /* @__PURE__ */ new Set();
14680
+ const firstById = /* @__PURE__ */ new Map();
14681
+ const anchorNames = /* @__PURE__ */ new Set();
14682
+ const stack = [document];
14683
+ while (stack.length > 0) {
14684
+ const node = stack.pop();
14685
+ if (isElement(node)) {
14686
+ present.add(node);
14687
+ const id = htmlIdOf(node);
14688
+ if (id !== null && !firstById.has(id)) firstById.set(id, node);
14689
+ const name = node.tagName === "a" ? getAttribute(node, "name") : void 0;
14690
+ if (name !== void 0 && name !== "") anchorNames.add(name);
14691
+ }
14692
+ if (isParent(node)) for (let index = node.childNodes.length - 1; index >= 0; index -= 1) stack.push(node.childNodes[index]);
14693
+ }
14694
+ return headings.filter(({ element, anchor }) => {
14695
+ if (!present.has(element) || firstById.get(anchor) !== element) return false;
14696
+ const fragment = fragmentOfAnchor(anchor);
14697
+ return fragment === anchor || !firstById.has(fragment) && !anchorNames.has(fragment);
14698
+ }).map(({ sectionId, anchor }) => ({
14699
+ sectionId,
14700
+ anchor
14701
+ }));
14702
+ }
14613
14703
  function insertFirstScript(document, source) {
14614
14704
  if (source.toLowerCase().includes("<\/script")) throw new Error("script text must not close itself");
14615
14705
  const head = document.childNodes.find((node) => isElement(node) && node.tagName === "html")?.childNodes.find((node) => isElement(node) && node.tagName === "head");
@@ -14745,7 +14835,8 @@ function renderDocument(input) {
14745
14835
  html: null,
14746
14836
  stylesheets,
14747
14837
  links: info.links,
14748
- diagnostics: info.diagnostics
14838
+ diagnostics: info.diagnostics,
14839
+ headingTargets: []
14749
14840
  };
14750
14841
  }
14751
14842
  const result = transformStaticHtml({
@@ -14757,7 +14848,8 @@ function renderDocument(input) {
14757
14848
  html: result.html,
14758
14849
  stylesheets,
14759
14850
  links: result.links,
14760
- diagnostics: result.diagnostics
14851
+ diagnostics: result.diagnostics,
14852
+ headingTargets: result.headingTargets
14761
14853
  };
14762
14854
  }
14763
14855
  function scanReferences(kind, source) {
@@ -5666,6 +5666,40 @@ const assetRecordSchema = strictObject({
5666
5666
  sha256: sha256Schema,
5667
5667
  byteLength: number().int().nonnegative()
5668
5668
  });
5669
+ const repositoryCheckoutSchema = discriminatedUnion("kind", [strictObject({
5670
+ id: string(),
5671
+ kind: literal("main")
5672
+ }), strictObject({
5673
+ id: string(),
5674
+ kind: literal("linked"),
5675
+ name: string(),
5676
+ branch: string().nullable()
5677
+ })]);
5678
+ const repositoryReasonSchema = _enum([
5679
+ "invalid-git-file",
5680
+ "invalid-git-dir",
5681
+ "link-mismatch",
5682
+ "unreadable",
5683
+ "limit-exceeded",
5684
+ "blocked-path"
5685
+ ]);
5686
+ const documentRepositorySchema = discriminatedUnion("state", [
5687
+ strictObject({
5688
+ state: literal("resolved"),
5689
+ id: string(),
5690
+ nameSegments: array(string()),
5691
+ checkout: repositoryCheckoutSchema.nullable(),
5692
+ pathInCheckout: array(string())
5693
+ }),
5694
+ strictObject({
5695
+ state: literal("unresolved"),
5696
+ id: string(),
5697
+ nameSegments: array(string()),
5698
+ pathInCheckout: array(string()),
5699
+ reason: repositoryReasonSchema
5700
+ }),
5701
+ strictObject({ state: literal("pending") })
5702
+ ]).nullable();
5669
5703
  const documentSummarySchema = strictObject({
5670
5704
  documentId: documentIdSchema,
5671
5705
  key: string().nullable(),
@@ -5674,6 +5708,8 @@ const documentSummarySchema = strictObject({
5674
5708
  title: string(),
5675
5709
  displayPath: string().nullable(),
5676
5710
  pathSegments: array(string()),
5711
+ canonicalPath: string().nullable(),
5712
+ repository: documentRepositorySchema,
5677
5713
  revision: revisionSchema.nullable(),
5678
5714
  sourceState: sourceStateSchema,
5679
5715
  searchState: searchStateSchema,
@@ -5881,6 +5917,10 @@ strictObject({
5881
5917
  })),
5882
5918
  links: array(renderLinkSchema),
5883
5919
  diagnostics: array(renderDiagnosticSchema),
5920
+ headingTargets: array(strictObject({
5921
+ sectionId: string().regex(/^sec_\d{4,}$/),
5922
+ anchor: string()
5923
+ })),
5884
5924
  bridge: strictObject({
5885
5925
  instanceId: string(),
5886
5926
  requestId: string()