asciidoctor 2.0.7 → 2.0.8
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 +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
|