@storyteller-platform/align 0.1.24 → 0.1.26

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 (47) hide show
  1. package/dist/align/align.cjs +21 -9
  2. package/dist/align/align.js +22 -11
  3. package/dist/align/getSentenceRanges.cjs +0 -58
  4. package/dist/align/getSentenceRanges.d.cts +1 -2
  5. package/dist/align/getSentenceRanges.d.ts +1 -2
  6. package/dist/align/getSentenceRanges.js +0 -57
  7. package/dist/align/interpolateSentenceRanges.cjs +124 -0
  8. package/dist/align/interpolateSentenceRanges.d.cts +23 -0
  9. package/dist/align/interpolateSentenceRanges.d.ts +23 -0
  10. package/dist/align/interpolateSentenceRanges.js +101 -0
  11. package/dist/align/search.cjs +18 -7
  12. package/dist/align/search.js +18 -7
  13. package/dist/align/slugify.cjs +31 -23
  14. package/dist/align/slugify.js +31 -23
  15. package/dist/index.d.cts +1 -2
  16. package/dist/index.d.ts +1 -2
  17. package/dist/markup/markup.cjs +21 -14
  18. package/dist/markup/markup.d.cts +2 -4
  19. package/dist/markup/markup.d.ts +2 -4
  20. package/dist/markup/markup.js +28 -16
  21. package/dist/markup/model.cjs +138 -5
  22. package/dist/markup/model.d.cts +2 -57
  23. package/dist/markup/model.d.ts +2 -57
  24. package/dist/markup/model.js +136 -5
  25. package/dist/markup/parseDom.cjs +80 -25
  26. package/dist/markup/parseDom.d.cts +4 -4
  27. package/dist/markup/parseDom.d.ts +4 -4
  28. package/dist/markup/parseDom.js +87 -24
  29. package/dist/markup/resolvedPos.cjs +85 -0
  30. package/dist/markup/resolvedPos.d.cts +2 -0
  31. package/dist/markup/resolvedPos.d.ts +2 -0
  32. package/dist/markup/resolvedPos.js +62 -0
  33. package/dist/markup/segmentation.cjs +4 -8
  34. package/dist/markup/segmentation.d.cts +3 -8
  35. package/dist/markup/segmentation.d.ts +3 -8
  36. package/dist/markup/segmentation.js +3 -7
  37. package/dist/markup/serializeDom.d.cts +1 -1
  38. package/dist/markup/serializeDom.d.ts +1 -1
  39. package/dist/markup/transform.cjs +59 -2
  40. package/dist/markup/transform.d.cts +8 -2
  41. package/dist/markup/transform.d.ts +8 -2
  42. package/dist/markup/transform.js +58 -1
  43. package/dist/model-Bv3yPEdd.d.cts +96 -0
  44. package/dist/model-Bv3yPEdd.d.ts +96 -0
  45. package/dist/snapshot/snapshot.cjs +8 -6
  46. package/dist/snapshot/snapshot.js +9 -7
  47. package/package.json +4 -4
