@asciidoctor/core 3.0.4 → 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
package/src/section.js
ADDED
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
// ESM conversion of section.rb
|
|
2
|
+
|
|
3
|
+
import { AbstractBlock } from './abstract_block.js'
|
|
4
|
+
import { Compliance } from './compliance.js'
|
|
5
|
+
import { InvalidSectionIdCharsRx } from './rx.js'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Methods for managing sections of AsciiDoc content in a document.
|
|
9
|
+
*/
|
|
10
|
+
export class Section extends AbstractBlock {
|
|
11
|
+
/**
|
|
12
|
+
* Create a new Section — mirrors the core Section.create() API.
|
|
13
|
+
* @param {AbstractBlock|null} [parent=null]
|
|
14
|
+
* @param {number|null} [level=null]
|
|
15
|
+
* @param {boolean} [numbered=false]
|
|
16
|
+
* @param {Object} [opts={}]
|
|
17
|
+
* @returns {Section}
|
|
18
|
+
*/
|
|
19
|
+
static create(parent = null, level = null, numbered = false, opts = {}) {
|
|
20
|
+
return new Section(parent, level, numbered, opts)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Initialize an Asciidoctor Section object.
|
|
25
|
+
* @param {AbstractBlock|null} [parent=null] - The parent AbstractBlock (Document or Section), or null.
|
|
26
|
+
* @param {number|null} [level=null] - The Integer level of this section (default: parent.level + 1 or 1).
|
|
27
|
+
* @param {boolean} [numbered=false] - Boolean indicating whether numbering is enabled.
|
|
28
|
+
* @param {Object} [opts={}] - An optional plain object of options.
|
|
29
|
+
*/
|
|
30
|
+
constructor(parent = null, level = null, numbered = false, opts = {}) {
|
|
31
|
+
super(parent, 'section', opts)
|
|
32
|
+
if (parent instanceof Section) {
|
|
33
|
+
this.level = level ?? parent.level + 1
|
|
34
|
+
this.special = parent.special
|
|
35
|
+
} else {
|
|
36
|
+
this.level = level ?? 1
|
|
37
|
+
this.special = false
|
|
38
|
+
}
|
|
39
|
+
this.numbered = numbered
|
|
40
|
+
this.index = 0
|
|
41
|
+
this.sectname = null
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* The name of this section — alias for title.
|
|
46
|
+
* @returns {string|null}
|
|
47
|
+
*/
|
|
48
|
+
get name() {
|
|
49
|
+
return this.title
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Check whether this section has any child Section objects.
|
|
54
|
+
* @returns {boolean}
|
|
55
|
+
*/
|
|
56
|
+
hasSections() {
|
|
57
|
+
return this._nextSectionIndex > 0
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Generate a String ID from the title of this section.
|
|
62
|
+
* This sync convenience method is only called outside of parsing (e.g. extensions).
|
|
63
|
+
* At that point #convertedTitle is already set, so this.title returns the fully-substituted
|
|
64
|
+
* HTML title — matching Ruby's behaviour where section.title calls apply_title_subs.
|
|
65
|
+
* @returns {string}
|
|
66
|
+
*/
|
|
67
|
+
generateId() {
|
|
68
|
+
return Section.generateId(this.title, this.document)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Get the section number for the current Section as a dot-separated String.
|
|
73
|
+
* @param {string} [delimiter='.'] - The separator between numerals.
|
|
74
|
+
* @param {string|false|null} [append=null] - String appended at the end, or false to omit trailing delimiter
|
|
75
|
+
* (default: null → same as delimiter).
|
|
76
|
+
* @returns {string} the section number String.
|
|
77
|
+
*/
|
|
78
|
+
sectnum(delimiter = '.', append = null) {
|
|
79
|
+
const suffix =
|
|
80
|
+
append !== null ? (append === false ? '' : append) : delimiter
|
|
81
|
+
if (this.level > 1 && this.getParent() instanceof Section) {
|
|
82
|
+
return `${this.getParent().sectnum(delimiter, delimiter)}${this.numeral ?? ''}${suffix}`
|
|
83
|
+
}
|
|
84
|
+
return `${this.numeral ?? ''}${suffix}`
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Generate cross-reference text for this section.
|
|
89
|
+
* Respects an explicit reftext if set; otherwise formats the section title
|
|
90
|
+
* according to xrefstyle ('full', 'short', or 'basic').
|
|
91
|
+
* @param {string|null} [xrefstyle=null]
|
|
92
|
+
* @returns {Promise<string|null>}
|
|
93
|
+
*/
|
|
94
|
+
async xreftext(xrefstyle = null) {
|
|
95
|
+
const val = this.reftext
|
|
96
|
+
if (val && val.length > 0) return val
|
|
97
|
+
|
|
98
|
+
// If the title is currently being computed (circular reference), return null so that
|
|
99
|
+
// the caller (convert_inline_anchor) falls back to the "[refid]" placeholder.
|
|
100
|
+
if (this._computingTitle) return null
|
|
101
|
+
|
|
102
|
+
// Compute the title now using the current catalog state if not already done.
|
|
103
|
+
// This ensures that forward xrefs in a section title are not resolved when the
|
|
104
|
+
// xreftext is first requested during parsing (before the target is registered).
|
|
105
|
+
await this.precomputeTitle()
|
|
106
|
+
|
|
107
|
+
if (xrefstyle) {
|
|
108
|
+
if (this.numbered) {
|
|
109
|
+
const type = this.sectname
|
|
110
|
+
switch (xrefstyle) {
|
|
111
|
+
case 'full': {
|
|
112
|
+
let quotedTitle
|
|
113
|
+
if (type === 'chapter' || type === 'appendix') {
|
|
114
|
+
quotedTitle = this.subPlaceholder(
|
|
115
|
+
await this.subQuotes('_%s_'),
|
|
116
|
+
this.title
|
|
117
|
+
)
|
|
118
|
+
} else {
|
|
119
|
+
const q = this.document.compatMode ? "``%s''" : '"`%s`"'
|
|
120
|
+
quotedTitle = this.subPlaceholder(
|
|
121
|
+
await this.subQuotes(q),
|
|
122
|
+
this.title
|
|
123
|
+
)
|
|
124
|
+
}
|
|
125
|
+
const signifier = this.document.attributes[`${type}-refsig`]
|
|
126
|
+
return signifier
|
|
127
|
+
? `${signifier} ${this.sectnum('.', ',')} ${quotedTitle}`
|
|
128
|
+
: `${this.sectnum('.', ',')} ${quotedTitle}`
|
|
129
|
+
}
|
|
130
|
+
case 'short': {
|
|
131
|
+
const signifier =
|
|
132
|
+
this.document.attributes[`${this.sectname}-refsig`]
|
|
133
|
+
return signifier
|
|
134
|
+
? `${signifier} ${this.sectnum('.', '')}`
|
|
135
|
+
: this.sectnum('.', '')
|
|
136
|
+
}
|
|
137
|
+
default: {
|
|
138
|
+
// 'basic'
|
|
139
|
+
const t = this.sectname
|
|
140
|
+
return t === 'chapter' || t === 'appendix'
|
|
141
|
+
? this.subPlaceholder(await this.subQuotes('_%s_'), this.title)
|
|
142
|
+
: this.title
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
} else {
|
|
146
|
+
// apply basic styling
|
|
147
|
+
const t = this.sectname
|
|
148
|
+
return t === 'chapter' || t === 'appendix'
|
|
149
|
+
? this.subPlaceholder(await this.subQuotes('_%s_'), this.title)
|
|
150
|
+
: this.title
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return this.title
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Append a content block to this block's list of blocks.
|
|
158
|
+
* If the child block is a Section, assign an index/numeral to it.
|
|
159
|
+
* @param {AbstractBlock} block - The child Block to append.
|
|
160
|
+
* @returns {this}
|
|
161
|
+
*/
|
|
162
|
+
append(block) {
|
|
163
|
+
if (block.context === 'section') this.assignNumeral(block)
|
|
164
|
+
return super.append(block)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// ── JavaScript-style accessors ────────────────────────────────────────────────
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Get the section title (alias of title).
|
|
171
|
+
* @returns {string|null}
|
|
172
|
+
*/
|
|
173
|
+
getName() {
|
|
174
|
+
return this.name
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Get the section name (e.g. 'section', 'appendix').
|
|
179
|
+
* @returns {string|null}
|
|
180
|
+
*/
|
|
181
|
+
getSectionName() {
|
|
182
|
+
return this.sectname ?? undefined
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Set the section name (e.g. 'section', 'appendix').
|
|
187
|
+
* @param {string|null} val
|
|
188
|
+
*/
|
|
189
|
+
setSectionName(val) {
|
|
190
|
+
this.sectname = val
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Get the 0-based index of this section within the parent block.
|
|
195
|
+
* @returns {number}
|
|
196
|
+
*/
|
|
197
|
+
getIndex() {
|
|
198
|
+
return this.index
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Set the 0-based index of this section within the parent block.
|
|
203
|
+
* @param {number} val
|
|
204
|
+
*/
|
|
205
|
+
setIndex(val) {
|
|
206
|
+
this.index = val
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Get whether this section is numbered.
|
|
211
|
+
* @returns {boolean}
|
|
212
|
+
*/
|
|
213
|
+
isNumbered() {
|
|
214
|
+
return this.numbered
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Get whether this section is a special section.
|
|
219
|
+
* @returns {boolean}
|
|
220
|
+
*/
|
|
221
|
+
isSpecial() {
|
|
222
|
+
return this.special
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Set whether this section is a special section.
|
|
227
|
+
* @param {boolean} val
|
|
228
|
+
*/
|
|
229
|
+
setSpecial(val) {
|
|
230
|
+
this.special = val
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Get the section numeral string.
|
|
235
|
+
* @returns {string|null}
|
|
236
|
+
*/
|
|
237
|
+
getNumeral() {
|
|
238
|
+
return this.numeral
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Set the section numeral string.
|
|
243
|
+
* @param {string|null} val
|
|
244
|
+
*/
|
|
245
|
+
setNumeral(val) {
|
|
246
|
+
this.numeral = val
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Get the section number string (dot-separated).
|
|
251
|
+
* @returns {string}
|
|
252
|
+
*/
|
|
253
|
+
getSectionNumeral() {
|
|
254
|
+
return this.sectnum()
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Get the section number string (alias of getSectionNumeral).
|
|
259
|
+
* @returns {string}
|
|
260
|
+
*/
|
|
261
|
+
getSectionNumber() {
|
|
262
|
+
return this.sectnum()
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
toString() {
|
|
266
|
+
if (this._title) {
|
|
267
|
+
const formalTitle = this.numbered
|
|
268
|
+
? `${this.sectnum()} ${this._title}`
|
|
269
|
+
: this._title
|
|
270
|
+
return `#<Section {level: ${this.level}, title: ${JSON.stringify(formalTitle)}, blocks: ${this.blocks.length}}>`
|
|
271
|
+
}
|
|
272
|
+
return super.toString()
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Generate a String ID from the given section title.
|
|
277
|
+
* @param {string} title - The String title.
|
|
278
|
+
* @param {object} document - The Document.
|
|
279
|
+
* @returns {string} the generated String ID.
|
|
280
|
+
*/
|
|
281
|
+
static generateId(title, document) {
|
|
282
|
+
const attrs = document.attributes
|
|
283
|
+
const pre = attrs.idprefix ?? '_'
|
|
284
|
+
let sep, sepSub, noSep
|
|
285
|
+
|
|
286
|
+
const rawSep = attrs.idseparator
|
|
287
|
+
if (rawSep !== undefined && rawSep !== null) {
|
|
288
|
+
if (rawSep.length === 0) {
|
|
289
|
+
noSep = true
|
|
290
|
+
sep = ''
|
|
291
|
+
sepSub = null
|
|
292
|
+
} else {
|
|
293
|
+
// Use only first character if multi-character
|
|
294
|
+
sep = rawSep.length === 1 ? rawSep : (attrs.idseparator = rawSep[0])
|
|
295
|
+
if (sep === '-' || sep === '.') {
|
|
296
|
+
sepSub = ' .-'
|
|
297
|
+
} else {
|
|
298
|
+
sepSub = ` ${sep}.-`
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
} else {
|
|
302
|
+
sep = '_'
|
|
303
|
+
sepSub = ' _.-'
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
let genId = `${pre}${title.toLowerCase().replace(new RegExp(InvalidSectionIdCharsRx.source, 'gu'), '')}`
|
|
307
|
+
|
|
308
|
+
if (noSep) {
|
|
309
|
+
genId = genId.replace(/ /g, '')
|
|
310
|
+
} else {
|
|
311
|
+
// Replace chars in sepSub with sep and squeeze consecutive sep chars
|
|
312
|
+
genId = _trS(genId, sepSub, sep)
|
|
313
|
+
if (genId.endsWith(sep)) genId = genId.slice(0, -sep.length)
|
|
314
|
+
// Ensure id doesn't begin with idseparator if idprefix is empty
|
|
315
|
+
if (pre === '' && genId.startsWith(sep)) genId = genId.slice(sep.length)
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const refs = document.catalog?.refs
|
|
319
|
+
if (refs && genId in refs) {
|
|
320
|
+
let cnt = Compliance.uniqueIdStartIndex
|
|
321
|
+
let candidate
|
|
322
|
+
do {
|
|
323
|
+
candidate = `${genId}${sep}${cnt}`
|
|
324
|
+
cnt++
|
|
325
|
+
} while (candidate in refs)
|
|
326
|
+
return candidate
|
|
327
|
+
}
|
|
328
|
+
return genId
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* @internal Translate every character in `fromChars` to `toChar` and squeeze
|
|
334
|
+
* consecutive runs of the translated character (mirrors Ruby's String#tr_s).
|
|
335
|
+
* @param {string} str
|
|
336
|
+
* @param {string} fromChars
|
|
337
|
+
* @param {string} toChar
|
|
338
|
+
* @returns {string}
|
|
339
|
+
*/
|
|
340
|
+
function _trS(str, fromChars, toChar) {
|
|
341
|
+
const set = new Set([...fromChars])
|
|
342
|
+
let result = ''
|
|
343
|
+
let prevWasSep = false
|
|
344
|
+
for (const ch of str) {
|
|
345
|
+
if (set.has(ch)) {
|
|
346
|
+
if (!prevWasSep) result += toChar
|
|
347
|
+
prevWasSep = true
|
|
348
|
+
} else {
|
|
349
|
+
result += ch
|
|
350
|
+
prevWasSep = false
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
return result
|
|
354
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// ESM port of lib/asciidoctor/stylesheets.rb
|
|
2
|
+
//
|
|
3
|
+
// Ruby-to-JavaScript notes:
|
|
4
|
+
// - Singleton: Ruby @__instance__ = new → module-level instance exported as Stylesheets.instance
|
|
5
|
+
// - primary_stylesheet_data memoisation: Ruby ||= → the CSS is a static import; no lazy load needed
|
|
6
|
+
// - File.read(...).rstrip → CSS is inlined at build time in src/data/stylesheet-data.js
|
|
7
|
+
// - STYLESHEETS_DIR = File.join(DATA_DIR, 'stylesheets') → not needed; CSS is a JS module
|
|
8
|
+
// - coderay / pygments methods → omitted (SyntaxHighlighter.for not needed here)
|
|
9
|
+
|
|
10
|
+
import defaultStylesheetData from './data/stylesheet-data.js'
|
|
11
|
+
|
|
12
|
+
class StylesheetsClass {
|
|
13
|
+
static DEFAULT_STYLESHEET_NAME = 'asciidoctor.css'
|
|
14
|
+
|
|
15
|
+
get primaryStylesheetName() {
|
|
16
|
+
return StylesheetsClass.DEFAULT_STYLESHEET_NAME
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async primaryStylesheetData() {
|
|
20
|
+
return defaultStylesheetData
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async embedPrimaryStylesheet() {
|
|
24
|
+
return `<style>\n${defaultStylesheetData}\n</style>`
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const Stylesheets = {
|
|
29
|
+
instance: new StylesheetsClass(),
|
|
30
|
+
}
|