@asciidoctor/core 3.0.3 → 4.0.0-alpha.1
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 +42 -10
- package/build/browser/index.js +24154 -0
- package/build/node/index.cjs +24735 -0
- package/{dist/css/asciidoctor.css → data/asciidoctor-default.css} +54 -53
- package/package.json +53 -100
- package/src/abstract_block.js +849 -0
- package/src/abstract_node.js +954 -0
- package/src/attribute_entry.js +12 -0
- package/src/attribute_list.js +380 -0
- package/src/block.js +168 -0
- package/src/browser/asset.js +22 -0
- package/src/browser/reader.js +138 -0
- package/src/browser.js +121 -0
- package/src/callouts.js +85 -0
- package/src/compliance.js +54 -0
- package/src/constants.js +665 -0
- package/src/convert.js +370 -0
- package/src/converter/composite.js +83 -0
- package/src/converter/docbook5.js +1031 -0
- package/src/converter/html5.js +1899 -0
- package/src/converter/manpage.js +935 -0
- package/src/converter/template.js +459 -0
- package/src/converter.js +478 -0
- package/src/data/stylesheet-data.js +2 -0
- package/src/document.js +2134 -0
- package/src/extensions.js +1952 -0
- package/src/footnote.js +28 -0
- package/src/helpers.js +355 -0
- package/src/index.js +138 -0
- package/src/inline.js +158 -0
- package/src/list.js +240 -0
- package/src/load.js +276 -0
- package/src/logging.js +526 -0
- package/src/parser.js +3661 -0
- package/src/path_resolver.js +472 -0
- package/src/reader.js +1755 -0
- package/src/rx.js +829 -0
- package/src/section.js +354 -0
- package/src/stylesheets.js +30 -0
- package/src/substitutors.js +2241 -0
- package/src/syntaxHighlighter/highlightjs.js +90 -0
- package/src/syntaxHighlighter/html_pipeline.js +33 -0
- package/src/syntax_highlighter.js +304 -0
- package/src/table.js +952 -0
- package/src/timings.js +78 -0
- package/types/abstract_block.d.ts +343 -0
- package/types/abstract_node.d.ts +471 -0
- package/types/attribute_entry.d.ts +7 -0
- package/types/attribute_list.d.ts +52 -0
- package/types/block.d.ts +55 -0
- package/types/browser/asset.d.ts +7 -0
- package/types/browser/reader.d.ts +29 -0
- package/types/callouts.d.ts +36 -0
- package/types/compliance.d.ts +23 -0
- package/types/constants.d.ts +268 -0
- package/types/convert.d.ts +34 -0
- package/types/converter/composite.d.ts +20 -0
- package/types/converter/docbook5.d.ts +41 -0
- package/types/converter/html5.d.ts +51 -0
- package/types/converter/manpage.d.ts +59 -0
- package/types/converter/template.d.ts +83 -0
- package/types/converter.d.ts +150 -0
- package/types/data/stylesheet-data.d.ts +2 -0
- package/types/document.d.ts +495 -0
- package/types/extensions.d.ts +876 -0
- package/types/footnote.d.ts +18 -0
- package/types/helpers.d.ts +146 -0
- package/types/index.d.ts +73 -3731
- package/types/inline.d.ts +69 -0
- package/types/list.d.ts +114 -0
- package/types/load.d.ts +39 -0
- package/types/logging.d.ts +187 -0
- package/types/parser.d.ts +114 -0
- package/types/path_resolver.d.ts +103 -0
- package/types/reader.d.ts +184 -0
- package/types/rx.d.ts +513 -0
- package/types/section.d.ts +122 -0
- package/types/stylesheets.d.ts +10 -0
- package/types/substitutors.d.ts +208 -0
- package/types/syntaxHighlighter/highlightjs.d.ts +33 -0
- package/types/syntaxHighlighter/html_pipeline.d.ts +16 -0
- package/types/syntax_highlighter.d.ts +167 -0
- package/types/table.d.ts +231 -0
- package/types/timings.d.ts +25 -0
- package/types/tsconfig.json +9 -0
- package/LICENSE +0 -21
- package/dist/browser/asciidoctor.js +0 -47654
- package/dist/browser/asciidoctor.min.js +0 -1452
- package/dist/graalvm/asciidoctor.js +0 -47402
- package/dist/node/asciidoctor.cjs +0 -21567
- package/dist/node/asciidoctor.js +0 -23037
|
@@ -0,0 +1,954 @@
|
|
|
1
|
+
// ESM conversion of abstract_node.rb
|
|
2
|
+
//
|
|
3
|
+
// Ruby-to-JavaScript notes:
|
|
4
|
+
// - Ruby symbols (:document, :context) are represented as plain strings.
|
|
5
|
+
// - attr_reader / attr_accessor are implemented as plain instance properties;
|
|
6
|
+
// cases where the setter has side effects use JS get/set pairs.
|
|
7
|
+
// - Ruby methods ending in ? are renamed: attr? → hasAttr, block? → isBlock,
|
|
8
|
+
// inline? → isInline, role? → hasRoleAttribute, has_role? → hasRole,
|
|
9
|
+
// option? → hasOption, reftext? → hasReftext.
|
|
10
|
+
// - Ruby methods ending in = that have side effects use JS set accessors:
|
|
11
|
+
// parent= → set parent(), role= → set role().
|
|
12
|
+
// - snake_case method/property names are converted to camelCase:
|
|
13
|
+
// node_name → nodeName, set_attr → setAttr, etc.
|
|
14
|
+
// - The Logging mixin (logger getter) is provided as a default on AbstractNode;
|
|
15
|
+
// it falls back to the document's logger or the global console.
|
|
16
|
+
// - The Substitutors mixin is applied via Object.assign(AbstractNode.prototype, Substitutors)
|
|
17
|
+
// after both modules are loaded (see the bottom of substitutors.js).
|
|
18
|
+
// - File I/O in generateDataUri / readAsset uses node:fs/promises async APIs.
|
|
19
|
+
// When the resolved path is an HTTP URI (browser: docdir is a URL), readAsset
|
|
20
|
+
// delegates to browser/asset.js (Fetch API) instead of using the filesystem.
|
|
21
|
+
// - generateDataUriFromUri and readContents use the Fetch API and are async;
|
|
22
|
+
// imageUri and readContents must be awaited when the data-uri + allow-uri-read
|
|
23
|
+
// combination is active.
|
|
24
|
+
// - Ruby's Set is represented as a JavaScript Set.
|
|
25
|
+
|
|
26
|
+
import { SafeMode, LF } from './constants.js'
|
|
27
|
+
import {
|
|
28
|
+
isUriish,
|
|
29
|
+
encodeSpacesInUri,
|
|
30
|
+
isExtname,
|
|
31
|
+
extname,
|
|
32
|
+
prepareSourceString,
|
|
33
|
+
} from './helpers.js'
|
|
34
|
+
|
|
35
|
+
// ── Node.js fs (lazy, optional) ───────────────────────────────────────────────
|
|
36
|
+
// Loaded on first use in Node.js; silently absent in browser/WebWorker environments.
|
|
37
|
+
let _fsp // undefined = not tried, null = unavailable, object = available
|
|
38
|
+
let _fsConstants // node:fs constants (R_OK etc.) — not on node:fs/promises
|
|
39
|
+
|
|
40
|
+
async function _requireFsp() {
|
|
41
|
+
if (_fsp !== undefined) return
|
|
42
|
+
try {
|
|
43
|
+
_fsp = await import('node:fs/promises')
|
|
44
|
+
_fsConstants = (await import('node:fs')).constants
|
|
45
|
+
} catch {
|
|
46
|
+
_fsp = null
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function isReadable(path) {
|
|
51
|
+
await _requireFsp()
|
|
52
|
+
if (!_fsp) return false
|
|
53
|
+
try {
|
|
54
|
+
await _fsp.access(path, _fsConstants.R_OK)
|
|
55
|
+
return true
|
|
56
|
+
} catch {
|
|
57
|
+
return false
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* An abstract base class that provides state and methods for managing a node of AsciiDoc content.
|
|
63
|
+
* The state and methods on this class are common to all content segments in an AsciiDoc document.
|
|
64
|
+
* @abstract
|
|
65
|
+
*/
|
|
66
|
+
export class AbstractNode {
|
|
67
|
+
/**
|
|
68
|
+
* @type {string|null|undefined}
|
|
69
|
+
* @internal
|
|
70
|
+
*/
|
|
71
|
+
_convertedReftext
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* @param {AbstractNode} parent
|
|
75
|
+
* @param {string} context
|
|
76
|
+
* @param {object} [opts={}]
|
|
77
|
+
*/
|
|
78
|
+
constructor(parent, context, opts = {}) {
|
|
79
|
+
// document is a special case – should refer to itself
|
|
80
|
+
if (context === 'document') {
|
|
81
|
+
/** @type {Document} */
|
|
82
|
+
this.document = /** @type {Document} */ this
|
|
83
|
+
} else if (parent) {
|
|
84
|
+
/** @internal */
|
|
85
|
+
this._parent = parent
|
|
86
|
+
/** @type {Document} */
|
|
87
|
+
this.document = parent.document
|
|
88
|
+
}
|
|
89
|
+
this.context = context
|
|
90
|
+
this.nodeName = String(context)
|
|
91
|
+
this.id = null
|
|
92
|
+
// NOTE the value of the attributes option may be undefined on an Inline node
|
|
93
|
+
const attrs = opts.attributes
|
|
94
|
+
this.attributes = attrs ? { ...attrs } : {}
|
|
95
|
+
this.passthroughs = []
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Alias for {@link getParent}.
|
|
100
|
+
* @see {getParent}
|
|
101
|
+
*/
|
|
102
|
+
get parent() {
|
|
103
|
+
return this._parent
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Alias for {@link setParent}.
|
|
108
|
+
* @see {setParent}
|
|
109
|
+
*/
|
|
110
|
+
set parent(parent) {
|
|
111
|
+
this._parent = parent
|
|
112
|
+
this.document = parent.document
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Alias for {@link getRole}.
|
|
117
|
+
* @see {getRole}
|
|
118
|
+
*/
|
|
119
|
+
get role() {
|
|
120
|
+
return this.attributes.role
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Set the value of the role attribute on this node.
|
|
125
|
+
*
|
|
126
|
+
* Accepts a single role name, a space-separated String, or an Array.
|
|
127
|
+
*
|
|
128
|
+
* @param {string|string[]} names - A single role name, a space-separated String, or an Array.
|
|
129
|
+
*/
|
|
130
|
+
set role(names) {
|
|
131
|
+
this.attributes.role = Array.isArray(names) ? names.join(' ') : names
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Alias for {@link getRoles}.
|
|
136
|
+
* @see {getRoles}
|
|
137
|
+
*/
|
|
138
|
+
get roles() {
|
|
139
|
+
const val = this.attributes.role
|
|
140
|
+
return val ? val.split(' ') : []
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* @returns {boolean} true if this AbstractNode is an instance of Block.
|
|
145
|
+
* @throws {Error} Subclasses must override this method.
|
|
146
|
+
*/
|
|
147
|
+
isBlock() {
|
|
148
|
+
throw new Error('NotImplementedError')
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* @returns {boolean} true if this AbstractNode is an instance of Inline.
|
|
153
|
+
* @throws {Error} Subclasses must override this method.
|
|
154
|
+
*/
|
|
155
|
+
isInline() {
|
|
156
|
+
throw new Error('NotImplementedError')
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Alias for {@link getConverter}.
|
|
161
|
+
* @see {getConverter}
|
|
162
|
+
* @returns {object} the converter instance.
|
|
163
|
+
*/
|
|
164
|
+
get converter() {
|
|
165
|
+
return this.document.converter
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Get the value of the specified attribute.
|
|
170
|
+
*
|
|
171
|
+
* Looks for the attribute on this node first. If not found and `fallbackName` is
|
|
172
|
+
* set, and this node is not the Document node, look for that attribute on the
|
|
173
|
+
* Document node. Otherwise, return `defaultValue`.
|
|
174
|
+
*
|
|
175
|
+
* @param {string} name - The attribute name to resolve.
|
|
176
|
+
* @param {*} [defaultValue=null] - The value to return if the attribute is not found.
|
|
177
|
+
* @param {string|boolean|null} [fallbackName=null] - When truthy, also checks the Document's
|
|
178
|
+
* attributes. Pass `true` to fall back using the same name, or a string to use a different name.
|
|
179
|
+
* @returns {*} the attribute value or defaultValue.
|
|
180
|
+
*
|
|
181
|
+
* @example <caption>Simple lookup</caption>
|
|
182
|
+
* block.getAttribute('language') // → 'ruby' or null
|
|
183
|
+
*
|
|
184
|
+
* @example <caption>With default</caption>
|
|
185
|
+
* block.getAttribute('linenums', false) // → false if not set
|
|
186
|
+
*
|
|
187
|
+
* @example <caption>Inherit from document if absent on block</caption>
|
|
188
|
+
* block.getAttribute('source-highlighter', null, true) // → falls back to doc attribute of same name
|
|
189
|
+
* block.getAttribute('linenums', null, 'source-linenums') // → falls back to 'source-linenums' on doc
|
|
190
|
+
*/
|
|
191
|
+
getAttribute(name, defaultValue = null, fallbackName = null) {
|
|
192
|
+
const key = String(name)
|
|
193
|
+
const val = this.attributes[key]
|
|
194
|
+
if (val != null) return val
|
|
195
|
+
if (fallbackName && this._parent) {
|
|
196
|
+
const fallbackKey = String(fallbackName === true ? name : fallbackName)
|
|
197
|
+
const docVal = this.document.attributes[fallbackKey]
|
|
198
|
+
if (docVal != null) return docVal
|
|
199
|
+
}
|
|
200
|
+
return defaultValue
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Check if the specified attribute is defined on this node, with optional
|
|
205
|
+
* value match and document-level fallback.
|
|
206
|
+
*
|
|
207
|
+
* @param {string} name - The attribute name.
|
|
208
|
+
* @param {*} [expectedValue=null] - When truthy, also checks that the resolved value equals this.
|
|
209
|
+
* @param {string|boolean|null} [fallbackName=null] - When truthy, also checks the Document's
|
|
210
|
+
* attributes. Pass `true` to use the same name, or a string for a different fallback name.
|
|
211
|
+
* @returns {boolean}
|
|
212
|
+
*
|
|
213
|
+
* @example <caption>Presence check</caption>
|
|
214
|
+
* block.hasAttribute('linenums') // → true/false
|
|
215
|
+
*
|
|
216
|
+
* @example <caption>Value match</caption>
|
|
217
|
+
* block.hasAttribute('language', 'ruby') // → true only when language === 'ruby'
|
|
218
|
+
*
|
|
219
|
+
* @example <caption>Inherit presence from document</caption>
|
|
220
|
+
* block.hasAttribute('source-highlighter', null, true) // → also checks doc-level attribute
|
|
221
|
+
*/
|
|
222
|
+
hasAttribute(name, expectedValue = null, fallbackName = null) {
|
|
223
|
+
const key = String(name)
|
|
224
|
+
if (expectedValue) {
|
|
225
|
+
const val =
|
|
226
|
+
this.attributes[key] ??
|
|
227
|
+
(fallbackName && this._parent
|
|
228
|
+
? this.document.attributes[
|
|
229
|
+
String(fallbackName === true ? name : fallbackName)
|
|
230
|
+
]
|
|
231
|
+
: null)
|
|
232
|
+
return expectedValue === val
|
|
233
|
+
}
|
|
234
|
+
return (
|
|
235
|
+
key in this.attributes ||
|
|
236
|
+
!!(
|
|
237
|
+
fallbackName &&
|
|
238
|
+
this._parent &&
|
|
239
|
+
String(fallbackName === true ? name : fallbackName) in
|
|
240
|
+
this.document.attributes
|
|
241
|
+
)
|
|
242
|
+
)
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Set the value of the specified attribute on this node.
|
|
247
|
+
*
|
|
248
|
+
* @param {string} name - The attribute name to assign.
|
|
249
|
+
* @param {*} [value=''] - The value to assign.
|
|
250
|
+
* @param {boolean} [overwrite=true] - When `false`, does nothing if the attribute already exists.
|
|
251
|
+
* @returns {string|boolean|null} `true` if the attribute was set, `false` if blocked by `overwrite=false`.
|
|
252
|
+
* Subclasses (e.g. `Document`) may return the resolved value string or `null` when the attribute is locked.
|
|
253
|
+
*/
|
|
254
|
+
setAttribute(name, value = '', overwrite = true) {
|
|
255
|
+
if (overwrite === false && name in this.attributes) return false
|
|
256
|
+
this.attributes[name] = value
|
|
257
|
+
return true
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Check if the specified attribute is defined with an optional value match.
|
|
262
|
+
* Alias for {@link hasAttribute}.
|
|
263
|
+
* @see {hasAttribute}
|
|
264
|
+
*/
|
|
265
|
+
isAttribute(name, expectedValue = null) {
|
|
266
|
+
if (expectedValue != null) return this.getAttribute(name) === expectedValue
|
|
267
|
+
return name in this.attributes
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Remove the attribute from this node.
|
|
272
|
+
*
|
|
273
|
+
* @param {string} name - The attribute name to remove.
|
|
274
|
+
* @returns {*} the previous value, or `undefined` if the attribute was not present.
|
|
275
|
+
*/
|
|
276
|
+
removeAttribute(name) {
|
|
277
|
+
const val = this.attributes[name]
|
|
278
|
+
delete this.attributes[name]
|
|
279
|
+
return val
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Check if the specified option attribute is enabled on this node.
|
|
284
|
+
* This method checks whether the `<name>-option` attribute is set.
|
|
285
|
+
*
|
|
286
|
+
* @param {string} name - The String or Symbol name of the option.
|
|
287
|
+
* @returns {boolean} true if the option is enabled, false otherwise.
|
|
288
|
+
*/
|
|
289
|
+
hasOption(name) {
|
|
290
|
+
return `${name}-option` in this.attributes
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Set the specified option on this node by setting the `<name>-option` attribute.
|
|
295
|
+
*
|
|
296
|
+
* @param {string} name - The String name of the option.
|
|
297
|
+
*/
|
|
298
|
+
setOption(name) {
|
|
299
|
+
this.attributes[`${name}-option`] = ''
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Retrieve the Set of option names that are enabled on this node.
|
|
304
|
+
*
|
|
305
|
+
* @returns {Set<string>} a Set of option name strings.
|
|
306
|
+
*/
|
|
307
|
+
enabledOptions() {
|
|
308
|
+
const result = new Set()
|
|
309
|
+
for (const k of Object.keys(this.attributes)) {
|
|
310
|
+
if (k.endsWith('-option')) result.add(k.slice(0, k.length - 7))
|
|
311
|
+
}
|
|
312
|
+
return result
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Update the attributes of this node with the new values.
|
|
317
|
+
*
|
|
318
|
+
* @param {Object} newAttributes - A plain object of additional attributes to assign.
|
|
319
|
+
* @returns {Object} the updated attributes object on this node.
|
|
320
|
+
*/
|
|
321
|
+
updateAttributes(newAttributes) {
|
|
322
|
+
return Object.assign(this.attributes, newAttributes)
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Check if the `role` attribute is set on this node, optionally matching an exact value.
|
|
327
|
+
*
|
|
328
|
+
* Unlike {@link hasRole}, which checks for an individual role name within a
|
|
329
|
+
* space-separated list, this method tests the raw `role` attribute string as a whole.
|
|
330
|
+
*
|
|
331
|
+
* @param {string|null} [expectedValue=null] - When provided, checks that the `role`
|
|
332
|
+
* attribute equals this string exactly.
|
|
333
|
+
* @returns {boolean}
|
|
334
|
+
*
|
|
335
|
+
* @example
|
|
336
|
+
* node.hasRoleAttribute() // → true if role attribute is set at all
|
|
337
|
+
* node.hasRoleAttribute('lead') // → true only when role === 'lead' (not 'lead primary')
|
|
338
|
+
*/
|
|
339
|
+
hasRoleAttribute(expectedValue = null) {
|
|
340
|
+
if (expectedValue != null) return expectedValue === this.attributes.role
|
|
341
|
+
return 'role' in this.attributes
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Check if the specified role name is present in this node's role list.
|
|
346
|
+
*
|
|
347
|
+
* @param {string} name - The String role name to find.
|
|
348
|
+
* @returns {boolean}
|
|
349
|
+
*/
|
|
350
|
+
hasRole(name) {
|
|
351
|
+
const val = this.attributes.role
|
|
352
|
+
return val ? ` ${val} `.includes(` ${name} `) : false
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Add the given role directly to this node.
|
|
357
|
+
*
|
|
358
|
+
* @param {string} name - The String role name to add.
|
|
359
|
+
* @returns {boolean} true if the role was added, false if it was already present.
|
|
360
|
+
*/
|
|
361
|
+
addRole(name) {
|
|
362
|
+
const val = this.attributes.role
|
|
363
|
+
if (val) {
|
|
364
|
+
if (` ${val} `.includes(` ${name} `)) return false
|
|
365
|
+
this.attributes.role = `${val} ${name}`
|
|
366
|
+
return true
|
|
367
|
+
}
|
|
368
|
+
this.attributes.role = name
|
|
369
|
+
return true
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Remove the given role directly from this node.
|
|
374
|
+
*
|
|
375
|
+
* @param {string} name - The String role name to remove.
|
|
376
|
+
* @returns {boolean} true if the role was removed, false if it was not present.
|
|
377
|
+
*/
|
|
378
|
+
removeRole(name) {
|
|
379
|
+
const val = this.attributes.role
|
|
380
|
+
if (!val) return false
|
|
381
|
+
const roles = val.split(' ')
|
|
382
|
+
const idx = roles.indexOf(name)
|
|
383
|
+
if (idx < 0) return false
|
|
384
|
+
roles.splice(idx, 1)
|
|
385
|
+
if (roles.length === 0) {
|
|
386
|
+
delete this.attributes.role
|
|
387
|
+
} else {
|
|
388
|
+
this.attributes.role = roles.join(' ')
|
|
389
|
+
}
|
|
390
|
+
return true
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Get the value of the reftext attribute with substitutions applied.
|
|
395
|
+
* The result is pre-computed during Document.parse() via {@link precomputeReftext}.
|
|
396
|
+
* Falls back to the raw reftext attribute if precomputeReftext() has not been called yet.
|
|
397
|
+
*
|
|
398
|
+
* @returns {string|null} the String reftext or null if not set.
|
|
399
|
+
*/
|
|
400
|
+
get reftext() {
|
|
401
|
+
if (this._convertedReftext !== undefined) return this._convertedReftext
|
|
402
|
+
const val = this.attributes.reftext
|
|
403
|
+
return val ?? null
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Pre-compute the reftext with substitutions applied asynchronously.
|
|
408
|
+
* Called during Document.parse() so the synchronous getter works during conversion.
|
|
409
|
+
*
|
|
410
|
+
* @returns {Promise<void>}
|
|
411
|
+
*/
|
|
412
|
+
async precomputeReftext() {
|
|
413
|
+
const val = this.attributes.reftext
|
|
414
|
+
this._convertedReftext =
|
|
415
|
+
val != null ? await this.applyReftextSubs(val) : null
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Check if the reftext attribute is defined.
|
|
420
|
+
*
|
|
421
|
+
* @returns {boolean}
|
|
422
|
+
*/
|
|
423
|
+
hasReftext() {
|
|
424
|
+
return 'reftext' in this.attributes
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Check whether this node has reftext — either an explicit 'reftext' attribute
|
|
429
|
+
* or a title that can serve as the cross-reference text.
|
|
430
|
+
* Mirrors Ruby's AbstractNode#reftext?
|
|
431
|
+
* @returns {boolean}
|
|
432
|
+
*/
|
|
433
|
+
isReftext() {
|
|
434
|
+
return this.hasAttribute('reftext') || !!this.title
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* Construct a reference or data URI to an icon image for the given name.
|
|
439
|
+
*
|
|
440
|
+
* If the 'icon' attribute is set on this node the name is ignored and the
|
|
441
|
+
* attribute value is used as the target path. Otherwise the icon path is built
|
|
442
|
+
* from 'iconsdir', the name, and 'icontype' (default: 'png').
|
|
443
|
+
*
|
|
444
|
+
* @param {string} name - The String name of the icon.
|
|
445
|
+
* @returns {Promise<string>} a Promise resolving to a String reference or data URI for the icon image.
|
|
446
|
+
*/
|
|
447
|
+
async iconUri(name) {
|
|
448
|
+
let icon
|
|
449
|
+
if (this.hasAttribute('icon')) {
|
|
450
|
+
icon = this.getAttribute('icon')
|
|
451
|
+
if (!isExtname(icon))
|
|
452
|
+
icon = `${icon}.${this.document.getAttribute('icontype', 'png')}`
|
|
453
|
+
} else {
|
|
454
|
+
icon = `${name}.${this.document.getAttribute('icontype', 'png')}`
|
|
455
|
+
}
|
|
456
|
+
return this.imageUri(icon, 'iconsdir')
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Construct a URI reference or data URI to the target image.
|
|
461
|
+
*
|
|
462
|
+
* If the target image is already a URI it is left untouched (unless data-uri
|
|
463
|
+
* conversion is requested). The image is resolved relative to the directory
|
|
464
|
+
* named by assetDirKey. When data-uri is enabled and the safe level permits,
|
|
465
|
+
* the image is embedded as a Base64 data URI.
|
|
466
|
+
*
|
|
467
|
+
* NOTE: When the document has both 'data-uri' and 'allow-uri-read' enabled
|
|
468
|
+
* and the resolved image URL is a remote URI, this method returns a Promise
|
|
469
|
+
* rather than a String. Await the result when that combination may be active.
|
|
470
|
+
*
|
|
471
|
+
* @param {string} targetImage - A String path to the target image.
|
|
472
|
+
* @param {string} [assetDirKey='imagesdir'] - The String attribute key for the image directory.
|
|
473
|
+
* @returns {Promise<string>} a Promise resolving to a String reference or data URI.
|
|
474
|
+
*/
|
|
475
|
+
async imageUri(targetImage, assetDirKey = 'imagesdir') {
|
|
476
|
+
const doc = this.document
|
|
477
|
+
if (doc.safe < SafeMode.SECURE && doc.hasAttribute('data-uri')) {
|
|
478
|
+
let imagesBase
|
|
479
|
+
if (
|
|
480
|
+
(isUriish(targetImage) &&
|
|
481
|
+
(targetImage = encodeSpacesInUri(targetImage))) ||
|
|
482
|
+
(assetDirKey &&
|
|
483
|
+
(imagesBase = this.getAttribute(assetDirKey, null, true)) &&
|
|
484
|
+
isUriish(imagesBase) &&
|
|
485
|
+
(targetImage = this.normalizeWebPath(targetImage, imagesBase, false)))
|
|
486
|
+
) {
|
|
487
|
+
return doc.hasAttribute('allow-uri-read')
|
|
488
|
+
? this.generateDataUriFromUri(
|
|
489
|
+
targetImage,
|
|
490
|
+
doc.hasAttribute('cache-uri')
|
|
491
|
+
)
|
|
492
|
+
: targetImage
|
|
493
|
+
}
|
|
494
|
+
return this.generateDataUri(targetImage, assetDirKey)
|
|
495
|
+
}
|
|
496
|
+
return this.normalizeWebPath(
|
|
497
|
+
targetImage,
|
|
498
|
+
assetDirKey ? this.getAttribute(assetDirKey, null, true) : null
|
|
499
|
+
)
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* Construct a URI reference to the target media.
|
|
504
|
+
*
|
|
505
|
+
* @param {string} target - A String reference to the target media.
|
|
506
|
+
* @param {string} [assetDirKey='imagesdir'] - The String attribute key for the media directory.
|
|
507
|
+
* @returns {string} a String reference for the target media.
|
|
508
|
+
*/
|
|
509
|
+
mediaUri(target, assetDirKey = 'imagesdir') {
|
|
510
|
+
return this.normalizeWebPath(
|
|
511
|
+
target,
|
|
512
|
+
assetDirKey ? this.getAttribute(assetDirKey, null, true) : null
|
|
513
|
+
)
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* Generate a data URI that embeds the image at the given local path.
|
|
518
|
+
*
|
|
519
|
+
* The image path is cleaned to prevent access outside the jail when the
|
|
520
|
+
* document safe level is SafeMode.SAFE or higher. The image data is read
|
|
521
|
+
* and Base64-encoded. In non-Node environments this method returns an empty
|
|
522
|
+
* data URI with a warning.
|
|
523
|
+
*
|
|
524
|
+
* @param {string} targetImage - A String path to the target image.
|
|
525
|
+
* @param {string|null} [assetDirKey=null] - The String attribute key for the image directory.
|
|
526
|
+
* @returns {Promise<string>} a Promise resolving to a String data URI.
|
|
527
|
+
*/
|
|
528
|
+
async generateDataUri(targetImage, assetDirKey = null) {
|
|
529
|
+
const ext = extname(targetImage, null)
|
|
530
|
+
const mimetype = ext
|
|
531
|
+
? ext === '.svg'
|
|
532
|
+
? 'image/svg+xml'
|
|
533
|
+
: `image/${ext.slice(1)}`
|
|
534
|
+
: 'application/octet-stream'
|
|
535
|
+
const imagePath = assetDirKey
|
|
536
|
+
? this.normalizeSystemPath(
|
|
537
|
+
targetImage,
|
|
538
|
+
this.getAttribute(assetDirKey, null, true),
|
|
539
|
+
null,
|
|
540
|
+
{ targetName: 'image' }
|
|
541
|
+
)
|
|
542
|
+
: this.normalizeSystemPath(targetImage)
|
|
543
|
+
if (isUriish(imagePath)) {
|
|
544
|
+
return await this.generateDataUriFromUri(
|
|
545
|
+
imagePath,
|
|
546
|
+
this.document.hasAttribute('cache-uri')
|
|
547
|
+
)
|
|
548
|
+
}
|
|
549
|
+
if (await isReadable(imagePath)) {
|
|
550
|
+
const data = await _fsp.readFile(imagePath)
|
|
551
|
+
return `data:${mimetype};base64,${data.toString('base64')}`
|
|
552
|
+
}
|
|
553
|
+
this.logger.warn(`image to embed not found or not readable: ${imagePath}`)
|
|
554
|
+
return `data:${mimetype};base64,`
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/**
|
|
558
|
+
* Read the image data from the specified URI and generate a data URI.
|
|
559
|
+
*
|
|
560
|
+
* The image data is fetched and Base64-encoded. The MIME type is taken from
|
|
561
|
+
* the Content-Type response header.
|
|
562
|
+
*
|
|
563
|
+
* NOTE: This method is async in JS (the Fetch API is async). When called from
|
|
564
|
+
* imageUri, the caller must await the returned Promise.
|
|
565
|
+
*
|
|
566
|
+
* @param {string} imageUri - The URI from which to read the image data (http/https/ftp).
|
|
567
|
+
* @param {boolean} [cacheUri=false] - A Boolean to control caching (not yet supported in JS).
|
|
568
|
+
* @returns {Promise<string>} a Promise resolving to a String data URI.
|
|
569
|
+
*/
|
|
570
|
+
async generateDataUriFromUri(imageUri, cacheUri = false) {
|
|
571
|
+
try {
|
|
572
|
+
const response = await fetch(imageUri)
|
|
573
|
+
if (response.ok) {
|
|
574
|
+
const mimetype = (
|
|
575
|
+
response.headers.get('content-type') || 'application/octet-stream'
|
|
576
|
+
)
|
|
577
|
+
.split(';')[0]
|
|
578
|
+
.trim()
|
|
579
|
+
const buffer = await response.arrayBuffer()
|
|
580
|
+
const base64 = btoa(
|
|
581
|
+
Array.from(new Uint8Array(buffer), (b) =>
|
|
582
|
+
String.fromCharCode(b)
|
|
583
|
+
).join('')
|
|
584
|
+
)
|
|
585
|
+
return `data:${mimetype};base64,${base64}`
|
|
586
|
+
} else {
|
|
587
|
+
const ext = extname(imageUri, null)
|
|
588
|
+
const mimetype = ext
|
|
589
|
+
? ext === '.svg'
|
|
590
|
+
? 'image/svg+xml'
|
|
591
|
+
: `image/${ext.slice(1)}`
|
|
592
|
+
: 'application/octet-stream'
|
|
593
|
+
this.logger.warn(
|
|
594
|
+
`image to embed not found or not readable: ${imageUri}`
|
|
595
|
+
)
|
|
596
|
+
return `data:${mimetype};base64,`
|
|
597
|
+
}
|
|
598
|
+
} catch {
|
|
599
|
+
this.logger.warn(`could not retrieve image data from URI: ${imageUri}`)
|
|
600
|
+
return imageUri
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* Normalize the asset file or directory to a concrete and rinsed path.
|
|
606
|
+
*
|
|
607
|
+
* Delegates to {@link normalizeSystemPath} with start set to document.baseDir.
|
|
608
|
+
*
|
|
609
|
+
* @param {string} assetRef - The String asset reference to normalize.
|
|
610
|
+
* @param {string} [assetName='path'] - The String label for the asset used in messages.
|
|
611
|
+
* @param {boolean} [autocorrect=true] - A Boolean indicating whether to recover from an illegal path.
|
|
612
|
+
* @returns {string} the normalized String path.
|
|
613
|
+
*/
|
|
614
|
+
normalizeAssetPath(assetRef, assetName = 'path', autocorrect = true) {
|
|
615
|
+
return this.normalizeSystemPath(assetRef, this.document.baseDir, null, {
|
|
616
|
+
targetName: assetName,
|
|
617
|
+
recover: autocorrect,
|
|
618
|
+
})
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
/**
|
|
622
|
+
* Resolve and normalize a secure path from the target and start paths.
|
|
623
|
+
*
|
|
624
|
+
* Prevents resolving a path outside the jail (defaulting to document.baseDir)
|
|
625
|
+
* when the document safe level is SafeMode.SAFE or higher.
|
|
626
|
+
*
|
|
627
|
+
* @param {string} target - The String target path.
|
|
628
|
+
* @param {string|null} [start=null] - The String start (parent) path.
|
|
629
|
+
* @param {string|null} [jail=null] - The String jail path.
|
|
630
|
+
* @param {Object} [opts={}] - A plain object of options:
|
|
631
|
+
* - `recover` {boolean} - Whether to automatically recover for illegal paths.
|
|
632
|
+
* - `targetName` {string} - Label used in messages for the path being resolved.
|
|
633
|
+
* @throws {Error} if a jail is specified and the resolved path is outside it.
|
|
634
|
+
* @returns {string} the resolved String path.
|
|
635
|
+
*/
|
|
636
|
+
normalizeSystemPath(target, start = null, jail = null, opts = {}) {
|
|
637
|
+
const doc = this.document
|
|
638
|
+
if (doc.safe < SafeMode.SAFE) {
|
|
639
|
+
if (start) {
|
|
640
|
+
if (!doc.pathResolver.root(start)) start = `${doc.baseDir}/${start}`
|
|
641
|
+
} else {
|
|
642
|
+
start = doc.baseDir
|
|
643
|
+
}
|
|
644
|
+
} else {
|
|
645
|
+
start = start ?? doc.baseDir
|
|
646
|
+
jail = jail ?? doc.baseDir
|
|
647
|
+
}
|
|
648
|
+
return doc.pathResolver.systemPath(target, start, jail, opts)
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
/**
|
|
652
|
+
* Normalize the web path using the PathResolver.
|
|
653
|
+
*
|
|
654
|
+
* @param {string} target - The String target path.
|
|
655
|
+
* @param {string|null} [start=null] - The String start (parent) path.
|
|
656
|
+
* @param {boolean} [preserveUriTarget=true] - Whether a URI target should be preserved as-is.
|
|
657
|
+
* @returns {string} the resolved String path.
|
|
658
|
+
*/
|
|
659
|
+
normalizeWebPath(target, start = null, preserveUriTarget = true) {
|
|
660
|
+
if (preserveUriTarget && isUriish(target)) return encodeSpacesInUri(target)
|
|
661
|
+
return this.document.pathResolver.webPath(target, start)
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
/**
|
|
665
|
+
* Read the contents of the file at the specified path.
|
|
666
|
+
*
|
|
667
|
+
* This method checks that the file is readable before attempting to read it.
|
|
668
|
+
*
|
|
669
|
+
* @param {string} path - The String path from which to read the contents.
|
|
670
|
+
* @param {Object} [opts={}] - A plain object of options:
|
|
671
|
+
* - `warnOnFailure` {boolean} - Whether a warning is issued when the file cannot be read (default: false).
|
|
672
|
+
* - `normalize` {boolean} - Whether lines are normalized and coerced to UTF-8 (default: false).
|
|
673
|
+
* - `label` {string} - Label for the file used in warning messages.
|
|
674
|
+
* @returns {Promise<string|null>} a Promise resolving to the file content, or null if not readable.
|
|
675
|
+
*/
|
|
676
|
+
async readAsset(path, opts = {}) {
|
|
677
|
+
// remap opts for backwards compatibility (boolean shorthand)
|
|
678
|
+
if (typeof opts !== 'object' || opts === null)
|
|
679
|
+
opts = { warnOnFailure: opts !== false }
|
|
680
|
+
if (isUriish(path)) {
|
|
681
|
+
// Browser: docdir is a URL so the resolved path is an HTTP URI; use fetch instead of fs.
|
|
682
|
+
const { readBrowserAsset } = await import('./browser/asset.js')
|
|
683
|
+
const text = await readBrowserAsset(path)
|
|
684
|
+
if (text != null)
|
|
685
|
+
return opts.normalize ? prepareSourceString(text).join(LF) : text
|
|
686
|
+
if (opts.warnOnFailure) {
|
|
687
|
+
const docfile = this.getAttribute('docfile') || '<stdin>'
|
|
688
|
+
const label = opts.label || 'file'
|
|
689
|
+
this.logger.warn(
|
|
690
|
+
`${docfile}: ${label} does not exist or cannot be read: ${path}`
|
|
691
|
+
)
|
|
692
|
+
}
|
|
693
|
+
return null
|
|
694
|
+
}
|
|
695
|
+
if (await isReadable(path)) {
|
|
696
|
+
if (opts.normalize) {
|
|
697
|
+
return prepareSourceString(await _fsp.readFile(path, 'utf8')).join(LF)
|
|
698
|
+
}
|
|
699
|
+
return _fsp.readFile(path, 'utf8')
|
|
700
|
+
}
|
|
701
|
+
if (opts.warnOnFailure) {
|
|
702
|
+
const docfile = this.getAttribute('docfile') || '<stdin>'
|
|
703
|
+
const label = opts.label || 'file'
|
|
704
|
+
this.logger.warn(
|
|
705
|
+
`${docfile}: ${label} does not exist or cannot be read: ${path}`
|
|
706
|
+
)
|
|
707
|
+
}
|
|
708
|
+
return null
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
/**
|
|
712
|
+
* Resolve the URI or system path to the target, then read and return its contents.
|
|
713
|
+
*
|
|
714
|
+
* When the resolved path is a URI and allow-uri-read is enabled, the content is
|
|
715
|
+
* fetched via the Fetch API (async). When it is a local path, the file is read
|
|
716
|
+
* via {@link readAsset}.
|
|
717
|
+
*
|
|
718
|
+
* @param {string} target - The URI or local path String from which to read the data.
|
|
719
|
+
* @param {Object} [opts={}] - A plain object of options:
|
|
720
|
+
* - `label` {string} - Label used in warning messages (default: 'asset').
|
|
721
|
+
* - `normalize` {boolean} - Whether the data should be normalized (default: false).
|
|
722
|
+
* - `start` {string} - Relative base path for resolving the target.
|
|
723
|
+
* - `warnOnFailure` {boolean} - Whether warnings are issued on failure (default: true).
|
|
724
|
+
* - `warnIfEmpty` {boolean} - Whether a warning is issued when the target contents are empty (default: false).
|
|
725
|
+
* @returns {Promise<string|null>} a Promise resolving to the content, or null on failure.
|
|
726
|
+
*/
|
|
727
|
+
async readContents(target, opts = {}) {
|
|
728
|
+
const doc = this.document
|
|
729
|
+
const label = opts.label || 'asset'
|
|
730
|
+
let contents
|
|
731
|
+
let resolvedTarget = target
|
|
732
|
+
const start = opts.start
|
|
733
|
+
const warnOnFailure = opts.warnOnFailure !== false
|
|
734
|
+
|
|
735
|
+
if (
|
|
736
|
+
isUriish(target) ||
|
|
737
|
+
(start &&
|
|
738
|
+
isUriish(start) &&
|
|
739
|
+
(resolvedTarget = doc.pathResolver.webPath(target, start)))
|
|
740
|
+
) {
|
|
741
|
+
if (doc.hasAttribute('allow-uri-read')) {
|
|
742
|
+
try {
|
|
743
|
+
const response = await fetch(resolvedTarget)
|
|
744
|
+
const text = await response.text()
|
|
745
|
+
contents = opts.normalize ? prepareSourceString(text).join(LF) : text
|
|
746
|
+
} catch {
|
|
747
|
+
if (warnOnFailure)
|
|
748
|
+
this.logger.warn(
|
|
749
|
+
`could not retrieve contents of ${label} at URI: ${resolvedTarget}`
|
|
750
|
+
)
|
|
751
|
+
}
|
|
752
|
+
} else if (warnOnFailure) {
|
|
753
|
+
this.logger.warn(
|
|
754
|
+
`cannot retrieve contents of ${label} at URI: ${resolvedTarget} (allow-uri-read attribute not enabled)`
|
|
755
|
+
)
|
|
756
|
+
}
|
|
757
|
+
} else {
|
|
758
|
+
resolvedTarget = this.normalizeSystemPath(target, opts.start, null, {
|
|
759
|
+
targetName: label,
|
|
760
|
+
})
|
|
761
|
+
contents = await this.readAsset(resolvedTarget, {
|
|
762
|
+
normalize: opts.normalize,
|
|
763
|
+
warnOnFailure,
|
|
764
|
+
label,
|
|
765
|
+
})
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
if (contents && opts.warnIfEmpty && contents.length === 0) {
|
|
769
|
+
this.logger.warn(`contents of ${label} is empty: ${resolvedTarget}`)
|
|
770
|
+
}
|
|
771
|
+
return contents
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
/**
|
|
775
|
+
* @deprecated Use `isUriish` from helpers.js instead.
|
|
776
|
+
* @param {string} str
|
|
777
|
+
* @returns {boolean}
|
|
778
|
+
*/
|
|
779
|
+
isUri(str) {
|
|
780
|
+
return isUriish(str)
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
/**
|
|
784
|
+
* Provide a default logger.
|
|
785
|
+
* The Logging mixin (logging.js) overrides this getter on the prototype.
|
|
786
|
+
*/
|
|
787
|
+
get logger() {
|
|
788
|
+
return this.document?.logger ?? console
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
// ── JavaScript-style accessors ────────────────────────────────────────────────
|
|
792
|
+
|
|
793
|
+
/**
|
|
794
|
+
* Get the logger for this node.
|
|
795
|
+
* @returns {object} the logger instance.
|
|
796
|
+
*/
|
|
797
|
+
getLogger() {
|
|
798
|
+
return this.logger
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
/**
|
|
802
|
+
* Retrieve the space-separated String role for this node.
|
|
803
|
+
*
|
|
804
|
+
* @returns {string|undefined} the role as a space-separated String.
|
|
805
|
+
*/
|
|
806
|
+
getRole() {
|
|
807
|
+
return this.role
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
/**
|
|
811
|
+
* Set the value of the role attribute on this node.
|
|
812
|
+
*
|
|
813
|
+
* Accepts a single role name, a space-separated String, an Array, or spread arguments.
|
|
814
|
+
*
|
|
815
|
+
* @param {...string|string[]} names - A single role name, a space-separated String, an Array,
|
|
816
|
+
* or multiple role names as spread arguments.
|
|
817
|
+
* @returns {string} the value of the role attribute.
|
|
818
|
+
*/
|
|
819
|
+
setRole(...names) {
|
|
820
|
+
this.role = names.length === 1 ? names[0] : names
|
|
821
|
+
return this.attributes.role
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
/**
|
|
825
|
+
* Retrieve the String role names for this node as an Array.
|
|
826
|
+
*
|
|
827
|
+
* @returns {string[]} the role names as a String Array, empty if the role attribute is absent.
|
|
828
|
+
*/
|
|
829
|
+
getRoles() {
|
|
830
|
+
return this.roles
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
/**
|
|
834
|
+
* Get the attributes hash for this node.
|
|
835
|
+
*
|
|
836
|
+
* @returns {Object} a plain Object of attributes.
|
|
837
|
+
*/
|
|
838
|
+
getAttributes() {
|
|
839
|
+
return this.attributes
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
/**
|
|
843
|
+
* Get the document to which this node belongs.
|
|
844
|
+
*
|
|
845
|
+
* @returns {Document} the Document.
|
|
846
|
+
*/
|
|
847
|
+
getDocument() {
|
|
848
|
+
return this.document
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
/**
|
|
852
|
+
* Get the parent node of this node.
|
|
853
|
+
*
|
|
854
|
+
* @returns {AbstractNode|undefined} the parent AbstractNode, or undefined for the root document.
|
|
855
|
+
*/
|
|
856
|
+
getParent() {
|
|
857
|
+
return this._parent
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
/**
|
|
861
|
+
* Set the parent of this node.
|
|
862
|
+
* Also updates the document reference.
|
|
863
|
+
*/
|
|
864
|
+
setParent(parent) {
|
|
865
|
+
this._parent = parent
|
|
866
|
+
this.document = parent.document
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
/**
|
|
870
|
+
* Get the String name of this node.
|
|
871
|
+
*
|
|
872
|
+
* @returns {string} the node name.
|
|
873
|
+
*/
|
|
874
|
+
getNodeName() {
|
|
875
|
+
return this.nodeName
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
/**
|
|
879
|
+
* Get the String id for this node.
|
|
880
|
+
*
|
|
881
|
+
* @returns {string|undefined} the id, or undefined if not set.
|
|
882
|
+
*/
|
|
883
|
+
getId() {
|
|
884
|
+
return this.id ?? undefined
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
/**
|
|
888
|
+
* Set the String id for this node.
|
|
889
|
+
*
|
|
890
|
+
* @param {string} id - The String id to assign.
|
|
891
|
+
*/
|
|
892
|
+
setId(id) {
|
|
893
|
+
this.id = id
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
/**
|
|
897
|
+
* Get the context name for this node.
|
|
898
|
+
*
|
|
899
|
+
* @returns {string} the context name.
|
|
900
|
+
*/
|
|
901
|
+
getContext() {
|
|
902
|
+
return this.context
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
/**
|
|
906
|
+
* Get the {Converter} instance being used to convert the current {Document}.
|
|
907
|
+
*
|
|
908
|
+
* @returns {object} the converter instance.
|
|
909
|
+
*/
|
|
910
|
+
getConverter() {
|
|
911
|
+
return this.converter
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
/**
|
|
915
|
+
* Get the icon URI for the named icon.
|
|
916
|
+
*
|
|
917
|
+
* @param {string} name - The String icon name.
|
|
918
|
+
* @returns {Promise<string>} a Promise resolving to a String URI.
|
|
919
|
+
*/
|
|
920
|
+
getIconUri(name) {
|
|
921
|
+
return this.iconUri(name)
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
/**
|
|
925
|
+
* Get the media URI for the target.
|
|
926
|
+
*
|
|
927
|
+
* @param {string} target - The String target path or URL.
|
|
928
|
+
* @param {string} [assetDirKey='imagesdir'] - The String asset directory attribute key.
|
|
929
|
+
* @returns {string} a String URI.
|
|
930
|
+
*/
|
|
931
|
+
getMediaUri(target, assetDirKey = 'imagesdir') {
|
|
932
|
+
return this.mediaUri(target, assetDirKey)
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
/**
|
|
936
|
+
* Get the image URI for the target image.
|
|
937
|
+
*
|
|
938
|
+
* @param {string} targetImage - The String target image path or URL.
|
|
939
|
+
* @param {string|null} [assetDirKey=null] - The String asset directory attribute key.
|
|
940
|
+
* @returns {Promise<string>} a Promise resolving to a String URI.
|
|
941
|
+
*/
|
|
942
|
+
getImageUri(targetImage, assetDirKey = null) {
|
|
943
|
+
return this.imageUri(targetImage, assetDirKey)
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
/**
|
|
947
|
+
* Get the value of the reftext attribute with substitutions applied.
|
|
948
|
+
*
|
|
949
|
+
* @returns {string|undefined} the reftext value, or undefined if not set.
|
|
950
|
+
*/
|
|
951
|
+
getReftext() {
|
|
952
|
+
return this.reftext ?? undefined
|
|
953
|
+
}
|
|
954
|
+
}
|