@@ -1,57 +1,2 @@
1
- import { ElementName } from '@storyteller-platform/epub';
2
-
3
- declare class Root {
4
- children: (Node | TextNode)[];
5
- constructor(children: (Node | TextNode)[]);
6
- isInline: boolean;
7
- isBlock: boolean;
8
- get border(): number;
9
- get textContent(): string;
10
- split(at: number): Root;
11
- copy(opts?: {
12
- children?: (Node | TextNode)[];
13
- }): Root;
14
- }
15
- declare class Node {
16
- tagName: ElementName;
17
- attrs: Record<string, string>;
18
- children: (Node | TextNode)[];
19
- marks: Mark[];
20
- constructor(tagName: ElementName, attrs?: Record<string, string>, children?: (Node | TextNode)[], marks?: Mark[]);
21
- get isLeaf(): boolean;
22
- get isInline(): boolean;
23
- get isBlock(): boolean;
24
- get border(): 0 | 1;
25
- get nodeSize(): number;
26
- get textContent(): string;
27
- split(at: number): Node;
28
- copy(opts?: {
29
- attrs?: Record<string, string>;
30
- children?: (Node | TextNode)[];
31
- marks?: Mark[];
32
- }): Node;
33
- }
34
- declare class Mark {
35
- tagName: ElementName;
36
- attrs: Record<string, string>;
37
- constructor(tagName: ElementName, attrs?: Record<string, string>);
38
- eq(other: Mark | undefined): boolean;
39
- }
40
- declare class TextNode {
41
- text: string;
42
- marks: Mark[];
43
- constructor(text: string, marks?: Mark[]);
44
- isLeaf: boolean;
45
- isInline: boolean;
46
- isBlock: boolean;
47
- border: number;
48
- get nodeSize(): number;
49
- get textContent(): string;
50
- split(at: number): TextNode[];
51
- copy(opts?: {
52
- marks?: Mark[];
53
- }): TextNode;
54
- }
55
- declare function descendants(root: Root | Node, cb: (node: Node | TextNode, pos: number, parent: Node | Root, index: number) => boolean, pos?: number): void;
56
-
57
- export { Mark, Node, Root, TextNode, descendants };
1
+ import '@storyteller-platform/epub';
2
+ export { F as FootnoteNode, M as Mark, N as Node, b as NoterefNode, R as Root, T as TextNode, d as descendants } from '../model-Bv3yPEdd.cjs';
@@ -1,57 +1,2 @@
1
- import { ElementName } from '@storyteller-platform/epub';
2
-
3
- declare class Root {
4
- children: (Node | TextNode)[];
5
- constructor(children: (Node | TextNode)[]);
6
- isInline: boolean;
7
- isBlock: boolean;
8
- get border(): number;
9
- get textContent(): string;
10
- split(at: number): Root;
11
- copy(opts?: {
12
- children?: (Node | TextNode)[];
13
- }): Root;
14
- }
15
- declare class Node {
16
- tagName: ElementName;
17
- attrs: Record<string, string>;
18
- children: (Node | TextNode)[];
19
- marks: Mark[];
20
- constructor(tagName: ElementName, attrs?: Record<string, string>, children?: (Node | TextNode)[], marks?: Mark[]);
21
- get isLeaf(): boolean;
22
- get isInline(): boolean;
23
- get isBlock(): boolean;
24
- get border(): 0 | 1;
25
- get nodeSize(): number;
26
- get textContent(): string;
27
- split(at: number): Node;
28
- copy(opts?: {
29
- attrs?: Record<string, string>;
30
- children?: (Node | TextNode)[];
31
- marks?: Mark[];
32
- }): Node;
33
- }
34
- declare class Mark {
35
- tagName: ElementName;
36
- attrs: Record<string, string>;
37
- constructor(tagName: ElementName, attrs?: Record<string, string>);
38
- eq(other: Mark | undefined): boolean;
39
- }
40
- declare class TextNode {
41
- text: string;
42
- marks: Mark[];
43
- constructor(text: string, marks?: Mark[]);
44
- isLeaf: boolean;
45
- isInline: boolean;
46
- isBlock: boolean;
47
- border: number;
48
- get nodeSize(): number;
49
- get textContent(): string;
50
- split(at: number): TextNode[];
51
- copy(opts?: {
52
- marks?: Mark[];
53
- }): TextNode;
54
- }
55
- declare function descendants(root: Root | Node, cb: (node: Node | TextNode, pos: number, parent: Node | Root, index: number) => boolean, pos?: number): void;
56
-
57
- export { Mark, Node, Root, TextNode, descendants };
1
+ import '@storyteller-platform/epub';
2
+ export { F as FootnoteNode, M as Mark, N as Node, b as NoterefNode, R as Root, T as TextNode, d as descendants } from '../model-Bv3yPEdd.js';
@@ -1,5 +1,6 @@
1
1
  import "../chunk-BIEQXUOY.js";
2
2
  import { enumerate } from "itertools";
3
+ import { ResolvedPos } from "./resolvedPos.js";
3
4
  import { BLOCKS } from "./semantics.js";
