asciidoctor 2.0.6 → 2.0.11
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.
- checksums.yaml +4 -4
- data/CHANGELOG.adoc +159 -6
- data/LICENSE +2 -1
- data/README-de.adoc +5 -5
- data/README-fr.adoc +4 -4
- data/README-jp.adoc +248 -183
- data/README-zh_CN.adoc +6 -6
- data/README.adoc +17 -11
- data/asciidoctor.gemspec +8 -8
- data/data/locale/attributes-ar.adoc +4 -3
- data/data/locale/attributes-bg.adoc +4 -3
- data/data/locale/attributes-ca.adoc +6 -5
- data/data/locale/attributes-cs.adoc +4 -3
- data/data/locale/attributes-da.adoc +6 -5
- data/data/locale/attributes-de.adoc +4 -4
- data/data/locale/attributes-en.adoc +4 -4
- data/data/locale/attributes-es.adoc +6 -5
- data/data/locale/attributes-fa.adoc +4 -3
- data/data/locale/attributes-fi.adoc +4 -3
- data/data/locale/attributes-fr.adoc +6 -5
- data/data/locale/attributes-hu.adoc +4 -3
- data/data/locale/attributes-id.adoc +4 -3
- data/data/locale/attributes-it.adoc +4 -3
- data/data/locale/attributes-ja.adoc +4 -3
- data/data/locale/{attributes-kr.adoc → attributes-ko.adoc} +4 -3
- data/data/locale/attributes-nb.adoc +4 -3
- data/data/locale/attributes-nl.adoc +4 -3
- data/data/locale/attributes-nn.adoc +4 -3
- data/data/locale/attributes-pl.adoc +8 -7
- data/data/locale/attributes-pt.adoc +6 -5
- data/data/locale/attributes-pt_BR.adoc +6 -5
- data/data/locale/attributes-ro.adoc +4 -3
- data/data/locale/attributes-ru.adoc +6 -5
- data/data/locale/attributes-sr.adoc +4 -4
- data/data/locale/attributes-sr_Latn.adoc +4 -4
- data/data/locale/attributes-sv.adoc +4 -4
- data/data/locale/attributes-tr.adoc +4 -3
- data/data/locale/attributes-uk.adoc +6 -5
- data/data/locale/attributes-zh_CN.adoc +4 -3
- data/data/locale/attributes-zh_TW.adoc +4 -3
- data/data/stylesheets/asciidoctor-default.css +29 -26
- data/lib/asciidoctor.rb +94 -1098
- data/lib/asciidoctor/abstract_block.rb +19 -11
- data/lib/asciidoctor/abstract_node.rb +21 -15
- data/lib/asciidoctor/attribute_list.rb +59 -67
- data/lib/asciidoctor/cli/invoker.rb +2 -0
- data/lib/asciidoctor/cli/options.rb +8 -8
- data/lib/asciidoctor/convert.rb +198 -0
- data/lib/asciidoctor/converter.rb +14 -13
- data/lib/asciidoctor/converter/docbook5.rb +9 -25
- data/lib/asciidoctor/converter/html5.rb +65 -42
- data/lib/asciidoctor/converter/manpage.rb +13 -12
- data/lib/asciidoctor/converter/template.rb +6 -3
- data/lib/asciidoctor/document.rb +40 -48
- data/lib/asciidoctor/extensions.rb +3 -3
- data/lib/asciidoctor/helpers.rb +38 -39
- data/lib/asciidoctor/inline.rb +1 -1
- data/lib/asciidoctor/load.rb +117 -0
- data/lib/asciidoctor/parser.rb +29 -25
- data/lib/asciidoctor/path_resolver.rb +35 -25
- data/lib/asciidoctor/reader.rb +14 -7
- data/lib/asciidoctor/rx.rb +722 -0
- data/lib/asciidoctor/substitutors.rb +62 -40
- data/lib/asciidoctor/syntax_highlighter.rb +22 -8
- data/lib/asciidoctor/syntax_highlighter/coderay.rb +1 -1
- data/lib/asciidoctor/syntax_highlighter/highlightjs.rb +12 -4
- data/lib/asciidoctor/syntax_highlighter/prettify.rb +7 -4
- data/lib/asciidoctor/syntax_highlighter/pygments.rb +2 -3
- data/lib/asciidoctor/syntax_highlighter/rouge.rb +18 -11
- data/lib/asciidoctor/table.rb +49 -20
- data/lib/asciidoctor/version.rb +1 -1
- data/man/asciidoctor.1 +17 -17
- data/man/asciidoctor.adoc +15 -14
- metadata +12 -9
data/lib/asciidoctor/parser.rb
CHANGED
@@ -433,8 +433,10 @@ class Parser
|
|
433
433
|
# is treated like an untitled section
|
434
434
|
elsif preamble # implies parent == document
|
435
435
|
if preamble.blocks?
|
436
|
+
if book || document.blocks[1] || !Compliance.unwrap_standalone_preamble
|
437
|
+
preamble.source_location = preamble.blocks[0].source_location if document.sourcemap
|
436
438
|
# unwrap standalone preamble (i.e., document has no sections) except for books, if permissible
|
437
|
-
|
439
|
+
else
|
438
440
|
document.blocks.shift
|
439
441
|
while (child_block = preamble.blocks.shift)
|
440
442
|
document << child_block
|
@@ -596,7 +598,8 @@ class Parser
|
|
596
598
|
end
|
597
599
|
end
|
598
600
|
if blk_ctx == :image
|
599
|
-
document.register :images,
|
601
|
+
document.register :images, target
|
602
|
+
attributes['imagesdir'] = doc_attrs['imagesdir']
|
600
603
|
# NOTE style is the value of the first positional attribute in the block attribute line
|
601
604
|
attributes['alt'] ||= style || (attributes['default-alt'] = Helpers.basename(target, true).tr('_-', ' '))
|
602
605
|
unless (scaledwidth = attributes.delete 'scaledwidth').nil_or_empty?
|
@@ -857,6 +860,7 @@ class Parser
|
|
857
860
|
when :literal
|
858
861
|
block = build_block(block_context, :verbatim, terminator, parent, reader, attributes)
|
859
862
|
when :example
|
863
|
+
attributes['caption'] = '' if attributes['collapsible-option']
|
860
864
|
block = build_block(block_context, :compound, terminator, parent, reader, attributes)
|
861
865
|
when :quote, :verse
|
862
866
|
AttributeList.rekey(attributes, [nil, 'attribution', 'citetitle'])
|
@@ -898,7 +902,7 @@ class Parser
|
|
898
902
|
# FIXME title and caption should be assigned when block is constructed (though we need to handle all cases)
|
899
903
|
if attributes['title']
|
900
904
|
block.title = block_title = attributes.delete 'title'
|
901
|
-
if (caption_attr_name =
|
905
|
+
if (caption_attr_name = CAPTION_ATTRIBUTE_NAMES[block.context]) && document.attributes[caption_attr_name]
|
902
906
|
block.assign_caption (attributes.delete 'caption')
|
903
907
|
end
|
904
908
|
end
|
@@ -1147,14 +1151,16 @@ class Parser
|
|
1147
1151
|
def self.catalog_inline_anchors text, block, document, reader
|
1148
1152
|
text.scan InlineAnchorScanRx do
|
1149
1153
|
if (id = $1)
|
1150
|
-
if (reftext = $2)
|
1151
|
-
next if (reftext.include? ATTR_REF_HEAD) && (reftext = document.sub_attributes reftext).empty?
|
1152
|
-
end
|
1154
|
+
next if (reftext = $2) && (reftext.include? ATTR_REF_HEAD) && (reftext = document.sub_attributes reftext).empty?
|
1153
1155
|
else
|
1154
1156
|
id = $3
|
1155
1157
|
if (reftext = $4)
|
1156
|
-
|
1157
|
-
|
1158
|
+
if reftext.include? ']'
|
1159
|
+
reftext = reftext.gsub '\]', ']'
|
1160
|
+
reftext = document.sub_attributes reftext if reftext.include? ATTR_REF_HEAD
|
1161
|
+
elsif (reftext.include? ATTR_REF_HEAD) && (reftext = document.sub_attributes reftext).empty?
|
1162
|
+
next
|
1163
|
+
end
|
1158
1164
|
end
|
1159
1165
|
end
|
1160
1166
|
unless document.register :refs, [id, (Inline.new block, :anchor, reftext, type: :ref, id: id)]
|
@@ -1532,7 +1538,7 @@ class Parser
|
|
1532
1538
|
|
1533
1539
|
reader.unshift_line this_line if this_line
|
1534
1540
|
|
1535
|
-
buffer
|
1541
|
+
buffer[detached_continuation] = '' if detached_continuation
|
1536
1542
|
|
1537
1543
|
until buffer.empty?
|
1538
1544
|
# strip trailing blank lines to prevent empty blocks
|
@@ -2118,6 +2124,8 @@ class Parser
|
|
2118
2124
|
name = 'sectnums'
|
2119
2125
|
elsif name == 'hardbreaks'
|
2120
2126
|
name = 'hardbreaks-option'
|
2127
|
+
elsif name == 'showtitle'
|
2128
|
+
store_attribute 'notitle', (value ? nil : ''), doc, attrs
|
2121
2129
|
end
|
2122
2130
|
|
2123
2131
|
if doc
|
@@ -2272,9 +2280,14 @@ class Parser
|
|
2272
2280
|
end
|
2273
2281
|
|
2274
2282
|
skipped = table_reader.skip_blank_lines || 0
|
2283
|
+
if attributes['header-option']
|
2284
|
+
table.has_header_option = true
|
2285
|
+
elsif skipped == 0 && !attributes['noheader-option']
|
2286
|
+
# NOTE: assume table has header until we know otherwise; if it doesn't (nil), cells in first row get reprocessed
|
2287
|
+
table.has_header_option = implicit_header = true
|
2288
|
+
end
|
2275
2289
|
parser_ctx = Table::ParserContext.new table_reader, table, attributes
|
2276
2290
|
format, loop_idx, implicit_header_boundary = parser_ctx.format, -1, nil
|
2277
|
-
implicit_header = true unless skipped > 0 || attributes['header-option'] || attributes['noheader-option']
|
2278
2291
|
|
2279
2292
|
while (line = table_reader.read_line)
|
2280
2293
|
if (beyond_first = (loop_idx += 1) > 0) && line.empty?
|
@@ -2294,7 +2307,7 @@ class Parser
|
|
2294
2307
|
implicit_header_boundary = nil if implicit_header_boundary
|
2295
2308
|
# otherwise, the cell continues from previous line
|
2296
2309
|
elsif implicit_header_boundary && implicit_header_boundary == loop_idx
|
2297
|
-
implicit_header
|
2310
|
+
table.has_header_option = implicit_header = implicit_header_boundary = nil
|
2298
2311
|
end
|
2299
2312
|
end
|
2300
2313
|
end
|
@@ -2306,7 +2319,7 @@ class Parser
|
|
2306
2319
|
if table_reader.has_more_lines? && table_reader.peek_line.empty?
|
2307
2320
|
implicit_header_boundary = 1
|
2308
2321
|
else
|
2309
|
-
implicit_header =
|
2322
|
+
table.has_header_option = implicit_header = nil
|
2310
2323
|
end
|
2311
2324
|
end
|
2312
2325
|
end
|
@@ -2357,7 +2370,7 @@ class Parser
|
|
2357
2370
|
case format
|
2358
2371
|
when 'csv'
|
2359
2372
|
if parser_ctx.buffer_has_unclosed_quotes?
|
2360
|
-
implicit_header
|
2373
|
+
table.has_header_option = implicit_header = implicit_header_boundary = nil if implicit_header_boundary && loop_idx == 0
|
2361
2374
|
parser_ctx.keep_cell_open
|
2362
2375
|
else
|
2363
2376
|
parser_ctx.close_cell true
|
@@ -2379,15 +2392,8 @@ class Parser
|
|
2379
2392
|
end
|
2380
2393
|
end
|
2381
2394
|
|
2382
|
-
unless (table.attributes['colcount'] ||= table.columns.size) == 0 || explicit_colspecs
|
2383
|
-
|
2384
|
-
end
|
2385
|
-
|
2386
|
-
if implicit_header
|
2387
|
-
table.has_header_option = true
|
2388
|
-
attributes['header-option'] = ''
|
2389
|
-
end
|
2390
|
-
|
2395
|
+
table.assign_column_widths unless (table.attributes['colcount'] ||= table.columns.size) == 0 || explicit_colspecs
|
2396
|
+
attributes['header-option'] = '' if implicit_header
|
2391
2397
|
table.partition_header_footer attributes
|
2392
2398
|
|
2393
2399
|
table
|
@@ -2578,9 +2584,7 @@ class Parser
|
|
2578
2584
|
attributes['role'] = (existing_role = attributes['role']).nil_or_empty? ? (parsed_attrs[:role].join ' ') : %(#{existing_role} #{parsed_attrs[:role].join ' '})
|
2579
2585
|
end
|
2580
2586
|
|
2581
|
-
if parsed_attrs.key? :option
|
2582
|
-
(opts = parsed_attrs[:option]).each {|opt| attributes[%(#{opt}-option)] = '' }
|
2583
|
-
end
|
2587
|
+
parsed_attrs[:option].each {|opt| attributes[%(#{opt}-option)] = '' } if parsed_attrs.key? :option
|
2584
2588
|
|
2585
2589
|
parsed_style
|
2586
2590
|
else
|
@@ -331,11 +331,12 @@ class PathResolver
|
|
331
331
|
|
332
332
|
# Public: Securely resolve a system path
|
333
333
|
#
|
334
|
-
#
|
335
|
-
#
|
336
|
-
# that
|
337
|
-
# path
|
338
|
-
#
|
334
|
+
# Resolves the target to an absolute path on the current filesystem. The target is assumed to be
|
335
|
+
# relative to the start path, jail path, or working directory (specified in the constructor), in
|
336
|
+
# that order. If a jail path is specified, the resolved path is forced to descend from the jail
|
337
|
+
# path. If a jail path is not provided, the resolved path may be any location on the system. If
|
338
|
+
# the target is an absolute path, use it as is (unless it breaches the jail path). Expands all
|
339
|
+
# parent and self references in the resolved path.
|
339
340
|
#
|
340
341
|
# target - the String target path
|
341
342
|
# start - the String start path from which to resolve a relative target; falls back to jail, if
|
@@ -347,8 +348,9 @@ class PathResolver
|
|
347
348
|
# automatically recover when an illegal path is encountered
|
348
349
|
# * :target_name is used in messages to refer to the path being resolved
|
349
350
|
#
|
350
|
-
#
|
351
|
-
# if specified. The path is posixified and all parent and self references in the path
|
351
|
+
# Returns an absolute String path relative to the start path, if specified, and confined to the
|
352
|
+
# jail path, if specified. The path is posixified and all parent and self references in the path
|
353
|
+
# are expanded.
|
352
354
|
def system_path target, start = nil, jail = nil, opts = {}
|
353
355
|
if jail
|
354
356
|
raise ::SecurityError, %(Jail is not an absolute path: #{jail}) unless root? jail
|
@@ -362,7 +364,7 @@ class PathResolver
|
|
362
364
|
if jail && !(descends_from? target_path, jail)
|
363
365
|
if opts.fetch :recover, true
|
364
366
|
logger.warn %(#{opts[:target_name] || 'path'} is outside of jail; recovering automatically)
|
365
|
-
target_segments,
|
367
|
+
target_segments, = partition_path target_path
|
366
368
|
jail_segments, jail_root = partition_path jail
|
367
369
|
return join_path jail_segments + target_segments, jail_root
|
368
370
|
else
|
@@ -371,7 +373,7 @@ class PathResolver
|
|
371
373
|
end
|
372
374
|
return target_path
|
373
375
|
else
|
374
|
-
target_segments,
|
376
|
+
target_segments, = partition_path target
|
375
377
|
end
|
376
378
|
else
|
377
379
|
target_segments = []
|
@@ -387,7 +389,7 @@ class PathResolver
|
|
387
389
|
return expand_path start
|
388
390
|
end
|
389
391
|
else
|
390
|
-
target_segments,
|
392
|
+
target_segments, = partition_path start
|
391
393
|
start = jail || @working_dir
|
392
394
|
end
|
393
395
|
elsif start.nil_or_empty?
|
@@ -419,7 +421,7 @@ class PathResolver
|
|
419
421
|
if (resolved_segments = start_segments + target_segments).include? DOT_DOT
|
420
422
|
unresolved_segments, resolved_segments = resolved_segments, []
|
421
423
|
if jail
|
422
|
-
jail_segments,
|
424
|
+
jail_segments, = partition_path jail unless jail_segments
|
423
425
|
warned = false
|
424
426
|
unresolved_segments.each do |segment|
|
425
427
|
if segment == DOT_DOT
|
@@ -450,7 +452,7 @@ class PathResolver
|
|
450
452
|
target_path
|
451
453
|
elsif opts.fetch :recover, true
|
452
454
|
logger.warn %(#{opts[:target_name] || 'path'} is outside of jail; recovering automatically)
|
453
|
-
jail_segments,
|
455
|
+
jail_segments, = partition_path jail unless jail_segments
|
454
456
|
join_path jail_segments + target_segments, jail_root
|
455
457
|
else
|
456
458
|
raise ::SecurityError, %(#{opts[:target_name] || 'path'} #{target} is outside of jail: #{jail} (disallowed in safe mode))
|
@@ -476,25 +478,15 @@ class PathResolver
|
|
476
478
|
def web_path target, start = nil
|
477
479
|
target = posixify target
|
478
480
|
start = posixify start
|
479
|
-
uri_prefix = nil
|
480
481
|
|
481
482
|
unless start.nil_or_empty? || (web_root? target)
|
482
|
-
target = (start.end_with? SLASH) ?
|
483
|
-
if (uri_prefix = Helpers.uri_prefix target)
|
484
|
-
target = target[uri_prefix.length..-1]
|
485
|
-
end
|
483
|
+
target, uri_prefix = extract_uri_prefix %(#{start}#{(start.end_with? SLASH) ? '' : SLASH}#{target})
|
486
484
|
end
|
487
485
|
|
488
486
|
# use this logic instead if we want to normalize target if it contains a URI
|
489
487
|
#unless web_root? target
|
490
|
-
#
|
491
|
-
#
|
492
|
-
# elsif !start.nil_or_empty?
|
493
|
-
# target = %(#{start}#{SLASH}#{target})
|
494
|
-
# if (uri_prefix = Helpers.uri_prefix target)
|
495
|
-
# target = target[uri_prefix.length..-1]
|
496
|
-
# end
|
497
|
-
# end
|
488
|
+
# target, uri_prefix = extract_uri_prefix target if preserve_uri_target
|
489
|
+
# target, uri_prefix = extract_uri_prefix %(#{start}#{SLASH}#{target}) unless uri_prefix || start.nil_or_empty?
|
498
490
|
#end
|
499
491
|
|
500
492
|
target_segments, target_root = partition_path target, true
|
@@ -521,5 +513,23 @@ class PathResolver
|
|
521
513
|
|
522
514
|
uri_prefix ? %(#{uri_prefix}#{resolved_path}) : resolved_path
|
523
515
|
end
|
516
|
+
|
517
|
+
private
|
518
|
+
|
519
|
+
# Internal: Efficiently extracts the URI prefix from the specified String if the String is a URI
|
520
|
+
#
|
521
|
+
# Uses the Asciidoctor::UriSniffRx regex to match the URI prefix in the specified String (e.g., http://). If present,
|
522
|
+
# the prefix is removed.
|
523
|
+
#
|
524
|
+
# str - the String to check
|
525
|
+
#
|
526
|
+
# returns a tuple containing the specified string without the URI prefix, if present, and the extracted URI prefix.
|
527
|
+
def extract_uri_prefix str
|
528
|
+
if (str.include? ':') && UriSniffRx =~ str
|
529
|
+
[(str.slice $&.length, str.length), $&]
|
530
|
+
else
|
531
|
+
str
|
532
|
+
end
|
533
|
+
end
|
524
534
|
end
|
525
535
|
end
|
data/lib/asciidoctor/reader.rb
CHANGED
@@ -570,17 +570,18 @@ class Reader
|
|
570
570
|
#
|
571
571
|
# data - A String Array or String of source data to be normalized.
|
572
572
|
# opts - A Hash of options to control how lines are prepared.
|
573
|
-
# :normalize - Enables line normalization, which coerces the encoding to UTF-8 and removes trailing whitespace
|
574
|
-
# (optional,
|
573
|
+
# :normalize - Enables line normalization, which coerces the encoding to UTF-8 and removes trailing whitespace;
|
574
|
+
# :rstrip removes all trailing whitespace; :chomp removes trailing newline only (optional, not set).
|
575
575
|
#
|
576
576
|
# Returns A String Array of source lines. If the source data is an Array, this method returns a copy.
|
577
577
|
def prepare_lines data, opts = {}
|
578
|
-
if opts[:normalize]
|
579
|
-
|
578
|
+
if (normalize = opts[:normalize])
|
579
|
+
trim_end = normalize == :chomp ? false : true
|
580
|
+
::Array === data ? (Helpers.prepare_source_array data, trim_end) : (Helpers.prepare_source_string data, trim_end)
|
580
581
|
elsif ::Array === data
|
581
582
|
data.drop 0
|
582
583
|
elsif data
|
583
|
-
data.split LF, -1
|
584
|
+
data.chomp.split LF, -1
|
584
585
|
else
|
585
586
|
[]
|
586
587
|
end
|
@@ -717,7 +718,7 @@ class PreprocessorReader < Reader
|
|
717
718
|
end
|
718
719
|
|
719
720
|
# effectively fill the buffer
|
720
|
-
if (@lines = prepare_lines data, normalize:
|
721
|
+
if (@lines = prepare_lines data, normalize: @process_lines || :chomp, condense: @process_lines, indent: attributes['indent']).empty?
|
721
722
|
pop_include
|
722
723
|
else
|
723
724
|
# FIXME we eventually want to handle leveloffset without affecting the lines
|
@@ -1060,7 +1061,13 @@ class PreprocessorReader < Reader
|
|
1060
1061
|
return inc_path
|
1061
1062
|
end
|
1062
1063
|
|
1064
|
+
if (enc = parsed_attrs['encoding']) && (::Encoding.find enc rescue nil)
|
1065
|
+
(read_mode_params = read_mode.split ':')[1] = enc
|
1066
|
+
read_mode = read_mode_params.join ':'
|
1067
|
+
end unless RUBY_ENGINE_OPAL
|
1068
|
+
|
1063
1069
|
inc_linenos = inc_tags = nil
|
1070
|
+
# NOTE attrlist is nil if missing from include directive
|
1064
1071
|
if attrlist
|
1065
1072
|
if parsed_attrs.key? 'lines'
|
1066
1073
|
inc_linenos = []
|
@@ -1148,7 +1155,7 @@ class PreprocessorReader < Reader
|
|
1148
1155
|
active_tag, select = tag_stack.empty? ? [nil, base_select] : tag_stack[-1]
|
1149
1156
|
elsif inc_tags.key? this_tag
|
1150
1157
|
include_cursor = create_include_cursor inc_path, expanded_target, inc_lineno
|
1151
|
-
if (idx = tag_stack.rindex {|key
|
1158
|
+
if (idx = tag_stack.rindex {|key,| key == this_tag })
|
1152
1159
|
idx == 0 ? tag_stack.shift : (tag_stack.delete_at idx)
|
1153
1160
|
logger.warn message_with_context %(mismatched end tag (expected '#{active_tag}' but found '#{this_tag}') at line #{inc_lineno} of include #{target_type}: #{inc_path}), source_location: cursor, include_location: include_cursor
|
1154
1161
|
else
|
@@ -0,0 +1,722 @@
|
|
1
|
+
module Asciidoctor
|
2
|
+
# A collection of regular expression constants used by the parser. (For speed, these are not defined in the Rx module,
|
3
|
+
# but rather directly in the Asciidoctor module).
|
4
|
+
#
|
5
|
+
# NOTE The following pattern, which appears frequently, captures the contents between square brackets, ignoring
|
6
|
+
# escaped closing brackets (closing brackets prefixed with a backslash '\' character)
|
7
|
+
#
|
8
|
+
# Pattern: \[(|#{CC_ALL}*?[^\\])\]
|
9
|
+
# Matches: [enclosed text] and [enclosed [text\]], not [enclosed text \\] or [\\] (as these require a trailing space)
|
10
|
+
module Rx; end
|
11
|
+
|
12
|
+
## Document header
|
13
|
+
|
14
|
+
# Matches the author info line immediately following the document title.
|
15
|
+
#
|
16
|
+
# Examples
|
17
|
+
#
|
18
|
+
# Doc Writer <doc@example.com>
|
19
|
+
# Mary_Sue Brontë
|
20
|
+
#
|
21
|
+
AuthorInfoLineRx = /^(#{CG_WORD}[#{CC_WORD}\-'.]*)(?: +(#{CG_WORD}[#{CC_WORD}\-'.]*))?(?: +(#{CG_WORD}[#{CC_WORD}\-'.]*))?(?: +<([^>]+)>)?$/
|
22
|
+
|
23
|
+
# Matches the delimiter that separates multiple authors.
|
24
|
+
#
|
25
|
+
# Examples
|
26
|
+
#
|
27
|
+
# Doc Writer; Junior Writer
|
28
|
+
#
|
29
|
+
AuthorDelimiterRx = /;(?: |$)/
|
30
|
+
|
31
|
+
# Matches the revision info line, which appears immediately following
|
32
|
+
# the author info line beneath the document title.
|
33
|
+
#
|
34
|
+
# Examples
|
35
|
+
#
|
36
|
+
# v1.0
|
37
|
+
# 2013-01-01
|
38
|
+
# v1.0, 2013-01-01: Ring in the new year release
|
39
|
+
# 1.0, Jan 01, 2013
|
40
|
+
#
|
41
|
+
RevisionInfoLineRx = /^(?:[^\d{]*(#{CC_ANY}*?),)? *(?!:)(#{CC_ANY}*?)(?: *(?!^),?: *(#{CC_ANY}*))?$/
|
42
|
+
|
43
|
+
# Matches the title and volnum in the manpage doctype.
|
44
|
+
#
|
45
|
+
# Examples
|
46
|
+
#
|
47
|
+
# = asciidoctor(1)
|
48
|
+
# = asciidoctor ( 1 )
|
49
|
+
#
|
50
|
+
ManpageTitleVolnumRx = /^(#{CC_ANY}+?) *\( *(#{CC_ANY}+?) *\)$/
|
51
|
+
|
52
|
+
# Matches the name and purpose in the manpage doctype.
|
53
|
+
#
|
54
|
+
# Examples
|
55
|
+
#
|
56
|
+
# asciidoctor - converts AsciiDoc source files to HTML, DocBook and other formats
|
57
|
+
#
|
58
|
+
ManpageNamePurposeRx = /^(#{CC_ANY}+?) +- +(#{CC_ANY}+)$/
|
59
|
+
|
60
|
+
## Preprocessor directives
|
61
|
+
|
62
|
+
# Matches a conditional preprocessor directive (e.g., ifdef, ifndef, ifeval and endif).
|
63
|
+
#
|
64
|
+
# Examples
|
65
|
+
#
|
66
|
+
# ifdef::basebackend-html[]
|
67
|
+
# ifndef::theme[]
|
68
|
+
# ifeval::["{asciidoctor-version}" >= "0.1.0"]
|
69
|
+
# ifdef::asciidoctor[Asciidoctor!]
|
70
|
+
# endif::theme[]
|
71
|
+
# endif::basebackend-html[]
|
72
|
+
# endif::[]
|
73
|
+
#
|
74
|
+
ConditionalDirectiveRx = /^(\\)?(ifdef|ifndef|ifeval|endif)::(\S*?(?:([,+])\S*?)?)\[(#{CC_ANY}+)?\]$/
|
75
|
+
|
76
|
+
# Matches a restricted (read as safe) eval expression.
|
77
|
+
#
|
78
|
+
# Examples
|
79
|
+
#
|
80
|
+
# "{asciidoctor-version}" >= "0.1.0"
|
81
|
+
#
|
82
|
+
EvalExpressionRx = /^(#{CC_ANY}+?) *([=!><]=|[><]) *(#{CC_ANY}+)$/
|
83
|
+
|
84
|
+
# Matches an include preprocessor directive.
|
85
|
+
#
|
86
|
+
# Examples
|
87
|
+
#
|
88
|
+
# include::chapter1.ad[]
|
89
|
+
# include::example.txt[lines=1;2;5..10]
|
90
|
+
#
|
91
|
+
IncludeDirectiveRx = /^(\\)?include::([^\[][^\[]*)\[(#{CC_ANY}+)?\]$/
|
92
|
+
|
93
|
+
# Matches a trailing tag directive in an include file.
|
94
|
+
#
|
95
|
+
# Examples
|
96
|
+
#
|
97
|
+
# // tag::try-catch[]
|
98
|
+
# try {
|
99
|
+
# someMethod();
|
100
|
+
# catch (Exception e) {
|
101
|
+
# log(e);
|
102
|
+
# }
|
103
|
+
# // end::try-catch[]
|
104
|
+
# NOTE m flag is required for Asciidoctor.js
|
105
|
+
TagDirectiveRx = /\b(?:tag|(e)nd)::(\S+?)\[\](?=$|[ \r])/m
|
106
|
+
|
107
|
+
## Attribute entries and references
|
108
|
+
|
109
|
+
# Matches a document attribute entry.
|
110
|
+
#
|
111
|
+
# Examples
|
112
|
+
#
|
113
|
+
# :foo: bar
|
114
|
+
# :First Name: Dan
|
115
|
+
# :sectnums!:
|
116
|
+
# :!toc:
|
117
|
+
# :long-entry: Attribute value lines ending in ' \' \
|
118
|
+
# are joined together as a single value, \
|
119
|
+
# collapsing the line breaks and indentation to \
|
120
|
+
# a single space.
|
121
|
+
#
|
122
|
+
AttributeEntryRx = /^:(!?#{CG_WORD}[^:]*):(?:[ \t]+(#{CC_ANY}*))?$/
|
123
|
+
|
124
|
+
# Matches invalid characters in an attribute name.
|
125
|
+
InvalidAttributeNameCharsRx = /[^#{CC_WORD}-]/
|
126
|
+
|
127
|
+
# Matches a pass inline macro that surrounds the value of an attribute
|
128
|
+
# entry once it has been parsed.
|
129
|
+
#
|
130
|
+
# Examples
|
131
|
+
#
|
132
|
+
# pass:[text]
|
133
|
+
# pass:a[{a} {b} {c}]
|
134
|
+
#
|
135
|
+
if RUBY_ENGINE == 'opal'
|
136
|
+
# NOTE In JavaScript, ^ and $ match the boundaries of the string when the m flag is not set
|
137
|
+
AttributeEntryPassMacroRx = /^pass:([a-z]+(?:,[a-z-]+)*)?\[(#{CC_ALL}*)\]$/
|
138
|
+
else
|
139
|
+
AttributeEntryPassMacroRx = /\Apass:([a-z]+(?:,[a-z-]+)*)?\[(.*)\]\Z/m
|
140
|
+
end
|
141
|
+
|
142
|
+
# Matches an inline attribute reference.
|
143
|
+
#
|
144
|
+
# Examples
|
145
|
+
#
|
146
|
+
# {foobar} or {app_name} or {product-version}
|
147
|
+
# {counter:sequence-name:1}
|
148
|
+
# {set:foo:bar}
|
149
|
+
# {set:name!}
|
150
|
+
#
|
151
|
+
AttributeReferenceRx = /(\\)?\{(#{CG_WORD}[#{CC_WORD}-]*|(set|counter2?):#{CC_ANY}+?)(\\)?\}/
|
152
|
+
|
153
|
+
## Paragraphs and delimited blocks
|
154
|
+
|
155
|
+
# Matches an anchor (i.e., id + optional reference text) on a line above a block.
|
156
|
+
#
|
157
|
+
# Examples
|
158
|
+
#
|
159
|
+
# [[idname]]
|
160
|
+
# [[idname,Reference Text]]
|
161
|
+
#
|
162
|
+
BlockAnchorRx = /^\[\[(?:|([#{CC_ALPHA}_:][#{CC_WORD}\-:.]*)(?:, *(#{CC_ANY}+))?)\]\]$/
|
163
|
+
|
164
|
+
# Matches an attribute list above a block element.
|
165
|
+
#
|
166
|
+
# Examples
|
167
|
+
#
|
168
|
+
# # strictly positional
|
169
|
+
# [quote, Adam Smith, Wealth of Nations]
|
170
|
+
#
|
171
|
+
# # name/value pairs
|
172
|
+
# [NOTE, caption="Good to know"]
|
173
|
+
#
|
174
|
+
# # as attribute reference
|
175
|
+
# [{lead}]
|
176
|
+
#
|
177
|
+
BlockAttributeListRx = /^\[(|[#{CC_WORD}.#%{,"']#{CC_ANY}*)\]$/
|
178
|
+
|
179
|
+
# A combined pattern that matches either a block anchor or a block attribute list.
|
180
|
+
#
|
181
|
+
# TODO this one gets hit a lot, should be optimized as much as possible
|
182
|
+
BlockAttributeLineRx = /^\[(?:|[#{CC_WORD}.#%{,"']#{CC_ANY}*|\[(?:|[#{CC_ALPHA}_:][#{CC_WORD}\-:.]*(?:, *#{CC_ANY}+)?)\])\]$/
|
183
|
+
|
184
|
+
# Matches a title above a block.
|
185
|
+
#
|
186
|
+
# Examples
|
187
|
+
#
|
188
|
+
# .Title goes here
|
189
|
+
#
|
190
|
+
BlockTitleRx = /^\.(\.?[^ \t.]#{CC_ANY}*)$/
|
191
|
+
|
192
|
+
# Matches an admonition label at the start of a paragraph.
|
193
|
+
#
|
194
|
+
# Examples
|
195
|
+
#
|
196
|
+
# NOTE: Just a little note.
|
197
|
+
# TIP: Don't forget!
|
198
|
+
#
|
199
|
+
AdmonitionParagraphRx = /^(#{ADMONITION_STYLES.to_a.join '|'}):[ \t]+/
|
200
|
+
|
201
|
+
# Matches a literal paragraph, which is a line of text preceded by at least one space.
|
202
|
+
#
|
203
|
+
# Examples
|
204
|
+
#
|
205
|
+
# <SPACE>Foo
|
206
|
+
# <TAB>Foo
|
207
|
+
LiteralParagraphRx = /^([ \t]+#{CC_ANY}*)$/
|
208
|
+
|
209
|
+
# Matches a comment block.
|
210
|
+
#
|
211
|
+
# Examples
|
212
|
+
#
|
213
|
+
# ////
|
214
|
+
# This is a block comment.
|
215
|
+
# It can span one or more lines.
|
216
|
+
# ////
|
217
|
+
#CommentBlockRx = %r(^/{4,}$)
|
218
|
+
|
219
|
+
# Matches a comment line.
|
220
|
+
#
|
221
|
+
# Examples
|
222
|
+
#
|
223
|
+
# // note to author
|
224
|
+
#
|
225
|
+
#CommentLineRx = %r(^//(?=[^/]|$))
|
226
|
+
|
227
|
+
## Section titles
|
228
|
+
|
229
|
+
# Matches an Atx (single-line) section title.
|
230
|
+
#
|
231
|
+
# Examples
|
232
|
+
#
|
233
|
+
# == Foo
|
234
|
+
# // ^ a level 1 (h2) section title
|
235
|
+
#
|
236
|
+
# == Foo ==
|
237
|
+
# // ^ also a level 1 (h2) section title
|
238
|
+
#
|
239
|
+
AtxSectionTitleRx = /^(=={0,5})[ \t]+(#{CC_ANY}+?)(?:[ \t]+\1)?$/
|
240
|
+
|
241
|
+
# Matches an extended Atx section title that includes support for the Markdown variant.
|
242
|
+
ExtAtxSectionTitleRx = /^(=={0,5}|#\#{0,5})[ \t]+(#{CC_ANY}+?)(?:[ \t]+\1)?$/
|
243
|
+
|
244
|
+
# Matches the title only (first line) of an Setext (two-line) section title.
|
245
|
+
# The title cannot begin with a dot and must have at least one alphanumeric character.
|
246
|
+
SetextSectionTitleRx = /^((?!\.)#{CC_ANY}*?#{CG_ALNUM}#{CC_ANY}*)$/
|
247
|
+
|
248
|
+
# Matches an anchor (i.e., id + optional reference text) inside a section title.
|
249
|
+
#
|
250
|
+
# Examples
|
251
|
+
#
|
252
|
+
# Section Title [[idname]]
|
253
|
+
# Section Title [[idname,Reference Text]]
|
254
|
+
#
|
255
|
+
InlineSectionAnchorRx = / (\\)?\[\[([#{CC_ALPHA}_:][#{CC_WORD}\-:.]*)(?:, *(#{CC_ANY}+))?\]\]$/
|
256
|
+
|
257
|
+
# Matches invalid ID characters in a section title.
|
258
|
+
#
|
259
|
+
# NOTE uppercase chars not included since expression is only run on a lowercase string
|
260
|
+
InvalidSectionIdCharsRx = /<[^>]+>|&(?:[a-z][a-z]+\d{0,2}|#\d\d\d{0,4}|#x[\da-f][\da-f][\da-f]{0,3});|[^ #{CC_WORD}\-.]+?/
|
261
|
+
|
262
|
+
# Matches an explicit section level style like sect1
|
263
|
+
#
|
264
|
+
SectionLevelStyleRx = /^sect\d$/
|
265
|
+
|
266
|
+
## Lists
|
267
|
+
|
268
|
+
# Detects the start of any list item.
|
269
|
+
#
|
270
|
+
# NOTE we only have to check as far as the blank character because we know it means non-whitespace follows.
|
271
|
+
# IMPORTANT if this regexp does not agree with the regexp for each list type, the parser will hang.
|
272
|
+
AnyListRx = %r(^(?:[ \t]*(?:-|\*\**|\.\.*|\u2022|\d+\.|[a-zA-Z]\.|[IVXivx]+\))[ \t]|(?!//[^/])[ \t]*[^ \t]#{CC_ANY}*?(?::::{0,2}|;;)(?:$|[ \t])|<(?:\d+|\.)>[ \t]))
|
273
|
+
|
274
|
+
# Matches an unordered list item (one level for hyphens, up to 5 levels for asterisks).
|
275
|
+
#
|
276
|
+
# Examples
|
277
|
+
#
|
278
|
+
# * Foo
|
279
|
+
# - Foo
|
280
|
+
#
|
281
|
+
# NOTE we know trailing (.*) will match at least one character because we strip trailing spaces
|
282
|
+
UnorderedListRx = /^[ \t]*(-|\*\**|\u2022)[ \t]+(#{CC_ANY}*)$/
|
283
|
+
|
284
|
+
# Matches an ordered list item (explicit numbering or up to 5 consecutive dots).
|
285
|
+
#
|
286
|
+
# Examples
|
287
|
+
#
|
288
|
+
# . Foo
|
289
|
+
# .. Foo
|
290
|
+
# 1. Foo (arabic, default)
|
291
|
+
# a. Foo (loweralpha)
|
292
|
+
# A. Foo (upperalpha)
|
293
|
+
# i. Foo (lowerroman)
|
294
|
+
# I. Foo (upperroman)
|
295
|
+
#
|
296
|
+
# NOTE leading space match is not always necessary, but is used for list reader
|
297
|
+
# NOTE we know trailing (.*) will match at least one character because we strip trailing spaces
|
298
|
+
OrderedListRx = /^[ \t]*(\.\.*|\d+\.|[a-zA-Z]\.|[IVXivx]+\))[ \t]+(#{CC_ANY}*)$/
|
299
|
+
|
300
|
+
# Matches the ordinals for each type of ordered list.
|
301
|
+
OrderedListMarkerRxMap = {
|
302
|
+
arabic: /\d+\./,
|
303
|
+
loweralpha: /[a-z]\./,
|
304
|
+
lowerroman: /[ivx]+\)/,
|
305
|
+
upperalpha: /[A-Z]\./,
|
306
|
+
upperroman: /[IVX]+\)/,
|
307
|
+
#lowergreek: /[a-z]\]/,
|
308
|
+
}
|
309
|
+
|
310
|
+
# Matches a description list entry.
|
311
|
+
#
|
312
|
+
# Examples
|
313
|
+
#
|
314
|
+
# foo::
|
315
|
+
# bar:::
|
316
|
+
# baz::::
|
317
|
+
# blah;;
|
318
|
+
#
|
319
|
+
# # the term may be followed by a description on the same line...
|
320
|
+
#
|
321
|
+
# foo:: The metasyntactic variable that commonly accompanies 'bar' (see also, <<bar>>).
|
322
|
+
#
|
323
|
+
# # ...or on a separate line, which may optionally be indented
|
324
|
+
#
|
325
|
+
# foo::
|
326
|
+
# The metasyntactic variable that commonly accompanies 'bar' (see also, <<bar>>).
|
327
|
+
#
|
328
|
+
# # attribute references may be used in both the term and the description
|
329
|
+
#
|
330
|
+
# {foo-term}:: {foo-desc}
|
331
|
+
#
|
332
|
+
# NOTE we know trailing (.*) will match at least one character because we strip trailing spaces
|
333
|
+
# NOTE must skip line comment when looking for next list item inside list
|
334
|
+
DescriptionListRx = %r(^(?!//[^/])[ \t]*([^ \t]#{CC_ANY}*?)(:::{0,2}|;;)(?:$|[ \t]+(#{CC_ANY}*)$))
|
335
|
+
|
336
|
+
# Matches a sibling description list item (excluding the delimiter specified by the key).
|
337
|
+
# NOTE must skip line comment when looking for sibling list item
|
338
|
+
DescriptionListSiblingRx = {
|
339
|
+
'::' => %r(^(?!//[^/])[ \t]*([^ \t]#{CC_ANY}*?[^:]|[^ \t:])(::)(?:$|[ \t]+(#{CC_ANY}*)$)),
|
340
|
+
':::' => %r(^(?!//[^/])[ \t]*([^ \t]#{CC_ANY}*?[^:]|[^ \t:])(:::)(?:$|[ \t]+(#{CC_ANY}*)$)),
|
341
|
+
'::::' => %r(^(?!//[^/])[ \t]*([^ \t]#{CC_ANY}*?[^:]|[^ \t:])(::::)(?:$|[ \t]+(#{CC_ANY}*)$)),
|
342
|
+
';;' => %r(^(?!//[^/])[ \t]*([^ \t]#{CC_ANY}*?)(;;)(?:$|[ \t]+(#{CC_ANY}*)$))
|
343
|
+
}
|
344
|
+
|
345
|
+
# Matches a callout list item.
|
346
|
+
#
|
347
|
+
# Examples
|
348
|
+
#
|
349
|
+
# <1> Explanation
|
350
|
+
#
|
351
|
+
# or
|
352
|
+
#
|
353
|
+
# <.> Explanation with automatic number
|
354
|
+
#
|
355
|
+
# NOTE we know trailing (.*) will match at least one character because we strip trailing spaces
|
356
|
+
CalloutListRx = /^<(\d+|\.)>[ \t]+(#{CC_ANY}*)$/
|
357
|
+
|
358
|
+
# Matches a callout reference inside literal text.
|
359
|
+
#
|
360
|
+
# Examples
|
361
|
+
# <1> (optionally prefixed by //, #, -- or ;; line comment chars)
|
362
|
+
# <1> <2> (multiple callouts on one line)
|
363
|
+
# <!--1--> (for XML-based languages)
|
364
|
+
# <.> (auto-numbered)
|
365
|
+
#
|
366
|
+
# NOTE extract regexps are applied line-by-line, so we can use $ as end-of-line char
|
367
|
+
CalloutExtractRx = %r(((?://|#|--|;;) ?)?(\\)?<!?(|--)(\d+|\.)\3>(?=(?: ?\\?<!?\3(?:\d+|\.)\3>)*$))
|
368
|
+
CalloutExtractRxt = '(\\\\)?<()(\\d+|\\.)>(?=(?: ?\\\\?<(?:\\d+|\\.)>)*$)'
|
369
|
+
CalloutExtractRxMap = ::Hash.new {|h, k| h[k] = /(#{k.empty? ? '' : "#{::Regexp.escape k} ?"})?#{CalloutExtractRxt}/ }
|
370
|
+
# NOTE special characters have not been replaced when scanning
|
371
|
+
CalloutScanRx = /\\?<!?(|--)(\d+|\.)\1>(?=(?: ?\\?<!?\1(?:\d+|\.)\1>)*#{CC_EOL})/
|
372
|
+
# NOTE special characters have already been replaced when converting to an SGML format
|
373
|
+
CalloutSourceRx = %r(((?://|#|--|;;) ?)?(\\)?<!?(|--)(\d+|\.)\3>(?=(?: ?\\?<!?\3(?:\d+|\.)\3>)*#{CC_EOL}))
|
374
|
+
CalloutSourceRxt = "(\\\\)?<()(\\d+|\\.)>(?=(?: ?\\\\?<(?:\\d+|\\.)>)*#{CC_EOL})"
|
375
|
+
CalloutSourceRxMap = ::Hash.new {|h, k| h[k] = /(#{k.empty? ? '' : "#{::Regexp.escape k} ?"})?#{CalloutSourceRxt}/ }
|
376
|
+
|
377
|
+
# A Hash of regexps for lists used for dynamic access.
|
378
|
+
ListRxMap = { ulist: UnorderedListRx, olist: OrderedListRx, dlist: DescriptionListRx, colist: CalloutListRx }
|
379
|
+
|
380
|
+
## Tables
|
381
|
+
|
382
|
+
# Parses the column spec (i.e., colspec) for a table.
|
383
|
+
#
|
384
|
+
# Examples
|
385
|
+
#
|
386
|
+
# 1*h,2*,^3e
|
387
|
+
#
|
388
|
+
ColumnSpecRx = /^(?:(\d+)\*)?([<^>](?:\.[<^>]?)?|(?:[<^>]?\.)?[<^>])?(\d+%?|~)?([a-z])?$/
|
389
|
+
|
390
|
+
# Parses the start and end of a cell spec (i.e., cellspec) for a table.
|
391
|
+
#
|
392
|
+
# Examples
|
393
|
+
#
|
394
|
+
# 2.3+<.>m
|
395
|
+
#
|
396
|
+
# FIXME use step-wise scan (or treetop) rather than this mega-regexp
|
397
|
+
CellSpecStartRx = /^[ \t]*(?:(\d+(?:\.\d*)?|(?:\d*\.)?\d+)([*+]))?([<^>](?:\.[<^>]?)?|(?:[<^>]?\.)?[<^>])?([a-z])?$/
|
398
|
+
CellSpecEndRx = /[ \t]+(?:(\d+(?:\.\d*)?|(?:\d*\.)?\d+)([*+]))?([<^>](?:\.[<^>]?)?|(?:[<^>]?\.)?[<^>])?([a-z])?$/
|
399
|
+
|
400
|
+
# Block macros
|
401
|
+
|
402
|
+
# Matches the custom block macro pattern.
|
403
|
+
#
|
404
|
+
# Examples
|
405
|
+
#
|
406
|
+
# gist::123456[]
|
407
|
+
#
|
408
|
+
#--
|
409
|
+
# NOTE we've relaxed the match for target to accomodate the short format (e.g., name::[attrlist])
|
410
|
+
CustomBlockMacroRx = /^(#{CG_WORD}[#{CC_WORD}-]*)::(|\S|\S#{CC_ANY}*?\S)\[(#{CC_ANY}+)?\]$/
|
411
|
+
|
412
|
+
# Matches an image, video or audio block macro.
|
413
|
+
#
|
414
|
+
# Examples
|
415
|
+
#
|
416
|
+
# image::filename.png[Caption]
|
417
|
+
# video::http://youtube.com/12345[Cats vs Dogs]
|
418
|
+
#
|
419
|
+
BlockMediaMacroRx = /^(image|video|audio)::(\S|\S#{CC_ANY}*?\S)\[(#{CC_ANY}+)?\]$/
|
420
|
+
|
421
|
+
# Matches the TOC block macro.
|
422
|
+
#
|
423
|
+
# Examples
|
424
|
+
#
|
425
|
+
# toc::[]
|
426
|
+
# toc::[levels=2]
|
427
|
+
#
|
428
|
+
BlockTocMacroRx = /^toc::\[(#{CC_ANY}+)?\]$/
|
429
|
+
|
430
|
+
## Inline macros
|
431
|
+
|
432
|
+
# Matches an anchor (i.e., id + optional reference text) in the flow of text.
|
433
|
+
#
|
434
|
+
# Examples
|
435
|
+
#
|
436
|
+
# [[idname]]
|
437
|
+
# [[idname,Reference Text]]
|
438
|
+
# anchor:idname[]
|
439
|
+
# anchor:idname[Reference Text]
|
440
|
+
#
|
441
|
+
InlineAnchorRx = /(\\)?(?:\[\[([#{CC_ALPHA}_:][#{CC_WORD}\-:.]*)(?:, *(#{CC_ANY}+?))?\]\]|anchor:([#{CC_ALPHA}_:][#{CC_WORD}\-:.]*)\[(?:\]|(#{CC_ANY}*?[^\\])\]))/
|
442
|
+
|
443
|
+
# Scans for a non-escaped anchor (i.e., id + optional reference text) in the flow of text.
|
444
|
+
InlineAnchorScanRx = /(?:^|[^\\\[])\[\[([#{CC_ALPHA}_:][#{CC_WORD}\-:.]*)(?:, *(#{CC_ANY}+?))?\]\]|(?:^|[^\\])anchor:([#{CC_ALPHA}_:][#{CC_WORD}\-:.]*)\[(?:\]|(#{CC_ANY}*?[^\\])\])/
|
445
|
+
|
446
|
+
# Scans for a leading, non-escaped anchor (i.e., id + optional reference text).
|
447
|
+
LeadingInlineAnchorRx = /^\[\[([#{CC_ALPHA}_:][#{CC_WORD}\-:.]*)(?:, *(#{CC_ANY}+?))?\]\]/
|
448
|
+
|
449
|
+
# Matches a bibliography anchor at the start of the list item text (in a bibliography list).
|
450
|
+
#
|
451
|
+
# Examples
|
452
|
+
#
|
453
|
+
# [[[Fowler_1997]]] Fowler M. ...
|
454
|
+
#
|
455
|
+
InlineBiblioAnchorRx = /^\[\[\[([#{CC_ALPHA}_:][#{CC_WORD}\-:.]*)(?:, *(#{CC_ANY}+?))?\]\]\]/
|
456
|
+
|
457
|
+
# Matches an inline e-mail address.
|
458
|
+
#
|
459
|
+
# doc.writer@example.com
|
460
|
+
#
|
461
|
+
InlineEmailRx = %r(([\\>:/])?#{CG_WORD}(?:&|[#{CC_WORD}\-.%+])*@#{CG_ALNUM}[#{CC_ALNUM}_\-.]*\.[a-zA-Z]{2,5}\b)
|
462
|
+
|
463
|
+
# Matches an inline footnote macro, which is allowed to span multiple lines.
|
464
|
+
#
|
465
|
+
# Examples
|
466
|
+
# footnote:[text] (not referenceable)
|
467
|
+
# footnote:id[text] (referenceable)
|
468
|
+
# footnote:id[] (reference)
|
469
|
+
# footnoteref:[id,text] (legacy)
|
470
|
+
# footnoteref:[id] (legacy)
|
471
|
+
#
|
472
|
+
InlineFootnoteMacroRx = /\\?footnote(?:(ref):|:([#{CC_WORD}-]+)?)\[(?:|(#{CC_ALL}*?[^\\]))\](?!<\/a>)/m
|
473
|
+
|
474
|
+
# Matches an image or icon inline macro.
|
475
|
+
#
|
476
|
+
# Examples
|
477
|
+
#
|
478
|
+
# image:filename.png[Alt Text]
|
479
|
+
# image:http://example.com/images/filename.png[Alt Text]
|
480
|
+
# image:filename.png[More [Alt\] Text] (alt text becomes "More [Alt] Text")
|
481
|
+
# icon:github[large]
|
482
|
+
#
|
483
|
+
# NOTE be as non-greedy as possible by not allowing newline or left square bracket in target
|
484
|
+
InlineImageMacroRx = /\\?i(?:mage|con):([^:\s\[](?:[^\n\[]*[^\s\[])?)\[(|#{CC_ALL}*?[^\\])\]/m
|
485
|
+
|
486
|
+
# Matches an indexterm inline macro, which may span multiple lines.
|
487
|
+
#
|
488
|
+
# Examples
|
489
|
+
#
|
490
|
+
# indexterm:[Tigers,Big cats]
|
491
|
+
# (((Tigers,Big cats)))
|
492
|
+
# indexterm2:[Tigers]
|
493
|
+
# ((Tigers))
|
494
|
+
#
|
495
|
+
InlineIndextermMacroRx = /\\?(?:(indexterm2?):\[(#{CC_ALL}*?[^\\])\]|\(\((#{CC_ALL}+?)\)\)(?!\)))/m
|
496
|
+
|
497
|
+
# Matches either the kbd or btn inline macro.
|
498
|
+
#
|
499
|
+
# Examples
|
500
|
+
#
|
501
|
+
# kbd:[F3]
|
502
|
+
# kbd:[Ctrl+Shift+T]
|
503
|
+
# kbd:[Ctrl+\]]
|
504
|
+
# kbd:[Ctrl,T]
|
505
|
+
# btn:[Save]
|
506
|
+
#
|
507
|
+
InlineKbdBtnMacroRx = /(\\)?(kbd|btn):\[(#{CC_ALL}*?[^\\])\]/m
|
508
|
+
|
509
|
+
# Matches an implicit link and some of the link inline macro.
|
510
|
+
#
|
511
|
+
# Examples
|
512
|
+
#
|
513
|
+
# https://github.com
|
514
|
+
# https://github.com[GitHub]
|
515
|
+
# <https://github.com>
|
516
|
+
# link:https://github.com[]
|
517
|
+
# "https://github.com[]"
|
518
|
+
#
|
519
|
+
# FIXME revisit! the main issue is we need different rules for implicit vs explicit
|
520
|
+
InlineLinkRx = %r((^|link:|#{CG_BLANK}|<|[>\(\)\[\];"'])(\\?(?:https?|file|ftp|irc)://[^\s\[\]<]*([^\s.,\[\]<]))(?:\[(|#{CC_ALL}*?[^\\])\])?)m
|
521
|
+
|
522
|
+
# Match a link or e-mail inline macro.
|
523
|
+
#
|
524
|
+
# Examples
|
525
|
+
#
|
526
|
+
# link:path[label]
|
527
|
+
# mailto:doc.writer@example.com[]
|
528
|
+
#
|
529
|
+
# NOTE be as non-greedy as possible by not allowing space or left square bracket in target
|
530
|
+
InlineLinkMacroRx = /\\?(?:link|(mailto)):(|[^:\s\[][^\s\[]*)\[(|#{CC_ALL}*?[^\\])\]/m
|
531
|
+
|
532
|
+
# Matches the name of a macro.
|
533
|
+
#
|
534
|
+
MacroNameRx = /^#{CG_WORD}[#{CC_WORD}-]*$/
|
535
|
+
|
536
|
+
# Matches a stem (and alternatives, asciimath and latexmath) inline macro, which may span multiple lines.
|
537
|
+
#
|
538
|
+
# Examples
|
539
|
+
#
|
540
|
+
# stem:[x != 0]
|
541
|
+
# asciimath:[x != 0]
|
542
|
+
# latexmath:[\sqrt{4} = 2]
|
543
|
+
#
|
544
|
+
InlineStemMacroRx = /\\?(stem|(?:latex|ascii)math):([a-z]+(?:,[a-z-]+)*)?\[(#{CC_ALL}*?[^\\])\]/m
|
545
|
+
|
546
|
+
# Matches a menu inline macro.
|
547
|
+
#
|
548
|
+
# Examples
|
549
|
+
#
|
550
|
+
# menu:File[Save As...]
|
551
|
+
# menu:Edit[]
|
552
|
+
# menu:View[Page Style > No Style]
|
553
|
+
# menu:View[Page Style, No Style]
|
554
|
+
#
|
555
|
+
InlineMenuMacroRx = /\\?menu:(#{CG_WORD}|[#{CC_WORD}&][^\n\[]*[^\s\[])\[ *(?:|(#{CC_ALL}*?[^\\]))\]/m
|
556
|
+
|
557
|
+
# Matches an implicit menu inline macro.
|
558
|
+
#
|
559
|
+
# Examples
|
560
|
+
#
|
561
|
+
# "File > New..."
|
562
|
+
#
|
563
|
+
InlineMenuRx = /\\?"([#{CC_WORD}&][^"]*?[ \n]+>[ \n]+[^"]*)"/
|
564
|
+
|
565
|
+
# Matches an inline passthrough, which may span multiple lines.
|
566
|
+
#
|
567
|
+
# Examples
|
568
|
+
#
|
569
|
+
# +text+
|
570
|
+
# `text` (compat)
|
571
|
+
#
|
572
|
+
# NOTE we always capture the attributes so we know when to use compatible (i.e., legacy) behavior
|
573
|
+
InlinePassRx = {
|
574
|
+
false => ['+', '`', /(^|[^#{CC_WORD};:])(?:\[([^\]]+)\])?(\\?(\+|`)(\S|\S#{CC_ALL}*?\S)\4)(?!#{CG_WORD})/m],
|
575
|
+
true => ['`', nil, /(^|[^`#{CC_WORD}])(?:\[([^\]]+)\])?(\\?(`)([^`\s]|[^`\s]#{CC_ALL}*?\S)\4)(?![`#{CC_WORD}])/m]
|
576
|
+
}
|
577
|
+
|
578
|
+
# Matches an inline plus passthrough spanning multiple lines, but only when it occurs directly
|
579
|
+
# inside constrained monospaced formatting in non-compat mode.
|
580
|
+
#
|
581
|
+
# Examples
|
582
|
+
#
|
583
|
+
# +text+
|
584
|
+
#
|
585
|
+
SinglePlusInlinePassRx = /^(\\)?\+(\S|\S#{CC_ALL}*?\S)\+$/m
|
586
|
+
|
587
|
+
# Matches several variants of the passthrough inline macro, which may span multiple lines.
|
588
|
+
#
|
589
|
+
# Examples
|
590
|
+
#
|
591
|
+
# +++text+++
|
592
|
+
# $$text$$
|
593
|
+
# pass:quotes[text]
|
594
|
+
#
|
595
|
+
# NOTE we have to support an empty pass:[] for compatibility with AsciiDoc Python
|
596
|
+
InlinePassMacroRx = /(?:(?:(\\?)\[([^\]]+)\])?(\\{0,2})(\+\+\+?|\$\$)(#{CC_ALL}*?)\4|(\\?)pass:([a-z]+(?:,[a-z-]+)*)?\[(|#{CC_ALL}*?[^\\])\])/m
|
597
|
+
|
598
|
+
# Matches an xref (i.e., cross-reference) inline macro, which may span multiple lines.
|
599
|
+
#
|
600
|
+
# Examples
|
601
|
+
#
|
602
|
+
# <<id,reftext>>
|
603
|
+
# xref:id[reftext]
|
604
|
+
#
|
605
|
+
# NOTE special characters have already been escaped, hence the entity references
|
606
|
+
# NOTE { is included in start characters to support target that begins with attribute reference in title content
|
607
|
+
InlineXrefMacroRx = %r(\\?(?:<<([#{CC_WORD}#/.:{]#{CC_ALL}*?)>>|xref:([#{CC_WORD}#/.:{]#{CC_ALL}*?)\[(?:\]|(#{CC_ALL}*?[^\\])\])))m
|
608
|
+
|
609
|
+
## Layout
|
610
|
+
|
611
|
+
# Matches a trailing + preceded by at least one space character,
|
612
|
+
# which forces a hard line break (<br> tag in HTML output).
|
613
|
+
#
|
614
|
+
# NOTE AsciiDoc Python allows + to be preceded by TAB; Asciidoctor does not
|
615
|
+
#
|
616
|
+
# Examples
|
617
|
+
#
|
618
|
+
# Humpty Dumpty sat on a wall, +
|
619
|
+
# Humpty Dumpty had a great fall.
|
620
|
+
#
|
621
|
+
if RUBY_ENGINE == 'opal'
|
622
|
+
# NOTE In JavaScript, ^ and $ only match the start and end of line if the multiline flag is present
|
623
|
+
HardLineBreakRx = /^(#{CC_ANY}*) \+$/m
|
624
|
+
else
|
625
|
+
# NOTE In Ruby, ^ and $ always match start and end of line
|
626
|
+
HardLineBreakRx = /^(.*) \+$/
|
627
|
+
end
|
628
|
+
|
629
|
+
# Matches a Markdown horizontal rule.
|
630
|
+
#
|
631
|
+
# Examples
|
632
|
+
#
|
633
|
+
# --- or - - -
|
634
|
+
# *** or * * *
|
635
|
+
# ___ or _ _ _
|
636
|
+
#
|
637
|
+
MarkdownThematicBreakRx = /^ {0,3}([-*_])( *)\1\2\1$/
|
638
|
+
|
639
|
+
# Matches an AsciiDoc or Markdown horizontal rule or AsciiDoc page break.
|
640
|
+
#
|
641
|
+
# Examples
|
642
|
+
#
|
643
|
+
# ''' (horizontal rule)
|
644
|
+
# <<< (page break)
|
645
|
+
# --- or - - - (horizontal rule, Markdown)
|
646
|
+
# *** or * * * (horizontal rule, Markdown)
|
647
|
+
# ___ or _ _ _ (horizontal rule, Markdown)
|
648
|
+
#
|
649
|
+
ExtLayoutBreakRx = /^(?:'{3,}|<{3,}|([-*_])( *)\1\2\1)$/
|
650
|
+
|
651
|
+
## General
|
652
|
+
|
653
|
+
# Matches consecutive blank lines.
|
654
|
+
#
|
655
|
+
# Examples
|
656
|
+
#
|
657
|
+
# one
|
658
|
+
#
|
659
|
+
# two
|
660
|
+
#
|
661
|
+
BlankLineRx = /\n{2,}/
|
662
|
+
|
663
|
+
# Matches a comma or semi-colon delimiter.
|
664
|
+
#
|
665
|
+
# Examples
|
666
|
+
#
|
667
|
+
# one,two
|
668
|
+
# three;four
|
669
|
+
#
|
670
|
+
#DataDelimiterRx = /[,;]/
|
671
|
+
|
672
|
+
# Matches whitespace (space, tab, newline) escaped by a backslash.
|
673
|
+
#
|
674
|
+
# Examples
|
675
|
+
#
|
676
|
+
# three\ blind\ mice
|
677
|
+
#
|
678
|
+
EscapedSpaceRx = /\\([ \t\n])/
|
679
|
+
|
680
|
+
# Detects if text is a possible candidate for the replacements substitution.
|
681
|
+
#
|
682
|
+
ReplaceableTextRx = /[&']|--|\.\.\.|\([CRT]M?\)/
|
683
|
+
|
684
|
+
# Matches a whitespace delimiter, a sequence of spaces, tabs, and/or newlines.
|
685
|
+
# Matches the parsing rules of %w strings in Ruby.
|
686
|
+
#
|
687
|
+
# Examples
|
688
|
+
#
|
689
|
+
# one two three four
|
690
|
+
# five six
|
691
|
+
#
|
692
|
+
# TODO change to /(?<!\\)[ \t\n]+/ once lookbehind assertions are implemented in all modern browsers
|
693
|
+
SpaceDelimiterRx = /([^\\])[ \t\n]+/
|
694
|
+
|
695
|
+
# Matches a + or - modifier in a subs list
|
696
|
+
#
|
697
|
+
SubModifierSniffRx = /[+-]/
|
698
|
+
|
699
|
+
# Matches one or more consecutive digits at the end of a line.
|
700
|
+
#
|
701
|
+
# Examples
|
702
|
+
#
|
703
|
+
# docbook5
|
704
|
+
# html5
|
705
|
+
#
|
706
|
+
TrailingDigitsRx = /\d+$/
|
707
|
+
|
708
|
+
# Detects strings that resemble URIs.
|
709
|
+
#
|
710
|
+
# Examples
|
711
|
+
# http://domain
|
712
|
+
# https://domain
|
713
|
+
# file:///path
|
714
|
+
# data:info
|
715
|
+
#
|
716
|
+
# not c:/sample.adoc or c:\sample.adoc
|
717
|
+
#
|
718
|
+
UriSniffRx = %r(^#{CG_ALPHA}[#{CC_ALNUM}.+-]+:/{0,2})
|
719
|
+
|
720
|
+
# Detects XML tags
|
721
|
+
XmlSanitizeRx = /<[^>]+>/
|
722
|
+
end
|