@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.
Files changed (91) hide show
  1. package/README.md +42 -10
  2. package/build/browser/index.js +24154 -0
  3. package/build/node/index.cjs +24735 -0
  4. package/{dist/css/asciidoctor.css → data/asciidoctor-default.css} +54 -53
  5. package/package.json +53 -100
  6. package/src/abstract_block.js +849 -0
  7. package/src/abstract_node.js +954 -0
  8. package/src/attribute_entry.js +12 -0
  9. package/src/attribute_list.js +380 -0
  10. package/src/block.js +168 -0
  11. package/src/browser/asset.js +22 -0
  12. package/src/browser/reader.js +138 -0
  13. package/src/browser.js +121 -0
  14. package/src/callouts.js +85 -0
  15. package/src/compliance.js +54 -0
  16. package/src/constants.js +665 -0
  17. package/src/convert.js +370 -0
  18. package/src/converter/composite.js +83 -0
  19. package/src/converter/docbook5.js +1031 -0
  20. package/src/converter/html5.js +1899 -0
  21. package/src/converter/manpage.js +935 -0
  22. package/src/converter/template.js +459 -0
  23. package/src/converter.js +478 -0
  24. package/src/data/stylesheet-data.js +2 -0
  25. package/src/document.js +2134 -0
  26. package/src/extensions.js +1952 -0
  27. package/src/footnote.js +28 -0
  28. package/src/helpers.js +355 -0
  29. package/src/index.js +138 -0
  30. package/src/inline.js +158 -0
  31. package/src/list.js +240 -0
  32. package/src/load.js +276 -0
  33. package/src/logging.js +526 -0
  34. package/src/parser.js +3661 -0
  35. package/src/path_resolver.js +472 -0
  36. package/src/reader.js +1755 -0
  37. package/src/rx.js +829 -0
  38. package/src/section.js +354 -0
  39. package/src/stylesheets.js +30 -0
  40. package/src/substitutors.js +2241 -0
  41. package/src/syntaxHighlighter/highlightjs.js +90 -0
  42. package/src/syntaxHighlighter/html_pipeline.js +33 -0
  43. package/src/syntax_highlighter.js +304 -0
  44. package/src/table.js +952 -0
  45. package/src/timings.js +78 -0
  46. package/types/abstract_block.d.ts +343 -0
  47. package/types/abstract_node.d.ts +471 -0
  48. package/types/attribute_entry.d.ts +7 -0
  49. package/types/attribute_list.d.ts +52 -0
  50. package/types/block.d.ts +55 -0
  51. package/types/browser/asset.d.ts +7 -0
  52. package/types/browser/reader.d.ts +29 -0
  53. package/types/callouts.d.ts +36 -0
  54. package/types/compliance.d.ts +23 -0
  55. package/types/constants.d.ts +268 -0
  56. package/types/convert.d.ts +34 -0
  57. package/types/converter/composite.d.ts +20 -0
  58. package/types/converter/docbook5.d.ts +41 -0
  59. package/types/converter/html5.d.ts +51 -0
  60. package/types/converter/manpage.d.ts +59 -0
  61. package/types/converter/template.d.ts +83 -0
  62. package/types/converter.d.ts +150 -0
  63. package/types/data/stylesheet-data.d.ts +2 -0
  64. package/types/document.d.ts +495 -0
  65. package/types/extensions.d.ts +876 -0
  66. package/types/footnote.d.ts +18 -0
  67. package/types/helpers.d.ts +146 -0
  68. package/types/index.d.ts +73 -3731
  69. package/types/inline.d.ts +69 -0
  70. package/types/list.d.ts +114 -0
  71. package/types/load.d.ts +39 -0
  72. package/types/logging.d.ts +187 -0
  73. package/types/parser.d.ts +114 -0
  74. package/types/path_resolver.d.ts +103 -0
  75. package/types/reader.d.ts +184 -0
  76. package/types/rx.d.ts +513 -0
  77. package/types/section.d.ts +122 -0
  78. package/types/stylesheets.d.ts +10 -0
  79. package/types/substitutors.d.ts +208 -0
  80. package/types/syntaxHighlighter/highlightjs.d.ts +33 -0
  81. package/types/syntaxHighlighter/html_pipeline.d.ts +16 -0
  82. package/types/syntax_highlighter.d.ts +167 -0
  83. package/types/table.d.ts +231 -0
  84. package/types/timings.d.ts +25 -0
  85. package/types/tsconfig.json +9 -0
  86. package/LICENSE +0 -21
  87. package/dist/browser/asciidoctor.js +0 -47654
  88. package/dist/browser/asciidoctor.min.js +0 -1452
  89. package/dist/graalvm/asciidoctor.js +0 -47402
  90. package/dist/node/asciidoctor.cjs +0 -21567
  91. 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
+ }