@u1f992/vivliostyle-index 0.2.4 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +230 -24
- package/dist/document-renderer.d.ts +7 -0
- package/dist/document-renderer.d.ts.map +1 -0
- package/dist/document-renderer.js +86 -0
- package/dist/document-renderer.js.map +1 -0
- package/dist/file-system.d.ts +11 -0
- package/dist/file-system.d.ts.map +1 -0
- package/dist/file-system.js +93 -0
- package/dist/file-system.js.map +1 -0
- package/dist/html.d.ts +4 -0
- package/dist/html.d.ts.map +1 -0
- package/dist/html.js +9 -0
- package/dist/html.js.map +1 -0
- package/dist/id.d.ts +5 -0
- package/dist/id.d.ts.map +1 -0
- package/dist/id.js +30 -0
- package/dist/id.js.map +1 -0
- package/dist/index-builder.d.ts +15 -0
- package/dist/index-builder.d.ts.map +1 -0
- package/dist/index-builder.js +138 -0
- package/dist/index-builder.js.map +1 -0
- package/dist/index-state.d.ts +29 -0
- package/dist/index-state.d.ts.map +1 -0
- package/dist/index-state.js +95 -0
- package/dist/index-state.js.map +1 -0
- package/dist/index.d.ts +45 -15
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +53 -122
- package/dist/index.js.map +1 -1
- package/dist/instruction.d.ts +37 -0
- package/dist/instruction.d.ts.map +1 -0
- package/dist/instruction.js +267 -0
- package/dist/instruction.js.map +1 -0
- package/dist/location.d.ts +2 -0
- package/dist/location.d.ts.map +1 -0
- package/dist/location.js +17 -0
- package/dist/location.js.map +1 -0
- package/dist/messages.d.ts +24 -0
- package/dist/messages.d.ts.map +1 -0
- package/dist/messages.js +114 -0
- package/dist/messages.js.map +1 -0
- package/dist/model.d.ts +77 -36
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +112 -148
- package/dist/model.js.map +1 -1
- package/dist/platform.d.ts +4 -0
- package/dist/platform.d.ts.map +1 -0
- package/dist/platform.js +13 -0
- package/dist/platform.js.map +1 -0
- package/dist/profile.d.ts +11 -0
- package/dist/profile.d.ts.map +1 -0
- package/dist/profile.js +17 -0
- package/dist/profile.js.map +1 -0
- package/dist/render.d.ts +175 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +285 -0
- package/dist/render.js.map +1 -0
- package/dist/sort.d.ts +22 -16
- package/dist/sort.d.ts.map +1 -1
- package/dist/sort.js +91 -53
- package/dist/sort.js.map +1 -1
- package/dist/source-snapshot.d.ts +21 -0
- package/dist/source-snapshot.d.ts.map +1 -0
- package/dist/source-snapshot.js +76 -0
- package/dist/source-snapshot.js.map +1 -0
- package/dist/target.d.ts +9 -0
- package/dist/target.d.ts.map +1 -0
- package/dist/target.js +17 -0
- package/dist/target.js.map +1 -0
- package/dist/template.d.ts +4 -0
- package/dist/template.d.ts.map +1 -0
- package/dist/template.js +15 -0
- package/dist/template.js.map +1 -0
- package/package.json +25 -17
- package/dist/command/expand.d.ts +0 -5
- package/dist/command/expand.d.ts.map +0 -1
- package/dist/command/expand.js +0 -193
- package/dist/command/expand.js.map +0 -1
- package/dist/command/insert-page.d.ts +0 -5
- package/dist/command/insert-page.d.ts.map +0 -1
- package/dist/command/insert-page.js +0 -32
- package/dist/command/insert-page.js.map +0 -1
- package/dist/command/insert-range.d.ts +0 -21
- package/dist/command/insert-range.d.ts.map +0 -1
- package/dist/command/insert-range.js +0 -61
- package/dist/command/insert-range.js.map +0 -1
- package/dist/command/insert-reference.d.ts +0 -4
- package/dist/command/insert-reference.d.ts.map +0 -1
- package/dist/command/insert-reference.js +0 -58
- package/dist/command/insert-reference.js.map +0 -1
- package/dist/command.d.ts +0 -25
- package/dist/command.d.ts.map +0 -1
- package/dist/command.js +0 -159
- package/dist/command.js.map +0 -1
- package/dist/resolve.d.ts +0 -3
- package/dist/resolve.d.ts.map +0 -1
- package/dist/resolve.js +0 -95
- package/dist/resolve.js.map +0 -1
- package/dist/util.d.ts +0 -10
- package/dist/util.d.ts.map +0 -1
- package/dist/util.js +0 -27
- package/dist/util.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,24 +1,230 @@
|
|
|
1
|
-
# @u1f992/vivliostyle-index
|
|
2
|
-
|
|
3
|
-
[unified](https://github.com/unifiedjs/unified) plugin
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
1
|
+
# @u1f992/vivliostyle-index
|
|
2
|
+
|
|
3
|
+
A [unified](https://github.com/unifiedjs/unified) plugin for generating indexes in [Vivliostyle CLI](https://github.com/vivliostyle/vivliostyle-cli) builds.
|
|
4
|
+
|
|
5
|
+
The indexing rules are based on the Japan Science and Technology Agency's SIST 13 (n.d.); Fujita (2019) provides an abridged commentary on it.
|
|
6
|
+
|
|
7
|
+
The default output follows and extends the index structure specified by the DAISY Consortium (n.d.). The plugin's `data-index-role` vocabulary similarly draws on and extends the index terms defined by the EPUB 3 Structural Semantics Vocabulary 1.1 (Herman and Garrish 2026). Index targets carry the DPUB-ARIA `doc-index` role (Garrish and Siegman 2025).
|
|
8
|
+
|
|
9
|
+
## Concept
|
|
10
|
+
|
|
11
|
+
This plugin encodes index-building instructions in URLs. A path-and-fragment pair uniquely identifies an index target, while the `q` query parameter contains the instruction. The instruction uses a DSL inspired by MakeIndex and upmendex; the following sections define its grammar.
|
|
12
|
+
|
|
13
|
+
See [the basic example configuration](examples/basic/vivliostyle.config.ts) for the required plugin setup. After configuring the plugin, add the following reference to `chapter.md`:
|
|
14
|
+
|
|
15
|
+
```html
|
|
16
|
+
<span data-index="index.md?q=a!Apple#index">Apple</span>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
In `index.md` in the same directory, provide the target navigation element:
|
|
20
|
+
|
|
21
|
+
```html
|
|
22
|
+
<nav id="index" role="doc-index"></nav>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The `data-index` value is a relative URL resolved against the document that contains it. Its path and fragment identify the `<nav>` in `index.md` as the index target; that element must carry the `doc-index` role. The instruction `a!Apple` registers the entry `Apple` in the group `a`, using the position of the `<span>` as its locator. The plugin fills the `<nav>` with the built index, and the generated locator links back to the `<span>`. If the `<span>` has no `id`, the plugin assigns one for this link. If a reference omits the path, its target is resolved within the referring document, allowing a document to host its own index.
|
|
26
|
+
|
|
27
|
+
As a consequence of this design, the `q` value is interpreted at two syntactic layers: first as part of a URL, then as an `application/x-www-form-urlencoded` query parameter. For a uniform reversible encoding, percent-encode `#`, `&`, `+`, and `%` in a raw instruction before placing it in `q`.
|
|
28
|
+
|
|
29
|
+
At the URL layer, `#` ends the query and starts the fragment ([query state](https://url.spec.whatwg.org/#query-state)). During query parsing, `&` separates parameters, `+` denotes a space, and a `%` followed by two ASCII hexadecimal digits introduces a percent-encoded byte ([`application/x-www-form-urlencoded` parsing](https://url.spec.whatwg.org/#urlencoded-parsing)) (WHATWG n.d.). Encoding every `%` prevents a sequence in the raw instruction from being decoded accidentally. For example, the instruction `a@A!ampersand@&|seealso{p@P!plus@+}` is written as:
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
index.md?q=a@A!ampersand@%26|seealso{p@P!plus@%2B}#index
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The following `sed` command percent-encodes those four characters in a raw instruction:
|
|
36
|
+
|
|
37
|
+
```shellsession
|
|
38
|
+
$ printf '%s\n' 'a@A!ampersand@&|seealso{p@P!plus@+}' | sed 's/%/%25/g; s/#/%23/g; s/&/%26/g; s/+/%2B/g'
|
|
39
|
+
a@A!ampersand@%26|seealso{p@P!plus@%2B}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Index modeling
|
|
43
|
+
|
|
44
|
+
A document contains zero or more indexes. Each index contains zero or more groups, and each group contains zero or more entries (Japanese: 「主見出し」). An entry contains zero or more locators (Japanese: 「所在指示」), preferred cross-references (`see`; Japanese: 「を見よ参照」), related cross-references (`see also`; Japanese: 「をも見よ参照」), and subentries (Japanese: 「副見出し」). A subentry has the same locator and cross-reference collections as an entry, but cannot contain further subentries.
|
|
45
|
+
|
|
46
|
+
Locators distinguish single pages from page ranges. Modeling every locator as a range would require the renderer to collapse equal endpoints into a single-page form.[^locator-css] A cross-reference targets either an entry or a subentry. Each locator and cross-reference also has an HTML template, primarily used to wrap its rendered form in decorative markup.
|
|
47
|
+
|
|
48
|
+
[^locator-css]: CSS cross-reference functions such as [`target-counter()`](https://drafts.csswg.org/css-content-3/#target-counter) and [`target-text()`](https://drafts.csswg.org/css-content-3/#target-text) retrieve information from one target at a time. They provide no conditional mechanism for comparing two range endpoints and collapsing the output when both resolve to the same page.
|
|
49
|
+
|
|
50
|
+
The following class diagram summarizes these relationships.
|
|
51
|
+
|
|
52
|
+
```mermaid
|
|
53
|
+
classDiagram
|
|
54
|
+
direction LR
|
|
55
|
+
|
|
56
|
+
Document "1" *-- "0..*" Index
|
|
57
|
+
Index "1" *-- "0..*" Group
|
|
58
|
+
Group "1" *-- "0..*" Entry
|
|
59
|
+
Entry "1" *-- "0..*" Locator
|
|
60
|
+
Entry "1" *-- "0..*" PreferredXref
|
|
61
|
+
Entry "1" *-- "0..*" RelatedXref
|
|
62
|
+
Entry "1" *-- "0..*" Subentry
|
|
63
|
+
Subentry "1" *-- "0..*" Locator
|
|
64
|
+
Subentry "1" *-- "0..*" PreferredXref
|
|
65
|
+
Subentry "1" *-- "0..*" RelatedXref
|
|
66
|
+
Locator <|-- PageLocator
|
|
67
|
+
Locator <|-- RangeLocator
|
|
68
|
+
Xref <|-- PreferredXref
|
|
69
|
+
Xref <|-- RelatedXref
|
|
70
|
+
XrefTarget <|-- Entry
|
|
71
|
+
XrefTarget <|-- Subentry
|
|
72
|
+
Xref "0..*" --> "1" XrefTarget
|
|
73
|
+
Locator "1" *-- "1" Template
|
|
74
|
+
Xref "1" *-- "1" Template
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
The implementation keys each index by the path-and-fragment pair of its output target; together they identify a DOM element. Each group, entry, and subentry key is a pair of `reading` and `html` values. In the DSL, this pair is written as `reading@display`; the display value becomes the key's inner HTML. A cross-reference identifies its target by the group and entry keys, plus the subentry key when present.
|
|
78
|
+
|
|
79
|
+
## Instruction syntax
|
|
80
|
+
|
|
81
|
+
An indexing reference carries its instruction in the `q` parameter of its `data-index` attribute. The instruction is the decoded value returned for `q` after parsing the URL query, including `+`-to-space conversion and percent-decoding. The lexer scans the decoded instruction from left to right. A backslash starts an escape; otherwise, the lexer selects the longest recognized token at each position and treats unmatched characters as literal text.
|
|
82
|
+
|
|
83
|
+
| Token | Role |
|
|
84
|
+
| --- | --- |
|
|
85
|
+
| `!` | Separates the group, entry, and optional subentry of an address |
|
|
86
|
+
| `@` | Separates a reading from its display value within a group, entry, or subentry |
|
|
87
|
+
| `\|` | Introduces a template |
|
|
88
|
+
| `\|(` | Marks a range start |
|
|
89
|
+
| `\|)` | Marks a range end |
|
|
90
|
+
| `\|see{` | Opens the target of a preferred cross-reference |
|
|
91
|
+
| `\|seealso{` | Opens the target of a related cross-reference |
|
|
92
|
+
| `}` | Closes a cross-reference target |
|
|
93
|
+
|
|
94
|
+
### Escaping
|
|
95
|
+
|
|
96
|
+
A backslash makes the next character literal text. Only `\`, `@`, `!`, `|`, `(`, `)`, `{`, and `}` can be escaped; a backslash before any other character is a syntax error.
|
|
97
|
+
|
|
98
|
+
An escaped character never participates in token matching. Escaping the leading `|` makes an entire `|`-prefixed sequence literal: `\|see{` spells the text `|see{`. Escaping a later character instead can cause the leading `|` to match the standalone template introducer; for example, `|see\{` introduces a template containing `see{`.
|
|
99
|
+
|
|
100
|
+
`(`, `)`, and `{` are not tokens on their own, but escaping them can prevent `|(`, `|)`, `|see{`, or `|seealso{` from matching. Escape `}` when it should be text rather than a cross-reference closer.
|
|
101
|
+
|
|
102
|
+
### Accepted instructions
|
|
103
|
+
|
|
104
|
+
Common instruction forms are shown below.
|
|
105
|
+
|
|
106
|
+
| Form | Example |
|
|
107
|
+
| --- | --- |
|
|
108
|
+
| Page | `a!Apple` |
|
|
109
|
+
| Range start | `a!Apple|(` |
|
|
110
|
+
| Range end | `a!Apple|)` |
|
|
111
|
+
| Preferred cross-reference | `a!Apple|see{b!Banana}` |
|
|
112
|
+
| Related cross-reference | `a!Apple|seealso{b!Banana}` |
|
|
113
|
+
| Template | `a!Apple|<strong><slot></slot></strong>` |
|
|
114
|
+
|
|
115
|
+
The diagram below shows every token sequence that forms an accepted instruction. Token-consuming transitions are labeled with tokens. Here, `text` means either a maximal run of literal characters or one escaped character. An unlabeled transition to `[*]` indicates that the instruction may end in the source state; an instruction is accepted only if all input has been consumed in such a state. A path through `range start` or `range end` represents a range boundary; one through `cross-reference target` represents a cross-reference; any other accepted path represents a page reference.
|
|
116
|
+
|
|
117
|
+
```mermaid
|
|
118
|
+
stateDiagram-v2
|
|
119
|
+
direction TB
|
|
120
|
+
|
|
121
|
+
state "address" as address {
|
|
122
|
+
direction TB
|
|
123
|
+
state "group" as a_g
|
|
124
|
+
state "group reading" as a_gr
|
|
125
|
+
state "group @" as a_ga
|
|
126
|
+
state "group display" as a_gd
|
|
127
|
+
state "entry" as a_e
|
|
128
|
+
state "entry reading" as a_er
|
|
129
|
+
state "entry @" as a_ea
|
|
130
|
+
state "entry display" as a_ed
|
|
131
|
+
state "subentry" as a_s
|
|
132
|
+
state "subentry reading" as a_sr
|
|
133
|
+
state "subentry @" as a_sa
|
|
134
|
+
state "subentry display" as a_sd
|
|
135
|
+
[*] --> a_g
|
|
136
|
+
a_g --> a_gr : text
|
|
137
|
+
a_gr --> a_gr : text
|
|
138
|
+
a_gr --> a_ga : @
|
|
139
|
+
a_ga --> a_gd : text
|
|
140
|
+
a_gd --> a_gd : text
|
|
141
|
+
a_gr --> a_e : !
|
|
142
|
+
a_gd --> a_e : !
|
|
143
|
+
a_e --> a_er : text
|
|
144
|
+
a_er --> a_er : text
|
|
145
|
+
a_er --> a_ea : @
|
|
146
|
+
a_ea --> a_ed : text
|
|
147
|
+
a_ed --> a_ed : text
|
|
148
|
+
a_er --> a_s : !
|
|
149
|
+
a_ed --> a_s : !
|
|
150
|
+
a_s --> a_sr : text
|
|
151
|
+
a_sr --> a_sr : text
|
|
152
|
+
a_sr --> a_sa : @
|
|
153
|
+
a_sa --> a_sd : text
|
|
154
|
+
a_sd --> a_sd : text
|
|
155
|
+
a_er --> [*]
|
|
156
|
+
a_ed --> [*]
|
|
157
|
+
a_sr --> [*]
|
|
158
|
+
a_sd --> [*]
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
state "cross-reference target" as target {
|
|
162
|
+
direction TB
|
|
163
|
+
state "group" as t_g
|
|
164
|
+
state "group reading" as t_gr
|
|
165
|
+
state "group @" as t_ga
|
|
166
|
+
state "group display" as t_gd
|
|
167
|
+
state "entry" as t_e
|
|
168
|
+
state "entry reading" as t_er
|
|
169
|
+
state "entry @" as t_ea
|
|
170
|
+
state "entry display" as t_ed
|
|
171
|
+
state "subentry" as t_s
|
|
172
|
+
state "subentry reading" as t_sr
|
|
173
|
+
state "subentry @" as t_sa
|
|
174
|
+
state "subentry display" as t_sd
|
|
175
|
+
[*] --> t_g
|
|
176
|
+
t_g --> t_gr : text
|
|
177
|
+
t_gr --> t_gr : text
|
|
178
|
+
t_gr --> t_ga : @
|
|
179
|
+
t_ga --> t_gd : text
|
|
180
|
+
t_gd --> t_gd : text
|
|
181
|
+
t_gr --> t_e : !
|
|
182
|
+
t_gd --> t_e : !
|
|
183
|
+
t_e --> t_er : text
|
|
184
|
+
t_er --> t_er : text
|
|
185
|
+
t_er --> t_ea : @
|
|
186
|
+
t_ea --> t_ed : text
|
|
187
|
+
t_ed --> t_ed : text
|
|
188
|
+
t_er --> t_s : !
|
|
189
|
+
t_ed --> t_s : !
|
|
190
|
+
t_s --> t_sr : text
|
|
191
|
+
t_sr --> t_sr : text
|
|
192
|
+
t_sr --> t_sa : @
|
|
193
|
+
t_sa --> t_sd : text
|
|
194
|
+
t_sd --> t_sd : text
|
|
195
|
+
t_er --> [*]
|
|
196
|
+
t_ed --> [*]
|
|
197
|
+
t_sr --> [*]
|
|
198
|
+
t_sd --> [*]
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
state "range start" as range_start
|
|
202
|
+
state "range end" as range_end
|
|
203
|
+
state "target closed" as xref_closed
|
|
204
|
+
state "template" as template
|
|
205
|
+
|
|
206
|
+
[*] --> address
|
|
207
|
+
address --> [*]
|
|
208
|
+
address --> template : |
|
|
209
|
+
address --> range_start : |(
|
|
210
|
+
address --> range_end : |)
|
|
211
|
+
address --> target : |see{
|
|
212
|
+
address --> target : |seealso{
|
|
213
|
+
range_start --> [*]
|
|
214
|
+
range_start --> template : |
|
|
215
|
+
range_end --> [*]
|
|
216
|
+
target --> xref_closed : }
|
|
217
|
+
xref_closed --> [*]
|
|
218
|
+
xref_closed --> template : |
|
|
219
|
+
template --> template : text
|
|
220
|
+
template --> [*]
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## References
|
|
224
|
+
|
|
225
|
+
- DAISY Consortium. n.d. “[Indexes](https://kb.daisy.org/publishing/docs/html/indexes.html).” *Accessible Publishing Knowledge Base*. Accessed August 18, 2026. Revision history: [publishing/docs/html/indexes.html](https://github.com/DAISY/kb/commits/main/publishing/docs/html/indexes.html).
|
|
226
|
+
- Fujita, Setsuko. 2019. *[本の索引の作り方](http://www.chijinshokan.co.jp/Books/ISBN978-4-8052-0932-5.htm)*. 地人書館.
|
|
227
|
+
- Garrish, Matt, and Tzviya Siegman, eds. 2025. “[`doc-index`](https://www.w3.org/TR/dpub-aria-1.1/#doc-index).” *Digital Publishing WAI-ARIA Module 1.1*. W3C Recommendation, June 12, 2025. World Wide Web Consortium. Revision history: [dpub-aria/index.html](https://github.com/w3c/aria/commits/main/dpub-aria/index.html).
|
|
228
|
+
- Herman, Ivan, and Matt Garrish, eds. 2026. “[Indexes](https://www.w3.org/TR/epub-ssv/#h_indexes).” *EPUB 3 Structural Semantics Vocabulary 1.1*. W3C Group Note, May 28, 2026. World Wide Web Consortium. Revision history: [wg-notes/ssv/index.html](https://github.com/w3c/epub-specs/commits/main/wg-notes/ssv/index.html).
|
|
229
|
+
- Japan Science and Technology Agency. n.d. “[SIST 13 索引作成](https://warp.ndl.go.jp/20220119/20220113214526id_/jipsti.jst.go.jp/sist/handbook/sist13/sist13_m.htm) [Indexes and Indexing].” Archived January 13, 2022, by the National Diet Library Web Archiving Project. Accessed August 18, 2026.
|
|
230
|
+
- WHATWG. n.d. “[URL](https://url.spec.whatwg.org/).” *WHATWG Living Standard*. Accessed August 19, 2026. Revision history: [url.bs](https://github.com/whatwg/url/commits/main/url.bs).
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type * as hast from "hast";
|
|
2
|
+
import type { VFile } from "vfile";
|
|
3
|
+
import type { BuiltIndex } from "./index-builder.ts";
|
|
4
|
+
import { type ResolvedIndexProfile } from "./profile.ts";
|
|
5
|
+
import type { TargetKey } from "./target.ts";
|
|
6
|
+
export declare function renderDocumentIndexes(root: hast.Root, documentPath: string, indexes: ReadonlyMap<TargetKey, BuiltIndex>, profiles: ReadonlyMap<string, ResolvedIndexProfile>, file: VFile): void;
|
|
7
|
+
//# sourceMappingURL=document-renderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"document-renderer.d.ts","sourceRoot":"","sources":["../src/document-renderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,IAAI,MAAM,MAAM,CAAC;AAIlC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAEnC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,EAAkB,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAGzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAyE7C,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,IAAI,CAAC,IAAI,EACf,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,WAAW,CAAC,SAAS,EAAE,UAAU,CAAC,EAC3C,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,oBAAoB,CAAC,EACnD,IAAI,EAAE,KAAK,GACV,IAAI,CAqBN"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { getAttribute } from "hast-util-get-attribute";
|
|
2
|
+
import { h } from "hastscript";
|
|
3
|
+
import { EXIT, visitParents } from "unist-util-visit-parents";
|
|
4
|
+
import { messages } from "./messages.js";
|
|
5
|
+
import { defaultProfile } from "./profile.js";
|
|
6
|
+
import { renderIndex } from "./render.js";
|
|
7
|
+
import { sort } from "./sort.js";
|
|
8
|
+
function collatableLanguage(language) {
|
|
9
|
+
try {
|
|
10
|
+
return Intl.Collator.supportedLocalesOf(language).length !== 0;
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function resolveLocales(language, file) {
|
|
17
|
+
if (language === undefined || language === "") {
|
|
18
|
+
return "en";
|
|
19
|
+
}
|
|
20
|
+
if (collatableLanguage(language)) {
|
|
21
|
+
return language;
|
|
22
|
+
}
|
|
23
|
+
file.message(...messages.unsupportedLanguage(language));
|
|
24
|
+
return "en";
|
|
25
|
+
}
|
|
26
|
+
function findTargetElement(root, id) {
|
|
27
|
+
// Valid HTML IDs are not necessarily valid unescaped CSS ID selectors.
|
|
28
|
+
let found;
|
|
29
|
+
visitParents(root, "element", (element, ancestors) => {
|
|
30
|
+
if (getAttribute(element, "id") !== id) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const language = [...ancestors, element]
|
|
34
|
+
.reverse()
|
|
35
|
+
.flatMap((ancestor) => {
|
|
36
|
+
const lang = ancestor.type === "element" ? getAttribute(ancestor, "lang") : null;
|
|
37
|
+
return lang === null ? [] : [lang];
|
|
38
|
+
})
|
|
39
|
+
.at(0);
|
|
40
|
+
found = { element, language };
|
|
41
|
+
return EXIT;
|
|
42
|
+
});
|
|
43
|
+
return found;
|
|
44
|
+
}
|
|
45
|
+
// The role attribute holds a token list (https://www.w3.org/TR/wai-aria-1.2/#host_general_role)
|
|
46
|
+
// split on the host language's ASCII whitespace, which is narrower than \s.
|
|
47
|
+
const roleSeparator = /[\t\n\f\r ]+/;
|
|
48
|
+
function carriesDocIndexRole(element) {
|
|
49
|
+
const role = getAttribute(element, "role");
|
|
50
|
+
return role !== null && role.split(roleSeparator).includes("doc-index");
|
|
51
|
+
}
|
|
52
|
+
function resolveProfile(element, target, profiles, file) {
|
|
53
|
+
const profileName = getAttribute(element, "data-index-profile");
|
|
54
|
+
if (profileName === null) {
|
|
55
|
+
return defaultProfile;
|
|
56
|
+
}
|
|
57
|
+
const profile = profiles.get(profileName);
|
|
58
|
+
if (profile === undefined) {
|
|
59
|
+
file.message(...messages.unknownIndexProfile(target, profileName));
|
|
60
|
+
return defaultProfile;
|
|
61
|
+
}
|
|
62
|
+
return profile;
|
|
63
|
+
}
|
|
64
|
+
export function renderDocumentIndexes(root, documentPath, indexes, profiles, file) {
|
|
65
|
+
for (const { target, index } of indexes.values()) {
|
|
66
|
+
if (target.path !== documentPath) {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
const found = findTargetElement(root, target.fragment);
|
|
70
|
+
if (!found) {
|
|
71
|
+
file.message(...messages.missingIndexTarget(target));
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const { element, language } = found;
|
|
75
|
+
if (!carriesDocIndexRole(element)) {
|
|
76
|
+
file.message(...messages.missingIndexRole(target));
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
const profile = resolveProfile(element, target, profiles, file);
|
|
80
|
+
const comparator = profile.comparator(resolveLocales(language, file));
|
|
81
|
+
const sorted = sort(index, comparator);
|
|
82
|
+
const renderer = profile.renderer({ h, index: sorted });
|
|
83
|
+
renderIndex(sorted, element, target.fragment, renderer);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=document-renderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"document-renderer.js","sourceRoot":"","sources":["../src/document-renderer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
export type FileSystem = {
|
|
3
|
+
readFileSync: (path: string) => string;
|
|
4
|
+
touchSync: (path: string) => void;
|
|
5
|
+
};
|
|
6
|
+
type BaseFileSystem = Pick<typeof fs, "readFileSync" | "utimesSync" | "statSync" | "openSync" | "writeSync" | "ftruncateSync" | "closeSync">;
|
|
7
|
+
type ExecuteFileSync = (file: string, args: readonly string[]) => void;
|
|
8
|
+
export declare function createFileSystem(base: BaseFileSystem, execute?: ExecuteFileSync): FileSystem;
|
|
9
|
+
export declare const nodeFileSystem: FileSystem;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=file-system.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-system.d.ts","sourceRoot":"","sources":["../src/file-system.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,MAAM,MAAM,UAAU,GAAG;IACvB,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACvC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC,CAAC;AAEF,KAAK,cAAc,GAAG,IAAI,CACxB,OAAO,EAAE,EACP,cAAc,GACd,YAAY,GACZ,UAAU,GACV,UAAU,GACV,WAAW,GACX,eAAe,GACf,WAAW,CACd,CAAC;AAEF,KAAK,eAAe,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,KAAK,IAAI,CAAC;AAiGvE,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,UAAU,CAK5F;AAED,eAAO,MAAM,cAAc,EAAE,UAAkD,CAAC"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
const systemTouchExecutables = ["/usr/bin/touch", "/bin/touch"];
|
|
4
|
+
const executeFileSync = (file, args) => {
|
|
5
|
+
execFileSync(file, args);
|
|
6
|
+
};
|
|
7
|
+
function updateTimestamp(base, fileName) {
|
|
8
|
+
const time = new Date();
|
|
9
|
+
base.utimesSync(fileName, time, time);
|
|
10
|
+
}
|
|
11
|
+
function appendAndRestoreSize(base, fileName) {
|
|
12
|
+
// Opening and closing a writable file does not update mtime. A real write does,
|
|
13
|
+
// so the last-resort path appends one byte and truncates it immediately. The
|
|
14
|
+
// original bytes and size survive, while the filesystem still records the write.
|
|
15
|
+
const originalSize = base.statSync(fileName).size;
|
|
16
|
+
const fd = base.openSync(fileName, "a");
|
|
17
|
+
try {
|
|
18
|
+
base.writeSync(fd, " ");
|
|
19
|
+
base.ftruncateSync(fd, originalSize);
|
|
20
|
+
}
|
|
21
|
+
finally {
|
|
22
|
+
base.closeSync(fd);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function hasErrorCode(error, code) {
|
|
26
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === code;
|
|
27
|
+
}
|
|
28
|
+
// execFileSync copies spawnSync fields onto both spawn errors and child exit errors.
|
|
29
|
+
// A spawn error still has status and signal properties, but both values are null;
|
|
30
|
+
// a started child has either a numeric exit status or a terminating signal.
|
|
31
|
+
function processStarted(error) {
|
|
32
|
+
return (typeof error === "object" &&
|
|
33
|
+
error !== null &&
|
|
34
|
+
(("status" in error && error.status !== null && error.status !== undefined) ||
|
|
35
|
+
("signal" in error && error.signal !== null && error.signal !== undefined)));
|
|
36
|
+
}
|
|
37
|
+
function executeSystemTouch(base, execute, fileName) {
|
|
38
|
+
// POSIX distinguishes explicit timestamps from "set both fields to now".
|
|
39
|
+
// Node's utimesSync supplies explicit values, which normally requires the
|
|
40
|
+
// file owner or CAP_FOWNER on Linux. The system touch command can request
|
|
41
|
+
// the kernel's current-time operation, which also permits a writable file
|
|
42
|
+
// owned by another UID.
|
|
43
|
+
//
|
|
44
|
+
// npm prepends node_modules/.bin to PATH. Absolute system locations prevent
|
|
45
|
+
// a package-provided executable from taking the place of the OS utility.
|
|
46
|
+
for (const executable of systemTouchExecutables) {
|
|
47
|
+
try {
|
|
48
|
+
// The option terminator keeps names such as "--help" from being parsed as
|
|
49
|
+
// command options. execFileSync also avoids shell interpretation entirely.
|
|
50
|
+
execute(executable, ["-c", "--", fileName]);
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
// Spawn failures have no child status or signal and can arise from a missing
|
|
54
|
+
// executable, noexec mounts, or Node's process permissions. Once a child has
|
|
55
|
+
// started, its failure describes the target filesystem and must be preserved.
|
|
56
|
+
if (!processStarted(error)) {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
// touch -c deliberately reports success when the target is absent. Restore
|
|
62
|
+
// the FileSystem contract by checking that the requested file still exists.
|
|
63
|
+
base.statSync(fileName);
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
function touchSync(base, execute, fileName) {
|
|
69
|
+
try {
|
|
70
|
+
// The Node API avoids spawning a process and preserves its precise filesystem
|
|
71
|
+
// errors. EPERM is exceptional because the OS current-time operation has a
|
|
72
|
+
// less restrictive permission model than Node's explicit timestamps.
|
|
73
|
+
updateTimestamp(base, fileName);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
if (!hasErrorCode(error, "EPERM")) {
|
|
78
|
+
throw error;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (execute && executeSystemTouch(base, execute, fileName)) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
appendAndRestoreSize(base, fileName);
|
|
85
|
+
}
|
|
86
|
+
export function createFileSystem(base, execute) {
|
|
87
|
+
return {
|
|
88
|
+
readFileSync: (path) => base.readFileSync(path, { encoding: "utf-8" }),
|
|
89
|
+
touchSync: (path) => touchSync(base, execute, path),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
export const nodeFileSystem = createFileSystem(fs, executeFileSync);
|
|
93
|
+
//# sourceMappingURL=file-system.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-system.js","sourceRoot":"","sources":["../src/file-system.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,MAAM,SAAS,CAAC;AAoBzB,MAAM,sBAAsB,GAAG,CAAC,gBAAgB,EAAE,YAAY,CAAU,CAAC;AAEzE,MAAM,eAAe,GAAoB,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE;IACtD,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAC3B,CAAC,CAAC;AAEF,SAAS,eAAe,CAAC,IAAoB,EAAE,QAAgB;IAC7D,MAAM,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;IACxB,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AACxC,CAAC;AAED,SAAS,oBAAoB,CAAC,IAAoB,EAAE,QAAgB;IAClE,gFAAgF;IAChF,6EAA6E;IAC7E,iFAAiF;IACjF,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC;IAClD,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IACxC,IAAI,CAAC;QACH,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QACxB,IAAI,CAAC,aAAa,CAAC,EAAE,EAAE,YAAY,CAAC,CAAC;IACvC,CAAC;YAAS,CAAC;QACT,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IACrB,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,KAAc,EAAE,IAAY;IAChD,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC;AAC/F,CAAC;AAED,qFAAqF;AACrF,kFAAkF;AAClF,4EAA4E;AAC5E,SAAS,cAAc,CAAC,KAAc;IACpC,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,CAAC,CAAC,QAAQ,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC;YACzE,CAAC,QAAQ,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAC9E,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CACzB,IAAoB,EACpB,OAAwB,EACxB,QAAgB;IAEhB,yEAAyE;IACzE,0EAA0E;IAC1E,0EAA0E;IAC1E,0EAA0E;IAC1E,wBAAwB;IACxB,EAAE;IACF,4EAA4E;IAC5E,yEAAyE;IACzE,KAAK,MAAM,UAAU,IAAI,sBAAsB,EAAE,CAAC;QAChD,IAAI,CAAC;YACH,0EAA0E;YAC1E,2EAA2E;YAC3E,OAAO,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;QAC9C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,6EAA6E;YAC7E,6EAA6E;YAC7E,8EAA8E;YAC9E,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC3B,SAAS;YACX,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;QACD,2EAA2E;QAC3E,4EAA4E;QAC5E,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,SAAS,CAAC,IAAoB,EAAE,OAAoC,EAAE,QAAgB;IAC7F,IAAI,CAAC;QACH,8EAA8E;QAC9E,2EAA2E;QAC3E,qEAAqE;QACrE,eAAe,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAChC,OAAO;IACT,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,CAAC;YAClC,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,IAAI,OAAO,IAAI,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,CAAC;QAC3D,OAAO;IACT,CAAC;IACD,oBAAoB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAoB,EAAE,OAAyB;IAC9E,OAAO;QACL,YAAY,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;QACtE,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC;KACpD,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,cAAc,GAAe,gBAAgB,CAAC,EAAE,EAAE,eAAe,CAAC,CAAC"}
|
package/dist/html.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../src/html.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,IAAI,MAAM,MAAM,CAAC;AAIlC,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC,cAAc,EAAE,CAIjE;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,UAE1C"}
|
package/dist/html.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { fromHtml } from "hast-util-from-html";
|
|
2
|
+
import { toText } from "hast-util-to-text";
|
|
3
|
+
export function parseFragment(html) {
|
|
4
|
+
return fromHtml(html, { fragment: true }).children.filter((child) => child.type !== "doctype");
|
|
5
|
+
}
|
|
6
|
+
export function fragmentToText(html) {
|
|
7
|
+
return toText(fromHtml(html, { fragment: true }));
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=html.js.map
|
package/dist/html.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html.js","sourceRoot":"","sources":["../src/html.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,OAAO,QAAQ,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,MAAM,CACvD,CAAC,KAAK,EAAgC,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAClE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACpD,CAAC"}
|
package/dist/id.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Key } from "./model.ts";
|
|
2
|
+
export declare const createSourceId: (xpath: string) => string;
|
|
3
|
+
export declare const createEntryId: (indexId: string, group: Key, entry: Key) => string;
|
|
4
|
+
export declare const createSubentryId: (indexId: string, group: Key, entry: Key, subentry: Key) => string;
|
|
5
|
+
//# sourceMappingURL=id.d.ts.map
|
package/dist/id.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"id.d.ts","sourceRoot":"","sources":["../src/id.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAwCtC,eAAO,MAAM,cAAc,UAAW,MAAM,KAAG,MAAqC,CAAC;AAErF,eAAO,MAAM,aAAa,YAAa,MAAM,SAAS,GAAG,SAAS,GAAG,KAAG,MACV,CAAC;AAE/D,eAAO,MAAM,gBAAgB,YAAa,MAAM,SAAS,GAAG,SAAS,GAAG,YAAY,GAAG,KAAG,MACf,CAAC"}
|
package/dist/id.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// TextEncoder is not injective: WHATWG Encoding replaces lone surrogates with U+FFFD.
|
|
2
|
+
const wtf8Bytes = (value) => {
|
|
3
|
+
const bytes = [];
|
|
4
|
+
for (const character of value) {
|
|
5
|
+
const codePoint = character.codePointAt(0);
|
|
6
|
+
if (codePoint <= 0x7f) {
|
|
7
|
+
bytes.push(codePoint);
|
|
8
|
+
}
|
|
9
|
+
else if (codePoint <= 0x7ff) {
|
|
10
|
+
bytes.push(0xc0 | (codePoint >> 6), 0x80 | (codePoint & 0x3f));
|
|
11
|
+
}
|
|
12
|
+
else if (codePoint <= 0xffff) {
|
|
13
|
+
bytes.push(0xe0 | (codePoint >> 12), 0x80 | ((codePoint >> 6) & 0x3f), 0x80 | (codePoint & 0x3f));
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
bytes.push(0xf0 | (codePoint >> 18), 0x80 | ((codePoint >> 12) & 0x3f), 0x80 | ((codePoint >> 6) & 0x3f), 0x80 | (codePoint & 0x3f));
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return bytes;
|
|
20
|
+
};
|
|
21
|
+
const encodeIdSegment = (value) => {
|
|
22
|
+
const binary = wtf8Bytes(value).reduce((binary, byte) => binary + String.fromCharCode(byte), "");
|
|
23
|
+
return btoa(binary).replaceAll("+", "-").replaceAll("/", "_").replaceAll("=", "");
|
|
24
|
+
};
|
|
25
|
+
const keySegments = (keys) => keys.flatMap(({ reading, html }) => [reading, html]);
|
|
26
|
+
const createId = (type, segments) => ["index", type, ...segments.map(encodeIdSegment)].join(".");
|
|
27
|
+
export const createSourceId = (xpath) => createId("source", [xpath]);
|
|
28
|
+
export const createEntryId = (indexId, group, entry) => createId("entry", [indexId, ...keySegments([group, entry])]);
|
|
29
|
+
export const createSubentryId = (indexId, group, entry, subentry) => createId("subentry", [indexId, ...keySegments([group, entry, subentry])]);
|
|
30
|
+
//# sourceMappingURL=id.js.map
|
package/dist/id.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"id.js","sourceRoot":"","sources":["../src/id.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type MessageArguments } from "./messages.ts";
|
|
2
|
+
import { type Index } from "./model.ts";
|
|
3
|
+
import type { SourceSnapshot } from "./source-snapshot.ts";
|
|
4
|
+
import type { Target, TargetKey } from "./target.ts";
|
|
5
|
+
export type BuiltIndex = Readonly<{
|
|
6
|
+
target: Target;
|
|
7
|
+
index: Index;
|
|
8
|
+
sourcePaths: readonly string[];
|
|
9
|
+
}>;
|
|
10
|
+
export type BuiltIndexes = Readonly<{
|
|
11
|
+
indexes: ReadonlyMap<TargetKey, BuiltIndex>;
|
|
12
|
+
messages: ReadonlyMap<string, readonly MessageArguments[]>;
|
|
13
|
+
}>;
|
|
14
|
+
export declare function buildIndexes(entryPaths: readonly string[], sources: ReadonlyMap<string, SourceSnapshot>): BuiltIndexes;
|
|
15
|
+
//# sourceMappingURL=index-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-builder.d.ts","sourceRoot":"","sources":["../src/index-builder.ts"],"names":[],"mappings":"AAKA,OAAO,EAAwB,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC5E,OAAO,EAML,KAAK,KAAK,EAEX,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAc,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACvE,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGrD,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,KAAK,CAAC;IACb,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;CAChC,CAAC,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,QAAQ,CAAC;IAClC,OAAO,EAAE,WAAW,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAC5C,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,gBAAgB,EAAE,CAAC,CAAC;CAC5D,CAAC,CAAC;AAuJH,wBAAgB,YAAY,CAC1B,UAAU,EAAE,SAAS,MAAM,EAAE,EAC7B,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,cAAc,CAAC,GAC3C,YAAY,CAmDd"}
|