@readium/navigator-html-injectables 1.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 (77) hide show
  1. package/README.MD +13 -0
  2. package/dist/index.js +3144 -0
  3. package/dist/index.umd.cjs +69 -0
  4. package/package.json +58 -0
  5. package/src/Loader.ts +85 -0
  6. package/src/comms/comms.ts +168 -0
  7. package/src/comms/index.ts +3 -0
  8. package/src/comms/keys.ts +42 -0
  9. package/src/comms/mid.ts +5 -0
  10. package/src/helpers/animation.ts +5 -0
  11. package/src/helpers/css.ts +16 -0
  12. package/src/helpers/document.ts +43 -0
  13. package/src/helpers/dom.ts +126 -0
  14. package/src/helpers/locator.ts +67 -0
  15. package/src/helpers/rect.ts +301 -0
  16. package/src/helpers/scrollSnapperHelper.ts +43 -0
  17. package/src/index.ts +3 -0
  18. package/src/modules/Decorator.ts +462 -0
  19. package/src/modules/Module.ts +23 -0
  20. package/src/modules/ModuleLibrary.ts +44 -0
  21. package/src/modules/Peripherals.ts +148 -0
  22. package/src/modules/index.ts +3 -0
  23. package/src/modules/setup/FixedSetup.ts +73 -0
  24. package/src/modules/setup/ReflowableSetup.ts +65 -0
  25. package/src/modules/setup/Setup.ts +131 -0
  26. package/src/modules/snapper/ColumnSnapper.ts +468 -0
  27. package/src/modules/snapper/ScrollSnapper.ts +168 -0
  28. package/src/modules/snapper/Snapper.ts +49 -0
  29. package/src/vendor/approx-string-match/LICENSE +21 -0
  30. package/src/vendor/approx-string-match/README.MD +1 -0
  31. package/src/vendor/approx-string-match/index.ts +362 -0
  32. package/src/vendor/hypothesis/README.MD +1 -0
  33. package/src/vendor/hypothesis/anchoring/api-types.ts +309 -0
  34. package/src/vendor/hypothesis/anchoring/html.ts +134 -0
  35. package/src/vendor/hypothesis/anchoring/match-quote.ts +163 -0
  36. package/src/vendor/hypothesis/anchoring/placeholder.ts +59 -0
  37. package/src/vendor/hypothesis/anchoring/text-range.ts +327 -0
  38. package/src/vendor/hypothesis/anchoring/trim-range.ts +220 -0
  39. package/src/vendor/hypothesis/anchoring/types.ts +377 -0
  40. package/src/vendor/hypothesis/anchoring/xpath.ts +164 -0
  41. package/src/vendor/hypothesis/tsconfig.json +33 -0
  42. package/src/vendor/hypothesis/types/shared.ts +40 -0
  43. package/types/src/Loader.d.ts +33 -0
  44. package/types/src/comms/comms.d.ts +40 -0
  45. package/types/src/comms/index.d.ts +3 -0
  46. package/types/src/comms/keys.d.ts +2 -0
  47. package/types/src/comms/mid.d.ts +1 -0
  48. package/types/src/helpers/animation.d.ts +1 -0
  49. package/types/src/helpers/css.d.ts +4 -0
  50. package/types/src/helpers/document.d.ts +8 -0
  51. package/types/src/helpers/dom.d.ts +15 -0
  52. package/types/src/helpers/locator.d.ts +2 -0
  53. package/types/src/helpers/rect.d.ts +10 -0
  54. package/types/src/helpers/scrollSnapperHelper.d.ts +5 -0
  55. package/types/src/index.d.ts +3 -0
  56. package/types/src/modules/Decorator.d.ts +43 -0
  57. package/types/src/modules/Module.d.ts +11 -0
  58. package/types/src/modules/ModuleLibrary.d.ts +5 -0
  59. package/types/src/modules/Peripherals.d.ts +39 -0
  60. package/types/src/modules/ReflowablePeripherals.d.ts +37 -0
  61. package/types/src/modules/index.d.ts +3 -0
  62. package/types/src/modules/setup/FixedSetup.d.ts +9 -0
  63. package/types/src/modules/setup/ReflowableSetup.d.ts +9 -0
  64. package/types/src/modules/setup/Setup.d.ts +17 -0
  65. package/types/src/modules/snapper/ColumnSnapper.d.ts +41 -0
  66. package/types/src/modules/snapper/ScrollSnapper.d.ts +16 -0
  67. package/types/src/modules/snapper/Snapper.d.ts +11 -0
  68. package/types/src/vendor/approx-string-match/index.d.ts +54 -0
  69. package/types/src/vendor/hypothesis/anchoring/api-types.d.ts +266 -0
  70. package/types/src/vendor/hypothesis/anchoring/html.d.ts +17 -0
  71. package/types/src/vendor/hypothesis/anchoring/match-quote.d.ts +30 -0
  72. package/types/src/vendor/hypothesis/anchoring/placeholder.d.ts +32 -0
  73. package/types/src/vendor/hypothesis/anchoring/text-range.d.ts +103 -0
  74. package/types/src/vendor/hypothesis/anchoring/trim-range.d.ts +17 -0
  75. package/types/src/vendor/hypothesis/anchoring/types.d.ts +102 -0
  76. package/types/src/vendor/hypothesis/anchoring/xpath.d.ts +15 -0
  77. package/types/src/vendor/hypothesis/types/shared.d.ts +32 -0
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Implementation of Myers' online approximate string matching algorithm [1],
3
+ * with additional optimizations suggested by [2].
4
+ *
5
+ * This has O((k/w) * n) expected-time where `n` is the length of the
6
+ * text, `k` is the maximum number of errors allowed (always <= the pattern
7
+ * length) and `w` is the word size. Because JS only supports bitwise operations
8
+ * on 32 bit integers, `w` is 32.
9
+ *
10
+ * As far as I am aware, there aren't any online algorithms which are
11
+ * significantly better for a wide range of input parameters. The problem can be
12
+ * solved faster using "filter then verify" approaches which first filter out
13
+ * regions of the text that cannot match using a "cheap" check and then verify
14
+ * the remaining potential matches. The verify step requires an algorithm such
15
+ * as this one however.
16
+ *
17
+ * The algorithm's approach is essentially to optimize the classic dynamic
18
+ * programming solution to the problem by computing columns of the matrix in
19
+ * word-sized chunks (ie. dealing with 32 chars of the pattern at a time) and
20
+ * avoiding calculating regions of the matrix where the minimum error count is
21
+ * guaranteed to exceed the input threshold.
22
+ *
23
+ * The paper consists of two parts, the first describes the core algorithm for
24
+ * matching patterns <= the size of a word (implemented by `advanceBlock` here).
25
+ * The second uses the core algorithm as part of a larger block-based algorithm
26
+ * to handle longer patterns.
27
+ *
28
+ * [1] G. Myers, “A Fast Bit-Vector Algorithm for Approximate String Matching
29
+ * Based on Dynamic Programming,” vol. 46, no. 3, pp. 395–415, 1999.
30
+ *
31
+ * [2] Šošić, M. (2014). An simd dynamic programming c/c++ library (Doctoral
32
+ * dissertation, Fakultet Elektrotehnike i računarstva, Sveučilište u Zagrebu).
33
+ */
34
+ /**
35
+ * Represents a match returned by a call to `search`.
36
+ */
37
+ export interface Match {
38
+ /** Start offset of match in text. */
39
+ start: number;
40
+ /** End offset of match in text. */
41
+ end: number;
42
+ /**
43
+ * The number of differences (insertions, deletions or substitutions) between
44
+ * the pattern and the approximate match in the text.
45
+ */
46
+ errors: number;
47
+ }
48
+ /**
49
+ * Search for the closest matches for `pattern` in `text`.
50
+ *
51
+ * Returns all matches that have the lowest number of errors, or an empty
52
+ * array if no match was found with `maxErrors` or fewer errors.
53
+ */
54
+ export default function search(text: string, pattern: string, maxErrors: number): Match[];
@@ -0,0 +1,266 @@
1
+ import type { ClientAnnotationData } from '../types/shared';
2
+ /**
3
+ * Type definitions for objects returned from the Hypothesis API.
4
+ *
5
+ * The canonical reference is the API documentation at
6
+ * https://h.readthedocs.io/en/latest/api-reference/
7
+ */
8
+ /**
9
+ * Metadata specifying how to call an API route.
10
+ */
11
+ export type RouteMetadata = {
12
+ /** HTTP method */
13
+ method: string;
14
+ /** URL template */
15
+ url: string;
16
+ /** Description of API route */
17
+ desc: string;
18
+ };
19
+ /** A nested map of API route name to route metadata. */
20
+ export type RouteMap = {
21
+ [key: string]: RouteMap | RouteMetadata;
22
+ };
23
+ /**
24
+ * Structure of the API index response (`/api`).
25
+ */
26
+ export type IndexResponse = {
27
+ links: RouteMap;
28
+ };
29
+ /**
30
+ * Structure of the Hypothesis links response (`/api/links`).
31
+ *
32
+ * This is a map of link name (eg. "account.settings") to URL. The URL may
33
+ * include ":"-prefixed placeholders/variables.
34
+ */
35
+ export type LinksResponse = Record<string, string>;
36
+ /**
37
+ * Selector which indicates the time range within a video or audio file that
38
+ * an annotation refers to.
39
+ */
40
+ export type MediaTimeSelector = {
41
+ type: 'MediaTimeSelector';
42
+ /** Offset from start of media in seconds. */
43
+ start: number;
44
+ /** Offset from start of media in seconds. */
45
+ end: number;
46
+ };
47
+ /**
48
+ * Selector which identifies a document region using the selected text plus
49
+ * the surrounding context.
50
+ */
51
+ export type TextQuoteSelector = {
52
+ type: 'TextQuoteSelector';
53
+ exact: string;
54
+ prefix?: string;
55
+ suffix?: string;
56
+ };
57
+ /**
58
+ * Selector which identifies a document region using UTF-16 character offsets
59
+ * in the document body's `textContent`.
60
+ */
61
+ export type TextPositionSelector = {
62
+ type: 'TextPositionSelector';
63
+ start: number;
64
+ end: number;
65
+ };
66
+ /**
67
+ * Selector which identifies a document region using XPaths and character offsets.
68
+ */
69
+ export type RangeSelector = {
70
+ type: 'RangeSelector';
71
+ startContainer: string;
72
+ endContainer: string;
73
+ startOffset: number;
74
+ endOffset: number;
75
+ };
76
+ /**
77
+ * Selector which identifies the Content Document within an EPUB that an
78
+ * annotation was made in.
79
+ */
80
+ export type EPUBContentSelector = {
81
+ type: 'EPUBContentSelector';
82
+ /**
83
+ * URL of the content document. This should be an absolute HTTPS URL if
84
+ * available, but may be relative to the root of the EPUB.
85
+ */
86
+ url: string;
87
+ /**
88
+ * EPUB Canonical Fragment Identifier for the table of contents entry that
89
+ * corresponds to the content document.
90
+ */
91
+ cfi?: string;
92
+ /** Title of the content document. */
93
+ title?: string;
94
+ };
95
+ /**
96
+ * Selector which identifies the page of a document that an annotation was made
97
+ * on.
98
+ *
99
+ * This selector is only applicable for document types where the association of
100
+ * content and page numbers can be done in a way that is independent of the
101
+ * viewer and display settings. This includes inherently paginated documents
102
+ * such as PDFs, but also content such as EPUBs when they include information
103
+ * about the location of page breaks in printed versions of a book. It does
104
+ * not include ordinary web pages or EPUBs without page break information
105
+ * however.
106
+ */
107
+ export type PageSelector = {
108
+ type: 'PageSelector';
109
+ /** The zero-based index of the page in the document's page sequence. */
110
+ index: number;
111
+ /**
112
+ * Either the page number that is displayed on the page, or the 1-based
113
+ * number of the page in the document's page sequence, if the pages do not
114
+ * have numbers on them.
115
+ */
116
+ label?: string;
117
+ };
118
+ /**
119
+ * Serialized representation of a region of a document which an annotation
120
+ * pertains to.
121
+ */
122
+ export type Selector = TextQuoteSelector | TextPositionSelector | RangeSelector | EPUBContentSelector | MediaTimeSelector | PageSelector;
123
+ /**
124
+ * An entry in the `target` field of an annotation which identifies the document
125
+ * and region of the document that it refers to.
126
+ */
127
+ export type Target = {
128
+ /** URI of the document */
129
+ source: string;
130
+ /** Region of the document */
131
+ selector?: Selector[];
132
+ };
133
+ export type UserInfo = {
134
+ display_name: string | null;
135
+ };
136
+ export type APIAnnotationData = {
137
+ /**
138
+ * The server-assigned ID for the annotation. This is only set once the
139
+ * annotation has been saved to the backend.
140
+ */
141
+ id?: string;
142
+ references?: string[];
143
+ created: string;
144
+ flagged?: boolean;
145
+ group: string;
146
+ updated: string;
147
+ tags: string[];
148
+ text: string;
149
+ uri: string;
150
+ user: string;
151
+ hidden: boolean;
152
+ document: {
153
+ title: string;
154
+ };
155
+ permissions: {
156
+ read: string[];
157
+ update: string[];
158
+ delete: string[];
159
+ };
160
+ /**
161
+ * The document and region this annotation refers to.
162
+ *
163
+ * The Hypothesis API structure allows for multiple targets, but the h
164
+ * server only supports one target per annotation.
165
+ */
166
+ target: Target[];
167
+ moderation?: {
168
+ flagCount: number;
169
+ };
170
+ links: {
171
+ /**
172
+ * A "bouncer" URL that takes the user to see the annotation in context
173
+ */
174
+ incontext?: string;
175
+ /** URL to view the annotation by itself. */
176
+ html?: string;
177
+ };
178
+ user_info?: UserInfo;
179
+ };
180
+ export type Annotation = ClientAnnotationData & APIAnnotationData;
181
+ /**
182
+ * An annotation which has been saved to the backend and assigned an ID.
183
+ */
184
+ export type SavedAnnotation = Annotation & {
185
+ id: string;
186
+ };
187
+ export type Profile = {
188
+ userid: string | null;
189
+ preferences: {
190
+ show_sidebar_tutorial?: boolean;
191
+ };
192
+ features: Record<string, boolean>;
193
+ user_info?: UserInfo;
194
+ };
195
+ export type Organization = {
196
+ name: string;
197
+ logo: string;
198
+ id: string;
199
+ default?: boolean;
200
+ };
201
+ export type GroupScopes = {
202
+ enforced: boolean;
203
+ uri_patterns: string[];
204
+ };
205
+ export type Group = {
206
+ /** The "pubid" of the group, unique per authority. */
207
+ id: string;
208
+ /** Fully-qualified ID with authority. */
209
+ groupid?: string;
210
+ type: 'private' | 'open';
211
+ /**
212
+ * Note: This field is nullable in the API, but we assign a default organization in the client.
213
+ */
214
+ organization: Organization;
215
+ scopes: GroupScopes | null;
216
+ links: {
217
+ html?: string;
218
+ };
219
+ logo: string;
220
+ isMember: boolean;
221
+ isScopedToUri: boolean;
222
+ name: string;
223
+ canLeave: boolean;
224
+ };
225
+ /**
226
+ * All Groups have an `id`, which is a server-assigned identifier. This is the
227
+ * primary field used to identify a Group.
228
+ *
229
+ * In some cases, specifically LMS, it is necessary for an outside service to
230
+ * be able to specify its own identifier. This gets stored in the `groupid`
231
+ * field of a Group. Only some Groups have a `groupid`.
232
+ *
233
+ * Application logic operates on `id`s, but we may receive `groupid`s in some
234
+ * cases from outside sevices, e.g. the `changeFocusModeUser` RPC method.
235
+ */
236
+ export type GroupIdentifier = NonNullable<Group['id'] | Group['groupid']>;
237
+ /**
238
+ * Query parameters for an `/api/search` API call.
239
+ *
240
+ * This type currently includes params that we've actually used.
241
+ *
242
+ * See https://h.readthedocs.io/en/latest/api-reference/#tag/annotations/paths/~1search/get
243
+ * for the complete list and usage of each.
244
+ */
245
+ export type SearchQuery = {
246
+ limit?: number;
247
+ uri?: string[];
248
+ group?: string;
249
+ order?: string;
250
+ references?: string;
251
+ search_after?: string;
252
+ sort?: string;
253
+ /** Undocument param that causes replies to be returned in a separate `replies` field. */
254
+ _separate_replies?: boolean;
255
+ };
256
+ /**
257
+ * Response to an `/api/search` API call.
258
+ *
259
+ * See https://h.readthedocs.io/en/latest/api-reference/#tag/annotations/paths/~1search/get
260
+ */
261
+ export type SearchResponse = {
262
+ total: number;
263
+ rows: Annotation[];
264
+ /** Undocumented property that is populated if `_separate_replies` query param was specified. */
265
+ replies?: Annotation[];
266
+ };
@@ -0,0 +1,17 @@
1
+ import type { MediaTimeSelector, RangeSelector, Selector, TextPositionSelector, TextQuoteSelector } from './api-types';
2
+ type Options = {
3
+ hint?: number;
4
+ };
5
+ /**
6
+ * Anchor a set of selectors.
7
+ *
8
+ * This function converts a set of selectors into a document range.
9
+ * It encapsulates the core anchoring algorithm, using the selectors alone or
10
+ * in combination to establish the best anchor within the document.
11
+ *
12
+ * @param root - The root element of the anchoring context
13
+ * @param selectors - The selectors to try
14
+ */
15
+ export declare function anchor(root: Element, selectors: Selector[], options?: Options): Promise<Range>;
16
+ export declare function describe(root: Element, range: Range): (MediaTimeSelector | TextQuoteSelector | TextPositionSelector | RangeSelector)[];
17
+ export {};
@@ -0,0 +1,30 @@
1
+ type Match = {
2
+ /** Start offset of match in text */
3
+ start: number;
4
+ /** End offset of match in text */
5
+ end: number;
6
+ /**
7
+ * Score for the match between 0 and 1.0, where 1.0 indicates a perfect match
8
+ * for the quote and context.
9
+ */
10
+ score: number;
11
+ };
12
+ type Context = {
13
+ /** Expected text before the quote */
14
+ prefix?: string;
15
+ /** Expected text after the quote */
16
+ suffix?: string;
17
+ /** Expected offset of match within text */
18
+ hint?: number;
19
+ };
20
+ /**
21
+ * Find the best approximate match for `quote` in `text`.
22
+ *
23
+ * @param text - Document text to search
24
+ * @param quote - String to find within `text`
25
+ * @param context - Context in which the quote originally appeared. This is
26
+ * used to choose the best match.
27
+ * @return `null` if no match exceeding the minimum quality threshold was found.
28
+ */
29
+ export declare function matchQuote(text: string, quote: string, context?: Context): Match | null;
30
+ export {};
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Create or return a placeholder element for anchoring.
3
+ *
4
+ * In document viewers such as PDF.js which only render a subset of long
5
+ * documents at a time, it may not be possible to anchor annotations to the
6
+ * actual text in pages which are off-screen. For these non-rendered pages,
7
+ * a "placeholder" element is created in the approximate X/Y location (eg.
8
+ * middle of the page) where the content will appear. Any highlights for that
9
+ * page are then rendered inside the placeholder.
10
+ *
11
+ * When the viewport is scrolled to the non-rendered page, the placeholder
12
+ * is removed and annotations are re-anchored to the real content.
13
+ *
14
+ * @param container - The container element for the page or tile which is not
15
+ * rendered.
16
+ */
17
+ export declare function createPlaceholder(container: HTMLElement): Element;
18
+ /**
19
+ * Return true if a page/tile container has a placeholder.
20
+ */
21
+ export declare function hasPlaceholder(container: HTMLElement): boolean;
22
+ /**
23
+ * Remove the placeholder element in `container`, if present.
24
+ */
25
+ export declare function removePlaceholder(container: HTMLElement): void;
26
+ /**
27
+ * Return true if `node` is inside a placeholder element created with `createPlaceholder`.
28
+ *
29
+ * This is typically used to test if a highlight element associated with an
30
+ * anchor is inside a placeholder.
31
+ */
32
+ export declare function isInPlaceholder(node: Node): boolean;
@@ -0,0 +1,103 @@
1
+ /**
2
+ * When resolving a TextPosition, specifies the direction to search for the
3
+ * nearest text node if `offset` is `0` and the element has no text.
4
+ */
5
+ export declare enum ResolveDirection {
6
+ FORWARDS = 1,
7
+ BACKWARDS = 2
8
+ }
9
+ /**
10
+ * Represents an offset within the text content of an element.
11
+ *
12
+ * This position can be resolved to a specific descendant node in the current
13
+ * DOM subtree of the element using the `resolve` method.
14
+ */
15
+ export declare class TextPosition {
16
+ element: Element;
17
+ offset: number;
18
+ constructor(element: Element, offset: number);
19
+ /**
20
+ * Return a copy of this position with offset relative to a given ancestor
21
+ * element.
22
+ *
23
+ * @param parent - Ancestor of `this.element`
24
+ */
25
+ relativeTo(parent: Element): TextPosition;
26
+ /**
27
+ * Resolve the position to a specific text node and offset within that node.
28
+ *
29
+ * Throws if `this.offset` exceeds the length of the element's text. In the
30
+ * case where the element has no text and `this.offset` is 0, the `direction`
31
+ * option determines what happens.
32
+ *
33
+ * Offsets at the boundary between two nodes are resolved to the start of the
34
+ * node that begins at the boundary.
35
+ *
36
+ * @param options.direction - Specifies in which direction to search for the
37
+ * nearest text node if `this.offset` is `0` and
38
+ * `this.element` has no text. If not specified an
39
+ * error is thrown.
40
+ *
41
+ * @throws {RangeError}
42
+ */
43
+ resolve(options?: {
44
+ direction?: ResolveDirection;
45
+ }): {
46
+ node: Text;
47
+ offset: number;
48
+ };
49
+ /**
50
+ * Construct a `TextPosition` that refers to the `offset`th character within
51
+ * `node`.
52
+ */
53
+ static fromCharOffset(node: Node, offset: number): TextPosition;
54
+ /**
55
+ * Construct a `TextPosition` representing the range start or end point (node, offset).
56
+ *
57
+ * @param node
58
+ * @param offset - Offset within the node
59
+ */
60
+ static fromPoint(node: Node, offset: number): TextPosition;
61
+ }
62
+ /**
63
+ * Represents a region of a document as a (start, end) pair of `TextPosition` points.
64
+ *
65
+ * Representing a range in this way allows for changes in the DOM content of the
66
+ * range which don't affect its text content, without affecting the text content
67
+ * of the range itself.
68
+ */
69
+ export declare class TextRange {
70
+ start: TextPosition;
71
+ end: TextPosition;
72
+ constructor(start: TextPosition, end: TextPosition);
73
+ /**
74
+ * Create a new TextRange whose `start` and `end` are computed relative to
75
+ * `element`. `element` must be an ancestor of both `start.element` and
76
+ * `end.element`.
77
+ */
78
+ relativeTo(element: Element): TextRange;
79
+ /**
80
+ * Resolve this TextRange to a (DOM) Range.
81
+ *
82
+ * The resulting DOM Range will always start and end in a `Text` node.
83
+ * Hence `TextRange.fromRange(range).toRange()` can be used to "shrink" a
84
+ * range to the text it contains.
85
+ *
86
+ * May throw if the `start` or `end` positions cannot be resolved to a range.
87
+ */
88
+ toRange(): Range;
89
+ /**
90
+ * Create a TextRange from a (DOM) Range
91
+ */
92
+ static fromRange(range: Range): TextRange;
93
+ /**
94
+ * Create a TextRange representing the `start`th to `end`th characters in
95
+ * `root`
96
+ */
97
+ static fromOffsets(root: Element, start: number, end: number): TextRange;
98
+ /**
99
+ * Return a new Range representing `range` trimmed of any leading or trailing
100
+ * whitespace
101
+ */
102
+ static trimmedRange(range: Range): Range;
103
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Return a new DOM Range that adjusts the start and end positions of `range` as
3
+ * needed such that:
4
+ *
5
+ * - `startContainer` and `endContainer` text nodes both contain at least one
6
+ * non-whitespace character within the Range's text content
7
+ * - `startOffset` and `endOffset` both reference non-whitespace characters,
8
+ * with `startOffset` immediately before the first non-whitespace character
9
+ * and `endOffset` immediately after the last
10
+ *
11
+ * Whitespace characters are those that are removed by `String.prototype.trim()`
12
+ *
13
+ * @param range - A DOM Range that whose `startContainer` and `endContainer` are
14
+ * both text nodes, and which contains at least one non-whitespace character.
15
+ * @throws {RangeError}
16
+ */
17
+ export declare function trimRange(range: Range): Range;
@@ -0,0 +1,102 @@
1
+ /**
2
+ * This module exports a set of classes for converting between DOM `Range`
3
+ * objects and different types of selectors. It is mostly a thin wrapper around a
4
+ * set of anchoring libraries. It serves two main purposes:
5
+ *
6
+ * 1. Providing a consistent interface across different types of anchors.
7
+ * 2. Insulating the rest of the code from API changes in the underlying anchoring
8
+ * libraries.
9
+ */
10
+ import type { MediaTimeSelector, RangeSelector, TextPositionSelector, TextQuoteSelector } from './api-types';
11
+ /**
12
+ * Converts between `RangeSelector` selectors and `Range` objects.
13
+ */
14
+ export declare class RangeAnchor {
15
+ root: Node;
16
+ range: Range;
17
+ /**
18
+ * @param root - A root element from which to anchor.
19
+ * @param range - A range describing the anchor.
20
+ */
21
+ constructor(root: Node, range: Range);
22
+ /**
23
+ * @param root - A root element from which to anchor.
24
+ * @param range - A range describing the anchor.
25
+ */
26
+ static fromRange(root: Node, range: Range): RangeAnchor;
27
+ /**
28
+ * Create an anchor from a serialized `RangeSelector` selector.
29
+ *
30
+ * @param root - A root element from which to anchor.
31
+ */
32
+ static fromSelector(root: Element, selector: RangeSelector): RangeAnchor;
33
+ toRange(): Range;
34
+ toSelector(): RangeSelector;
35
+ }
36
+ /**
37
+ * Converts between `TextPositionSelector` selectors and `Range` objects.
38
+ */
39
+ export declare class TextPositionAnchor {
40
+ root: Element;
41
+ start: number;
42
+ end: number;
43
+ constructor(root: Element, start: number, end: number);
44
+ static fromRange(root: Element, range: Range): TextPositionAnchor;
45
+ static fromSelector(root: Element, selector: TextPositionSelector): TextPositionAnchor;
46
+ toSelector(): TextPositionSelector;
47
+ toRange(): Range;
48
+ }
49
+ type QuoteMatchOptions = {
50
+ /** Expected position of match in text. See `matchQuote`. */
51
+ hint?: number;
52
+ };
53
+ export type TextQuoteAnchorContext = {
54
+ prefix?: string;
55
+ suffix?: string;
56
+ };
57
+ /**
58
+ * Converts between `TextQuoteSelector` selectors and `Range` objects.
59
+ */
60
+ export declare class TextQuoteAnchor {
61
+ root: Element;
62
+ exact: string;
63
+ context: TextQuoteAnchorContext;
64
+ /**
65
+ * @param root - A root element from which to anchor.
66
+ */
67
+ constructor(root: Element, exact: string, context?: TextQuoteAnchorContext);
68
+ /**
69
+ * Create a `TextQuoteAnchor` from a range.
70
+ *
71
+ * Will throw if `range` does not contain any text nodes.
72
+ */
73
+ static fromRange(root: Element, range: Range): TextQuoteAnchor;
74
+ static fromSelector(root: Element, selector: TextQuoteSelector): TextQuoteAnchor;
75
+ toSelector(): TextQuoteSelector;
76
+ toRange(options?: QuoteMatchOptions): Range;
77
+ toPositionAnchor(options?: QuoteMatchOptions): TextPositionAnchor;
78
+ }
79
+ export declare class MediaTimeAnchor {
80
+ root: Element;
81
+ /** Offset from start of media in seconds. */
82
+ start: number;
83
+ /** Offset from end of media in seconds. */
84
+ end: number;
85
+ constructor(root: Element, start: number, end: number);
86
+ /**
87
+ * Return a {@link MediaTimeAnchor} that represents a range, or `null` if
88
+ * no time range information is present on elements in the range.
89
+ */
90
+ static fromRange(root: Element, range: Range): MediaTimeAnchor | null;
91
+ /**
92
+ * Convert this anchor to a DOM range.
93
+ *
94
+ * This returned range will start from the beginning of the element whose
95
+ * associated time range includes `start` and continue to the end of the
96
+ * element whose associated time range includes `end`.
97
+ */
98
+ toRange(): Range;
99
+ static fromSelector(root: Element, selector: MediaTimeSelector): MediaTimeAnchor;
100
+ toSelector(): MediaTimeSelector;
101
+ }
102
+ export {};
@@ -0,0 +1,15 @@
1
+ /**
2
+ * A simple XPath generator which can generate XPaths of the form
3
+ * /tag[index]/tag[index].
4
+ *
5
+ * @param node - The node to generate a path to
6
+ * @param root - Root node to which the returned path is relative
7
+ */
8
+ export declare function xpathFromNode(node: Node, root: Node): string;
9
+ /**
10
+ * Finds an element node using an XPath relative to `root`
11
+ *
12
+ * Example:
13
+ * node = nodeFromXPath('/main/article[1]/p[3]', document.body)
14
+ */
15
+ export declare function nodeFromXPath(xpath: string, root?: Element): Node | null;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Clusters provide the client application a mechanism for categorizing
3
+ * annotations so that their drawn anchor highlights may be styled distinctively
4
+ * in the annotated document. An annotation can only belong to one cluster.
5
+ */
6
+ export type HighlightCluster = 'other-content' | 'user-annotations' | 'user-highlights';
7
+ /**
8
+ * Annotation properties not present on API objects, but added by the client
9
+ */
10
+ export type ClientAnnotationData = {
11
+ $cluster?: HighlightCluster;
12
+ /**
13
+ * Client-side identifier: set even if annotation does not have a
14
+ * server-provided `id` (i.e. is unsaved)
15
+ */
16
+ $tag: string;
17
+ /**
18
+ * Flag indicating whether waiting for the annotation to anchor timed out
19
+ */
20
+ $anchorTimeout?: boolean;
21
+ /**
22
+ * Flag indicating that this annotation was created using the "Highlight" button,
23
+ * as opposed to "Annotate".
24
+ */
25
+ $highlight?: boolean;
26
+ /**
27
+ * Flag indicating that this annotation was not found in the document.
28
+ * It is initially `undefined` while anchoring is in progress and then set to
29
+ * `true` if anchoring failed or `false` if it succeeded.
30
+ */
31
+ $orphan?: boolean;
32
+ };