@asciidoctor/core 3.0.4 → 4.0.0-alpha.2
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 +24156 -0
- package/build/node/index.cjs +24737 -0
- package/{dist/css/asciidoctor.css → data/asciidoctor-default.css} +54 -53
- package/package.json +55 -97
- package/src/abstract_block.js +857 -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 +1893 -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 +346 -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.cts +75 -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/rx.js
ADDED
|
@@ -0,0 +1,829 @@
|
|
|
1
|
+
// ESM conversion of rx.rb
|
|
2
|
+
// A collection of regular expression constants used by the parser.
|
|
3
|
+
//
|
|
4
|
+
// Ruby → JavaScript regex engine differences handled here:
|
|
5
|
+
//
|
|
6
|
+
// Ruby \p{Alpha} → JS \p{Alphabetic} (Unicode Binary Property, requires 'u' flag)
|
|
7
|
+
// Ruby \p{Alnum} → JS \p{Alphabetic}\p{N} (inside […]) or [\p{Alphabetic}\p{N}]
|
|
8
|
+
// Ruby \p{Word} → JS \p{Alphabetic}\p{N}\p{Pc} (Letter + Number + Connector Punct)
|
|
9
|
+
// Ruby \p{Blank} → JS \p{Zs}\t (Unicode Space_Separator + tab)
|
|
10
|
+
// Ruby CC_ALL (. with /m) → [\s\S] (no 's' flag needed)
|
|
11
|
+
// Ruby CC_ANY (.) → .
|
|
12
|
+
// Ruby ^ / $ → always line anchors in Ruby; in JS only with 'm' flag
|
|
13
|
+
// Ruby \A / \Z → ^ / $ in JS (string anchors, no 'm' flag)
|
|
14
|
+
//
|
|
15
|
+
// IMPORTANT – 'u' flag and unset back-references:
|
|
16
|
+
// Without 'u': \n to an unset group matches the empty string (Ruby-compatible).
|
|
17
|
+
// With 'u': \n to an unset group fails (stricter).
|
|
18
|
+
// → InlineLinkRx is intentionally kept WITHOUT the 'u' flag because it relies on
|
|
19
|
+
// the (?!\2) trick (negative lookahead of an unset back-reference) to guard the
|
|
20
|
+
// angle-bracket branch. All other patterns use 'u'.
|
|
21
|
+
|
|
22
|
+
// ── Character class string constants ─────────────────────────────────────────
|
|
23
|
+
// CC_* → raw content for insertion INSIDE a character class: [${CC_WORD}]
|
|
24
|
+
// CG_* → complete character class GROUP for standalone use: ${CG_WORD}
|
|
25
|
+
//
|
|
26
|
+
// These are runtime strings whose value contains real regex syntax (single
|
|
27
|
+
// backslashes) so that String.raw`…${CC_WORD}…` produces correct regex source.
|
|
28
|
+
|
|
29
|
+
export const CC_ALL = '[\\s\\S]' // any char including newlines (Ruby . with /m flag)
|
|
30
|
+
export const CC_ANY = '.' // any char except newlines
|
|
31
|
+
export const CC_EOL = '$' // end of line / string
|
|
32
|
+
|
|
33
|
+
// \p{Alphabetic} ≈ Ruby \p{Alpha} – all Unicode alphabetic characters
|
|
34
|
+
export const CC_ALPHA = '\\p{Alphabetic}' // inside [...]
|
|
35
|
+
export const CG_ALPHA = '\\p{Alphabetic}' // standalone (unary property, no brackets needed)
|
|
36
|
+
|
|
37
|
+
// \p{Alphabetic}\p{N} ≈ Ruby \p{Alnum} – alphabetics + all Unicode numbers
|
|
38
|
+
export const CC_ALNUM = '\\p{Alphabetic}\\p{N}' // inside [...]
|
|
39
|
+
export const CG_ALNUM = '[\\p{Alphabetic}\\p{N}]' // standalone group
|
|
40
|
+
|
|
41
|
+
// \p{Alphabetic}\p{N}\p{Pc} ≈ Ruby \p{Word}
|
|
42
|
+
// Letter + Number + Connector Punctuation (underscore, undertie, …)
|
|
43
|
+
export const CC_WORD = '\\p{Alphabetic}\\p{N}\\p{Pc}' // inside [...]
|
|
44
|
+
export const CG_WORD = '[\\p{Alphabetic}\\p{N}\\p{Pc}]' // standalone group
|
|
45
|
+
|
|
46
|
+
// \p{Zs}\t ≈ Ruby \p{Blank} – Unicode Space_Separator category + tab
|
|
47
|
+
export const CG_BLANK = '[\\p{Zs}\\t]' // standalone group
|
|
48
|
+
|
|
49
|
+
// Attribute list pattern fragment: \[([^\[\]]+)\]
|
|
50
|
+
// Ruby: QuoteAttributeListRxt = %(\\[([^\\[\\]]+)\\])
|
|
51
|
+
export const QuoteAttributeListRxt = '\\[([^\\[\\]]+)\\]'
|
|
52
|
+
|
|
53
|
+
// ── Helpers ───────────────────────────────────────────────────────────────────
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Build a regex with the Unicode flag ('u'), enabling \p{…} property escapes.
|
|
57
|
+
* @param {string} src - Regex source string (use String.raw for easy authoring).
|
|
58
|
+
* @param {string} extraFlags - Additional flags, e.g. 'm' for multiline ^ / $
|
|
59
|
+
*/
|
|
60
|
+
const ru = (src, extraFlags = '') => new RegExp(src, `u${extraFlags}`)
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Escape all regex metacharacters in str (equivalent to Regexp.escape in Ruby).
|
|
64
|
+
*/
|
|
65
|
+
function escapeRegex(str) {
|
|
66
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Build a lazy-initialised regex map, mirroring Ruby's Hash.new { |h,k| h[k] = … }.
|
|
71
|
+
* Accessing map[key] creates and caches the regex for that key.
|
|
72
|
+
*/
|
|
73
|
+
function makeLazyRxMap(buildFn) {
|
|
74
|
+
const cache = new Map()
|
|
75
|
+
return new Proxy(Object.create(null), {
|
|
76
|
+
get(_target, key) {
|
|
77
|
+
if (typeof key !== 'string') return undefined
|
|
78
|
+
if (!cache.has(key)) cache.set(key, buildFn(key))
|
|
79
|
+
return cache.get(key)
|
|
80
|
+
},
|
|
81
|
+
})
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// ── Document header ───────────────────────────────────────────────────────────
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Matches the author info line immediately following the document title.
|
|
88
|
+
* @example
|
|
89
|
+
* Doc Writer <doc@example.com>
|
|
90
|
+
* Mary_Sue Brontë
|
|
91
|
+
*/
|
|
92
|
+
export const AuthorInfoLineRx = ru(
|
|
93
|
+
String.raw`^(${CG_WORD}[${CC_WORD}\-'.]*)(?: +(${CG_WORD}[${CC_WORD}\-'.]*))?` +
|
|
94
|
+
String.raw`(?: +(${CG_WORD}[${CC_WORD}\-'.]*))?(?:[ ]+<([^>]+)>)?$`
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Matches the delimiter that separates multiple authors.
|
|
99
|
+
* @example
|
|
100
|
+
* Doc Writer; Junior Writer
|
|
101
|
+
*/
|
|
102
|
+
export const AuthorDelimiterRx = /;(?: |$)/
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Matches the revision info line immediately following the author info line.
|
|
106
|
+
* @example
|
|
107
|
+
* v1.0
|
|
108
|
+
* 2013-01-01
|
|
109
|
+
* v1.0, 2013-01-01: Ring in the new year release
|
|
110
|
+
*/
|
|
111
|
+
export const RevisionInfoLineRx =
|
|
112
|
+
/^(?:[^\d{]*(.*?),)? *(?!:)(.*?)(?: *(?!^),?: *(.*))?$/
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Matches the title and volnum in the manpage doctype.
|
|
116
|
+
* @example
|
|
117
|
+
* = asciidoctor(1)
|
|
118
|
+
* = asciidoctor ( 1 )
|
|
119
|
+
*/
|
|
120
|
+
export const ManpageTitleVolnumRx = /^(.+?) *\( *(.+?) *\)$/
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Matches the name and purpose in the manpage doctype.
|
|
124
|
+
* @example
|
|
125
|
+
* asciidoctor - converts AsciiDoc source files to HTML, DocBook and other formats
|
|
126
|
+
*/
|
|
127
|
+
export const ManpageNamePurposeRx = /^(.+?) +- +(.+)$/
|
|
128
|
+
|
|
129
|
+
// ── Preprocessor directives ───────────────────────────────────────────────────
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Matches a conditional preprocessor directive (ifdef, ifndef, ifeval, endif).
|
|
133
|
+
* @example
|
|
134
|
+
* ifdef::basebackend-html[]
|
|
135
|
+
* ifeval::["{asciidoctor-version}" >= "0.1.0"]
|
|
136
|
+
* endif::[]
|
|
137
|
+
*/
|
|
138
|
+
export const ConditionalDirectiveRx =
|
|
139
|
+
/^(\\)?(ifdef|ifndef|ifeval|endif)::(\S*?(?:([,+])\S*?)?)\[(.+)?\]$/
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Matches a restricted (safe) eval expression.
|
|
143
|
+
* @example
|
|
144
|
+
* "{asciidoctor-version}" >= "0.1.0"
|
|
145
|
+
*/
|
|
146
|
+
export const EvalExpressionRx = /^(.+?) *([=!><]=|[><]) *(.+)$/
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Matches an include preprocessor directive.
|
|
150
|
+
* @example
|
|
151
|
+
* include::chapter1.ad[]
|
|
152
|
+
* include::example.txt[lines=1;2;5..10]
|
|
153
|
+
*/
|
|
154
|
+
export const IncludeDirectiveRx =
|
|
155
|
+
/^(\\)?include::([^\s[](?:[^[]*[^\s[])?)\[(.+)?\]$/
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Matches a trailing tag directive in an include file.
|
|
159
|
+
*
|
|
160
|
+
* NOTE: 'm' flag required so that $ matches end-of-line (not only end-of-string) in JS.
|
|
161
|
+
* NOTE: accounts for \r in Windows line endings.
|
|
162
|
+
* @example
|
|
163
|
+
* // tag::try-catch[]
|
|
164
|
+
* // end::try-catch[]
|
|
165
|
+
*/
|
|
166
|
+
export const TagDirectiveRx = /\b(?:tag|(e)nd)::(\S+?)\[\](?=$|[ \r])/m
|
|
167
|
+
|
|
168
|
+
// ── Attribute entries and references ─────────────────────────────────────────
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Matches a document attribute entry.
|
|
172
|
+
* @example
|
|
173
|
+
* :foo: bar
|
|
174
|
+
* :First Name: Dan
|
|
175
|
+
* :sectnums!:
|
|
176
|
+
*/
|
|
177
|
+
export const AttributeEntryRx = ru(
|
|
178
|
+
String.raw`^:(!?${CG_WORD}[^:]*):(?:[ \t]+(.*))?$`
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
/** Matches invalid characters in an attribute name. */
|
|
182
|
+
export const InvalidAttributeNameCharsRx = ru(String.raw`[^${CC_WORD}\-]`)
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Matches a pass inline macro surrounding an attribute entry value.
|
|
186
|
+
*
|
|
187
|
+
* NOTE: ^ / $ are string anchors here (no 'm' flag). [\s\S]* allows multi-line values.
|
|
188
|
+
* @example
|
|
189
|
+
* pass:[text]
|
|
190
|
+
* pass:a[{a} {b} {c}]
|
|
191
|
+
*/
|
|
192
|
+
export const AttributeEntryPassMacroRx =
|
|
193
|
+
/^pass:([a-z]+(?:,[a-z-]+)*)?\[([\s\S]*)\]$/
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Matches an inline attribute reference.
|
|
197
|
+
* @example
|
|
198
|
+
* {foobar}
|
|
199
|
+
* {counter:sequence-name:1}
|
|
200
|
+
* {set:foo:bar}
|
|
201
|
+
*/
|
|
202
|
+
export const AttributeReferenceRx = ru(
|
|
203
|
+
String.raw`(\\)?\{(${CG_WORD}[${CC_WORD}\-]*|(set|counter2?):.*?)(\\)?\}`
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
// ── Paragraphs and delimited blocks ──────────────────────────────────────────
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Matches an anchor (id + optional reference text) on a line above a block.
|
|
210
|
+
* @example
|
|
211
|
+
* [[idname]]
|
|
212
|
+
* [[idname,Reference Text]]
|
|
213
|
+
*/
|
|
214
|
+
export const BlockAnchorRx = ru(
|
|
215
|
+
String.raw`^\[\[(?:|([${CC_ALPHA}_:][${CC_WORD}\-:.]*)(?:, *(.+))?)\]\]$`
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Matches an attribute list above a block element.
|
|
220
|
+
* @example
|
|
221
|
+
* [quote, Adam Smith, Wealth of Nations]
|
|
222
|
+
* [{lead}]
|
|
223
|
+
*/
|
|
224
|
+
export const BlockAttributeListRx = ru(
|
|
225
|
+
String.raw`^\[(|[${CC_WORD}.#%{,"'].*)\]$`
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
/** Combined pattern matching either a block anchor or a block attribute list. */
|
|
229
|
+
export const BlockAttributeLineRx = ru(
|
|
230
|
+
String.raw`^\[(?:|[${CC_WORD}.#%{,"'].*|\[(?:|[${CC_ALPHA}_:][${CC_WORD}\-:.]*(?:, *.+)?)\])\]$`
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Matches a title above a block.
|
|
235
|
+
* @example
|
|
236
|
+
* .Title goes here
|
|
237
|
+
*/
|
|
238
|
+
export const BlockTitleRx = /^\.(\.?[^ \t.].*)$/
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Matches an admonition label at the start of a paragraph.
|
|
242
|
+
* @example
|
|
243
|
+
* NOTE: Just a little note.
|
|
244
|
+
* TIP: Don't forget!
|
|
245
|
+
*/
|
|
246
|
+
export const AdmonitionParagraphRx =
|
|
247
|
+
/^(NOTE|TIP|IMPORTANT|WARNING|CAUTION):[ \t]+/
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Matches a literal paragraph (line preceded by at least one space or tab).
|
|
251
|
+
* @example
|
|
252
|
+
* <SPACE>Foo
|
|
253
|
+
* <TAB>Foo
|
|
254
|
+
*/
|
|
255
|
+
export const LiteralParagraphRx = /^([ \t]+.*)$/
|
|
256
|
+
|
|
257
|
+
// ── Section titles ────────────────────────────────────────────────────────────
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Matches an Atx (single-line) section title.
|
|
261
|
+
* @example
|
|
262
|
+
* == Foo
|
|
263
|
+
* == Foo ==
|
|
264
|
+
*/
|
|
265
|
+
export const AtxSectionTitleRx = /^(=={0,5})[ \t]+(.+?)(?:[ \t]+\1)?$/
|
|
266
|
+
|
|
267
|
+
/** Extended Atx section title supporting the Markdown variant (#). */
|
|
268
|
+
export const ExtAtxSectionTitleRx =
|
|
269
|
+
/^(=={0,5}|##{0,5})[ \t]+(.+?)(?:[ \t]+\1)?$/
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Matches the first line of a Setext (two-line) section title.
|
|
273
|
+
* Must not start with '.' and must contain at least one alphanumeric character.
|
|
274
|
+
*/
|
|
275
|
+
export const SetextSectionTitleRx = ru(String.raw`^((?!\.).*?${CG_ALNUM}.*)$`)
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Matches an anchor inside a section title.
|
|
279
|
+
* @example
|
|
280
|
+
* Section Title [[idname]]
|
|
281
|
+
* Section Title [[idname,Reference Text]]
|
|
282
|
+
*/
|
|
283
|
+
export const InlineSectionAnchorRx = ru(
|
|
284
|
+
String.raw` (\\)?\[\[([${CC_ALPHA}_:][${CC_WORD}\-:.]*)(?:, *(.+?))?\]\]$`
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Matches invalid ID characters in a section title.
|
|
289
|
+
* NOTE: Uppercase excluded; expression is run only on a lowercase string.
|
|
290
|
+
*/
|
|
291
|
+
export const InvalidSectionIdCharsRx = ru(
|
|
292
|
+
String.raw`<[^>]+>|&(?:[a-z][a-z]+\d{0,2}|#\d\d\d{0,4}|#x[\da-f][\da-f][\da-f]{0,3});|[^ ${CC_WORD}\-.]+?`
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
/** Matches an explicit section level style like sect1. */
|
|
296
|
+
export const SectionLevelStyleRx = /^sect\d$/
|
|
297
|
+
|
|
298
|
+
// ── Lists ─────────────────────────────────────────────────────────────────────
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Detects the start of any list item.
|
|
302
|
+
*
|
|
303
|
+
* NOTE: Check only up to the blank character since non-whitespace follows.
|
|
304
|
+
* IMPORTANT: Must agree with the per-list-type regexps or the parser will hang.
|
|
305
|
+
*/
|
|
306
|
+
export const AnyListRx =
|
|
307
|
+
/^(?:[ \t]*(?:-|\*\**|\.\.*|\u2022|\d+\.|[a-zA-Z]\.|[IVXivx]+\))[ \t]|(?!\/\/[^/])[ \t]*[^ \t].*?(?::::{0,2}|;;)(?:$|[ \t])|<(?:\d+|\.)>[ \t])/
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Matches an unordered list item.
|
|
311
|
+
* @example
|
|
312
|
+
* * Foo
|
|
313
|
+
* - Foo
|
|
314
|
+
*/
|
|
315
|
+
export const UnorderedListRx = /^[ \t]*(-|\*\**|\u2022)[ \t]+([\s\S]*)$/
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Matches an ordered list item.
|
|
319
|
+
* @example
|
|
320
|
+
* . Foo 1. Foo a. Foo I. Foo
|
|
321
|
+
*/
|
|
322
|
+
export const OrderedListRx =
|
|
323
|
+
/^[ \t]*(\.\.*|\d+\.|[a-zA-Z]\.|[IVXivx]+\))[ \t]+([\s\S]*)$/
|
|
324
|
+
|
|
325
|
+
/** Ordinal pattern for each ordered list type. */
|
|
326
|
+
export const OrderedListMarkerRxMap = {
|
|
327
|
+
arabic: /\d+\./,
|
|
328
|
+
loweralpha: /[a-z]\./,
|
|
329
|
+
lowerroman: /[ivx]+\)/,
|
|
330
|
+
upperalpha: /[A-Z]\./,
|
|
331
|
+
upperroman: /[IVX]+\)/,
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Matches a description list entry.
|
|
336
|
+
* @example
|
|
337
|
+
* foo::
|
|
338
|
+
* foo:: The metasyntactic variable …
|
|
339
|
+
*/
|
|
340
|
+
export const DescriptionListRx =
|
|
341
|
+
/^(?!\/\/[^/])[ \t]*([^ \t].*?)(:::{0,2}|;;)(?:$|[ \t]+([\s\S]*)$)/
|
|
342
|
+
|
|
343
|
+
/** Matches a sibling description list item (excluding the delimiter given by key). */
|
|
344
|
+
export const DescriptionListSiblingRx = {
|
|
345
|
+
'::': /^(?!\/\/[^/])[ \t]*([^ \t].*?[^:]|[^ \t:])(::)(?:$|[ \t]+([\s\S]*)$)/,
|
|
346
|
+
':::':
|
|
347
|
+
/^(?!\/\/[^/])[ \t]*([^ \t].*?[^:]|[^ \t:])(:::)(?:$|[ \t]+([\s\S]*)$)/,
|
|
348
|
+
'::::':
|
|
349
|
+
/^(?!\/\/[^/])[ \t]*([^ \t].*?[^:]|[^ \t:])(::::)(?:$|[ \t]+([\s\S]*)$)/,
|
|
350
|
+
';;': /^(?!\/\/[^/])[ \t]*([^ \t].*?)(;;)(?:$|[ \t]+([\s\S]*)$)/,
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Matches a callout list item.
|
|
355
|
+
* @example
|
|
356
|
+
* <1> Explanation
|
|
357
|
+
* <.> Explanation with automatic number
|
|
358
|
+
*/
|
|
359
|
+
export const CalloutListRx = /^<(\d+|\.)>[ \t]+([\s\S]*)$/
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Matches a callout reference inside literal text (applied line-by-line).
|
|
363
|
+
*
|
|
364
|
+
* Group layout:
|
|
365
|
+
* 1 – optional line-comment prefix (// # -- ;;)
|
|
366
|
+
* 2 – backslash escape
|
|
367
|
+
* 3 – optional XML comment delimiter (--)
|
|
368
|
+
* 4 – callout number or dot
|
|
369
|
+
*/
|
|
370
|
+
export const CalloutExtractRx =
|
|
371
|
+
/((?:\/\/|#|--|;;) ?)?(\\)?<!?(|--)(\d+|\.)\3>(?=(?: ?\\?<!?\3(?:\d+|\.)\3>)*$)/m
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Template string for CalloutExtractRxMap entries.
|
|
375
|
+
* Runtime value: (\\)?<()(\d+|\.)>(?=(?: ?\\?<(?:\d+|\.)>)*$)
|
|
376
|
+
* Note: 'm' flag added so $ matches end-of-line (Ruby regex default behaviour).
|
|
377
|
+
*/
|
|
378
|
+
export const CalloutExtractRxt =
|
|
379
|
+
'(\\\\)?<()([\\d]+|\\.)>(?=(?: ?\\\\?<(?:\\d+|\\.)>)*$)'
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Lazy map: line-comment string → callout-extract regex.
|
|
383
|
+
* Mirrors Ruby: Hash.new { |h,k| h[k] = /(prefix)?#{CalloutExtractRxt}/ }
|
|
384
|
+
*/
|
|
385
|
+
export const CalloutExtractRxMap = makeLazyRxMap((key) => {
|
|
386
|
+
const prefix = key ? `(${escapeRegex(key)} ?)?` : '()?'
|
|
387
|
+
return new RegExp(`${prefix}${CalloutExtractRxt}`, 'm')
|
|
388
|
+
})
|
|
389
|
+
|
|
390
|
+
/** Matches a callout reference when scanning source (special chars NOT yet replaced). */
|
|
391
|
+
export const CalloutScanRx =
|
|
392
|
+
/\\?<!?(|--)(\d+|\.)\1>(?=(?: ?\\?<!?\1(?:\d+|\.)\1>)*$)/m
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Matches a callout reference in HTML output (special chars already replaced).
|
|
396
|
+
*
|
|
397
|
+
* Group layout mirrors CalloutExtractRx.
|
|
398
|
+
* Note: 'm' flag so $ matches end-of-line, matching Ruby regex semantics.
|
|
399
|
+
*/
|
|
400
|
+
export const CalloutSourceRx =
|
|
401
|
+
/((?:\/\/|#|--|;;) ?)?(\\)?<!?(|--)(\d+|\.)\3>(?=(?: ?\\?<!?\3(?:\d+|\.)\3>)*$)/m
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Template string for CalloutSourceRxMap entries.
|
|
405
|
+
* Runtime value: (\\)?<()(\d+|\.)>(?=(?: ?\\?<(?:\d+|\.)>)*$)
|
|
406
|
+
*/
|
|
407
|
+
export const CalloutSourceRxt =
|
|
408
|
+
'(\\\\)?<()([\\d]+|\\.)>(?=(?: ?\\\\?<(?:\\d+|\\.)>)*$)'
|
|
409
|
+
|
|
410
|
+
/** Lazy map: line-comment string → callout-source regex. */
|
|
411
|
+
export const CalloutSourceRxMap = makeLazyRxMap((key) => {
|
|
412
|
+
const prefix = key ? `(${escapeRegex(key)} ?)?` : '()?'
|
|
413
|
+
return new RegExp(`${prefix}${CalloutSourceRxt}`, 'm')
|
|
414
|
+
})
|
|
415
|
+
|
|
416
|
+
/** Dynamic map from list context to its regex. */
|
|
417
|
+
export const ListRxMap = {
|
|
418
|
+
ulist: UnorderedListRx,
|
|
419
|
+
olist: OrderedListRx,
|
|
420
|
+
dlist: DescriptionListRx,
|
|
421
|
+
colist: CalloutListRx,
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// ── Tables ────────────────────────────────────────────────────────────────────
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Parses the column test (colspec) for a table.
|
|
428
|
+
* @example
|
|
429
|
+
* 1*h,2*,^3e
|
|
430
|
+
*/
|
|
431
|
+
export const ColumnSpecRx =
|
|
432
|
+
/^(?:(\d+)\*)?([<^>](?:\.[<^>]?)?|(?:[<^>]?\.)?[<^>])?(\d+%?|~)?([a-z])?$/
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Parses the start of a cell test.
|
|
436
|
+
* @example
|
|
437
|
+
* 2.3+<.>m
|
|
438
|
+
*/
|
|
439
|
+
export const CellSpecStartRx =
|
|
440
|
+
/^[ \t]*(?:(\d+(?:\.\d*)?|(?:\d*\.)?\d+)([*+]))?([<^>](?:\.[<^>]?)?|(?:[<^>]?\.)?[<^>])?([a-z])?$/
|
|
441
|
+
|
|
442
|
+
/** Parses the end of a cell test. */
|
|
443
|
+
export const CellSpecEndRx =
|
|
444
|
+
/[ \t]+(?:(\d+(?:\.\d*)?|(?:\d*\.)?\d+)([*+]))?([<^>](?:\.[<^>]?)?|(?:[<^>]?\.)?[<^>])?([a-z])?$/
|
|
445
|
+
|
|
446
|
+
// ── Block macros ──────────────────────────────────────────────────────────────
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Matches the custom block macro pattern.
|
|
450
|
+
* @example
|
|
451
|
+
* gist::123456[]
|
|
452
|
+
*/
|
|
453
|
+
export const CustomBlockMacroRx = ru(
|
|
454
|
+
String.raw`^(${CG_WORD}[${CC_WORD}\-]*)::(|\S|\S.*?\S)\[(.+)?\]$`
|
|
455
|
+
)
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* Matches an image, video or audio block macro.
|
|
459
|
+
* @example
|
|
460
|
+
* image::filename.png[Caption]
|
|
461
|
+
* video::http://youtube.com/12345[Cats vs Dogs]
|
|
462
|
+
*/
|
|
463
|
+
export const BlockMediaMacroRx = /^(image|video|audio)::(\S|\S.*?\S)\[(.+)?\]$/
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* Matches the TOC block macro.
|
|
467
|
+
* @example
|
|
468
|
+
* toc::[]
|
|
469
|
+
* toc::[levels=2]
|
|
470
|
+
*/
|
|
471
|
+
export const BlockTocMacroRx = /^toc::\[(.+)?\]$/
|
|
472
|
+
|
|
473
|
+
// ── Inline macros ─────────────────────────────────────────────────────────────
|
|
474
|
+
|
|
475
|
+
/**
|
|
476
|
+
* Matches an anchor (id + optional reference text) in the flow of text.
|
|
477
|
+
*
|
|
478
|
+
* Group layout:
|
|
479
|
+
* 1 – backslash escape
|
|
480
|
+
* 2 – id (double-bracket form)
|
|
481
|
+
* 3 – reftext (double-bracket form)
|
|
482
|
+
* 4 – id (anchor: macro form)
|
|
483
|
+
* 5 – reftext (anchor: macro form)
|
|
484
|
+
* @example
|
|
485
|
+
* [[idname]]
|
|
486
|
+
* [[idname,Reference Text]]
|
|
487
|
+
* anchor:idname[]
|
|
488
|
+
* anchor:idname[Reference Text]
|
|
489
|
+
*/
|
|
490
|
+
export const InlineAnchorRx = ru(
|
|
491
|
+
String.raw`(\\)?(?:\[\[([${CC_ALPHA}_:][${CC_WORD}\-:.]*)(?:, *(.+?))? ?\]\]` +
|
|
492
|
+
String.raw`|anchor:([${CC_ALPHA}_:][${CC_WORD}\-:.]*)\[(?:\]|([\s\S]*?[^\\])\]))`
|
|
493
|
+
)
|
|
494
|
+
|
|
495
|
+
/** Scans for a non-escaped anchor in the flow of text. */
|
|
496
|
+
export const InlineAnchorScanRx = ru(
|
|
497
|
+
String.raw`(?:^|[^\\\[])\[\[([${CC_ALPHA}_:][${CC_WORD}\-:.]*)(?:, *(.+?))? ?\]\]` +
|
|
498
|
+
String.raw`|(?:^|[^\\])anchor:([${CC_ALPHA}_:][${CC_WORD}\-:.]*)\[(?:\]|(.*?[^\\])\])`
|
|
499
|
+
)
|
|
500
|
+
|
|
501
|
+
/** Scans for a leading, non-escaped anchor. */
|
|
502
|
+
export const LeadingInlineAnchorRx = ru(
|
|
503
|
+
String.raw`^\[\[([${CC_ALPHA}_:][${CC_WORD}\-:.]*)(?:, *(.+?))?\]\]`
|
|
504
|
+
)
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* Matches a bibliography anchor at the start of a list item.
|
|
508
|
+
* @example
|
|
509
|
+
* [[[Fowler_1997]]] Fowler M. ...
|
|
510
|
+
*/
|
|
511
|
+
export const InlineBiblioAnchorRx = ru(
|
|
512
|
+
String.raw`^\[\[\[([${CC_ALPHA}_:][${CC_WORD}\-:.]*)(?:, *(.+?))?\]\]\]`
|
|
513
|
+
)
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* Matches an inline e-mail address.
|
|
517
|
+
* @example
|
|
518
|
+
* doc.writer@example.com
|
|
519
|
+
*/
|
|
520
|
+
export const InlineEmailRx = ru(
|
|
521
|
+
String.raw`([\\>:/])?${CG_WORD}(?:&|[${CC_WORD}\-.%+])*` +
|
|
522
|
+
String.raw`@${CG_ALNUM}[${CC_ALNUM}_\-.]*\.[a-zA-Z]{2,5}\b`
|
|
523
|
+
)
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
* Matches an inline footnote macro (may span multiple lines).
|
|
527
|
+
*
|
|
528
|
+
* NOTE: [\s\S]*? allows multiline content (Ruby /m + CC_ALL).
|
|
529
|
+
* NOTE: (?!</a>) avoids matching inside an anchor tag.
|
|
530
|
+
* @example
|
|
531
|
+
* footnote:[text]
|
|
532
|
+
* footnote:id[text]
|
|
533
|
+
* footnoteref:[id,text] (legacy)
|
|
534
|
+
*/
|
|
535
|
+
export const InlineFootnoteMacroRx = ru(
|
|
536
|
+
String.raw`\\?footnote(?:(ref):|:([${CC_WORD}\-]+)?)\[(?:|([\s\S]*?[^\\]))\](?!</a>)`
|
|
537
|
+
)
|
|
538
|
+
|
|
539
|
+
/**
|
|
540
|
+
* Matches an image or icon inline macro (may span multiple lines).
|
|
541
|
+
* @example
|
|
542
|
+
* image:filename.png[Alt Text]
|
|
543
|
+
* icon:github[large]
|
|
544
|
+
*/
|
|
545
|
+
export const InlineImageMacroRx =
|
|
546
|
+
/\\?i(?:mage|con):([^:\s[](?:[^\n[]*[^\s[])?)\[(|[\s\S]*?[^\\])\]/
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* Matches an indexterm inline macro (may span multiple lines).
|
|
550
|
+
* @example
|
|
551
|
+
* indexterm:[Tigers,Big cats]
|
|
552
|
+
* (((Tigers,Big cats)))
|
|
553
|
+
* ((Tigers))
|
|
554
|
+
*/
|
|
555
|
+
export const InlineIndextermMacroRx =
|
|
556
|
+
/\\?(?:(indexterm2?):\[([\s\S]*?[^\\])\]|\(\(([\s\S]+?)\)\)(?!\)))/
|
|
557
|
+
|
|
558
|
+
/**
|
|
559
|
+
* Matches either the kbd or btn inline macro (may span multiple lines).
|
|
560
|
+
* @example
|
|
561
|
+
* kbd:[F3] kbd:[Ctrl+Shift+T] btn:[Save]
|
|
562
|
+
*/
|
|
563
|
+
export const InlineKbdBtnMacroRx = /(\\)?(kbd|btn):\[([\s\S]*?[^\\])\]/
|
|
564
|
+
|
|
565
|
+
/**
|
|
566
|
+
* Matches an implicit link and the link inline macro.
|
|
567
|
+
*
|
|
568
|
+
* NOTE: This is the Opal/JS variant of the pattern.
|
|
569
|
+
* Group 2 captures ':' inside a lookahead from the <<protocol> branch.
|
|
570
|
+
* (?!\2) then guards the >-terminated branch: when group 2 IS ':',
|
|
571
|
+
* the guard prevents matching '://' at the start of the path; when group 2
|
|
572
|
+
* is UNSET (other prefix branches), (?!\2) expands to (?!"") which ALWAYS
|
|
573
|
+
* FAILS – correctly preventing the > branch for non-< prefixes.
|
|
574
|
+
*
|
|
575
|
+
* *** NO 'u' FLAG: the (?!\2) guard relies on unset back-references matching
|
|
576
|
+
* the empty string, which only holds in non-Unicode mode. ***
|
|
577
|
+
*
|
|
578
|
+
* Group layout:
|
|
579
|
+
* 1 – prefix (^, link:, blank, \\?< or punctuation)
|
|
580
|
+
* 2 – ':' captured by lookahead (only when prefix is \\?<)
|
|
581
|
+
* 3 – URL scheme + ://
|
|
582
|
+
* 4 – target before [ (formal macro)
|
|
583
|
+
* 5 – attrlist (formal macro, may be empty)
|
|
584
|
+
* 6 – target before > (angle-bracket autolink, requires < prefix)
|
|
585
|
+
* 7 – target (bare autolink)
|
|
586
|
+
* 8 – last non-terminating char of bare target
|
|
587
|
+
* @example
|
|
588
|
+
* https://github.com
|
|
589
|
+
* https://github.com[GitHub]
|
|
590
|
+
* <https://github.com>
|
|
591
|
+
* link:https://github.com[]
|
|
592
|
+
*/
|
|
593
|
+
export const InlineLinkRx =
|
|
594
|
+
/(^|link:|[ \t\u00a0]|\\?<(?=\\?(?:https?|file|ftp|irc)(:))|[>()[\];"'])(\\?(?:https?|file|ftp|irc):\/\/)(?:([^\s[\]]+)\[(|[\s\S]*?[^\\])\]|(?!\2)([^\s]+?)>|([^\s[\]<]*([^\s,.?![\]<)])))/m
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* Matches a link or e-mail inline macro (may span multiple lines).
|
|
598
|
+
* @example
|
|
599
|
+
* link:path[label]
|
|
600
|
+
* mailto:doc.writer@example.com[]
|
|
601
|
+
*/
|
|
602
|
+
export const InlineLinkMacroRx =
|
|
603
|
+
/\\?(?:link|(mailto)):(|[^:\s[][^\s[]*)\[(|[\s\S]*?[^\\])\]/
|
|
604
|
+
|
|
605
|
+
/** Matches the name of a macro. */
|
|
606
|
+
export const MacroNameRx = ru(String.raw`^${CG_WORD}[${CC_WORD}\-]*$`)
|
|
607
|
+
|
|
608
|
+
/**
|
|
609
|
+
* Matches a stem (and alternatives) inline macro (may span multiple lines).
|
|
610
|
+
* @example
|
|
611
|
+
* stem:[x != 0]
|
|
612
|
+
* latexmath:[\sqrt{4} = 2]
|
|
613
|
+
*/
|
|
614
|
+
export const InlineStemMacroRx =
|
|
615
|
+
/\\?(stem|(?:latex|ascii)math):([a-z]+(?:,[a-z-]+)*)?\[([\s\S]*?[^\\])\]/
|
|
616
|
+
|
|
617
|
+
/**
|
|
618
|
+
* Matches a menu inline macro (may span multiple lines).
|
|
619
|
+
* @example
|
|
620
|
+
* menu:File[Save As...]
|
|
621
|
+
* menu:View[Page Style > No Style]
|
|
622
|
+
*/
|
|
623
|
+
export const InlineMenuMacroRx = ru(
|
|
624
|
+
String.raw`\\?menu:(${CG_WORD}|[${CC_WORD}&][^\n\[]*[^\s\[])` +
|
|
625
|
+
String.raw`\[ *(?:|([\s\S]*?[^\\]))\]`
|
|
626
|
+
)
|
|
627
|
+
|
|
628
|
+
/**
|
|
629
|
+
* Matches an implicit menu inline macro.
|
|
630
|
+
* @example
|
|
631
|
+
* "File > New..."
|
|
632
|
+
*/
|
|
633
|
+
export const InlineMenuRx = ru(
|
|
634
|
+
String.raw`\\?"([${CC_WORD}&][^"]*?[ \n]+>[ \n]+[^"]*)"`
|
|
635
|
+
)
|
|
636
|
+
|
|
637
|
+
/**
|
|
638
|
+
* Matches an inline passthrough (may span multiple lines).
|
|
639
|
+
*
|
|
640
|
+
* Group layout (false / non-compat):
|
|
641
|
+
* 1 – preceding context or escape boundary
|
|
642
|
+
* 2 – '[' captured by lookahead (back-reference trick for attribute list detection)
|
|
643
|
+
* 3 – x- / 'attrlist x-' content
|
|
644
|
+
* 4 – QuoteAttributeListRxt content
|
|
645
|
+
* 5 – optional backslash before opening delimiter
|
|
646
|
+
* 6 – full quoted span (including delimiters)
|
|
647
|
+
* 7 – opening/closing delimiter (+ or `)
|
|
648
|
+
* 8 – span content
|
|
649
|
+
*
|
|
650
|
+
* Group layout (true / compat):
|
|
651
|
+
* 1 – preceding char or start-of-line
|
|
652
|
+
* 2 – ($) end-of-string sentinel (never matches in inline text, preserves group count)
|
|
653
|
+
* 3 – empty group paired with sentinel
|
|
654
|
+
* 4 – QuoteAttributeListRxt content
|
|
655
|
+
* 5 – optional backslash before opening delimiter
|
|
656
|
+
* 6 – full quoted span
|
|
657
|
+
* 7 – opening/closing delimiter (`)
|
|
658
|
+
* 8 – span content
|
|
659
|
+
*
|
|
660
|
+
* NOTE: 'u' flag used, but the 'm' flag is also set so that ^ is a line anchor.
|
|
661
|
+
* Unset optional back-references (\5?) with 'u' flag: the '?' quantifier
|
|
662
|
+
* allows 0 occurrences, so the match continues even when the group is unset.
|
|
663
|
+
* @example
|
|
664
|
+
* +text+
|
|
665
|
+
* [x-]+text+
|
|
666
|
+
* `text` (compat only)
|
|
667
|
+
*/
|
|
668
|
+
export const InlinePassRx = {
|
|
669
|
+
false: [
|
|
670
|
+
'+',
|
|
671
|
+
'-]',
|
|
672
|
+
ru(
|
|
673
|
+
String.raw`((?:^|[^${CC_WORD};:\\])(?=(\[)|\+)|\\(?=\[)|(?=\\\+))` +
|
|
674
|
+
String.raw`(?:\2(x-|[^\[\]]+ x-)\]|(?:` +
|
|
675
|
+
QuoteAttributeListRxt +
|
|
676
|
+
String.raw`)?(?=(\\)?\+))` +
|
|
677
|
+
String.raw`(\5?(\+|` +
|
|
678
|
+
'`' +
|
|
679
|
+
String.raw`)(\S|\S` +
|
|
680
|
+
CC_ALL +
|
|
681
|
+
String.raw`*?\S)\7)(?!${CG_WORD})`,
|
|
682
|
+
'm'
|
|
683
|
+
),
|
|
684
|
+
],
|
|
685
|
+
true: [
|
|
686
|
+
'`',
|
|
687
|
+
null,
|
|
688
|
+
ru(
|
|
689
|
+
String.raw`(^|[^` +
|
|
690
|
+
'`' +
|
|
691
|
+
String.raw`${CC_WORD}])(?:($)()|(?:` +
|
|
692
|
+
QuoteAttributeListRxt +
|
|
693
|
+
String.raw`)(?=(\\?)))?` +
|
|
694
|
+
String.raw`(\5?(` +
|
|
695
|
+
'`' +
|
|
696
|
+
String.raw`)([^` +
|
|
697
|
+
'`' +
|
|
698
|
+
String.raw`\s]|[^` +
|
|
699
|
+
'`' +
|
|
700
|
+
String.raw`\s]` +
|
|
701
|
+
CC_ALL +
|
|
702
|
+
String.raw`*?\S)\7)(?![` +
|
|
703
|
+
'`' +
|
|
704
|
+
String.raw`${CC_WORD}])`,
|
|
705
|
+
'm'
|
|
706
|
+
),
|
|
707
|
+
],
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
/**
|
|
711
|
+
* Matches several variants of the passthrough inline macro (may span multiple lines).
|
|
712
|
+
*
|
|
713
|
+
* Group layout:
|
|
714
|
+
* 1 – optional backslash before attribute list
|
|
715
|
+
* 2 – attribute list content (QuoteAttributeListRxt)
|
|
716
|
+
* 3 – backslash(es) before delimiter (0–2)
|
|
717
|
+
* 4 – delimiter: +++, ++, or $$
|
|
718
|
+
* 5 – content between delimiters (\4 closes)
|
|
719
|
+
* 6 – backslash before pass: macro
|
|
720
|
+
* 7 – subs list after pass:
|
|
721
|
+
* 8 – content inside pass:[…]
|
|
722
|
+
* @example
|
|
723
|
+
* +++text+++
|
|
724
|
+
* $$text$$
|
|
725
|
+
* pass:quotes[text]
|
|
726
|
+
* pass:[]
|
|
727
|
+
*/
|
|
728
|
+
export const InlinePassMacroRx = new RegExp(
|
|
729
|
+
`(?:(?:(\\\\?)${QuoteAttributeListRxt})?(\\\\{0,2})(\\+\\+\\+?|\\$\\$)([\\s\\S]*?)\\4|(\\\\?)pass:([a-z]+(?:,[a-z-]+)*)?\\[(|[\\s\\S]*?[^\\\\])\\])`
|
|
730
|
+
)
|
|
731
|
+
|
|
732
|
+
/**
|
|
733
|
+
* Matches an xref (cross-reference) inline macro (may span multiple lines).
|
|
734
|
+
*
|
|
735
|
+
* NOTE: { included to support targets beginning with an attribute reference.
|
|
736
|
+
* NOTE: Special characters are already entity-encoded in the matched text.
|
|
737
|
+
*
|
|
738
|
+
* Group layout:
|
|
739
|
+
* 1 – target of <<…>> form
|
|
740
|
+
* 2 – target of xref:…[] form
|
|
741
|
+
* 3 – link text inside xref:…[…]
|
|
742
|
+
* @example
|
|
743
|
+
* <<id,reftext>>
|
|
744
|
+
* xref:id[reftext]
|
|
745
|
+
*/
|
|
746
|
+
export const InlineXrefMacroRx = ru(
|
|
747
|
+
String.raw`\\?(?:<<([${CC_WORD}#/.:{]` +
|
|
748
|
+
CC_ALL +
|
|
749
|
+
String.raw`*?)>>` +
|
|
750
|
+
String.raw`|xref:([${CC_WORD}#/.:{]` +
|
|
751
|
+
CC_ALL +
|
|
752
|
+
String.raw`*?)\[(?:\]|(` +
|
|
753
|
+
CC_ALL +
|
|
754
|
+
String.raw`*?[^\\])\]))`
|
|
755
|
+
)
|
|
756
|
+
|
|
757
|
+
// ── Layout ────────────────────────────────────────────────────────────────────
|
|
758
|
+
|
|
759
|
+
/**
|
|
760
|
+
* Matches a trailing + preceded by at least one space, forcing a hard line break.
|
|
761
|
+
*
|
|
762
|
+
* NOTE: 'm' flag required so that ^ / $ are line anchors (not string anchors) in JS.
|
|
763
|
+
* @example
|
|
764
|
+
* Humpty Dumpty sat on a wall, +
|
|
765
|
+
* Humpty Dumpty had a great fall.
|
|
766
|
+
*/
|
|
767
|
+
export const HardLineBreakRx = /^(.*) \+$/m
|
|
768
|
+
|
|
769
|
+
/**
|
|
770
|
+
* Matches a Markdown horizontal rule.
|
|
771
|
+
* @example
|
|
772
|
+
* --- or - - -
|
|
773
|
+
* *** or * * *
|
|
774
|
+
* ___ or _ _ _
|
|
775
|
+
*/
|
|
776
|
+
export const MarkdownThematicBreakRx = /^ {0,3}([-*_])( *)\1\2\1$/
|
|
777
|
+
|
|
778
|
+
/**
|
|
779
|
+
* Matches an AsciiDoc or Markdown horizontal rule, or an AsciiDoc page break.
|
|
780
|
+
* @example
|
|
781
|
+
* ''' <<< --- *** ___
|
|
782
|
+
*/
|
|
783
|
+
export const ExtLayoutBreakRx = /^(?:'{3,}|<{3,}|([-*_])( *)\1\2\1)$/
|
|
784
|
+
|
|
785
|
+
// ── General ───────────────────────────────────────────────────────────────────
|
|
786
|
+
|
|
787
|
+
/** Matches consecutive blank lines. */
|
|
788
|
+
export const BlankLineRx = /\n{2,}/
|
|
789
|
+
|
|
790
|
+
/**
|
|
791
|
+
* Matches whitespace escaped by a backslash.
|
|
792
|
+
* @example
|
|
793
|
+
* three\ blind\ mice
|
|
794
|
+
*/
|
|
795
|
+
export const EscapedSpaceRx = /\\([ \t\n])/g
|
|
796
|
+
|
|
797
|
+
/** Detects text that may contain replaceable characters. */
|
|
798
|
+
export const ReplaceableTextRx = /[&']|--|\.\.\.|\([CRT]M?\)/
|
|
799
|
+
|
|
800
|
+
/**
|
|
801
|
+
* Matches a whitespace delimiter (space, tab, newline).
|
|
802
|
+
* Replicates the parsing rules of Ruby %w strings.
|
|
803
|
+
*
|
|
804
|
+
* TODO: Replace with /(?<!\\)[ \t\n]+/ when lookbehind is universally available.
|
|
805
|
+
*/
|
|
806
|
+
export const SpaceDelimiterRx = /([^\\])[ \t\n]+/g
|
|
807
|
+
|
|
808
|
+
/** Matches a + or - modifier in a subs list. */
|
|
809
|
+
export const SubModifierSniffRx = /[+-]/
|
|
810
|
+
|
|
811
|
+
/**
|
|
812
|
+
* Matches one or more consecutive digits at the end of a line.
|
|
813
|
+
* @example
|
|
814
|
+
* docbook5 html5
|
|
815
|
+
*/
|
|
816
|
+
export const TrailingDigitsRx = /\d+$/
|
|
817
|
+
|
|
818
|
+
/**
|
|
819
|
+
* Detects strings that resemble URIs.
|
|
820
|
+
*
|
|
821
|
+
* NOTE: ^ is used as a string-start anchor (no 'm' flag), equivalent to Ruby \A.
|
|
822
|
+
* NOTE: Does NOT match Windows paths like c:/sample.adoc or c:\sample.adoc.
|
|
823
|
+
* @example
|
|
824
|
+
* http://domain https://domain file:///path data:info
|
|
825
|
+
*/
|
|
826
|
+
export const UriSniffRx = ru(String.raw`^${CG_ALPHA}[${CC_ALNUM}.+\-]+:\/{0,2}`)
|
|
827
|
+
|
|
828
|
+
/** Detects XML tags. */
|
|
829
|
+
export const XmlSanitizeRx = /<[^>]+>/
|