asciidoctor 2.0.7 → 2.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.adoc +37 -3
- data/LICENSE +2 -1
- data/README-de.adoc +3 -3
- data/README-fr.adoc +3 -3
- data/README-jp.adoc +3 -3
- data/README-zh_CN.adoc +3 -3
- data/README.adoc +6 -4
- data/asciidoctor.gemspec +1 -1
- data/data/stylesheets/asciidoctor-default.css +5 -5
- data/lib/asciidoctor.rb +54 -782
- data/lib/asciidoctor/abstract_block.rb +4 -3
- data/lib/asciidoctor/abstract_node.rb +3 -7
- data/lib/asciidoctor/converter.rb +1 -1
- data/lib/asciidoctor/converter/docbook5.rb +6 -18
- data/lib/asciidoctor/converter/html5.rb +9 -3
- data/lib/asciidoctor/converter/manpage.rb +1 -1
- data/lib/asciidoctor/converter/template.rb +3 -3
- data/lib/asciidoctor/extensions.rb +1 -1
- data/lib/asciidoctor/helpers.rb +23 -32
- data/lib/asciidoctor/path_resolver.rb +21 -13
- data/lib/asciidoctor/rx.rb +720 -0
- data/lib/asciidoctor/syntax_highlighter.rb +7 -1
- data/lib/asciidoctor/version.rb +1 -1
- data/man/asciidoctor.1 +4 -4
- data/man/asciidoctor.adoc +2 -1
- metadata +3 -2
@@ -38,12 +38,13 @@ class AbstractBlock < AbstractNode
|
|
38
38
|
@blocks = []
|
39
39
|
@subs = []
|
40
40
|
@id = @title = @caption = @numeral = @style = @default_subs = @source_location = nil
|
41
|
-
|
42
|
-
when :document, :section
|
41
|
+
if context == :document || context == :section
|
43
42
|
@level = @next_section_index = 0
|
44
43
|
@next_section_ordinal = 1
|
44
|
+
elsif AbstractBlock === parent
|
45
|
+
@level = parent.level
|
45
46
|
else
|
46
|
-
@level =
|
47
|
+
@level = nil
|
47
48
|
end
|
48
49
|
end
|
49
50
|
|
@@ -310,14 +310,10 @@ class AbstractNode
|
|
310
310
|
# Returns A String reference or data URI for the target image
|
311
311
|
def image_uri(target_image, asset_dir_key = 'imagesdir')
|
312
312
|
if (doc = @document).safe < SafeMode::SECURE && (doc.attr? 'data-uri')
|
313
|
-
if ((Helpers.uriish? target_image) && (target_image = Helpers.
|
313
|
+
if ((Helpers.uriish? target_image) && (target_image = Helpers.encode_spaces_in_uri target_image)) ||
|
314
314
|
(asset_dir_key && (images_base = doc.attr asset_dir_key) && (Helpers.uriish? images_base) &&
|
315
315
|
(target_image = normalize_web_path target_image, images_base, false))
|
316
|
-
|
317
|
-
generate_data_uri_from_uri target_image, (doc.attr? 'cache-uri')
|
318
|
-
else
|
319
|
-
target_image
|
320
|
-
end
|
316
|
+
(doc.attr? 'allow-uri-read') ? (generate_data_uri_from_uri target_image, (doc.attr? 'cache-uri')) : target_image
|
321
317
|
else
|
322
318
|
generate_data_uri target_image, asset_dir_key
|
323
319
|
end
|
@@ -474,7 +470,7 @@ class AbstractNode
|
|
474
470
|
# Returns the resolved [String] path
|
475
471
|
def normalize_web_path(target, start = nil, preserve_uri_target = true)
|
476
472
|
if preserve_uri_target && (Helpers.uriish? target)
|
477
|
-
Helpers.
|
473
|
+
Helpers.encode_spaces_in_uri target
|
478
474
|
else
|
479
475
|
@document.path_resolver.web_path target, start
|
480
476
|
end
|
@@ -25,8 +25,8 @@ class Converter::DocBook5Converter < Converter::Base
|
|
25
25
|
MANPAGE_SECTION_TAGS = { 'section' => 'refsection', 'synopsis' => 'refsynopsisdiv' }
|
26
26
|
TABLE_PI_NAMES = ['dbhtml', 'dbfo', 'dblatex']
|
27
27
|
|
28
|
-
CopyrightRx = /^(
|
29
|
-
ImageMacroRx = /^image::?(
|
28
|
+
CopyrightRx = /^(#{CC_ANY}+?)(?: ((?:\d{4}\-)?\d{4}))?$/
|
29
|
+
ImageMacroRx = /^image::?(\S|\S#{CC_ANY}*?\S)\[(#{CC_ANY}+)?\]$/
|
30
30
|
|
31
31
|
def initialize backend, opts = {}
|
32
32
|
@backend = backend
|
@@ -35,20 +35,8 @@ class Converter::DocBook5Converter < Converter::Base
|
|
35
35
|
|
36
36
|
def convert_document node
|
37
37
|
result = ['<?xml version="1.0" encoding="UTF-8"?>']
|
38
|
-
if node.attr? 'toc'
|
39
|
-
|
40
|
-
result << %(<?asciidoc-toc maxdepth="#{node.attr 'toclevels'}"?>)
|
41
|
-
else
|
42
|
-
result << '<?asciidoc-toc?>'
|
43
|
-
end
|
44
|
-
end
|
45
|
-
if node.attr? 'sectnums'
|
46
|
-
if node.attr? 'sectnumlevels'
|
47
|
-
result << %(<?asciidoc-numbered maxdepth="#{node.attr 'sectnumlevels'}"?>)
|
48
|
-
else
|
49
|
-
result << '<?asciidoc-numbered?>'
|
50
|
-
end
|
51
|
-
end
|
38
|
+
result << ((node.attr? 'toclevels') ? %(<?asciidoc-toc maxdepth="#{node.attr 'toclevels'}"?>) : '<?asciidoc-toc?>') if node.attr? 'toc'
|
39
|
+
result << ((node.attr? 'sectnumlevels') ? %(<?asciidoc-numbered maxdepth="#{node.attr 'sectnumlevels'}"?>) : '<?asciidoc-numbered?>') if node.attr? 'sectnums'
|
52
40
|
lang_attribute = (node.attr? 'nolang') ? '' : %( xml:lang="#{node.attr 'lang', 'en'}")
|
53
41
|
if (root_tag_name = node.doctype) == 'manpage'
|
54
42
|
root_tag_name = 'refentry'
|
@@ -634,7 +622,7 @@ class Converter::DocBook5Converter < Converter::Base
|
|
634
622
|
if (reftext.include? '<') && ((reftext = reftext.gsub XmlSanitizeRx, '').include? ' ')
|
635
623
|
reftext = (reftext.squeeze ' ').strip
|
636
624
|
end
|
637
|
-
reftext =
|
625
|
+
reftext = reftext.gsub '"', '"' if reftext.include? '"'
|
638
626
|
%(#{attrs} xreflabel="#{reftext}")
|
639
627
|
else
|
640
628
|
attrs
|
@@ -742,7 +730,7 @@ class Converter::DocBook5Converter < Converter::Base
|
|
742
730
|
if (cover_image.include? ':') && ImageMacroRx =~ cover_image
|
743
731
|
attrlist = $2
|
744
732
|
cover_image = doc.image_uri $1
|
745
|
-
|
733
|
+
if attrlist
|
746
734
|
attrs = (AttributeList.new attrlist).parse ['alt', 'width', 'height']
|
747
735
|
if attrs.key? 'scaledwidth'
|
748
736
|
# NOTE scalefit="1" is the default in this case
|
@@ -23,9 +23,15 @@ class Converter::Html5Converter < Converter::Base
|
|
23
23
|
|
24
24
|
DropAnchorRx = /<(?:a[^>+]+|\/a)>/
|
25
25
|
StemBreakRx = / *\\\n(?:\\?\n)*|\n\n+/
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
if RUBY_ENGINE == 'opal'
|
27
|
+
# NOTE In JavaScript, ^ matches the start of the string when the m flag is not set
|
28
|
+
SvgPreambleRx = /^#{CC_ALL}*?(?=<svg\b)/
|
29
|
+
SvgStartTagRx = /^<svg[^>]*>/
|
30
|
+
else
|
31
|
+
SvgPreambleRx = /\A.*?(?=<svg\b)/m
|
32
|
+
SvgStartTagRx = /\A<svg[^>]*>/
|
33
|
+
end
|
34
|
+
DimensionAttributeRx = /\s(?:width|height|style)=(["'])#{CC_ANY}*?\1/
|
29
35
|
|
30
36
|
def initialize backend, opts = {}
|
31
37
|
@backend = backend
|
@@ -17,7 +17,7 @@ class Converter::ManPageConverter < Converter::Base
|
|
17
17
|
|
18
18
|
LiteralBackslashRx = /(?:\A|[^#{ESC}])\\/
|
19
19
|
LeadingPeriodRx = /^\./
|
20
|
-
EscapedMacroRx = /^(?:#{ESC}\\c\n)?#{ESC}\.((?:URL|MTO) "
|
20
|
+
EscapedMacroRx = /^(?:#{ESC}\\c\n)?#{ESC}\.((?:URL|MTO) "#{CC_ANY}*?" "#{CC_ANY}*?" )( |[^\s]*)(#{CC_ANY}*?)(?: *#{ESC}\\c)?$/
|
21
21
|
MockBoundaryRx = /<\/?BOUNDARY>/
|
22
22
|
EmDashCharRefRx = /—(?:​)?/
|
23
23
|
EllipsisCharRefRx = /…(?:​)?/
|
@@ -34,8 +34,8 @@ class Converter::TemplateConverter < Converter::Base
|
|
34
34
|
}
|
35
35
|
|
36
36
|
begin
|
37
|
-
require 'concurrent/
|
38
|
-
@caches = { scans: ::Concurrent::
|
37
|
+
require 'concurrent/map' unless defined? ::Concurrent::Map
|
38
|
+
@caches = { scans: ::Concurrent::Map.new, templates: ::Concurrent::Map.new }
|
39
39
|
rescue ::LoadError
|
40
40
|
@caches = { scans: {}, templates: {} }
|
41
41
|
end
|
@@ -71,7 +71,7 @@ class Converter::TemplateConverter < Converter::Base
|
|
71
71
|
end
|
72
72
|
case opts[:template_cache]
|
73
73
|
when true
|
74
|
-
logger.warn 'optional gem \'concurrent-ruby\' is not available. This gem is recommended when using the default template cache.' unless defined? ::Concurrent::
|
74
|
+
logger.warn 'optional gem \'concurrent-ruby\' is not available. This gem is recommended when using the default template cache.' unless defined? ::Concurrent::Map
|
75
75
|
@caches = self.class.caches
|
76
76
|
when ::Hash
|
77
77
|
@caches = opts[:template_cache]
|
@@ -622,7 +622,7 @@ module Extensions
|
|
622
622
|
|
623
623
|
def resolve_regexp name, format
|
624
624
|
raise ::ArgumentError, %(invalid name for inline macro: #{name}) unless MacroNameRx.match? name
|
625
|
-
@@rx_cache[[name, format]] ||= /\\?#{name}:#{format == :short ? '(){0}' : '(\S+?)'}\[(
|
625
|
+
@@rx_cache[[name, format]] ||= /\\?#{name}:#{format == :short ? '(){0}' : '(\S+?)'}\[(|#{CC_ANY}*?[^\\])\]/
|
626
626
|
end
|
627
627
|
end
|
628
628
|
|
data/lib/asciidoctor/helpers.rb
CHANGED
@@ -2,7 +2,9 @@
|
|
2
2
|
module Asciidoctor
|
3
3
|
# Internal: Except where noted, a module that contains internal helper functions.
|
4
4
|
module Helpers
|
5
|
-
|
5
|
+
module_function
|
6
|
+
|
7
|
+
# Public: Require the specified library using Kernel#require.
|
6
8
|
#
|
7
9
|
# Attempts to load the library specified in the first argument using the
|
8
10
|
# Kernel#require. Rescues the LoadError if the library is not available and
|
@@ -21,7 +23,7 @@ module Helpers
|
|
21
23
|
# Otherwise, if on_failure is :abort, Kernel#raise is called with an appropriate message.
|
22
24
|
# Otherwise, if on_failure is :warn, Kernel#warn is called with an appropriate message and nil returned.
|
23
25
|
# Otherwise, nil is returned.
|
24
|
-
def
|
26
|
+
def require_library name, gem_name = true, on_failure = :abort
|
25
27
|
require name
|
26
28
|
rescue ::LoadError
|
27
29
|
include Logging unless include? Logging
|
@@ -57,7 +59,7 @@ module Helpers
|
|
57
59
|
# data - the source data Array to prepare (no nil entries allowed)
|
58
60
|
#
|
59
61
|
# returns a String Array of prepared lines
|
60
|
-
def
|
62
|
+
def prepare_source_array data
|
61
63
|
return [] if data.empty?
|
62
64
|
if (leading_2_bytes = (leading_bytes = (first = data[0]).unpack 'C3').slice 0, 2) == BOM_BYTES_UTF_16LE
|
63
65
|
data[0] = first.byteslice 2, first.bytesize
|
@@ -87,7 +89,7 @@ module Helpers
|
|
87
89
|
# data - the source data String to prepare
|
88
90
|
#
|
89
91
|
# returns a String Array of prepared lines
|
90
|
-
def
|
92
|
+
def prepare_source_string data
|
91
93
|
return [] if data.nil_or_empty?
|
92
94
|
if (leading_2_bytes = (leading_bytes = data.unpack 'C3').slice 0, 2) == BOM_BYTES_UTF_16LE
|
93
95
|
data = (data.byteslice 2, data.bytesize).encode UTF_8, ::Encoding::UTF_16LE
|
@@ -110,29 +112,17 @@ module Helpers
|
|
110
112
|
# str - the String to check
|
111
113
|
#
|
112
114
|
# returns true if the String is a URI, false if it is not
|
113
|
-
def
|
115
|
+
def uriish? str
|
114
116
|
(str.include? ':') && (UriSniffRx.match? str)
|
115
117
|
end
|
116
118
|
|
117
|
-
# Internal: Efficiently retrieves the URI prefix of the specified String
|
118
|
-
#
|
119
|
-
# Uses the Asciidoctor::UriSniffRx regex to match the URI prefix in the
|
120
|
-
# specified String (e.g., http://), if present.
|
121
|
-
#
|
122
|
-
# str - the String to check
|
123
|
-
#
|
124
|
-
# returns the string URI prefix if the string is a URI, otherwise nil
|
125
|
-
def self.uri_prefix str
|
126
|
-
(str.include? ':') && UriSniffRx =~ str ? $& : nil
|
127
|
-
end
|
128
|
-
|
129
119
|
# Internal: Encode a URI component String for safe inclusion in a URI.
|
130
120
|
#
|
131
121
|
# str - the URI component String to encode
|
132
122
|
#
|
133
123
|
# Returns the String with all reserved URI characters encoded (e.g., /, &, =, space, etc).
|
134
124
|
if RUBY_ENGINE == 'opal'
|
135
|
-
def
|
125
|
+
def encode_uri_component str
|
136
126
|
# patch necessary to adhere with RFC-3986 (and thus CGI.escape)
|
137
127
|
# see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent#Description
|
138
128
|
%x(
|
@@ -143,17 +133,17 @@ module Helpers
|
|
143
133
|
end
|
144
134
|
else
|
145
135
|
CGI = ::CGI
|
146
|
-
def
|
136
|
+
def encode_uri_component str
|
147
137
|
CGI.escape str
|
148
138
|
end
|
149
139
|
end
|
150
140
|
|
151
|
-
# Internal:
|
141
|
+
# Internal: Apply URI path encoding to spaces in the specified string (i.e., convert spaces to %20).
|
152
142
|
#
|
153
143
|
# str - the String to encode
|
154
144
|
#
|
155
|
-
# Returns the String with all spaces replaced with %20.
|
156
|
-
def
|
145
|
+
# Returns the specified String with all spaces replaced with %20.
|
146
|
+
def encode_spaces_in_uri str
|
157
147
|
(str.include? ' ') ? (str.gsub ' ', '%20') : str
|
158
148
|
end
|
159
149
|
|
@@ -167,7 +157,7 @@ module Helpers
|
|
167
157
|
# # => "part1/chapter1"
|
168
158
|
#
|
169
159
|
# Returns the String filename with the file extension removed
|
170
|
-
def
|
160
|
+
def rootname filename
|
171
161
|
if (last_dot_idx = filename.rindex '.')
|
172
162
|
(filename.index '/', last_dot_idx) ? filename : (filename.slice 0, last_dot_idx)
|
173
163
|
else
|
@@ -190,7 +180,7 @@ module Helpers
|
|
190
180
|
# # => "tiger"
|
191
181
|
#
|
192
182
|
# Returns the String filename with leading directories removed and, if specified, the extension removed
|
193
|
-
def
|
183
|
+
def basename filename, drop_ext = nil
|
194
184
|
if drop_ext
|
195
185
|
::File.basename filename, (drop_ext == true ? (extname filename) : drop_ext)
|
196
186
|
else
|
@@ -203,7 +193,7 @@ module Helpers
|
|
203
193
|
# path - The path String to check; expects a posix path
|
204
194
|
#
|
205
195
|
# Returns true if the path has a file extension, false otherwise
|
206
|
-
def
|
196
|
+
def extname? path
|
207
197
|
(last_dot_idx = path.rindex '.') && !(path.index '/', last_dot_idx)
|
208
198
|
end
|
209
199
|
|
@@ -217,7 +207,7 @@ module Helpers
|
|
217
207
|
#
|
218
208
|
# Returns the String file extension (with the leading dot included) or the fallback value if the path has no file extension.
|
219
209
|
if ::File::ALT_SEPARATOR
|
220
|
-
def
|
210
|
+
def extname path, fallback = ''
|
221
211
|
if (last_dot_idx = path.rindex '.')
|
222
212
|
(path.index '/', last_dot_idx) || (path.index ::File::ALT_SEPARATOR, last_dot_idx) ? fallback : (path.slice last_dot_idx, path.length)
|
223
213
|
else
|
@@ -225,7 +215,7 @@ module Helpers
|
|
225
215
|
end
|
226
216
|
end
|
227
217
|
else
|
228
|
-
def
|
218
|
+
def extname path, fallback = ''
|
229
219
|
if (last_dot_idx = path.rindex '.')
|
230
220
|
(path.index '/', last_dot_idx) ? fallback : (path.slice last_dot_idx, path.length)
|
231
221
|
else
|
@@ -235,7 +225,7 @@ module Helpers
|
|
235
225
|
end
|
236
226
|
|
237
227
|
# Internal: Make a directory, ensuring all parent directories exist.
|
238
|
-
def
|
228
|
+
def mkdir_p dir
|
239
229
|
unless ::File.directory? dir
|
240
230
|
unless (parent_dir = ::File.dirname dir) == '.'
|
241
231
|
mkdir_p parent_dir
|
@@ -252,13 +242,14 @@ module Helpers
|
|
252
242
|
'M' => 1000, 'CM' => 900, 'D' => 500, 'CD' => 400, 'C' => 100, 'XC' => 90,
|
253
243
|
'L' => 50, 'XL' => 40, 'X' => 10, 'IX' => 9, 'V' => 5, 'IV' => 4, 'I' => 1
|
254
244
|
}
|
245
|
+
private_constant :ROMAN_NUMERALS
|
255
246
|
|
256
247
|
# Internal: Converts an integer to a Roman numeral.
|
257
248
|
#
|
258
249
|
# val - the [Integer] value to convert
|
259
250
|
#
|
260
251
|
# Returns the [String] roman numeral for this integer
|
261
|
-
def
|
252
|
+
def int_to_roman val
|
262
253
|
ROMAN_NUMERALS.map do |l, i|
|
263
254
|
repeat, val = val.divmod i
|
264
255
|
l * repeat
|
@@ -272,7 +263,7 @@ module Helpers
|
|
272
263
|
# current - the value to increment as a String or Integer
|
273
264
|
#
|
274
265
|
# returns the next value in the sequence according to the current value's type
|
275
|
-
def
|
266
|
+
def nextval current
|
276
267
|
if ::Integer === current
|
277
268
|
current + 1
|
278
269
|
else
|
@@ -291,14 +282,14 @@ module Helpers
|
|
291
282
|
#
|
292
283
|
# Returns a Class if the specified object is a Class (but not a Module) or
|
293
284
|
# a String that resolves to a Class; otherwise, nil
|
294
|
-
def
|
285
|
+
def resolve_class object
|
295
286
|
::Class === object ? object : (::String === object ? (class_for_name object) : nil)
|
296
287
|
end
|
297
288
|
|
298
289
|
# Internal: Resolves a Class object (not a Module) for the qualified name.
|
299
290
|
#
|
300
291
|
# Returns Class
|
301
|
-
def
|
292
|
+
def class_for_name qualified_name
|
302
293
|
raise unless ::Class === (resolved = ::Object.const_get qualified_name, false)
|
303
294
|
resolved
|
304
295
|
rescue
|
@@ -476,25 +476,15 @@ class PathResolver
|
|
476
476
|
def web_path target, start = nil
|
477
477
|
target = posixify target
|
478
478
|
start = posixify start
|
479
|
-
uri_prefix = nil
|
480
479
|
|
481
480
|
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
|
481
|
+
target, uri_prefix = extract_uri_prefix %(#{start}#{(start.end_with? SLASH) ? '' : SLASH}#{target})
|
486
482
|
end
|
487
483
|
|
488
484
|
# use this logic instead if we want to normalize target if it contains a URI
|
489
485
|
#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
|
486
|
+
# target, uri_prefix = extract_uri_prefix target if preserve_uri_target
|
487
|
+
# target, uri_prefix = extract_uri_prefix %(#{start}#{SLASH}#{target}) unless uri_prefix || start.nil_or_empty?
|
498
488
|
#end
|
499
489
|
|
500
490
|
target_segments, target_root = partition_path target, true
|
@@ -521,5 +511,23 @@ class PathResolver
|
|
521
511
|
|
522
512
|
uri_prefix ? %(#{uri_prefix}#{resolved_path}) : resolved_path
|
523
513
|
end
|
514
|
+
|
515
|
+
private
|
516
|
+
|
517
|
+
# Internal: Efficiently extracts the URI prefix from the specified String if the String is a URI
|
518
|
+
#
|
519
|
+
# Uses the Asciidoctor::UriSniffRx regex to match the URI prefix in the specified String (e.g., http://). If present,
|
520
|
+
# the prefix is removed.
|
521
|
+
#
|
522
|
+
# str - the String to check
|
523
|
+
#
|
524
|
+
# returns a tuple containing the specified string without the URI prefix, if present, and the extracted URI prefix.
|
525
|
+
def extract_uri_prefix str
|
526
|
+
if (str.include? ':') && UriSniffRx =~ str
|
527
|
+
[(str.slice $&.length, str.length), $&]
|
528
|
+
else
|
529
|
+
str
|
530
|
+
end
|
531
|
+
end
|
524
532
|
end
|
525
533
|
end
|
@@ -0,0 +1,720 @@
|
|
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}*?[^\\]))\]/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
|
+
#
|
518
|
+
# FIXME revisit! the main issue is we need different rules for implicit vs explicit
|
519
|
+
InlineLinkRx = %r((^|link:|#{CG_BLANK}|<|[>\(\)\[\];])(\\?(?:https?|file|ftp|irc)://[^\s\[\]<]*([^\s.,\[\]<]))(?:\[(|#{CC_ALL}*?[^\\])\])?)m
|
520
|
+
|
521
|
+
# Match a link or e-mail inline macro.
|
522
|
+
#
|
523
|
+
# Examples
|
524
|
+
#
|
525
|
+
# link:path[label]
|
526
|
+
# mailto:doc.writer@example.com[]
|
527
|
+
#
|
528
|
+
# NOTE be as non-greedy as possible by not allowing space or left square bracket in target
|
529
|
+
InlineLinkMacroRx = /\\?(?:link|(mailto)):(|[^:\s\[][^\s\[]*)\[(|#{CC_ALL}*?[^\\])\]/m
|
530
|
+
|
531
|
+
# Matches the name of a macro.
|
532
|
+
#
|
533
|
+
MacroNameRx = /^#{CG_WORD}[#{CC_WORD}-]*$/
|
534
|
+
|
535
|
+
# Matches a stem (and alternatives, asciimath and latexmath) inline macro, which may span multiple lines.
|
536
|
+
#
|
537
|
+
# Examples
|
538
|
+
#
|
539
|
+
# stem:[x != 0]
|
540
|
+
# asciimath:[x != 0]
|
541
|
+
# latexmath:[\sqrt{4} = 2]
|
542
|
+
#
|
543
|
+
InlineStemMacroRx = /\\?(stem|(?:latex|ascii)math):([a-z]+(?:,[a-z-]+)*)?\[(#{CC_ALL}*?[^\\])\]/m
|
544
|
+
|
545
|
+
# Matches a menu inline macro.
|
546
|
+
#
|
547
|
+
# Examples
|
548
|
+
#
|
549
|
+
# menu:File[Save As...]
|
550
|
+
# menu:View[Page Style > No Style]
|
551
|
+
# menu:View[Page Style, No Style]
|
552
|
+
#
|
553
|
+
InlineMenuMacroRx = /\\?menu:(#{CG_WORD}|[#{CC_WORD}&][^\n\[]*[^\s\[])\[ *(#{CC_ALL}*?[^\\])?\]/m
|
554
|
+
|
555
|
+
# Matches an implicit menu inline macro.
|
556
|
+
#
|
557
|
+
# Examples
|
558
|
+
#
|
559
|
+
# "File > New..."
|
560
|
+
#
|
561
|
+
InlineMenuRx = /\\?"([#{CC_WORD}&][^"]*?[ \n]+>[ \n]+[^"]*)"/
|
562
|
+
|
563
|
+
# Matches an inline passthrough, which may span multiple lines.
|
564
|
+
#
|
565
|
+
# Examples
|
566
|
+
#
|
567
|
+
# +text+
|
568
|
+
# `text` (compat)
|
569
|
+
#
|
570
|
+
# NOTE we always capture the attributes so we know when to use compatible (i.e., legacy) behavior
|
571
|
+
InlinePassRx = {
|
572
|
+
false => ['+', '`', /(^|[^#{CC_WORD};:])(?:\[([^\]]+)\])?(\\?(\+|`)(\S|\S#{CC_ALL}*?\S)\4)(?!#{CG_WORD})/m],
|
573
|
+
true => ['`', nil, /(^|[^`#{CC_WORD}])(?:\[([^\]]+)\])?(\\?(`)([^`\s]|[^`\s]#{CC_ALL}*?\S)\4)(?![`#{CC_WORD}])/m]
|
574
|
+
}
|
575
|
+
|
576
|
+
# Matches an inline plus passthrough spanning multiple lines, but only when it occurs directly
|
577
|
+
# inside constrained monospaced formatting in non-compat mode.
|
578
|
+
#
|
579
|
+
# Examples
|
580
|
+
#
|
581
|
+
# +text+
|
582
|
+
#
|
583
|
+
SinglePlusInlinePassRx = /^(\\)?\+(\S|\S#{CC_ALL}*?\S)\+$/m
|
584
|
+
|
585
|
+
# Matches several variants of the passthrough inline macro, which may span multiple lines.
|
586
|
+
#
|
587
|
+
# Examples
|
588
|
+
#
|
589
|
+
# +++text+++
|
590
|
+
# $$text$$
|
591
|
+
# pass:quotes[text]
|
592
|
+
#
|
593
|
+
# NOTE we have to support an empty pass:[] for compatibility with AsciiDoc Python
|
594
|
+
InlinePassMacroRx = /(?:(?:(\\?)\[([^\]]+)\])?(\\{0,2})(\+\+\+?|\$\$)(#{CC_ALL}*?)\4|(\\?)pass:([a-z]+(?:,[a-z-]+)*)?\[(|#{CC_ALL}*?[^\\])\])/m
|
595
|
+
|
596
|
+
# Matches an xref (i.e., cross-reference) inline macro, which may span multiple lines.
|
597
|
+
#
|
598
|
+
# Examples
|
599
|
+
#
|
600
|
+
# <<id,reftext>>
|
601
|
+
# xref:id[reftext]
|
602
|
+
#
|
603
|
+
# NOTE special characters have already been escaped, hence the entity references
|
604
|
+
# NOTE { is included in start characters to support target that begins with attribute reference in title content
|
605
|
+
InlineXrefMacroRx = %r(\\?(?:<<([#{CC_WORD}#/.:{]#{CC_ALL}*?)>>|xref:([#{CC_WORD}#/.:{]#{CC_ALL}*?)\[(?:\]|(#{CC_ALL}*?[^\\])\])))m
|
606
|
+
|
607
|
+
## Layout
|
608
|
+
|
609
|
+
# Matches a trailing + preceded by at least one space character,
|
610
|
+
# which forces a hard line break (<br> tag in HTML output).
|
611
|
+
#
|
612
|
+
# NOTE AsciiDoc Python allows + to be preceded by TAB; Asciidoctor does not
|
613
|
+
#
|
614
|
+
# Examples
|
615
|
+
#
|
616
|
+
# Humpty Dumpty sat on a wall, +
|
617
|
+
# Humpty Dumpty had a great fall.
|
618
|
+
#
|
619
|
+
if RUBY_ENGINE == 'opal'
|
620
|
+
# NOTE In JavaScript, ^ and $ only match the start and end of line if the multiline flag is present
|
621
|
+
HardLineBreakRx = /^(#{CC_ANY}*) \+$/m
|
622
|
+
else
|
623
|
+
# NOTE In Ruby, ^ and $ always match start and end of line
|
624
|
+
HardLineBreakRx = /^(.*) \+$/
|
625
|
+
end
|
626
|
+
|
627
|
+
# Matches a Markdown horizontal rule.
|
628
|
+
#
|
629
|
+
# Examples
|
630
|
+
#
|
631
|
+
# --- or - - -
|
632
|
+
# *** or * * *
|
633
|
+
# ___ or _ _ _
|
634
|
+
#
|
635
|
+
MarkdownThematicBreakRx = /^ {0,3}([-*_])( *)\1\2\1$/
|
636
|
+
|
637
|
+
# Matches an AsciiDoc or Markdown horizontal rule or AsciiDoc page break.
|
638
|
+
#
|
639
|
+
# Examples
|
640
|
+
#
|
641
|
+
# ''' (horizontal rule)
|
642
|
+
# <<< (page break)
|
643
|
+
# --- or - - - (horizontal rule, Markdown)
|
644
|
+
# *** or * * * (horizontal rule, Markdown)
|
645
|
+
# ___ or _ _ _ (horizontal rule, Markdown)
|
646
|
+
#
|
647
|
+
ExtLayoutBreakRx = /^(?:'{3,}|<{3,}|([-*_])( *)\1\2\1)$/
|
648
|
+
|
649
|
+
## General
|
650
|
+
|
651
|
+
# Matches consecutive blank lines.
|
652
|
+
#
|
653
|
+
# Examples
|
654
|
+
#
|
655
|
+
# one
|
656
|
+
#
|
657
|
+
# two
|
658
|
+
#
|
659
|
+
BlankLineRx = /\n{2,}/
|
660
|
+
|
661
|
+
# Matches a comma or semi-colon delimiter.
|
662
|
+
#
|
663
|
+
# Examples
|
664
|
+
#
|
665
|
+
# one,two
|
666
|
+
# three;four
|
667
|
+
#
|
668
|
+
#DataDelimiterRx = /[,;]/
|
669
|
+
|
670
|
+
# Matches whitespace (space, tab, newline) escaped by a backslash.
|
671
|
+
#
|
672
|
+
# Examples
|
673
|
+
#
|
674
|
+
# three\ blind\ mice
|
675
|
+
#
|
676
|
+
EscapedSpaceRx = /\\([ \t\n])/
|
677
|
+
|
678
|
+
# Detects if text is a possible candidate for the replacements substitution.
|
679
|
+
#
|
680
|
+
ReplaceableTextRx = /[&']|--|\.\.\.|\([CRT]M?\)/
|
681
|
+
|
682
|
+
# Matches a whitespace delimiter, a sequence of spaces, tabs, and/or newlines.
|
683
|
+
# Matches the parsing rules of %w strings in Ruby.
|
684
|
+
#
|
685
|
+
# Examples
|
686
|
+
#
|
687
|
+
# one two three four
|
688
|
+
# five six
|
689
|
+
#
|
690
|
+
# TODO change to /(?<!\\)[ \t\n]+/ once lookbehind assertions are implemented in all modern browsers
|
691
|
+
SpaceDelimiterRx = /([^\\])[ \t\n]+/
|
692
|
+
|
693
|
+
# Matches a + or - modifier in a subs list
|
694
|
+
#
|
695
|
+
SubModifierSniffRx = /[+-]/
|
696
|
+
|
697
|
+
# Matches one or more consecutive digits at the end of a line.
|
698
|
+
#
|
699
|
+
# Examples
|
700
|
+
#
|
701
|
+
# docbook5
|
702
|
+
# html5
|
703
|
+
#
|
704
|
+
TrailingDigitsRx = /\d+$/
|
705
|
+
|
706
|
+
# Detects strings that resemble URIs.
|
707
|
+
#
|
708
|
+
# Examples
|
709
|
+
# http://domain
|
710
|
+
# https://domain
|
711
|
+
# file:///path
|
712
|
+
# data:info
|
713
|
+
#
|
714
|
+
# not c:/sample.adoc or c:\sample.adoc
|
715
|
+
#
|
716
|
+
UriSniffRx = %r(^#{CG_ALPHA}[#{CC_ALNUM}.+-]+:/{0,2})
|
717
|
+
|
718
|
+
# Detects XML tags
|
719
|
+
XmlSanitizeRx = /<[^>]+>/
|
720
|
+
end
|