4
5
  class Root {
5
6
  constructor(children) {
@@ -13,6 +14,12 @@ class Root {
13
14
  get textContent() {
14
15
  return this.children.reduce((acc, child) => acc + child.textContent, "");
15
16
  }
17
+ get nodeSize() {
18
+ return this.border + (this.children.reduce((acc, child) => acc + child.nodeSize, 0) || 1) + this.border;
19
+ }
20
+ get contentSize() {
21
+ return this.nodeSize - this.border * 2;
22
+ }
16
23
  split(at) {
17
24
  const children = [];
18
25
  let pos = this.border;
@@ -31,6 +38,58 @@ class Root {
31
38
  copy(opts = {}) {
32
39
  return new Root(opts.children ?? this.children);
33
40
  }
41
+ findIndex(pos) {
42
+ if (pos === 0) return { index: 0, offset: pos };
43
+ if (pos === this.contentSize) {
44
+ return { index: this.children.length, offset: pos };
45
+ }
46
+ if (pos > this.contentSize || pos < 0) {
47
+ throw new RangeError(`Position ${pos} outside of fragment`);
48
+ }
49
+ for (let i = 0, curPos = 0; ; i++) {
50
+ const cur = this.children[i];
51
+ const end = curPos + cur.nodeSize;
52
+ if (end >= pos) {
53
+ if (end === pos) return { index: i + 1, offset: end };
54
+ return { index: i, offset: curPos };
55
+ }
56
+ curPos = end;
57
+ }
58
+ }
59
+ replace(at, withNode) {
60
+ const children = [];
61
+ let pos = this.border;
62
+ for (const child of this.children) {
63
+ if (at === pos) {
64
+ children.push(withNode);
65
+ } else if (at > pos && at < pos + child.nodeSize) {
66
+ if (child instanceof TextNode) {
67
+ throw new Error("Tried to replace at a position within a text node");
68
+ }
69
+ children.push(child.replace(at - pos, withNode));
70
+ } else {
71
+ children.push(child);
72
+ }
73
+ pos += children.at(-1).nodeSize;
74
+ }
75
+ return this.copy({ children });
76
+ }
77
+ cut(pos) {
78
+ let currentPos = this.border;
79
+ for (const child of this.children) {
80
+ if (pos === currentPos) {
81
+ return child;
82
+ }
83
+ if (pos > currentPos && pos < currentPos + child.nodeSize) {
84
+ return child.cut(pos - currentPos);
85
+ }
86
+ currentPos += child.nodeSize;
87
+ }
88
+ return null;
89
+ }
90
+ resolve(pos) {
91
+ return ResolvedPos.resolve(this, pos);
92
+ }
34
93
  }
35
94
  class Node {
36
95
  constructor(tagName, attrs = {}, children = [], marks = []) {
@@ -54,6 +113,9 @@ class Node {
54
113
  get nodeSize() {
55
114
  return this.border + (this.children.reduce((acc, child) => acc + child.nodeSize, 0) || 1) + this.border;
56
115
  }
116
+ get contentSize() {
117
+ return this.nodeSize - this.border * 2;
118
+ }
57
119
  get textContent() {
58
120
  return this.children.reduce((acc, child) => acc + child.textContent, "");
59
121
  }
@@ -76,14 +138,74 @@ class Node {
76
138
  }
77
139
  return this.copy({ children });
78
140
  }
141
+ static instance() {
142
+ return this;
143
+ }
144
+ static create(klass, ...args) {
145
+ return new klass(...args);
146
+ }
79
147
  copy(opts = {}) {
80
- return new Node(
148
+ return Node.create(
149
+ this.constructor,
81
150
  this.tagName,
82
151
  opts.attrs ?? this.attrs,
83
152
  opts.children ?? this.children,
84
153
  opts.marks ?? this.marks
85
154
  );
86
155
  }
156
+ replace(at, withNode) {
157
+ const children = [];
158
+ let pos = this.border;
159
+ for (const child of this.children) {
160
+ if (at === pos) {
161
+ children.push(withNode);
162
+ } else if (at > pos && at < pos + child.nodeSize) {
163
+ if (child instanceof TextNode) {
164
+ throw new Error("Tried to replace at a position within a text node");
165
+ }
166
+ children.push(child.replace(at - pos, withNode));
167
+ } else {
168
+ children.push(child);
169
+ }
170
+ pos += children.at(-1).nodeSize;
171
+ }
172
+ return this.copy({ children });
173
+ }
174
+ cut(pos) {
175
+ let currentPos = this.border;
176
+ for (const child of this.children) {
177
+ if (pos === currentPos) {
178
+ return child;
179
+ }
180
+ if (pos > currentPos && pos < currentPos + child.nodeSize) {
181
+ return child.cut(pos - currentPos);
182
+ }
183
+ currentPos += child.nodeSize;
184
+ }
185
+ return null;
186
+ }
187
+ findIndex(pos) {
188
+ if (pos === 0) return { index: 0, offset: pos };
189
+ if (pos === this.contentSize) {
190
+ return { index: this.children.length, offset: pos };
191
+ }
192
+ if (pos > this.contentSize || pos < 0) {
193
+ throw new RangeError(`Position ${pos} outside of fragment`);
194
+ }
195
+ for (let i = 0, curPos = 0; ; i++) {
196
+ const cur = this.children[i];
197
+ const end = curPos + cur.nodeSize;
198
+ if (end >= pos) {
199
+ if (end === pos) return { index: i + 1, offset: end };
200
+ return { index: i, offset: curPos };
201
+ }
202
+ curPos = end;
203
+ }
204
+ }
205
+ }
206
+ class NoterefNode extends Node {
207
+ }
208
+ class FootnoteNode extends Node {
87
209
  }
88
210
  class Mark {
89
211
  constructor(tagName, attrs = {}) {
@@ -112,6 +234,9 @@ class TextNode {
112
234
  get nodeSize() {
113
235
  return this.text.length;
114
236
  }
237
+ get contentSize() {
238
+ return this.nodeSize;
239
+ }
115
240
  get textContent() {
116
241
  return this.text;
117
242
  }
@@ -126,19 +251,25 @@ class TextNode {
126
251
  copy(opts = {}) {
127
252
  return new TextNode(this.text, opts.marks ?? this.marks);
128
253
  }
254
+ cut(pos) {
255
+ return new TextNode(this.text.slice(pos));
256
+ }
129
257
  }
130
- function descendants(root, cb, pos = 0) {
131
- for (const [i, child] of enumerate(root.children)) {
132
- const descend = cb(child, pos, root, i);
258
+ function descendants(node, cb, pos = 0) {
259
+ pos += node.border;
260
+ for (const [i, child] of enumerate(node.children)) {
261
+ const descend = cb(child, pos, node, i);
133
262
  if (descend && !child.isLeaf) {
134
- descendants(child, cb, pos + child.border);
263
+ descendants(child, cb, pos);
135
264
  }
136
265
  pos += child.nodeSize;
137
266
  }
138
267
  }
139
268
  export {
269
+ FootnoteNode,
140
270
  Mark,
141
271
  Node,
272
+ NoterefNode,
142
273
  Root,
143
274
  TextNode,
144
275
  descendants
@@ -18,42 +18,97 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var parseDom_exports = {};
20
20
  __export(parseDom_exports, {
21
- parseDom: () => parseDom,
22
- parseDomNode: () => parseDomNode
21
+ findFootnotePairs: () => findFootnotePairs,
22
+ parseDom: () => parseDom
23
23
  });
24
24
  module.exports = __toCommonJS(parseDom_exports);
25
25
  var import_epub = require("@storyteller-platform/epub");
26
26
  var import_model = require("./model.cjs");
27
27
  var import_semantics = require("./semantics.cjs");
28
28
  function parseDom(xml) {
29
- const children = xml.flatMap((node) => parseDomNode(node));
30
- return new import_model.Root(children);
29
+ const parser = new Parser();
30
+ return parser.parseDom(xml);
31
31
  }
32
- function parseDomNode(xmlNode, marks) {
33
- if (import_epub.Epub.isXmlTextNode(xmlNode)) {
34
- return new import_model.TextNode(xmlNode["#text"], marks);
32
+ const FOOTNOTE_ROLES = ["footnote", "rearnote", "endnote", "note"];
33
+ class Parser {
34
+ parseDom(xml) {
35
+ const children = this.parseDomChildren(xml);
36
+ return new import_model.Root(children);
35
37
  }
36
- const tagName = import_epub.Epub.getXmlElementName(xmlNode);
37
- if (import_semantics.BLOCKS.includes(tagName)) {
38
- return new import_model.Node(
39
- tagName,
40
- import_epub.Epub.getXmlAttributes(xmlNode),
41
- import_epub.Epub.getXmlChildren(xmlNode).flatMap((child) => parseDomNode(child)),
42
- marks
43
- );
38
+ parseDomChildren(xml, pos = 0) {
39
+ const children = [];
40
+ for (const child of xml) {
41
+ const result = this.parseDomNode(child, pos);
42
+ const nodes = Array.isArray(result) ? result : [result];
43
+ children.push(...nodes);
44
+ pos += nodes.reduce((acc, node) => acc + node.nodeSize, 0);
45
+ }
46
+ return children;
44
47
  }
45
- if (!import_epub.Epub.getXmlChildren(xmlNode).length) {
46
- return new import_model.Node(tagName, import_epub.Epub.getXmlAttributes(xmlNode), [], marks);
48
+ parseDomNode(xmlNode, pos, marks) {
49
+ if (import_epub.Epub.isXmlTextNode(xmlNode)) {
50
+ return new import_model.TextNode(xmlNode["#text"], marks);
51
+ }
52
+ const tagName = import_epub.Epub.getXmlElementName(xmlNode);
53
+ const attrs = import_epub.Epub.getXmlAttributes(xmlNode);
54
+ const blockChildren = this.parseDomChildren(
55
+ import_epub.Epub.getXmlChildren(xmlNode),
56
+ pos + 1
57
+ );
58
+ if (tagName === "a" && attrs["epub:type"] === "noteref") {
59
+ const node = new import_model.NoterefNode(tagName, attrs, blockChildren, marks);
60
+ return node;
61
+ }
62
+ if (FOOTNOTE_ROLES.includes(attrs["epub:type"] ?? "") && attrs["id"]) {
63
+ const footnoteNode = new import_model.FootnoteNode(
64
+ tagName,
65
+ attrs,
66
+ blockChildren,
67
+ marks
68
+ );
69
+ return footnoteNode;
70
+ }
71
+ if (import_semantics.BLOCKS.includes(tagName)) {
72
+ return new import_model.Node(tagName, attrs, blockChildren, marks);
73
+ }
74
+ if (!import_epub.Epub.getXmlChildren(xmlNode).length) {
75
+ return new import_model.Node(tagName, import_epub.Epub.getXmlAttributes(xmlNode), [], marks);
76
+ }
77
+ return import_epub.Epub.getXmlChildren(xmlNode).flatMap(
78
+ (child) => this.parseDomNode(child, pos, [
79
+ ...marks ?? [],
80
+ new import_model.Mark(tagName, import_epub.Epub.getXmlAttributes(xmlNode))
81
+ ])
82
+ );
47
83
  }
48
- return import_epub.Epub.getXmlChildren(xmlNode).flatMap(
49
- (child) => parseDomNode(child, [
50
- ...marks ?? [],
51
- new import_model.Mark(tagName, import_epub.Epub.getXmlAttributes(xmlNode))
52
- ])
53
- );
84
+ }
85
+ function findFootnotePairs(root) {
86
+ const noterefs = /* @__PURE__ */ new Map();
87
+ const pairs = /* @__PURE__ */ new Map();
88
+ (0, import_model.descendants)(root, (node, pos) => {
89
+ if (node instanceof import_model.NoterefNode) {
90
+ const id = node.attrs["href"]?.slice(1);
91
+ if (id) {
92
+ noterefs.set(id, pos);
93
+ }
94
+ return false;
95
+ }
96
+ if (node instanceof import_model.FootnoteNode) {
97
+ const id = node.attrs["id"];
98
+ if (id) {
99
+ const noterefPos = noterefs.get(id);
100
+ if (noterefPos !== void 0) {
101
+ pairs.set(noterefPos, pos);
102
+ }
103
+ }
104
+ return false;
105
+ }
106
+ return true;
107
+ });
108
+ return pairs;
54
109
  }
55
110
  // Annotate the CommonJS export names for ESM import in node:
56
111
  0 && (module.exports = {
57
- parseDom,
58
- parseDomNode
112
+ findFootnotePairs,
113
+ parseDom
59
114
  });
@@ -1,7 +1,7 @@
1
- import { ParsedXml, XmlNode } from '@storyteller-platform/epub';
2
- import { Root, Mark, Node, TextNode } from './model.cjs';
1
+ import { ParsedXml } from '@storyteller-platform/epub';
2
+ import { R as Root, N as Node } from '../model-Bv3yPEdd.cjs';
3
3
 
4
4
  declare function parseDom(xml: ParsedXml): Root;
5
- declare function parseDomNode(xmlNode: XmlNode, marks?: Mark[]): Node | TextNode | (Node | TextNode)[];
5
+ declare function findFootnotePairs(root: Root | Node): Map<number, number>;
6
6
 
7
- export { parseDom, parseDomNode };
7
+ export { findFootnotePairs, parseDom };
@@ -1,7 +1,7 @@
1
- import { ParsedXml, XmlNode } from '@storyteller-platform/epub';
2
- import { Root, Mark, Node, TextNode } from './model.js';
1
+ import { ParsedXml } from '@storyteller-platform/epub';
2
+ import { R as Root, N as Node } from '../model-Bv3yPEdd.js';
3
3
 
4
4
  declare function parseDom(xml: ParsedXml): Root;
5
- declare function parseDomNode(xmlNode: XmlNode, marks?: Mark[]): Node | TextNode | (Node | TextNode)[];
5
+ declare function findFootnotePairs(root: Root | Node): Map<number, number>;
6
6
 
7
- export { parseDom, parseDomNode };
7
+ export { findFootnotePairs, parseDom };
@@ -1,35 +1,98 @@
1
1
  import "../chunk-BIEQXUOY.js";
2
2
  import { Epub } from "@storyteller-platform/epub";
3
- import { Mark, Node, Root, TextNode } from "./model.js";
3
+ import {
4
+ FootnoteNode,
5
+ Mark,
6
+ Node,
7
+ NoterefNode,
8
+ Root,
9
+ TextNode,
10
+ descendants
11
+ } from "./model.js";
4
12
  import { BLOCKS } from "./semantics.js";
5
13
  function parseDom(xml) {
6
- const children = xml.flatMap((node) => parseDomNode(node));
7
- return new Root(children);
14
+ const parser = new Parser();
15
+ return parser.parseDom(xml);
8
16
  }
9
- function parseDomNode(xmlNode, marks) {
10
- if (Epub.isXmlTextNode(xmlNode)) {
11
- return new TextNode(xmlNode["#text"], marks);
17
+ const FOOTNOTE_ROLES = ["footnote", "rearnote", "endnote", "note"];
18
+ class Parser {
19
+ parseDom(xml) {
20
+ const children = this.parseDomChildren(xml);
21
+ return new Root(children);
12
22
  }
13
- const tagName = Epub.getXmlElementName(xmlNode);
14
- if (BLOCKS.includes(tagName)) {
15
- return new Node(
16
- tagName,
17
- Epub.getXmlAttributes(xmlNode),
18
- Epub.getXmlChildren(xmlNode).flatMap((child) => parseDomNode(child)),
19
- marks
20
- );
23
+ parseDomChildren(xml, pos = 0) {
24
+ const children = [];
25
+ for (const child of xml) {
26
+ const result = this.parseDomNode(child, pos);
27
+ const nodes = Array.isArray(result) ? result : [result];
28
+ children.push(...nodes);
29
+ pos += nodes.reduce((acc, node) => acc + node.nodeSize, 0);
30
+ }
31
+ return children;
21
32
  }
22
- if (!Epub.getXmlChildren(xmlNode).length) {
23
- return new Node(tagName, Epub.getXmlAttributes(xmlNode), [], marks);
33
+ parseDomNode(xmlNode, pos, marks) {
34
+ if (Epub.isXmlTextNode(xmlNode)) {
35
+ return new TextNode(xmlNode["#text"], marks);
36
+ }
37
+ const tagName = Epub.getXmlElementName(xmlNode);
38
+ const attrs = Epub.getXmlAttributes(xmlNode);
39
+ const blockChildren = this.parseDomChildren(
40
+ Epub.getXmlChildren(xmlNode),
41
+ pos + 1
42
+ );
43
+ if (tagName === "a" && attrs["epub:type"] === "noteref") {
44
+ const node = new NoterefNode(tagName, attrs, blockChildren, marks);
45
+ return node;
46
+ }
47
+ if (FOOTNOTE_ROLES.includes(attrs["epub:type"] ?? "") && attrs["id"]) {
48
+ const footnoteNode = new FootnoteNode(
49
+ tagName,
50
+ attrs,
51
+ blockChildren,
52
+ marks
53
+ );
54
+ return footnoteNode;
55
+ }
56
+ if (BLOCKS.includes(tagName)) {
57
+ return new Node(tagName, attrs, blockChildren, marks);
58
+ }
59
+ if (!Epub.getXmlChildren(xmlNode).length) {
60
+ return new Node(tagName, Epub.getXmlAttributes(xmlNode), [], marks);
61
+ }
62
+ return Epub.getXmlChildren(xmlNode).flatMap(
63
+ (child) => this.parseDomNode(child, pos, [
64
+ ...marks ?? [],
65
+ new Mark(tagName, Epub.getXmlAttributes(xmlNode))
66
+ ])
67
+ );
24
68
  }
25
- return Epub.getXmlChildren(xmlNode).flatMap(
26
- (child) => parseDomNode(child, [
27
- ...marks ?? [],
28
- new Mark(tagName, Epub.getXmlAttributes(xmlNode))
29
- ])
30
- );
69
+ }
70
+ function findFootnotePairs(root) {
71
+ const noterefs = /* @__PURE__ */ new Map();
72
+ const pairs = /* @__PURE__ */ new Map();
73
+ descendants(root, (node, pos) => {
74
+ if (node instanceof NoterefNode) {
75
+ const id = node.attrs["href"]?.slice(1);
76
+ if (id) {
77
+ noterefs.set(id, pos);
78
+ }
79
+ return false;
80
+ }
81
+ if (node instanceof FootnoteNode) {
82
+ const id = node.attrs["id"];
83
+ if (id) {
84
+ const noterefPos = noterefs.get(id);
85
+ if (noterefPos !== void 0) {
86
+ pairs.set(noterefPos, pos);
87
+ }
88
+ }
89
+ return false;
90
+ }
91
+ return true;
92
+ });
93
+ return pairs;
31
94
  }
32
95
  export {
33
- parseDom,
34
- parseDomNode
96
+ findFootnotePairs,
97
+ parseDom
35
98
  };
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var resolvedPos_exports = {};
20
+ __export(resolvedPos_exports, {
21
+ ResolvedPos: () => ResolvedPos
22
+ });
23
+ module.exports = __toCommonJS(resolvedPos_exports);
24
+ var import_model = require("./model.cjs");
25
+ class ResolvedPos {
26
+ constructor(pos, path, parentOffset) {
27
+ this.pos = pos;
28
+ this.path = path;
29
+ this.parentOffset = parentOffset;
30
+ this.depth = path.length / 3 - 1;
31
+ }
32
+ depth;
33
+ static resolve(doc, pos) {
34
+ if (!(pos >= 0 && pos <= doc.nodeSize - doc.border * 2)) {
35
+ throw new RangeError(`Position ${pos} out of range`);
36
+ }
37
+ const path = [];
38
+ let start = 0;
39
+ let parentOffset = pos;
40
+ for (let node = doc; ; ) {
41
+ const { index, offset } = node.findIndex(parentOffset);
42
+ const rem = parentOffset - offset;
43
+ path.push(node, index, start + offset);
44
+ if (!rem) break;
45
+ node = node.children[index];
46
+ if (node instanceof import_model.TextNode) break;
47
+ parentOffset = rem - 1;
48
+ start += offset + 1;
49
+ }
50
+ return new ResolvedPos(pos, path, parentOffset);
51
+ }
52
+ get parent() {
53
+ return this.node(this.depth);
54
+ }
55
+ node(depth) {
56
+ return this.path[this.resolveDepth(depth) * 3];
57
+ }
58
+ index(depth) {
59
+ return this.path[this.resolveDepth(depth) * 3 + 1];
60
+ }
61
+ get nodeAfter() {
62
+ const parent = this.parent;
63
+ const index = this.index(this.depth);
64
+ if (index === parent.children.length) return null;
65
+ const dOff = this.pos - this.path.at(-1);
66
+ const child = parent.children[index];
67
+ return dOff ? parent.children[index].cut(dOff) : child;
68
+ }
69
+ before(depth) {
70
+ depth = this.resolveDepth(depth);
71
+ if (!depth) {
72
+ throw new Error("There is no position before the top-level node");
73
+ }
74
+ return depth == this.depth + 1 ? this.pos : this.path[depth * 3 - 1];
75
+ }
76
+ resolveDepth(val) {
77
+ if (val == null) return this.depth;
78
+ if (val < 0) return this.depth + val;
79
+ return val;
80
+ }
81
+ }
82
+ // Annotate the CommonJS export names for ESM import in node:
83
+ 0 && (module.exports = {
84
+ ResolvedPos
85
+ });
@@ -0,0 +1,2 @@
1
+ export { a as ResolvedPos } from '../model-Bv3yPEdd.cjs';
2
+ import '@storyteller-platform/epub';
@@ -0,0 +1,2 @@
1
+ export { a as ResolvedPos } from '../model-Bv3yPEdd.js';
2
+ import '@storyteller-platform/epub';