asciidoctor 1.5.5 → 1.5.6
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of asciidoctor might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.adoc +216 -1
- data/CONTRIBUTING.adoc +2 -2
- data/Gemfile +20 -1
- data/LICENSE.adoc +1 -1
- data/README-fr.adoc +4 -3
- data/README-jp.adoc +11 -10
- data/README-zh_CN.adoc +4 -3
- data/README.adoc +17 -202
- data/Rakefile +41 -25
- data/asciidoctor.gemspec +9 -10
- data/data/locale/attributes.adoc +216 -34
- data/data/stylesheets/asciidoctor-default.css +23 -16
- data/features/step_definitions.rb +15 -19
- data/features/xref.feature +584 -20
- data/lib/asciidoctor.rb +292 -278
- data/lib/asciidoctor/abstract_block.rb +155 -94
- data/lib/asciidoctor/abstract_node.rb +108 -94
- data/lib/asciidoctor/attribute_list.rb +30 -22
- data/lib/asciidoctor/block.rb +7 -7
- data/lib/asciidoctor/cli/invoker.rb +47 -34
- data/lib/asciidoctor/cli/options.rb +22 -11
- data/lib/asciidoctor/converter.rb +3 -3
- data/lib/asciidoctor/converter/base.rb +2 -2
- data/lib/asciidoctor/converter/composite.rb +1 -1
- data/lib/asciidoctor/converter/docbook45.rb +2 -2
- data/lib/asciidoctor/converter/docbook5.rb +132 -87
- data/lib/asciidoctor/converter/factory.rb +0 -1
- data/lib/asciidoctor/converter/html5.rb +116 -98
- data/lib/asciidoctor/converter/manpage.rb +51 -52
- data/lib/asciidoctor/converter/template.rb +47 -36
- data/lib/asciidoctor/core_ext.rb +8 -2
- data/lib/asciidoctor/core_ext/1.8.7/hash/key.rb +4 -0
- data/lib/asciidoctor/core_ext/1.8.7/io/binread.rb +6 -0
- data/lib/asciidoctor/core_ext/1.8.7/io/write.rb +5 -0
- data/lib/asciidoctor/core_ext/1.8.7/string/chr.rb +1 -1
- data/lib/asciidoctor/core_ext/1.8.7/string/{limit.rb → limit_bytesize.rb} +7 -6
- data/lib/asciidoctor/core_ext/1.8.7/symbol/empty.rb +6 -0
- data/lib/asciidoctor/core_ext/1.8.7/symbol/length.rb +1 -1
- data/lib/asciidoctor/core_ext/nil_or_empty.rb +5 -5
- data/lib/asciidoctor/core_ext/regexp/is_match.rb +3 -0
- data/lib/asciidoctor/core_ext/string/{limit.rb → limit_bytesize.rb} +2 -2
- data/lib/asciidoctor/document.rb +216 -213
- data/lib/asciidoctor/extensions.rb +318 -185
- data/lib/asciidoctor/helpers.rb +35 -35
- data/lib/asciidoctor/inline.rb +32 -1
- data/lib/asciidoctor/list.rb +22 -6
- data/lib/asciidoctor/parser.rb +1008 -1038
- data/lib/asciidoctor/path_resolver.rb +46 -50
- data/lib/asciidoctor/reader.rb +275 -251
- data/lib/asciidoctor/section.rb +86 -58
- data/lib/asciidoctor/stylesheets.rb +6 -6
- data/lib/asciidoctor/substitutors.rb +567 -649
- data/lib/asciidoctor/table.rb +163 -108
- data/lib/asciidoctor/version.rb +1 -1
- data/man/asciidoctor.1 +18 -16
- data/man/asciidoctor.adoc +15 -13
- data/test/attributes_test.rb +138 -22
- data/test/blocks_test.rb +377 -97
- data/test/converter_test.rb +13 -0
- data/test/document_test.rb +244 -34
- data/test/extensions_test.rb +409 -42
- data/test/fixtures/asciidoc_index.txt +521 -0
- data/test/fixtures/basic-docinfo-footer.html +6 -0
- data/test/fixtures/basic-docinfo-footer.xml +8 -0
- data/test/fixtures/basic-docinfo.html +1 -0
- data/test/fixtures/basic-docinfo.xml +4 -0
- data/test/fixtures/basic.asciidoc +5 -0
- data/test/fixtures/chapter-a.adoc +3 -0
- data/test/fixtures/child-include.adoc +5 -0
- data/test/fixtures/circle.svg +9 -0
- data/test/fixtures/custom-backends/erb/html5/block_paragraph.html.erb +6 -0
- data/test/fixtures/custom-backends/haml/docbook45/block_paragraph.xml.haml +6 -0
- data/test/fixtures/custom-backends/haml/html5-tweaks/block_paragraph.html.haml +1 -0
- data/test/fixtures/custom-backends/haml/html5/block_paragraph.html.haml +3 -0
- data/test/fixtures/custom-backends/haml/html5/block_sidebar.html.haml +5 -0
- data/test/fixtures/custom-backends/slim/docbook45/block_paragraph.xml.slim +6 -0
- data/test/fixtures/custom-backends/slim/html5/block_paragraph.html.slim +3 -0
- data/test/fixtures/custom-backends/slim/html5/block_sidebar.html.slim +5 -0
- data/test/fixtures/custom-docinfodir/basic-docinfo.html +1 -0
- data/test/fixtures/custom-docinfodir/docinfo.html +1 -0
- data/test/fixtures/docinfo-footer.html +1 -0
- data/test/fixtures/docinfo-footer.xml +9 -0
- data/test/fixtures/docinfo.html +1 -0
- data/test/fixtures/docinfo.xml +3 -0
- data/test/fixtures/dot.gif +0 -0
- data/test/fixtures/encoding.asciidoc +13 -0
- data/test/fixtures/grandchild-include.adoc +3 -0
- data/test/fixtures/hello-asciidoctor.pdf +69 -0
- data/test/fixtures/include-file.asciidoc +24 -0
- data/test/fixtures/include-file.ml +3 -0
- data/test/fixtures/include-file.xml +5 -0
- data/test/fixtures/master.adoc +5 -0
- data/test/fixtures/mismatched-end-tag.adoc +7 -0
- data/test/fixtures/parent-include-restricted.adoc +5 -0
- data/test/fixtures/parent-include.adoc +5 -0
- data/test/fixtures/sample.asciidoc +26 -0
- data/test/fixtures/stylesheets/custom.css +3 -0
- data/test/fixtures/subs-docinfo.html +2 -0
- data/test/fixtures/subs.adoc +7 -0
- data/test/fixtures/tagged-class-enclosed.rb +26 -0
- data/test/fixtures/tagged-class.rb +23 -0
- data/test/fixtures/tip.gif +0 -0
- data/test/invoker_test.rb +82 -4
- data/test/links_test.rb +312 -37
- data/test/lists_test.rb +204 -25
- data/test/manpage_test.rb +191 -4
- data/test/options_test.rb +18 -1
- data/test/paragraphs_test.rb +32 -7
- data/test/parser_test.rb +150 -30
- data/test/paths_test.rb +47 -13
- data/test/preamble_test.rb +1 -1
- data/test/reader_test.rb +366 -126
- data/test/sections_test.rb +203 -56
- data/test/substitutions_test.rb +339 -131
- data/test/tables_test.rb +315 -15
- data/test/test_helper.rb +400 -0
- data/test/text_test.rb +5 -5
- metadata +110 -22
data/lib/asciidoctor.rb
CHANGED
@@ -7,10 +7,10 @@ RUBY_MIN_VERSION_2 = (RUBY_VERSION >= '2')
|
|
7
7
|
|
8
8
|
require 'set'
|
9
9
|
|
10
|
-
# NOTE RUBY_ENGINE == 'opal' conditional blocks are filtered by the Opal preprocessor
|
10
|
+
# NOTE RUBY_ENGINE == 'opal' conditional blocks like this are filtered by the Opal preprocessor
|
11
11
|
if RUBY_ENGINE == 'opal'
|
12
|
-
#
|
13
|
-
require 'asciidoctor/
|
12
|
+
# this require is satisfied by the Asciidoctor.js build; it augments the Ruby environment for Asciidoctor.js
|
13
|
+
require 'asciidoctor/js'
|
14
14
|
else
|
15
15
|
autoload :Base64, 'base64'
|
16
16
|
autoload :OpenURI, 'open-uri'
|
@@ -62,7 +62,7 @@ module Asciidoctor
|
|
62
62
|
|
63
63
|
# A safe mode level that closely parallels safe mode in AsciiDoc. This value
|
64
64
|
# prevents access to files which reside outside of the parent directory of
|
65
|
-
# the source file and disables any macro other than the include::[]
|
65
|
+
# the source file and disables any macro other than the include::[] directive.
|
66
66
|
SAFE = 1;
|
67
67
|
|
68
68
|
# A safe mode level that disallows the document from setting attributes
|
@@ -76,7 +76,7 @@ module Asciidoctor
|
|
76
76
|
# A safe mode level that disallows the document from attempting to read
|
77
77
|
# files from the file system and including the contents of them into the
|
78
78
|
# document, in additional to all the security features of SafeMode::SERVER.
|
79
|
-
# For instance, this level disallows use of the include::[]
|
79
|
+
# For instance, this level disallows use of the include::[] directive and the
|
80
80
|
# embedding of binary content (data uri), stylesheets and JavaScripts
|
81
81
|
# referenced by the document.(Asciidoctor and trusted extensions may still
|
82
82
|
# be allowed to embed trusted content into the document).
|
@@ -93,13 +93,28 @@ module Asciidoctor
|
|
93
93
|
# enforced)!
|
94
94
|
#PARANOID = 100;
|
95
95
|
|
96
|
+
rec = {}
|
97
|
+
constants.each {|sym| rec[const_get sym] = sym.to_s.downcase }
|
98
|
+
@names_by_value = rec
|
99
|
+
|
100
|
+
def self.value_for_name name
|
101
|
+
const_get name.upcase
|
102
|
+
end
|
103
|
+
|
104
|
+
def self.name_for_value value
|
105
|
+
@names_by_value[value]
|
106
|
+
end
|
107
|
+
|
108
|
+
def self.names
|
109
|
+
@names_by_value.values
|
110
|
+
end
|
96
111
|
end
|
97
112
|
|
98
113
|
# Flags to control compliance with the behavior of AsciiDoc
|
99
114
|
module Compliance
|
100
115
|
@keys = ::Set.new
|
101
116
|
class << self
|
102
|
-
|
117
|
+
attr_reader :keys
|
103
118
|
end
|
104
119
|
|
105
120
|
# Defines a new compliance key and assigns an initial value.
|
@@ -117,8 +132,8 @@ module Asciidoctor
|
|
117
132
|
# Compliance value: true
|
118
133
|
define :block_terminates_paragraph, true
|
119
134
|
|
120
|
-
# AsciiDoc does not
|
121
|
-
# (literal, listing, source, verse) as verbatim
|
135
|
+
# AsciiDoc does not parse paragraphs with a verbatim style
|
136
|
+
# (i.e., literal, listing, source, verse) as verbatim content.
|
122
137
|
# This options allows this behavior to be modified
|
123
138
|
# Compliance value: false
|
124
139
|
define :strict_verbatim_paragraphs, true
|
@@ -172,7 +187,7 @@ module Asciidoctor
|
|
172
187
|
ROOT_PATH = ::File.dirname ::File.dirname ::File.expand_path __FILE__
|
173
188
|
|
174
189
|
# The absolute lib path of the Asciidoctor RubyGem
|
175
|
-
LIB_PATH = ::File.join ROOT_PATH, 'lib'
|
190
|
+
#LIB_PATH = ::File.join ROOT_PATH, 'lib'
|
176
191
|
|
177
192
|
# The absolute data path of the Asciidoctor RubyGem
|
178
193
|
DATA_PATH = ::File.join ROOT_PATH, 'data'
|
@@ -195,19 +210,15 @@ module Asciidoctor
|
|
195
210
|
FORCE_ENCODING = COERCE_ENCODING && ::Encoding.default_external != ::Encoding::UTF_8
|
196
211
|
|
197
212
|
# Byte arrays for UTF-* Byte Order Marks
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
BOM_BYTES_UTF_16BE = "\xfe\xff".bytes.to_a
|
213
|
+
BOM_BYTES_UTF_8 = [0xef, 0xbb, 0xbf]
|
214
|
+
BOM_BYTES_UTF_16LE = [0xff, 0xfe]
|
215
|
+
BOM_BYTES_UTF_16BE = [0xfe, 0xff]
|
202
216
|
|
203
217
|
# Flag to indicate that line length should be calculated using a unicode mode hint
|
204
218
|
FORCE_UNICODE_LINE_LENGTH = !::RUBY_MIN_VERSION_1_9
|
205
219
|
|
206
|
-
# Flag to indicate whether gsub can use a Hash to map matches to replacements
|
207
|
-
SUPPORTS_GSUB_RESULT_HASH = ::RUBY_MIN_VERSION_1_9 && !::RUBY_ENGINE_OPAL
|
208
|
-
|
209
220
|
# The endline character used for output; stored in constant table as an optimization
|
210
|
-
EOL = "\n"
|
221
|
+
LF = EOL = "\n"
|
211
222
|
|
212
223
|
# The null character to use for splitting attribute values
|
213
224
|
NULL = "\0"
|
@@ -243,6 +254,7 @@ module Asciidoctor
|
|
243
254
|
'docbook' => '.xml',
|
244
255
|
'pdf' => '.pdf',
|
245
256
|
'epub' => '.epub',
|
257
|
+
'manpage' => '.man',
|
246
258
|
'asciidoc' => '.adoc'
|
247
259
|
}
|
248
260
|
|
@@ -256,7 +268,7 @@ module Asciidoctor
|
|
256
268
|
'.txt' => true
|
257
269
|
}
|
258
270
|
|
259
|
-
|
271
|
+
SETEXT_SECTION_LEVELS = {
|
260
272
|
'=' => 0,
|
261
273
|
'-' => 1,
|
262
274
|
'~' => 2,
|
@@ -266,6 +278,10 @@ module Asciidoctor
|
|
266
278
|
|
267
279
|
ADMONITION_STYLES = ['NOTE', 'TIP', 'IMPORTANT', 'WARNING', 'CAUTION'].to_set
|
268
280
|
|
281
|
+
ADMONITION_STYLE_LEADERS = ['N', 'T', 'I', 'W', 'C'].to_set
|
282
|
+
|
283
|
+
CALLOUT_LIST_LEADERS = ['<', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'].to_set
|
284
|
+
|
269
285
|
PARAGRAPH_STYLES = ['comment', 'example', 'literal', 'listing', 'normal', 'pass', 'quote', 'sidebar', 'source', 'verse', 'abstract', 'partintro'].to_set
|
270
286
|
|
271
287
|
VERBATIM_STYLES = ['literal', 'listing', 'source', 'verse'].to_set
|
@@ -287,16 +303,21 @@ module Asciidoctor
|
|
287
303
|
'```' => [:fenced_code, ::Set.new]
|
288
304
|
}
|
289
305
|
|
290
|
-
DELIMITED_BLOCK_LEADERS = DELIMITED_BLOCKS.keys.map {|key| key
|
306
|
+
DELIMITED_BLOCK_LEADERS = DELIMITED_BLOCKS.keys.map {|key| key.slice 0, 2 }.to_set
|
291
307
|
|
292
|
-
|
308
|
+
LAYOUT_BREAK_CHARS = {
|
293
309
|
'\'' => :thematic_break,
|
310
|
+
'<' => :page_break
|
311
|
+
}
|
312
|
+
|
313
|
+
MARKDOWN_THEMATIC_BREAK_CHARS = {
|
294
314
|
'-' => :thematic_break,
|
295
315
|
'*' => :thematic_break,
|
296
|
-
'_' => :thematic_break
|
297
|
-
'<' => :page_break
|
316
|
+
'_' => :thematic_break
|
298
317
|
}
|
299
318
|
|
319
|
+
HYBRID_LAYOUT_BREAK_CHARS = LAYOUT_BREAK_CHARS.merge MARKDOWN_THEMATIC_BREAK_CHARS
|
320
|
+
|
300
321
|
#LIST_CONTEXTS = [:ulist, :olist, :dlist, :colist]
|
301
322
|
|
302
323
|
NESTABLE_LIST_CONTEXTS = [:ulist, :olist, :dlist]
|
@@ -305,37 +326,48 @@ module Asciidoctor
|
|
305
326
|
ORDERED_LIST_STYLES = [:arabic, :loweralpha, :lowerroman, :upperalpha, :upperroman] #, :lowergreek]
|
306
327
|
|
307
328
|
ORDERED_LIST_KEYWORDS = {
|
329
|
+
#'arabic' => '1',
|
330
|
+
#'decimal' => '1',
|
308
331
|
'loweralpha' => 'a',
|
309
332
|
'lowerroman' => 'i',
|
333
|
+
#'lowergreek' => 'a',
|
310
334
|
'upperalpha' => 'A',
|
311
335
|
'upperroman' => 'I'
|
312
|
-
#'lowergreek' => 'a'
|
313
|
-
#'arabic' => '1'
|
314
|
-
#'decimal' => '1'
|
315
336
|
}
|
316
337
|
|
317
338
|
LIST_CONTINUATION = '+'
|
318
339
|
|
319
|
-
# NOTE AsciiDoc Python
|
320
|
-
|
340
|
+
# NOTE AsciiDoc Python allows + to be preceded by TAB; Asciidoctor does not
|
341
|
+
HARD_LINE_BREAK = ' +'
|
321
342
|
|
322
343
|
LINE_CONTINUATION = ' \\'
|
323
344
|
|
324
345
|
LINE_CONTINUATION_LEGACY = ' +'
|
325
346
|
|
326
347
|
BLOCK_MATH_DELIMITERS = {
|
327
|
-
:asciimath => ['
|
328
|
-
:latexmath => ['
|
348
|
+
:asciimath => ['\$', '\$'],
|
349
|
+
:latexmath => ['\[', '\]'],
|
329
350
|
}
|
330
351
|
|
331
352
|
INLINE_MATH_DELIMITERS = {
|
332
|
-
:asciimath => ['
|
333
|
-
:latexmath => ['
|
353
|
+
:asciimath => ['\$', '\$'],
|
354
|
+
:latexmath => ['\(', '\)'],
|
334
355
|
}
|
335
356
|
|
336
357
|
# attributes which be changed within the content of the document (but not
|
337
358
|
# header) because it has semantic meaning; ex. sectnums
|
338
|
-
FLEXIBLE_ATTRIBUTES =
|
359
|
+
FLEXIBLE_ATTRIBUTES = ['sectnums']
|
360
|
+
|
361
|
+
# map of file extension to comment affixes for languages that only support circumfix comments
|
362
|
+
CIRCUMFIX_COMMENTS = {
|
363
|
+
['/*', '*/'] => ['.css'],
|
364
|
+
['(*', '*)'] => ['.ml', '.mli', '.nb'],
|
365
|
+
['<!--', '-->'] => ['.html', '.xhtml', '.xml', '.xsl'],
|
366
|
+
['<%--', '--%>'] => ['.asp', '.jsp']
|
367
|
+
}.inject({}) {|accum, (affixes, exts)|
|
368
|
+
exts.each {|ext| accum[ext] = { :prefix => affixes[0], :suffix => affixes[-1] } }
|
369
|
+
accum
|
370
|
+
}
|
339
371
|
|
340
372
|
# A collection of regular expressions used by the parser.
|
341
373
|
#
|
@@ -343,8 +375,8 @@ module Asciidoctor
|
|
343
375
|
# contents between square brackets, ignoring escaped closing brackets
|
344
376
|
# (closing brackets prefixed with a backslash '\' character)
|
345
377
|
#
|
346
|
-
# Pattern:
|
347
|
-
# Matches: [enclosed text
|
378
|
+
# Pattern: \[(|.*?[^\\])\]
|
379
|
+
# Matches: [enclosed text] and [enclosed [text\]], not [enclosed text \\] or [\\] (as these require a trailing space)
|
348
380
|
#
|
349
381
|
#(pseudo)module Rx
|
350
382
|
|
@@ -353,26 +385,13 @@ module Asciidoctor
|
|
353
385
|
|
354
386
|
# NOTE \w matches only the ASCII word characters, whereas [[:word:]] or \p{Word} matches any character in the Unicode word category.
|
355
387
|
|
356
|
-
# character classes for the Regexp engine(s) in JavaScript
|
357
|
-
if RUBY_ENGINE == 'opal'
|
358
|
-
CC_ALPHA = 'a-zA-Z'
|
359
|
-
CG_ALPHA = '[a-zA-Z]'
|
360
|
-
CC_ALNUM = 'a-zA-Z0-9'
|
361
|
-
CG_ALNUM = '[a-zA-Z0-9]'
|
362
|
-
CG_BLANK = '[ \\t]'
|
363
|
-
CC_EOL = '(?=\\n|$)'
|
364
|
-
CG_GRAPH = '[\\x21-\\x7E]' # non-blank character
|
365
|
-
CC_ALL = '[\s\S]' # any character, including newlines (alternatively, [^])
|
366
|
-
CC_WORD = 'a-zA-Z0-9_'
|
367
|
-
CG_WORD = '[a-zA-Z0-9_]'
|
368
388
|
# character classes for the Regexp engine in Ruby >= 2 (Ruby 1.9 supports \p{} but has problems w/ encoding)
|
369
|
-
|
389
|
+
if ::RUBY_MIN_VERSION_2
|
370
390
|
CC_ALPHA = CG_ALPHA = '\p{Alpha}'
|
371
391
|
CC_ALNUM = CG_ALNUM = '\p{Alnum}'
|
372
392
|
CC_ALL = '.'
|
373
393
|
CG_BLANK = '\p{Blank}'
|
374
394
|
CC_EOL = '$'
|
375
|
-
CG_GRAPH = '\p{Graph}'
|
376
395
|
CC_WORD = CG_WORD = '\p{Word}'
|
377
396
|
# character classes for the Regexp engine in Ruby < 2
|
378
397
|
else
|
@@ -381,18 +400,18 @@ module Asciidoctor
|
|
381
400
|
CC_ALL = '.'
|
382
401
|
CC_ALNUM = '[:alnum:]'
|
383
402
|
CG_ALNUM = '[[:alnum:]]'
|
384
|
-
CG_BLANK = '[[:blank:]]'
|
385
403
|
CC_EOL = '$'
|
386
|
-
CG_GRAPH = '[[:graph:]]' # non-blank character
|
387
404
|
if ::RUBY_MIN_VERSION_1_9
|
405
|
+
CG_BLANK = '[[:blank:]]'
|
388
406
|
CC_WORD = '[:word:]'
|
389
407
|
CG_WORD = '[[:word:]]'
|
390
408
|
else
|
391
409
|
# NOTE Ruby 1.8 cannot match word characters beyond the ASCII range; if you need this feature, upgrade!
|
410
|
+
CG_BLANK = '[ \t]'
|
392
411
|
CC_WORD = '[:alnum:]_'
|
393
412
|
CG_WORD = '[[:alnum:]_]'
|
394
413
|
end
|
395
|
-
end
|
414
|
+
end unless RUBY_ENGINE == 'opal'
|
396
415
|
|
397
416
|
## Document header
|
398
417
|
|
@@ -415,15 +434,16 @@ module Asciidoctor
|
|
415
434
|
# v1.0, 2013-01-01: Ring in the new year release
|
416
435
|
# 1.0, Jan 01, 2013
|
417
436
|
#
|
418
|
-
RevisionInfoLineRx = /^(?:\D*(.*?),)?(
|
437
|
+
RevisionInfoLineRx = /^(?:\D*(.*?),)?(?: *(?!:)(.*?))(?: *(?!^): *(.*))?$/
|
419
438
|
|
420
439
|
# Matches the title and volnum in the manpage doctype.
|
421
440
|
#
|
422
441
|
# Examples
|
423
442
|
#
|
443
|
+
# = asciidoctor(1)
|
424
444
|
# = asciidoctor ( 1 )
|
425
445
|
#
|
426
|
-
ManpageTitleVolnumRx = /^(
|
446
|
+
ManpageTitleVolnumRx = /^(.+?) *\( *(.+?) *\)$/
|
427
447
|
|
428
448
|
# Matches the name and purpose in the manpage doctype.
|
429
449
|
#
|
@@ -431,7 +451,7 @@ module Asciidoctor
|
|
431
451
|
#
|
432
452
|
# asciidoctor - converts AsciiDoc source files to HTML, DocBook and other formats
|
433
453
|
#
|
434
|
-
ManpageNamePurposeRx = /^(
|
454
|
+
ManpageNamePurposeRx = /^(.+?) +- +(.+)$/
|
435
455
|
|
436
456
|
## Preprocessor directives
|
437
457
|
|
@@ -447,7 +467,7 @@ module Asciidoctor
|
|
447
467
|
# endif::basebackend-html[]
|
448
468
|
# endif::[]
|
449
469
|
#
|
450
|
-
ConditionalDirectiveRx =
|
470
|
+
ConditionalDirectiveRx = /^(\\)?(ifdef|ifndef|ifeval|endif)::(\S*?(?:([,+])\S*?)?)\[(.+)?\]$/
|
451
471
|
|
452
472
|
# Matches a restricted (read as safe) eval expression.
|
453
473
|
#
|
@@ -455,7 +475,7 @@ module Asciidoctor
|
|
455
475
|
#
|
456
476
|
# "{asciidoctor-version}" >= "0.1.0"
|
457
477
|
#
|
458
|
-
EvalExpressionRx = /^(
|
478
|
+
EvalExpressionRx = /^(.+?) *([=!><]=|[><]) *(.+)$/
|
459
479
|
|
460
480
|
# Matches an include preprocessor directive.
|
461
481
|
#
|
@@ -464,7 +484,7 @@ module Asciidoctor
|
|
464
484
|
# include::chapter1.ad[]
|
465
485
|
# include::example.txt[lines=1;2;5..10]
|
466
486
|
#
|
467
|
-
IncludeDirectiveRx =
|
487
|
+
IncludeDirectiveRx = /^(\\)?include::([^\[][^\[]*)\[(.*)\]$/
|
468
488
|
|
469
489
|
# Matches a trailing tag directive in an include file.
|
470
490
|
#
|
@@ -477,7 +497,7 @@ module Asciidoctor
|
|
477
497
|
# log(e);
|
478
498
|
# }
|
479
499
|
# // end::try-catch[]
|
480
|
-
TagDirectiveRx = /\b(?:tag|end)
|
500
|
+
TagDirectiveRx = /\b(?:tag|(end))::(\S+)\[\]$/
|
481
501
|
|
482
502
|
## Attribute entries and references
|
483
503
|
|
@@ -489,34 +509,41 @@ module Asciidoctor
|
|
489
509
|
# :First Name: Dan
|
490
510
|
# :sectnums!:
|
491
511
|
# :!toc:
|
492
|
-
# :long-entry: Attribute value lines ending in '
|
493
|
-
# are joined together as a single value,
|
494
|
-
# collapsing the line breaks and indentation to
|
512
|
+
# :long-entry: Attribute value lines ending in ' \' \
|
513
|
+
# are joined together as a single value, \
|
514
|
+
# collapsing the line breaks and indentation to \
|
495
515
|
# a single space.
|
496
516
|
#
|
497
|
-
AttributeEntryRx = /^:(!?\w.*?):(
|
517
|
+
AttributeEntryRx = /^:(!?\w.*?):(?:[ \t]+(.*))?$/
|
498
518
|
|
499
519
|
# Matches invalid characters in an attribute name.
|
500
520
|
InvalidAttributeNameCharsRx = /[^\w\-]/
|
501
521
|
|
502
|
-
# Matches
|
522
|
+
# Matches a pass inline macro that surrounds the value of an attribute
|
523
|
+
# entry once it has been parsed.
|
503
524
|
#
|
504
525
|
# Examples
|
505
526
|
#
|
506
527
|
# pass:[text]
|
528
|
+
# pass:a[{a} {b} {c}]
|
507
529
|
#
|
508
|
-
|
530
|
+
if RUBY_ENGINE == 'opal'
|
531
|
+
# In JavaScript, ^ and $ match the boundaries of the string when the m flag is not set
|
532
|
+
AttributeEntryPassMacroRx = /^pass:([a-z]+(?:,[a-z]+)*)?\[([\S\s]*)\]$/
|
533
|
+
else
|
534
|
+
AttributeEntryPassMacroRx = /\Apass:([a-z]+(?:,[a-z]+)*)?\[(.*)\]\Z/m
|
535
|
+
end
|
509
536
|
|
510
537
|
# Matches an inline attribute reference.
|
511
538
|
#
|
512
539
|
# Examples
|
513
540
|
#
|
514
|
-
# {
|
515
|
-
# {counter:
|
541
|
+
# {foobar} or {app_name} or {product-version}
|
542
|
+
# {counter:sequence-name:1}
|
516
543
|
# {set:foo:bar}
|
517
544
|
# {set:name!}
|
518
545
|
#
|
519
|
-
AttributeReferenceRx = /(\\)?\{((set|counter2?)
|
546
|
+
AttributeReferenceRx = /(\\)?\{(\w+[-\w]*|(set|counter2?):.+?)(\\)?\}/
|
520
547
|
|
521
548
|
## Paragraphs and delimited blocks
|
522
549
|
|
@@ -527,7 +554,7 @@ module Asciidoctor
|
|
527
554
|
# [[idname]]
|
528
555
|
# [[idname,Reference Text]]
|
529
556
|
#
|
530
|
-
BlockAnchorRx = /^\[\[(?:|([#{CC_ALPHA}:
|
557
|
+
BlockAnchorRx = /^\[\[(?:|([#{CC_ALPHA}_:][#{CC_WORD}:.-]*)(?:, *(.+))?)\]\]$/
|
531
558
|
|
532
559
|
# Matches an attribute list above a block element.
|
533
560
|
#
|
@@ -542,12 +569,12 @@ module Asciidoctor
|
|
542
569
|
# # as attribute reference
|
543
570
|
# [{lead}]
|
544
571
|
#
|
545
|
-
BlockAttributeListRx = /^\[(
|
572
|
+
BlockAttributeListRx = /^\[(|[#{CC_WORD}.#%{,"'].*)\]$/
|
546
573
|
|
547
574
|
# A combined pattern that matches either a block anchor or a block attribute list.
|
548
575
|
#
|
549
576
|
# TODO this one gets hit a lot, should be optimized as much as possible
|
550
|
-
BlockAttributeLineRx = /^\[(
|
577
|
+
BlockAttributeLineRx = /^\[(?:|[#{CC_WORD}.#%{,"'].*|\[(?:|[#{CC_ALPHA}_:][#{CC_WORD}:.-]*(?:, *.+)?)\])\]$/
|
551
578
|
|
552
579
|
# Matches a title above a block.
|
553
580
|
#
|
@@ -555,7 +582,7 @@ module Asciidoctor
|
|
555
582
|
#
|
556
583
|
# .Title goes here
|
557
584
|
#
|
558
|
-
BlockTitleRx = /^\.([
|
585
|
+
BlockTitleRx = /^\.([^ \t.].*)$/
|
559
586
|
|
560
587
|
# Matches an admonition label at the start of a paragraph.
|
561
588
|
#
|
@@ -564,7 +591,7 @@ module Asciidoctor
|
|
564
591
|
# NOTE: Just a little note.
|
565
592
|
# TIP: Don't forget!
|
566
593
|
#
|
567
|
-
AdmonitionParagraphRx = /^(#{ADMONITION_STYLES.to_a * '|'})
|
594
|
+
AdmonitionParagraphRx = /^(#{ADMONITION_STYLES.to_a * '|'}):[ \t]+/
|
568
595
|
|
569
596
|
# Matches a literal paragraph, which is a line of text preceded by at least one space.
|
570
597
|
#
|
@@ -572,7 +599,7 @@ module Asciidoctor
|
|
572
599
|
#
|
573
600
|
# <SPACE>Foo
|
574
601
|
# <TAB>Foo
|
575
|
-
LiteralParagraphRx = /^(
|
602
|
+
LiteralParagraphRx = /^([ \t]+.*)$/
|
576
603
|
|
577
604
|
# Matches a comment block.
|
578
605
|
#
|
@@ -582,7 +609,7 @@ module Asciidoctor
|
|
582
609
|
# This is a block comment.
|
583
610
|
# It can span one or more lines.
|
584
611
|
# ////
|
585
|
-
CommentBlockRx = %r
|
612
|
+
CommentBlockRx = %r(^/{4,}$)
|
586
613
|
|
587
614
|
# Matches a comment line.
|
588
615
|
#
|
@@ -590,7 +617,7 @@ module Asciidoctor
|
|
590
617
|
#
|
591
618
|
# // an then whatever
|
592
619
|
#
|
593
|
-
CommentLineRx = %r
|
620
|
+
CommentLineRx = %r(^//(?=[^/]|$))
|
594
621
|
|
595
622
|
## Section titles
|
596
623
|
|
@@ -607,20 +634,12 @@ module Asciidoctor
|
|
607
634
|
# match[1] is the delimiter, whose length determines the level
|
608
635
|
# match[2] is the title itself
|
609
636
|
# match[3] is an inline anchor, which becomes the section id
|
610
|
-
AtxSectionRx = /^(
|
637
|
+
AtxSectionRx = /^(=={0,5}|#\#{0,5})[ \t]+(.+?)(?:[ \t]+\1)?$/
|
611
638
|
|
612
639
|
# Matches the restricted section name for a two-line (Setext-style) section title.
|
613
640
|
# The name cannot begin with a dot and has at least one alphanumeric character.
|
614
641
|
SetextSectionTitleRx = /^((?=.*#{CG_WORD}+.*)[^.].*?)$/
|
615
642
|
|
616
|
-
# Matches the underline in a two-line (Setext-style) section title.
|
617
|
-
#
|
618
|
-
# Examples
|
619
|
-
#
|
620
|
-
# ====== || ------ || ~~~~~~ || ^^^^^^ || ++++++
|
621
|
-
#
|
622
|
-
SetextSectionLineRx = /^(?:=|-|~|\^|\+)+$/
|
623
|
-
|
624
643
|
# Matches an anchor (i.e., id + optional reference text) inside a section title.
|
625
644
|
#
|
626
645
|
# Examples
|
@@ -628,10 +647,12 @@ module Asciidoctor
|
|
628
647
|
# Section Title [[idname]]
|
629
648
|
# Section Title [[idname,Reference Text]]
|
630
649
|
#
|
631
|
-
InlineSectionAnchorRx =
|
650
|
+
InlineSectionAnchorRx = / (\\)?\[\[([#{CC_ALPHA}_:][#{CC_WORD}:.-]*)(?:, *(.+))?\]\]$/
|
632
651
|
|
633
652
|
# Matches invalid characters in a section id.
|
634
|
-
|
653
|
+
#
|
654
|
+
# NOTE uppercase chars are not included since the expression is used on a lowercased string
|
655
|
+
InvalidSectionIdCharsRx = /&(?:[a-z][a-z]+\d{0,2}|#\d\d\d{0,4}|#x[\da-f][\da-f][\da-f]{0,3});|[^#{CC_WORD}]+?/
|
635
656
|
|
636
657
|
# Matches the block style used to designate a section title as a floating title.
|
637
658
|
#
|
@@ -647,7 +668,7 @@ module Asciidoctor
|
|
647
668
|
# Detects the start of any list item.
|
648
669
|
#
|
649
670
|
# NOTE we only have to check as far as the blank character because we know it means non-whitespace follows.
|
650
|
-
AnyListRx = /^(
|
671
|
+
AnyListRx = /^(?:[ \t]*(?:-|\*\*{0,4}|\.\.{0,4}|\u2022\u2022{0,4}|\d+\.|[a-zA-Z]\.|[IVXivx]+\))[ \t]|[ \t]*.*?(?::{2,4}|;;)(?:$|[ \t])|<?\d+>[ \t])/
|
651
672
|
|
652
673
|
# Matches an unordered list item (one level for hyphens, up to 5 levels for asterisks).
|
653
674
|
#
|
@@ -657,8 +678,7 @@ module Asciidoctor
|
|
657
678
|
# - Foo
|
658
679
|
#
|
659
680
|
# NOTE we know trailing (.*) will match at least one character because we strip trailing spaces
|
660
|
-
|
661
|
-
UnorderedListRx = /^#{CG_BLANK}*(-|\*{1,5}|\u2022{1,5})#{CG_BLANK}+(.*)$/
|
681
|
+
UnorderedListRx = /^[ \t]*(-|\*\*{0,4}|\u2022\u2022{0,4})[ \t]+(.*)$/
|
662
682
|
|
663
683
|
# Matches an ordered list item (explicit numbering or up to 5 consecutive dots).
|
664
684
|
#
|
@@ -674,11 +694,11 @@ module Asciidoctor
|
|
674
694
|
#
|
675
695
|
# NOTE leading space match is not always necessary, but is used for list reader
|
676
696
|
# NOTE we know trailing (.*) will match at least one character because we strip trailing spaces
|
677
|
-
OrderedListRx =
|
697
|
+
OrderedListRx = /^[ \t]*(\.\.{0,4}|\d+\.|[a-zA-Z]\.|[IVXivx]+\))[ \t]+(.*)$/
|
678
698
|
|
679
699
|
# Matches the ordinals for each type of ordered list.
|
680
700
|
OrderedListMarkerRxMap = {
|
681
|
-
:arabic => /\d
|
701
|
+
:arabic => /\d+\./,
|
682
702
|
:loweralpha => /[a-z]\./,
|
683
703
|
:lowerroman => /[ivx]+\)/,
|
684
704
|
:upperalpha => /[A-Z]\./,
|
@@ -711,15 +731,15 @@ module Asciidoctor
|
|
711
731
|
# NOTE negative match for comment line is intentional since that isn't handled when looking for next list item
|
712
732
|
# TODO check for line comment when scanning lines instead of in regex
|
713
733
|
#
|
714
|
-
DescriptionListRx =
|
734
|
+
DescriptionListRx = %r(^(?!//)[ \t]*(.*?)(:{2,4}|;;)(?:[ \t]+(.*))?$)
|
715
735
|
|
716
736
|
# Matches a sibling description list item (which does not include the type in the key).
|
717
737
|
DescriptionListSiblingRx = {
|
718
738
|
# (?:.*?[^:])? - a non-capturing group which grabs longest sequence of characters that doesn't end w/ colon
|
719
|
-
'::' =>
|
720
|
-
':::' =>
|
721
|
-
'::::' =>
|
722
|
-
';;' =>
|
739
|
+
'::' => %r(^(?!//)[ \t]*((?:.*[^:])?)(::)(?:[ \t]+(.*))?$),
|
740
|
+
':::' => %r(^(?!//)[ \t]*((?:.*[^:])?)(:::)(?:[ \t]+(.*))?$),
|
741
|
+
'::::' => %r(^(?!//)[ \t]*((?:.*[^:])?)(::::)(?:[ \t]+(.*))?$),
|
742
|
+
';;' => %r(^(?!//)[ \t]*(.*)(;;)(?:[ \t]+(.*))?$)
|
723
743
|
}
|
724
744
|
|
725
745
|
# Matches a callout list item.
|
@@ -729,7 +749,10 @@ module Asciidoctor
|
|
729
749
|
# <1> Foo
|
730
750
|
#
|
731
751
|
# NOTE we know trailing (.*) will match at least one character because we strip trailing spaces
|
732
|
-
CalloutListRx = /^<?(\d+)
|
752
|
+
CalloutListRx = /^<?(\d+)>[ \t]+(.*)$/
|
753
|
+
|
754
|
+
# Detects a potential callout list item.
|
755
|
+
CalloutListSniffRx = /^<?\d+>/
|
733
756
|
|
734
757
|
# Matches a callout reference inside literal text.
|
735
758
|
#
|
@@ -739,12 +762,12 @@ module Asciidoctor
|
|
739
762
|
# <!--1--> (for XML-based languages)
|
740
763
|
#
|
741
764
|
# NOTE extract regexps are applied line-by-line, so we can use $ as end-of-line char
|
742
|
-
CalloutExtractRx =
|
765
|
+
CalloutExtractRx = %r((?:(?://|#|--|;;) ?)?(\\)?<!?(|--)(\d+)\2>(?=(?: ?\\?<!?\2\d+\2>)*$))
|
743
766
|
CalloutExtractRxt = '(\\\\)?<()(\\d+)>(?=(?: ?\\\\?<\\d+>)*$)'
|
744
767
|
# NOTE special characters have not been replaced when scanning
|
745
|
-
|
768
|
+
CalloutScanRx = /\\?<!?(|--)(\d+)\1>(?=(?: ?\\?<!?\1\d+\1>)*#{CC_EOL})/
|
746
769
|
# NOTE special characters have already been replaced when converting to an SGML format
|
747
|
-
CalloutSourceRx =
|
770
|
+
CalloutSourceRx = %r((?:(?://|#|--|;;) ?)?(\\)?<!?(|--)(\d+)\2>(?=(?: ?\\?<!?\2\d+\2>)*#{CC_EOL}))
|
748
771
|
CalloutSourceRxt = "(\\\\)?<()(\\d+)>(?=(?: ?\\\\?<\\d+>)*#{CC_EOL})"
|
749
772
|
|
750
773
|
# A Hash of regexps for lists used for dynamic access.
|
@@ -772,12 +795,12 @@ module Asciidoctor
|
|
772
795
|
# 2.3+<.>m
|
773
796
|
#
|
774
797
|
# FIXME use step-wise scan (or treetop) rather than this mega-regexp
|
775
|
-
CellSpecStartRx =
|
776
|
-
CellSpecEndRx =
|
798
|
+
CellSpecStartRx = /^[ \t]*(?:(\d+(?:\.\d*)?|(?:\d*\.)?\d+)([*+]))?([<^>](?:\.[<^>]?)?|(?:[<^>]?\.)?[<^>])?([a-z])?$/
|
799
|
+
CellSpecEndRx = /[ \t]+(?:(\d+(?:\.\d*)?|(?:\d*\.)?\d+)([*+]))?([<^>](?:\.[<^>]?)?|(?:[<^>]?\.)?[<^>])?([a-z])?$/
|
777
800
|
|
778
801
|
# Block macros
|
779
802
|
|
780
|
-
# Matches the
|
803
|
+
# Matches the custom block macro pattern.
|
781
804
|
#
|
782
805
|
# Examples
|
783
806
|
#
|
@@ -785,7 +808,7 @@ module Asciidoctor
|
|
785
808
|
#
|
786
809
|
#--
|
787
810
|
# NOTE we've relaxed the match for target to accomodate the short format (e.g., name::[attrlist])
|
788
|
-
|
811
|
+
CustomBlockMacroRx = /^(#{CG_WORD}+)::(|\S|\S.*?\S)\[(.*)\]$/
|
789
812
|
|
790
813
|
# Matches an image, video or audio block macro.
|
791
814
|
#
|
@@ -794,7 +817,7 @@ module Asciidoctor
|
|
794
817
|
# image::filename.png[Caption]
|
795
818
|
# video::http://youtube.com/12345[Cats vs Dogs]
|
796
819
|
#
|
797
|
-
|
820
|
+
BlockMediaMacroRx = /^(image|video|audio)::(\S|\S.*?\S)\[(.*)\]$/
|
798
821
|
|
799
822
|
# Matches the TOC block macro.
|
800
823
|
#
|
@@ -803,7 +826,7 @@ module Asciidoctor
|
|
803
826
|
# toc::[]
|
804
827
|
# toc::[levels=2]
|
805
828
|
#
|
806
|
-
|
829
|
+
BlockTocMacroRx = /^toc::\[(.*)\]$/
|
807
830
|
|
808
831
|
## Inline macros
|
809
832
|
|
@@ -816,21 +839,24 @@ module Asciidoctor
|
|
816
839
|
# anchor:idname[]
|
817
840
|
# anchor:idname[Reference Text]
|
818
841
|
#
|
819
|
-
InlineAnchorRx =
|
842
|
+
InlineAnchorRx = /(\\)?(?:\[\[([#{CC_ALPHA}_:][#{CC_WORD}:.-]*)(?:, *(.+?))?\]\]|anchor:([#{CC_ALPHA}_:][#{CC_WORD}:.-]*)\[(?:\]|(.*?[^\\])\]))/
|
843
|
+
|
844
|
+
# Scans for a non-escaped anchor (i.e., id + optional reference text) in the flow of text.
|
845
|
+
InlineAnchorScanRx = /(?:^|[^\\\[])\[\[([#{CC_ALPHA}_:][#{CC_WORD}:.-]*)(?:, *(.+?))?\]\]|(?:^|[^\\])anchor:([#{CC_ALPHA}_:][#{CC_WORD}:.-]*)\[(?:\]|(.*?[^\\])\])/
|
820
846
|
|
821
|
-
# Matches a bibliography anchor
|
847
|
+
# Matches a bibliography anchor at the start of the list item text (in a bibliography list).
|
822
848
|
#
|
823
849
|
# Examples
|
824
850
|
#
|
825
|
-
# [[[
|
851
|
+
# [[[Fowler_1997]]] Fowler M. ...
|
826
852
|
#
|
827
|
-
InlineBiblioAnchorRx =
|
853
|
+
InlineBiblioAnchorRx = /^\[\[\[([#{CC_ALPHA}_:][#{CC_WORD}:.-]*)(?:, *(.+?))?\]\]\]/
|
828
854
|
|
829
855
|
# Matches an inline e-mail address.
|
830
856
|
#
|
831
857
|
# doc.writer@example.com
|
832
858
|
#
|
833
|
-
|
859
|
+
EmailInlineRx = %r(([\\>:/])?#{CG_WORD}[#{CC_WORD}.%+-]*@#{CG_ALNUM}[#{CC_ALNUM}.-]*\.#{CG_ALPHA}{2,4}\b)
|
834
860
|
|
835
861
|
# Matches an inline footnote macro, which is allowed to span multiple lines.
|
836
862
|
#
|
@@ -839,7 +865,7 @@ module Asciidoctor
|
|
839
865
|
# footnoteref:[id,text]
|
840
866
|
# footnoteref:[id]
|
841
867
|
#
|
842
|
-
|
868
|
+
InlineFootnoteMacroRx = /\\?(footnote(?:ref)?):\[(#{CC_ALL}*?[^\\])\]/m
|
843
869
|
|
844
870
|
# Matches an image or icon inline macro.
|
845
871
|
#
|
@@ -850,7 +876,8 @@ module Asciidoctor
|
|
850
876
|
# image:filename.png[More [Alt\] Text] (alt text becomes "More [Alt] Text")
|
851
877
|
# icon:github[large]
|
852
878
|
#
|
853
|
-
|
879
|
+
# NOTE be as non-greedy as possible by not allowing endline or left square bracket in target
|
880
|
+
InlineImageMacroRx = /\\?i(?:mage|con):([^:\s\[](?:[^\n\[]*[^\s\[])?)\[(|#{CC_ALL}*?[^\\])\]/m
|
854
881
|
|
855
882
|
# Matches an indexterm inline macro, which may span multiple lines.
|
856
883
|
#
|
@@ -861,7 +888,7 @@ module Asciidoctor
|
|
861
888
|
# indexterm2:[Tigers]
|
862
889
|
# ((Tigers))
|
863
890
|
#
|
864
|
-
|
891
|
+
InlineIndextermMacroRx = /\\?(?:(indexterm2?):\[(#{CC_ALL}*?[^\\])\]|\(\((#{CC_ALL}+?)\)\)(?!\)))/m
|
865
892
|
|
866
893
|
# Matches either the kbd or btn inline macro.
|
867
894
|
#
|
@@ -873,26 +900,19 @@ module Asciidoctor
|
|
873
900
|
# kbd:[Ctrl,T]
|
874
901
|
# btn:[Save]
|
875
902
|
#
|
876
|
-
|
877
|
-
|
878
|
-
# Matches the delimiter used for kbd value.
|
879
|
-
#
|
880
|
-
# Examples
|
881
|
-
#
|
882
|
-
# Ctrl + Alt+T
|
883
|
-
# Ctrl,T
|
884
|
-
#
|
885
|
-
KbdDelimiterRx = /(?:\+|,)(?=#{CG_BLANK}*[^\1])/
|
903
|
+
InlineKbdBtnMacroRx = /(\\)?(kbd|btn):\[(#{CC_ALL}*?[^\\])\]/m
|
886
904
|
|
887
905
|
# Matches an implicit link and some of the link inline macro.
|
888
906
|
#
|
889
907
|
# Examples
|
890
908
|
#
|
891
|
-
#
|
892
|
-
#
|
909
|
+
# https://github.com
|
910
|
+
# https://github.com[GitHub]
|
911
|
+
# <https://github.com>
|
912
|
+
# link:https://github.com[]
|
893
913
|
#
|
894
914
|
# FIXME revisit! the main issue is we need different rules for implicit vs explicit
|
895
|
-
LinkInlineRx = %r
|
915
|
+
LinkInlineRx = %r((^|link:|#{CG_BLANK}|<|[>\(\)\[\];])(\\?(?:https?|file|ftp|irc)://[^\s\[\]<]*[^\s.,\[\]<])(?:\[(|#{CC_ALL}*?[^\\])\])?)m
|
896
916
|
|
897
917
|
# Match a link or e-mail inline macro.
|
898
918
|
#
|
@@ -901,7 +921,12 @@ module Asciidoctor
|
|
901
921
|
# link:path[label]
|
902
922
|
# mailto:doc.writer@example.com[]
|
903
923
|
#
|
904
|
-
|
924
|
+
# NOTE be as non-greedy as possible by not allowing space or left square bracket in target
|
925
|
+
InlineLinkMacroRx = /\\?(?:link|(mailto)):(|[^:\s\[][^\s\[]*)\[(|#{CC_ALL}*?[^\\])\]/m
|
926
|
+
|
927
|
+
# Matches the name of a macro.
|
928
|
+
#
|
929
|
+
MacroNameRx = /^#{CG_WORD}+$/
|
905
930
|
|
906
931
|
# Matches a stem (and alternatives, asciimath and latexmath) inline macro, which may span multiple lines.
|
907
932
|
#
|
@@ -911,17 +936,17 @@ module Asciidoctor
|
|
911
936
|
# asciimath:[x != 0]
|
912
937
|
# latexmath:[\sqrt{4} = 2]
|
913
938
|
#
|
914
|
-
|
939
|
+
InlineStemMacroRx = /\\?(stem|(?:latex|ascii)math):([a-z]+(?:,[a-z]+)*)?\[(#{CC_ALL}*?[^\\])\]/m
|
915
940
|
|
916
941
|
# Matches a menu inline macro.
|
917
942
|
#
|
918
943
|
# Examples
|
919
944
|
#
|
920
|
-
# menu:File[
|
945
|
+
# menu:File[Save As...]
|
921
946
|
# menu:View[Page Style > No Style]
|
922
947
|
# menu:View[Page Style, No Style]
|
923
948
|
#
|
924
|
-
|
949
|
+
InlineMenuMacroRx = /\\?menu:(#{CG_WORD}|[#{CC_WORD}&][^\n\[]*[^\s\[])\[ *(#{CC_ALL}*?[^\\])?\]/m
|
925
950
|
|
926
951
|
# Matches an implicit menu inline macro.
|
927
952
|
#
|
@@ -929,7 +954,7 @@ module Asciidoctor
|
|
929
954
|
#
|
930
955
|
# "File > New..."
|
931
956
|
#
|
932
|
-
MenuInlineRx = /\\?"(#{
|
957
|
+
MenuInlineRx = /\\?"([#{CC_WORD}&][^"]*?[ \n]+>[ \n]+[^"]*)"/
|
933
958
|
|
934
959
|
# Matches an inline passthrough value, which may span multiple lines.
|
935
960
|
#
|
@@ -940,8 +965,8 @@ module Asciidoctor
|
|
940
965
|
#
|
941
966
|
# NOTE we always capture the attributes so we know when to use compatible (i.e., legacy) behavior
|
942
967
|
PassInlineRx = {
|
943
|
-
false => ['+', '`', /(^|[^#{CC_WORD};:])(?:\[([^\]]
|
944
|
-
true => ['`', nil, /(^|[^`#{CC_WORD}])(?:\[([^\]]
|
968
|
+
false => ['+', '`', /(^|[^#{CC_WORD};:])(?:\[([^\]]+)\])?(\\?(\+|`)(\S|\S#{CC_ALL}*?\S)\4)(?!#{CG_WORD})/m],
|
969
|
+
true => ['`', nil, /(^|[^`#{CC_WORD}])(?:\[([^\]]+)\])?(\\?(`)([^`\s]|[^`\s]#{CC_ALL}*?\S)\4)(?![`#{CC_WORD}])/m]
|
945
970
|
}
|
946
971
|
|
947
972
|
# Matches several variants of the passthrough inline macro, which may span multiple lines.
|
@@ -952,7 +977,8 @@ module Asciidoctor
|
|
952
977
|
# $$text$$
|
953
978
|
# pass:quotes[text]
|
954
979
|
#
|
955
|
-
|
980
|
+
# NOTE we have to support an empty pass:[] for compatibility with AsciiDoc Python
|
981
|
+
InlinePassMacroRx = /(?:(?:(\\?)\[([^\]]+)\])?(\\{0,2})(\+\+\+?|\$\$)(#{CC_ALL}*?)\4|(\\?)pass:([a-z]+(?:,[a-z]+)*)?\[(|#{CC_ALL}*?[^\\])\])/m
|
956
982
|
|
957
983
|
# Matches an xref (i.e., cross-reference) inline macro, which may span multiple lines.
|
958
984
|
#
|
@@ -962,78 +988,70 @@ module Asciidoctor
|
|
962
988
|
# xref:id[reftext]
|
963
989
|
#
|
964
990
|
# NOTE special characters have already been escaped, hence the entity references
|
965
|
-
|
991
|
+
# NOTE { is included in start characters to support target that begins with attribute reference in title content
|
992
|
+
InlineXrefMacroRx = %r(\\?(?:<<([#{CC_WORD}#/.:{]#{CC_ALL}*?)>>|xref:([#{CC_WORD}#/.:{]#{CC_ALL}*?)\[(#{CC_ALL}*?[^\\])?\]))m
|
966
993
|
|
967
994
|
## Layout
|
968
995
|
|
969
996
|
# Matches a trailing + preceded by at least one space character,
|
970
997
|
# which forces a hard line break (<br> tag in HTML output).
|
971
998
|
#
|
999
|
+
# NOTE AsciiDoc Python allows + to be preceded by TAB; Asciidoctor does not
|
1000
|
+
#
|
972
1001
|
# Examples
|
973
1002
|
#
|
974
1003
|
# Humpty Dumpty sat on a wall, +
|
975
1004
|
# Humpty Dumpty had a great fall.
|
976
1005
|
#
|
977
1006
|
if RUBY_ENGINE == 'opal'
|
978
|
-
# NOTE
|
979
|
-
|
1007
|
+
# NOTE In Ruby, ^ and $ always match start and end of line, respectively; JavaScript only does so in multiline mode
|
1008
|
+
HardLineBreakRx = /^(.*) \+$/m
|
980
1009
|
else
|
981
|
-
|
1010
|
+
HardLineBreakRx = /^(.*) \+$/
|
982
1011
|
end
|
983
1012
|
|
984
|
-
# Matches
|
1013
|
+
# Matches a Markdown horizontal rule.
|
985
1014
|
#
|
986
1015
|
# Examples
|
987
1016
|
#
|
988
|
-
#
|
989
|
-
#
|
1017
|
+
# --- or - - -
|
1018
|
+
# *** or * * *
|
1019
|
+
# ___ or _ _ _
|
990
1020
|
#
|
991
|
-
|
1021
|
+
MarkdownThematicBreakRx = /^ {0,3}([-*_])( *)\1\2\1$/
|
992
1022
|
|
993
1023
|
# Matches an AsciiDoc or Markdown horizontal rule or AsciiDoc page break.
|
994
1024
|
#
|
995
1025
|
# Examples
|
996
1026
|
#
|
997
|
-
# '''
|
998
|
-
# --- or - - - (horizontal rule)
|
999
|
-
# *** or * * * (horizontal rule)
|
1027
|
+
# ''' (horizontal rule)
|
1000
1028
|
# <<< (page break)
|
1029
|
+
# --- or - - - (horizontal rule, Markdown)
|
1030
|
+
# *** or * * * (horizontal rule, Markdown)
|
1031
|
+
# ___ or _ _ _ (horizontal rule, Markdown)
|
1001
1032
|
#
|
1002
|
-
|
1033
|
+
HybridLayoutBreakRx = /^(?:'{3,}|<{3,}|([-*_])( *)\1\2\1)$/
|
1003
1034
|
|
1004
1035
|
## General
|
1005
1036
|
|
1006
|
-
# Matches
|
1007
|
-
#
|
1008
|
-
# NOTE allows for empty space in line as it could be left by the template engine
|
1009
|
-
BlankLineRx = /^#{CG_BLANK}*\n/
|
1010
|
-
|
1011
|
-
# Matches a comma or semi-colon delimiter.
|
1037
|
+
# Matches consecutive blank lines.
|
1012
1038
|
#
|
1013
1039
|
# Examples
|
1014
1040
|
#
|
1015
|
-
# one
|
1016
|
-
# three;four
|
1017
|
-
#
|
1018
|
-
DataDelimiterRx = /,|;/
|
1019
|
-
|
1020
|
-
# Matches a single-line of text enclosed in double quotes, capturing the quote char and text.
|
1021
|
-
#
|
1022
|
-
# Examples
|
1041
|
+
# one
|
1023
1042
|
#
|
1024
|
-
#
|
1043
|
+
# two
|
1025
1044
|
#
|
1026
|
-
|
1045
|
+
BlankLineRx = /\n{2,}/
|
1027
1046
|
|
1028
|
-
# Matches
|
1047
|
+
# Matches a comma or semi-colon delimiter.
|
1029
1048
|
#
|
1030
1049
|
# Examples
|
1031
1050
|
#
|
1032
|
-
#
|
1033
|
-
#
|
1034
|
-
# still want to be matched."
|
1051
|
+
# one,two
|
1052
|
+
# three;four
|
1035
1053
|
#
|
1036
|
-
|
1054
|
+
DataDelimiterRx = /[,;]/
|
1037
1055
|
|
1038
1056
|
# Matches one or more consecutive digits at the end of a line.
|
1039
1057
|
#
|
@@ -1044,21 +1062,28 @@ module Asciidoctor
|
|
1044
1062
|
#
|
1045
1063
|
TrailingDigitsRx = /\d+$/
|
1046
1064
|
|
1047
|
-
# Matches
|
1065
|
+
# Matches whitespace (space, tab, newline) escaped by a backslash.
|
1048
1066
|
#
|
1049
1067
|
# Examples
|
1050
1068
|
#
|
1051
|
-
#
|
1069
|
+
# three\ blind\ mice
|
1070
|
+
#
|
1071
|
+
EscapedSpaceRx = /\\([ \t\n])/
|
1072
|
+
|
1073
|
+
# Detects if text is a possible candidate for the replacements substitution.
|
1052
1074
|
#
|
1053
|
-
|
1075
|
+
ReplaceableTextRx = /[&']|--|\.\.\.|\([CRT]M?\)/
|
1054
1076
|
|
1055
|
-
# Matches a
|
1077
|
+
# Matches a whitespace delimiter, a sequence of spaces, tabs, and/or newlines.
|
1078
|
+
# Matches the parsing rules of %w strings in Ruby.
|
1056
1079
|
#
|
1057
1080
|
# Examples
|
1058
1081
|
#
|
1059
|
-
# one two
|
1082
|
+
# one two three four
|
1083
|
+
# five six
|
1060
1084
|
#
|
1061
|
-
|
1085
|
+
# TODO change to /(?<!\\)[ \t\n]+/ after dropping support for Ruby 1.8.7
|
1086
|
+
SpaceDelimiterRx = /([^\\])[ \t\n]+/
|
1062
1087
|
|
1063
1088
|
# Matches a + or - modifier in a subs list
|
1064
1089
|
#
|
@@ -1066,10 +1091,8 @@ module Asciidoctor
|
|
1066
1091
|
|
1067
1092
|
# Matches any character with multibyte support explicitly enabled (length of multibyte char = 1)
|
1068
1093
|
#
|
1069
|
-
|
1070
|
-
|
1071
|
-
UnicodeCharScanRx = unless RUBY_ENGINE == 'opal'
|
1072
|
-
FORCE_UNICODE_LINE_LENGTH ? /./u : nil
|
1094
|
+
unless RUBY_ENGINE == 'opal'
|
1095
|
+
UnicodeCharScanRx = /./u if FORCE_UNICODE_LINE_LENGTH
|
1073
1096
|
end
|
1074
1097
|
|
1075
1098
|
# Detects strings that resemble URIs.
|
@@ -1082,7 +1105,7 @@ module Asciidoctor
|
|
1082
1105
|
#
|
1083
1106
|
# not c:/sample.adoc or c:\sample.adoc
|
1084
1107
|
#
|
1085
|
-
UriSniffRx = %r
|
1108
|
+
UriSniffRx = %r(^#{CG_ALPHA}[#{CC_ALNUM}.+-]+:/{0,2})
|
1086
1109
|
|
1087
1110
|
# Detects the end of an implicit URI in the text
|
1088
1111
|
#
|
@@ -1092,36 +1115,10 @@ module Asciidoctor
|
|
1092
1115
|
# >http://google.com<
|
1093
1116
|
# (See http://google.com):
|
1094
1117
|
#
|
1095
|
-
|
1118
|
+
UriTerminatorRx = /[);:]$/
|
1096
1119
|
|
1097
1120
|
# Detects XML tags
|
1098
1121
|
XmlSanitizeRx = /<[^>]+>/
|
1099
|
-
|
1100
|
-
# Unused
|
1101
|
-
|
1102
|
-
# Detects any fenced block delimiter, including:
|
1103
|
-
# listing, literal, example, sidebar, quote, passthrough, table and fenced code
|
1104
|
-
# Does not match open blocks or air quotes
|
1105
|
-
# TIP position the most common blocks towards the front of the pattern
|
1106
|
-
#BlockDelimiterRx = %r{^(?:(?:-|\.|=|\*|_|\+|/){4,}|[\|,;!]={3,}|(?:`|~){3,}.*)$}
|
1107
|
-
|
1108
|
-
# Matches an escaped single quote within a word
|
1109
|
-
#
|
1110
|
-
# Examples
|
1111
|
-
#
|
1112
|
-
# Here\'s Johnny!
|
1113
|
-
#
|
1114
|
-
#EscapedSingleQuoteRx = /(#{CG_WORD})\\'(#{CG_WORD})/
|
1115
|
-
# an alternative if our backend generates single-quoted html/xml attributes
|
1116
|
-
#EscapedSingleQuoteRx = /(#{CG_WORD}|=)\\'(#{CG_WORD})/
|
1117
|
-
|
1118
|
-
# Matches whitespace at the beginning of the line
|
1119
|
-
#LeadingSpacesRx = /^(#{CG_BLANK}*)/
|
1120
|
-
|
1121
|
-
# Matches parent directory references at the beginning of a path
|
1122
|
-
#LeadingParentDirsRx = /^(?:\.\.\/)*/
|
1123
|
-
|
1124
|
-
#StripLineWise = /\A(?:\s*\n)?(#{CC_ALL}*?)\s*\z/m
|
1125
1122
|
#end
|
1126
1123
|
|
1127
1124
|
INTRINSIC_ATTRIBUTES = {
|
@@ -1162,57 +1159,57 @@ module Asciidoctor
|
|
1162
1159
|
# the order in which they are replaced is important
|
1163
1160
|
quote_subs = [
|
1164
1161
|
# **strong**
|
1165
|
-
[:strong, :unconstrained, /\\?(?:\[([^\]]
|
1162
|
+
[:strong, :unconstrained, /\\?(?:\[([^\]]+)\])?\*\*(#{CC_ALL}+?)\*\*/m],
|
1166
1163
|
|
1167
1164
|
# *strong*
|
1168
|
-
[:strong, :constrained, /(^|[^#{CC_WORD};:}])(?:\[([^\]]
|
1165
|
+
[:strong, :constrained, /(^|[^#{CC_WORD};:}])(?:\[([^\]]+)\])?\*(\S|\S#{CC_ALL}*?\S)\*(?!#{CG_WORD})/m],
|
1169
1166
|
|
1170
1167
|
# "`double-quoted`"
|
1171
|
-
[:double, :constrained, /(^|[^#{CC_WORD};:}])(?:\[([^\]]
|
1168
|
+
[:double, :constrained, /(^|[^#{CC_WORD};:}])(?:\[([^\]]+)\])?"`(\S|\S#{CC_ALL}*?\S)`"(?!#{CG_WORD})/m],
|
1172
1169
|
|
1173
1170
|
# '`single-quoted`'
|
1174
|
-
[:single, :constrained, /(^|[^#{CC_WORD};:`}])(?:\[([^\]]
|
1171
|
+
[:single, :constrained, /(^|[^#{CC_WORD};:`}])(?:\[([^\]]+)\])?'`(\S|\S#{CC_ALL}*?\S)`'(?!#{CG_WORD})/m],
|
1175
1172
|
|
1176
1173
|
# ``monospaced``
|
1177
|
-
[:monospaced, :unconstrained, /\\?(?:\[([^\]]
|
1174
|
+
[:monospaced, :unconstrained, /\\?(?:\[([^\]]+)\])?``(#{CC_ALL}+?)``/m],
|
1178
1175
|
|
1179
1176
|
# `monospaced`
|
1180
|
-
[:monospaced, :constrained, /(^|[^#{CC_WORD};:"'`}])(?:\[([^\]]
|
1177
|
+
[:monospaced, :constrained, /(^|[^#{CC_WORD};:"'`}])(?:\[([^\]]+)\])?`(\S|\S#{CC_ALL}*?\S)`(?![#{CC_WORD}"'`])/m],
|
1181
1178
|
|
1182
1179
|
# __emphasis__
|
1183
|
-
[:emphasis, :unconstrained, /\\?(?:\[([^\]]
|
1180
|
+
[:emphasis, :unconstrained, /\\?(?:\[([^\]]+)\])?__(#{CC_ALL}+?)__/m],
|
1184
1181
|
|
1185
1182
|
# _emphasis_
|
1186
|
-
[:emphasis, :constrained, /(^|[^#{CC_WORD};:}])(?:\[([^\]]
|
1183
|
+
[:emphasis, :constrained, /(^|[^#{CC_WORD};:}])(?:\[([^\]]+)\])?_(\S|\S#{CC_ALL}*?\S)_(?!#{CG_WORD})/m],
|
1187
1184
|
|
1188
1185
|
# ##mark## (referred to in AsciiDoc Python as unquoted)
|
1189
|
-
[:mark, :unconstrained, /\\?(?:\[([^\]]
|
1186
|
+
[:mark, :unconstrained, /\\?(?:\[([^\]]+)\])?##(#{CC_ALL}+?)##/m],
|
1190
1187
|
|
1191
1188
|
# #mark# (referred to in AsciiDoc Python as unquoted)
|
1192
|
-
[:mark, :constrained, /(^|[^#{CC_WORD}&;:}])(?:\[([^\]]
|
1189
|
+
[:mark, :constrained, /(^|[^#{CC_WORD}&;:}])(?:\[([^\]]+)\])?#(\S|\S#{CC_ALL}*?\S)#(?!#{CG_WORD})/m],
|
1193
1190
|
|
1194
1191
|
# ^superscript^
|
1195
|
-
[:superscript, :unconstrained, /\\?(?:\[([^\]]
|
1192
|
+
[:superscript, :unconstrained, /\\?(?:\[([^\]]+)\])?\^(\S+?)\^/],
|
1196
1193
|
|
1197
1194
|
# ~subscript~
|
1198
|
-
[:subscript, :unconstrained, /\\?(?:\[([^\]]
|
1195
|
+
[:subscript, :unconstrained, /\\?(?:\[([^\]]+)\])?~(\S+?)~/]
|
1199
1196
|
]
|
1200
1197
|
|
1201
1198
|
compat_quote_subs = quote_subs.dup
|
1202
1199
|
# ``quoted''
|
1203
|
-
compat_quote_subs[2] = [:double, :constrained, /(^|[^#{CC_WORD};:}])(?:\[([^\]]
|
1200
|
+
compat_quote_subs[2] = [:double, :constrained, /(^|[^#{CC_WORD};:}])(?:\[([^\]]+)\])?``(\S|\S#{CC_ALL}*?\S)''(?!#{CG_WORD})/m]
|
1204
1201
|
# `quoted'
|
1205
|
-
compat_quote_subs[3] = [:single, :constrained, /(^|[^#{CC_WORD};:}])(?:\[([^\]]
|
1202
|
+
compat_quote_subs[3] = [:single, :constrained, /(^|[^#{CC_WORD};:}])(?:\[([^\]]+)\])?`(\S|\S#{CC_ALL}*?\S)'(?!#{CG_WORD})/m]
|
1206
1203
|
# ++monospaced++
|
1207
|
-
compat_quote_subs[4] = [:monospaced, :unconstrained, /\\?(?:\[([^\]]
|
1204
|
+
compat_quote_subs[4] = [:monospaced, :unconstrained, /\\?(?:\[([^\]]+)\])?\+\+(#{CC_ALL}+?)\+\+/m]
|
1208
1205
|
# +monospaced+
|
1209
|
-
compat_quote_subs[5] = [:monospaced, :constrained, /(^|[^#{CC_WORD};:}])(?:\[([^\]]
|
1206
|
+
compat_quote_subs[5] = [:monospaced, :constrained, /(^|[^#{CC_WORD};:}])(?:\[([^\]]+)\])?\+(\S|\S#{CC_ALL}*?\S)\+(?!#{CG_WORD})/m]
|
1210
1207
|
# #unquoted#
|
1211
1208
|
#compat_quote_subs[8] = [:unquoted, *compat_quote_subs[8][1..-1]]
|
1212
1209
|
# ##unquoted##
|
1213
1210
|
#compat_quote_subs[9] = [:unquoted, *compat_quote_subs[9][1..-1]]
|
1214
1211
|
# 'emphasis'
|
1215
|
-
compat_quote_subs.insert 3, [:emphasis, :constrained, /(^|[^#{CC_WORD};:}])(?:\[([^\]]
|
1212
|
+
compat_quote_subs.insert 3, [:emphasis, :constrained, /(^|[^#{CC_WORD};:}])(?:\[([^\]]+)\])?'(\S|\S#{CC_ALL}*?\S)'(?!#{CG_WORD})/m]
|
1216
1213
|
|
1217
1214
|
QUOTE_SUBS = {
|
1218
1215
|
false => quote_subs,
|
@@ -1251,7 +1248,7 @@ module Asciidoctor
|
|
1251
1248
|
# left double arrow <=
|
1252
1249
|
[/\\?<=/, '⇐', :none],
|
1253
1250
|
# restore entities
|
1254
|
-
[/\\?(&)amp;((?:[a-zA-Z]{2
|
1251
|
+
[/\\?(&)amp;((?:[a-zA-Z][a-zA-Z]+\d{0,2}|#\d\d\d{0,4}|#x[\da-fA-F][\da-fA-F][\da-fA-F]{0,3});)/, '', :bounding]
|
1255
1252
|
]
|
1256
1253
|
|
1257
1254
|
class << self
|
@@ -1274,36 +1271,28 @@ module Asciidoctor
|
|
1274
1271
|
timings.start :read
|
1275
1272
|
end
|
1276
1273
|
|
1277
|
-
|
1278
|
-
{}
|
1274
|
+
if !(attrs = options[:attributes])
|
1275
|
+
attrs = {}
|
1279
1276
|
elsif ::Hash === attrs || (::RUBY_ENGINE_JRUBY && ::Java::JavaUtil::Map === attrs)
|
1280
|
-
attrs.dup
|
1277
|
+
attrs = attrs.dup
|
1281
1278
|
elsif ::Array === attrs
|
1282
|
-
attrs
|
1279
|
+
attrs, attrs_arr = {}, attrs
|
1280
|
+
attrs_arr.each do |entry|
|
1283
1281
|
k, v = entry.split '=', 2
|
1284
|
-
|
1285
|
-
accum
|
1282
|
+
attrs[k] = v || ''
|
1286
1283
|
end
|
1287
1284
|
elsif ::String === attrs
|
1288
|
-
# convert non-escaped spaces
|
1289
|
-
|
1290
|
-
|
1291
|
-
attrs = attrs.gsub(SpaceDelimiterRx, %(#{capture_1}#{NULL})).gsub(EscapedSpaceRx, capture_1)
|
1292
|
-
attrs.split(NULL).inject({}) do |accum, entry|
|
1285
|
+
# condense and convert non-escaped spaces to null, unescape escaped spaces, then split on null
|
1286
|
+
attrs, attrs_arr = {}, attrs.gsub(SpaceDelimiterRx, %(\\1#{NULL})).gsub(EscapedSpaceRx, '\1').split(NULL)
|
1287
|
+
attrs_arr.each do |entry|
|
1293
1288
|
k, v = entry.split '=', 2
|
1294
|
-
|
1295
|
-
accum
|
1289
|
+
attrs[k] = v || ''
|
1296
1290
|
end
|
1297
1291
|
elsif (attrs.respond_to? :keys) && (attrs.respond_to? :[])
|
1298
1292
|
# convert it to a Hash as we know it
|
1299
|
-
|
1300
|
-
attrs = {}
|
1301
|
-
original_attrs.keys.each do |key|
|
1302
|
-
attrs[key] = original_attrs[key]
|
1303
|
-
end
|
1304
|
-
attrs
|
1293
|
+
attrs = ::Hash[attrs.keys.map {|k| [k, attrs[k]] }]
|
1305
1294
|
else
|
1306
|
-
raise ::ArgumentError, %(illegal type for attributes option: #{attrs.class.ancestors})
|
1295
|
+
raise ::ArgumentError, %(illegal type for attributes option: #{attrs.class.ancestors * ' < '})
|
1307
1296
|
end
|
1308
1297
|
|
1309
1298
|
lines = nil
|
@@ -1311,15 +1300,21 @@ module Asciidoctor
|
|
1311
1300
|
# TODO cli checks if input path can be read and is file, but might want to add check to API
|
1312
1301
|
input_path = ::File.expand_path input.path
|
1313
1302
|
# See https://reproducible-builds.org/specs/source-date-epoch/
|
1314
|
-
|
1303
|
+
# NOTE Opal can't call key? on ENV
|
1304
|
+
input_mtime = ::ENV['SOURCE_DATE_EPOCH'] ? ::Time.at(Integer ::ENV['SOURCE_DATE_EPOCH']).utc : input.mtime
|
1315
1305
|
lines = input.readlines
|
1316
1306
|
# hold off on setting infile and indir until we get a better sense of their purpose
|
1317
|
-
|
1318
|
-
|
1319
|
-
|
1320
|
-
docdate =
|
1321
|
-
|
1322
|
-
|
1307
|
+
attrs['docfile'] = input_path
|
1308
|
+
attrs['docdir'] = ::File.dirname input_path
|
1309
|
+
attrs['docname'] = Helpers.basename input_path, (attrs['docfilesuffix'] = ::File.extname input_path)
|
1310
|
+
if (docdate = attrs['docdate'])
|
1311
|
+
attrs['docyear'] ||= ((docdate.index '-') == 4 ? (docdate.slice 0, 4) : nil)
|
1312
|
+
else
|
1313
|
+
docdate = attrs['docdate'] = (input_mtime.strftime '%Y-%m-%d')
|
1314
|
+
attrs['docyear'] ||= input_mtime.year.to_s
|
1315
|
+
end
|
1316
|
+
doctime = (attrs['doctime'] ||= input_mtime.strftime('%H:%M:%S %Z'))
|
1317
|
+
attrs['docdatetime'] = %(#{docdate} #{doctime})
|
1323
1318
|
elsif input.respond_to? :readlines
|
1324
1319
|
# NOTE tty, pipes & sockets can't be rewound, but can't be sniffed easily either
|
1325
1320
|
# just fail the rewind operation silently to handle all cases
|
@@ -1329,7 +1324,7 @@ module Asciidoctor
|
|
1329
1324
|
end
|
1330
1325
|
lines = input.readlines
|
1331
1326
|
elsif ::String === input
|
1332
|
-
lines = input.lines.
|
1327
|
+
lines = ::RUBY_MIN_VERSION_2 ? input.lines : input.each_line.to_a
|
1333
1328
|
elsif ::Array === input
|
1334
1329
|
lines = input.dup
|
1335
1330
|
else
|
@@ -1341,17 +1336,14 @@ module Asciidoctor
|
|
1341
1336
|
timings.start :parse
|
1342
1337
|
end
|
1343
1338
|
|
1344
|
-
|
1345
|
-
|
1346
|
-
else
|
1347
|
-
doc = (Document.new lines, options).parse
|
1348
|
-
end
|
1339
|
+
options[:attributes] = attrs
|
1340
|
+
doc = options[:parse] == false ? (Document.new lines, options) : (Document.new lines, options).parse
|
1349
1341
|
|
1350
1342
|
timings.record :parse if timings
|
1351
1343
|
doc
|
1352
1344
|
rescue => ex
|
1353
1345
|
begin
|
1354
|
-
context = %(asciidoctor: FAILED: #{
|
1346
|
+
context = %(asciidoctor: FAILED: #{attrs['docfile'] || '<stdin>'}: Failed to load AsciiDoc document)
|
1355
1347
|
if ex.respond_to? :exception
|
1356
1348
|
# The original message must be explicitely preserved when wrapping a Ruby exception
|
1357
1349
|
wrapped_ex = ex.exception %(#{context} - #{ex.message})
|
@@ -1381,7 +1373,7 @@ module Asciidoctor
|
|
1381
1373
|
#
|
1382
1374
|
# Returns the Asciidoctor::Document
|
1383
1375
|
def load_file filename, options = {}
|
1384
|
-
|
1376
|
+
::File.open(filename) {|file| self.load file, options }
|
1385
1377
|
end
|
1386
1378
|
|
1387
1379
|
# Public: Parse the AsciiDoc source input into an Asciidoctor::Document and
|
@@ -1436,27 +1428,26 @@ module Asciidoctor
|
|
1436
1428
|
return self.load input, options
|
1437
1429
|
else
|
1438
1430
|
write_to_same_dir = false
|
1439
|
-
stream_output = to_file.respond_to? :write
|
1440
|
-
write_to_target = stream_output ? false : to_file
|
1431
|
+
write_to_target = (stream_output = to_file.respond_to? :write) ? false : to_file
|
1441
1432
|
end
|
1442
1433
|
|
1443
1434
|
unless options.key? :header_footer
|
1444
1435
|
options[:header_footer] = true if write_to_same_dir || write_to_target
|
1445
1436
|
end
|
1446
1437
|
|
1447
|
-
# NOTE
|
1438
|
+
# NOTE outfile may be controlled by document attributes, so resolve outfile after loading
|
1448
1439
|
if write_to_same_dir
|
1449
1440
|
input_path = ::File.expand_path input.path
|
1450
1441
|
options[:to_dir] = (outdir = ::File.dirname input_path)
|
1451
1442
|
elsif write_to_target
|
1452
1443
|
if to_dir
|
1453
1444
|
if to_file
|
1454
|
-
options[:to_dir] = ::File.
|
1445
|
+
options[:to_dir] = ::File.expand_path ::File.join to_dir, to_file, '..'
|
1455
1446
|
else
|
1456
1447
|
options[:to_dir] = ::File.expand_path to_dir
|
1457
1448
|
end
|
1458
1449
|
elsif to_file
|
1459
|
-
options[:to_dir] = ::File.
|
1450
|
+
options[:to_dir] = ::File.expand_path to_file, '..'
|
1460
1451
|
end
|
1461
1452
|
else
|
1462
1453
|
options[:to_dir] = nil
|
@@ -1464,13 +1455,13 @@ module Asciidoctor
|
|
1464
1455
|
|
1465
1456
|
doc = self.load input, options
|
1466
1457
|
|
1467
|
-
if write_to_same_dir
|
1458
|
+
if write_to_same_dir # write to file in same directory
|
1468
1459
|
outfile = ::File.join outdir, %(#{doc.attributes['docname']}#{doc.outfilesuffix})
|
1469
1460
|
if outfile == input_path
|
1470
1461
|
raise ::IOError, %(input file and output file cannot be the same: #{outfile})
|
1471
1462
|
end
|
1472
|
-
elsif write_to_target
|
1473
|
-
working_dir = options.
|
1463
|
+
elsif write_to_target # write to explicit file or directory
|
1464
|
+
working_dir = (options.key? :base_dir) ? (::File.expand_path options[:base_dir]) : (::File.expand_path ::Dir.pwd)
|
1474
1465
|
# QUESTION should the jail be the working_dir or doc.base_dir???
|
1475
1466
|
jail = doc.safe >= SafeMode::SAFE ? working_dir : nil
|
1476
1467
|
if to_dir
|
@@ -1488,6 +1479,10 @@ module Asciidoctor
|
|
1488
1479
|
outdir = ::File.dirname outfile
|
1489
1480
|
end
|
1490
1481
|
|
1482
|
+
if ::File === input && outfile == (::File.expand_path input.path)
|
1483
|
+
raise ::IOError, %(input file and output file cannot be the same: #{outfile})
|
1484
|
+
end
|
1485
|
+
|
1491
1486
|
unless ::File.directory? outdir
|
1492
1487
|
if mkdirs
|
1493
1488
|
Helpers.mkdir_p outdir
|
@@ -1496,7 +1491,7 @@ module Asciidoctor
|
|
1496
1491
|
raise ::IOError, %(target directory does not exist: #{to_dir})
|
1497
1492
|
end
|
1498
1493
|
end
|
1499
|
-
else
|
1494
|
+
else # write to stream
|
1500
1495
|
outfile = to_file
|
1501
1496
|
outdir = nil
|
1502
1497
|
end
|
@@ -1542,10 +1537,8 @@ module Asciidoctor
|
|
1542
1537
|
stylesheet_src = doc.normalize_system_path stylesheet_src
|
1543
1538
|
end
|
1544
1539
|
stylesheet_dst = doc.normalize_system_path stylesheet, stylesoutdir, (doc.safe >= SafeMode::SAFE ? outdir : nil)
|
1545
|
-
|
1546
|
-
::
|
1547
|
-
f.write stylesheet_content
|
1548
|
-
}
|
1540
|
+
if stylesheet_src != stylesheet_dst && (stylesheet_content = doc.read_asset stylesheet_src, :warn_on_failure => true, :label => 'stylesheet')
|
1541
|
+
::IO.write stylesheet_dst, stylesheet_content
|
1549
1542
|
end
|
1550
1543
|
end
|
1551
1544
|
|
@@ -1563,7 +1556,7 @@ module Asciidoctor
|
|
1563
1556
|
end
|
1564
1557
|
|
1565
1558
|
# Alias render to convert to maintain backwards compatibility
|
1566
|
-
alias
|
1559
|
+
alias render convert
|
1567
1560
|
|
1568
1561
|
# Public: Parse the contents of the AsciiDoc source file into an
|
1569
1562
|
# Asciidoctor::Document and convert it to the specified backend format.
|
@@ -1576,20 +1569,39 @@ module Asciidoctor
|
|
1576
1569
|
# Returns the Document object if the converted String is written to a
|
1577
1570
|
# file, otherwise the converted String
|
1578
1571
|
def convert_file filename, options = {}
|
1579
|
-
|
1572
|
+
::File.open(filename) {|file| self.convert file, options }
|
1580
1573
|
end
|
1581
1574
|
|
1582
1575
|
# Alias render_file to convert_file to maintain backwards compatibility
|
1583
|
-
alias
|
1576
|
+
alias render_file convert_file
|
1577
|
+
|
1578
|
+
# Internal: Automatically load the Asciidoctor::Extensions module.
|
1579
|
+
#
|
1580
|
+
# Requires the Asciidoctor::Extensions module if the name is :Extensions.
|
1581
|
+
# Otherwise, delegates to the super method.
|
1582
|
+
#
|
1583
|
+
# This method provides the same functionality as using autoload on
|
1584
|
+
# Asciidoctor::Extensions, except that the constant isn't recognized as
|
1585
|
+
# defined prior to it being loaded.
|
1586
|
+
#
|
1587
|
+
# Returns the resolved constant, if resolved, otherwise nothing.
|
1588
|
+
def const_missing name
|
1589
|
+
if name == :Extensions
|
1590
|
+
require 'asciidoctor/extensions'
|
1591
|
+
Extensions
|
1592
|
+
else
|
1593
|
+
super
|
1594
|
+
end
|
1595
|
+
end unless RUBY_ENGINE == 'opal'
|
1584
1596
|
|
1585
1597
|
end
|
1586
1598
|
|
1587
1599
|
if RUBY_ENGINE == 'opal'
|
1588
|
-
require 'asciidoctor/version'
|
1589
1600
|
require 'asciidoctor/timings'
|
1601
|
+
require 'asciidoctor/version'
|
1590
1602
|
else
|
1591
|
-
autoload :VERSION, 'asciidoctor/version'
|
1592
1603
|
autoload :Timings, 'asciidoctor/timings'
|
1604
|
+
autoload :VERSION, 'asciidoctor/version'
|
1593
1605
|
end
|
1594
1606
|
end
|
1595
1607
|
|
@@ -1609,7 +1621,6 @@ require 'asciidoctor/attribute_list'
|
|
1609
1621
|
require 'asciidoctor/block'
|
1610
1622
|
require 'asciidoctor/callouts'
|
1611
1623
|
require 'asciidoctor/converter'
|
1612
|
-
require 'asciidoctor/converter/html5' if RUBY_ENGINE_OPAL
|
1613
1624
|
require 'asciidoctor/document'
|
1614
1625
|
require 'asciidoctor/inline'
|
1615
1626
|
require 'asciidoctor/list'
|
@@ -1619,3 +1630,6 @@ require 'asciidoctor/reader'
|
|
1619
1630
|
require 'asciidoctor/section'
|
1620
1631
|
require 'asciidoctor/stylesheets'
|
1621
1632
|
require 'asciidoctor/table'
|
1633
|
+
|
1634
|
+
# this require is satisfied by the Asciidoctor.js build; it supplies compile and runtime overrides for Asciidoctor.js
|
1635
|
+
require 'asciidoctor/js/postscript' if RUBY_ENGINE == 'opal'
|