asciidoctor 0.1.2 → 0.1.3
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/Gemfile +10 -0
- data/Guardfile +18 -0
- data/LICENSE +1 -1
- data/README.adoc +65 -21
- data/Rakefile +10 -0
- data/asciidoctor.gemspec +17 -35
- data/compat/asciidoc.conf +130 -13
- data/lib/asciidoctor.rb +107 -87
- data/lib/asciidoctor/abstract_block.rb +6 -2
- data/lib/asciidoctor/abstract_node.rb +21 -13
- data/lib/asciidoctor/attribute_list.rb +2 -5
- data/{stylesheets/asciidoctor.css → lib/asciidoctor/backends/_stylesheets.rb} +96 -46
- data/lib/asciidoctor/backends/base_template.rb +9 -4
- data/lib/asciidoctor/backends/docbook45.rb +246 -138
- data/lib/asciidoctor/backends/html5.rb +580 -381
- data/lib/asciidoctor/block.rb +2 -50
- data/lib/asciidoctor/cli/options.rb +9 -8
- data/lib/asciidoctor/document.rb +35 -45
- data/lib/asciidoctor/helpers.rb +10 -0
- data/lib/asciidoctor/lexer.rb +456 -148
- data/lib/asciidoctor/list_item.rb +0 -21
- data/lib/asciidoctor/path_resolver.rb +18 -12
- data/lib/asciidoctor/reader.rb +71 -26
- data/lib/asciidoctor/renderer.rb +2 -19
- data/lib/asciidoctor/section.rb +0 -1
- data/lib/asciidoctor/substituters.rb +150 -36
- data/lib/asciidoctor/table.rb +30 -24
- data/lib/asciidoctor/version.rb +1 -1
- data/man/asciidoctor.1 +22 -16
- data/man/asciidoctor.ad +24 -16
- data/test/attributes_test.rb +50 -0
- data/test/blocks_test.rb +660 -9
- data/test/document_test.rb +191 -14
- data/test/fixtures/encoding.asciidoc +8 -0
- data/test/invoker_test.rb +47 -0
- data/test/lexer_test.rb +172 -0
- data/test/links_test.rb +28 -0
- data/test/lists_test.rb +172 -13
- data/test/options_test.rb +29 -2
- data/test/paragraphs_test.rb +105 -47
- data/test/paths_test.rb +3 -3
- data/test/reader_test.rb +46 -0
- data/test/sections_test.rb +365 -12
- data/test/substitutions_test.rb +127 -11
- data/test/tables_test.rb +81 -14
- data/test/test_helper.rb +18 -7
- data/test/text_test.rb +17 -5
- metadata +9 -36
data/lib/asciidoctor.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
|
-
|
1
|
+
if RUBY_VERSION < '1.9'
|
2
|
+
require 'rubygems'
|
3
|
+
end
|
2
4
|
require 'strscan'
|
3
5
|
require 'set'
|
4
6
|
|
5
7
|
$:.unshift(File.dirname(__FILE__))
|
6
|
-
#$:.unshift(File.join(File.dirname(__FILE__), '..', 'vendor'))
|
7
8
|
|
8
9
|
# Public: Methods for parsing Asciidoc input files and rendering documents
|
9
10
|
# using eRuby templates.
|
@@ -91,6 +92,12 @@ module Asciidoctor
|
|
91
92
|
# The root path of the Asciidoctor gem
|
92
93
|
ROOT_PATH = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
93
94
|
|
95
|
+
# Flag to indicate whether encoding of external strings needs to be forced to UTF-8
|
96
|
+
# _All_ input data must be force encoded to UTF-8 if Encoding.default_external is *not* UTF-8
|
97
|
+
# Address failures performing string operations that are reported as "invalid byte sequence in US-ASCII"
|
98
|
+
# Ruby 1.8 doesn't seem to experience this problem (perhaps because it isn't validating the encodings)
|
99
|
+
FORCE_ENCODING = RUBY_VERSION > '1.9' && Encoding.default_external != Encoding::UTF_8
|
100
|
+
|
94
101
|
# The default document type
|
95
102
|
# Can influence markup generated by render templates
|
96
103
|
DEFAULT_DOCTYPE = 'article'
|
@@ -98,11 +105,9 @@ module Asciidoctor
|
|
98
105
|
# The backend determines the format of the rendered output, default to html5
|
99
106
|
DEFAULT_BACKEND = 'html5'
|
100
107
|
|
101
|
-
DEFAULT_STYLESHEET_PATH = File.join(ROOT_PATH, 'stylesheets', 'asciidoctor.css')
|
102
|
-
|
103
108
|
DEFAULT_STYLESHEET_KEYS = ['', 'DEFAULT'].to_set
|
104
109
|
|
105
|
-
DEFAULT_STYLESHEET_NAME =
|
110
|
+
DEFAULT_STYLESHEET_NAME = 'asciidoctor.css'
|
106
111
|
|
107
112
|
# Pointers to the preferred version for a given backend.
|
108
113
|
BACKEND_ALIASES = {
|
@@ -133,21 +138,22 @@ module Asciidoctor
|
|
133
138
|
|
134
139
|
ADMONITION_STYLES = ['NOTE', 'TIP', 'IMPORTANT', 'WARNING', 'CAUTION'].to_set
|
135
140
|
|
136
|
-
|
137
|
-
PARAGRAPH_STYLES = ['comment', 'example', 'literal', 'listing', 'normal', 'pass', 'quote', 'sidebar', 'source', 'verse'].to_set
|
141
|
+
PARAGRAPH_STYLES = ['comment', 'example', 'literal', 'listing', 'normal', 'pass', 'quote', 'sidebar', 'source', 'verse', 'abstract', 'partintro'].to_set
|
138
142
|
|
139
143
|
VERBATIM_STYLES = ['literal', 'listing', 'source', 'verse'].to_set
|
140
144
|
|
141
145
|
DELIMITED_BLOCKS = {
|
142
|
-
|
143
|
-
'--' => [:open, ['comment', 'example', 'literal', 'listing', 'pass', 'quote', 'sidebar', 'source', 'verse', 'admonition'].to_set],
|
146
|
+
'--' => [:open, ['comment', 'example', 'literal', 'listing', 'pass', 'quote', 'sidebar', 'source', 'verse', 'admonition', 'abstract', 'partintro'].to_set],
|
144
147
|
'----' => [:listing, ['literal', 'source'].to_set],
|
145
148
|
'....' => [:literal, ['listing', 'source'].to_set],
|
146
149
|
'====' => [:example, ['admonition'].to_set],
|
147
150
|
'****' => [:sidebar, Set.new],
|
148
151
|
'____' => [:quote, ['verse'].to_set],
|
152
|
+
'""' => [:quote, ['verse'].to_set],
|
149
153
|
'++++' => [:pass, Set.new],
|
150
154
|
'|===' => [:table, Set.new],
|
155
|
+
',===' => [:table, Set.new],
|
156
|
+
':===' => [:table, Set.new],
|
151
157
|
'!===' => [:table, Set.new],
|
152
158
|
'////' => [:comment, Set.new],
|
153
159
|
'```' => [:fenced_code, Set.new],
|
@@ -173,12 +179,19 @@ module Asciidoctor
|
|
173
179
|
:upperroman => /[IVX]+\)/
|
174
180
|
}
|
175
181
|
|
182
|
+
ORDERED_LIST_KEYWORDS = {
|
183
|
+
'loweralpha' => 'a',
|
184
|
+
'lowerroman' => 'i',
|
185
|
+
'upperalpha' => 'A',
|
186
|
+
'upperroman' => 'I'
|
187
|
+
}
|
188
|
+
|
176
189
|
LIST_CONTINUATION = '+'
|
177
190
|
|
178
191
|
LINE_BREAK = ' +'
|
179
192
|
|
180
193
|
# NOTE allows for empty space in line as it could be left by the template engine
|
181
|
-
|
194
|
+
BLANK_LINE_PATTERN = /^[[:blank:]]*\n/
|
182
195
|
|
183
196
|
LINE_FEED_ENTITY = ' ' # or 

|
184
197
|
|
@@ -200,7 +213,12 @@ module Asciidoctor
|
|
200
213
|
# a block to be different lengths
|
201
214
|
# this option requires that they be the same
|
202
215
|
# Compliance value: false
|
203
|
-
:congruent_block_delimiters => true
|
216
|
+
:congruent_block_delimiters => true,
|
217
|
+
|
218
|
+
# AsciiDoc will recognize commonly-used Markdown syntax
|
219
|
+
# to the degree it does not interfere with existing
|
220
|
+
# AsciiDoc behavior.
|
221
|
+
:markdown_syntax => true
|
204
222
|
}
|
205
223
|
|
206
224
|
# The following pattern, which appears frequently, captures the contents between square brackets,
|
@@ -223,10 +241,11 @@ module Asciidoctor
|
|
223
241
|
# [[ref]] (anywhere inline)
|
224
242
|
:anchor_macro => /\\?\[\[([\w":].*?)\]\]/,
|
225
243
|
|
226
|
-
# matches any block delimiter:
|
227
|
-
#
|
228
|
-
#
|
229
|
-
|
244
|
+
# matches any unbounded block delimiter:
|
245
|
+
# listing, literal, example, sidebar, quote, passthrough, table, fenced code
|
246
|
+
# does not include open block or air quotes
|
247
|
+
# TIP position the most common blocks towards the front of the pattern
|
248
|
+
:any_blk => %r{^(?:(?:-|\.|=|\*|_|\+|/){4,}|[\|,;!]={3,}|(?:`|~){3,}.*)$},
|
230
249
|
|
231
250
|
# detect a list item of any sort
|
232
251
|
# [[:graph:]] is a non-blank character
|
@@ -262,15 +281,15 @@ module Asciidoctor
|
|
262
281
|
# [NOTE, caption="Good to know"]
|
263
282
|
# Can be defined by an attribute
|
264
283
|
# [{lead}]
|
265
|
-
:blk_attr_list => /^\[(|[[:blank:]]*[\w\{
|
284
|
+
:blk_attr_list => /^\[(|[[:blank:]]*[\w\{,.#"'].*)\]$/,
|
266
285
|
|
267
286
|
# block attribute list or block id (bulk query)
|
268
|
-
:attr_line => /^\[(|[[:blank:]]*[\w\{
|
287
|
+
:attr_line => /^\[(|[[:blank:]]*[\w\{,.#"'].*|\[[^\[\]]*\])\]$/,
|
269
288
|
|
270
289
|
# attribute reference
|
271
290
|
# {foo}
|
272
291
|
# {counter:pcount:1}
|
273
|
-
:attr_ref => /(
|
292
|
+
:attr_ref => /(\\)?\{((set|counter2?):.+?|\w+(?:[\-]\w+)*)(\\)?\}/,
|
274
293
|
|
275
294
|
# The author info line the appears immediately following the document title
|
276
295
|
# John Doe <john@anonymous.com>
|
@@ -297,18 +316,18 @@ module Asciidoctor
|
|
297
316
|
# // (and then whatever)
|
298
317
|
:comment => %r{^//(?:[^/]|$)},
|
299
318
|
|
300
|
-
# one,two
|
301
|
-
|
302
|
-
|
303
|
-
|
319
|
+
# one,two;three;four
|
320
|
+
:ssv_or_csv_delim => /,|;/,
|
321
|
+
|
322
|
+
# one two three
|
323
|
+
:space_delim => /([^\\])[[:blank:]]+/,
|
304
324
|
|
305
|
-
#
|
306
|
-
#
|
307
|
-
|
308
|
-
:semicolon_delim => /[[:blank:]]*;[[:blank:]]*/,
|
325
|
+
# Ctrl + Alt+T
|
326
|
+
# Ctrl,T
|
327
|
+
:kbd_delim => /(?:\+|,)(?=[[:blank:]]*[^\1])/,
|
309
328
|
|
310
|
-
# one
|
311
|
-
:
|
329
|
+
# one\ two\ three
|
330
|
+
:escaped_space => /\\([[:blank:]])/,
|
312
331
|
|
313
332
|
# 29
|
314
333
|
:digits => /^\d+$/,
|
@@ -330,14 +349,27 @@ module Asciidoctor
|
|
330
349
|
'::::' => /^[[:blank:]]*((?:.*[^:])?)(::::)(?:[[:blank:]]+(.*))?$/,
|
331
350
|
';;' => /^[[:blank:]]*(.*)(;;)(?:[[:blank:]]+(.*))?$/
|
332
351
|
},
|
333
|
-
# ====
|
334
|
-
#:example => /^={4,}$/,
|
335
352
|
|
336
353
|
# footnote:[text]
|
337
354
|
# footnoteref:[id,text]
|
338
355
|
# footnoteref:[id]
|
339
356
|
:footnote_macro => /\\?(footnote|footnoteref):\[((?:\\\]|[^\]])*?)\]/,
|
340
357
|
|
358
|
+
# kbd:[F3]
|
359
|
+
# kbd:[Ctrl+Shift+T]
|
360
|
+
# kbd:[Ctrl+\]]
|
361
|
+
# kbd:[Ctrl,T]
|
362
|
+
# btn:[Save]
|
363
|
+
:kbd_btn_macro => /\\?(?:kbd|btn):\[((?:\\\]|[^\]])+?)\]/,
|
364
|
+
|
365
|
+
# menu:File[New...]
|
366
|
+
# menu:View[Page Style > No Style]
|
367
|
+
# menu:View[Page Style, No Style]
|
368
|
+
:menu_macro => /\\?menu:(\w|\w.*?\S)\[[[:blank:]]*(.+?)?\]/,
|
369
|
+
|
370
|
+
# "File > New..."
|
371
|
+
:menu_inline_macro => /\\?"(\w[^"]*?[[:blank:]]*>[[:blank:]]*[^"[:blank:]][^"]*)"/,
|
372
|
+
|
341
373
|
# image::filename.png[Caption]
|
342
374
|
# video::http://youtube.com/12345[Cats vs Dogs]
|
343
375
|
:media_blk_macro => /^(image|video|audio)::(\S+?)\[((?:\\\]|[^\]])*?)\]$/,
|
@@ -371,7 +403,7 @@ module Asciidoctor
|
|
371
403
|
|
372
404
|
# inline link and some inline link macro
|
373
405
|
# FIXME revisit!
|
374
|
-
:link_inline => %r{(^|link:|\s|>|<|[\(\)\[\]])(\\?(?:https?|ftp)://[^\s\[<]*[^\s.,\[<])(?:\[((?:\\\]|[^\]])*?)\])?},
|
406
|
+
:link_inline => %r{(^|link:|\s|>|<|[\(\)\[\]])(\\?(?:https?|ftp|irc)://[^\s\[<]*[^\s.,\[<])(?:\[((?:\\\]|[^\]])*?)\])?},
|
375
407
|
|
376
408
|
# inline link macro
|
377
409
|
# link:path[label]
|
@@ -381,18 +413,9 @@ module Asciidoctor
|
|
381
413
|
# doc.writer@asciidoc.org
|
382
414
|
:email_inline => /[\\>:]?\w[\w.%+-]*@[[:alnum:]][[:alnum:].-]*\.[[:alpha:]]{2,4}\b/,
|
383
415
|
|
384
|
-
# ----
|
385
|
-
#:listing => /^\-{4,}$/,
|
386
|
-
|
387
|
-
# ....
|
388
|
-
#:literal => /^\.{4,}$/,
|
389
|
-
|
390
416
|
# <TAB>Foo or one-or-more-spaces-or-tabs then whatever
|
391
417
|
:lit_par => /^([[:blank:]]+.*)$/,
|
392
418
|
|
393
|
-
# --
|
394
|
-
#:open_blk => /^\-\-$/,
|
395
|
-
|
396
419
|
# . Foo (up to 5 consecutive dots)
|
397
420
|
# 1. Foo (arabic, default)
|
398
421
|
# a. Foo (loweralpha)
|
@@ -406,9 +429,6 @@ module Asciidoctor
|
|
406
429
|
# <<< (pagebreak)
|
407
430
|
:break_line => /^('|<){3,}$/,
|
408
431
|
|
409
|
-
# ++++
|
410
|
-
#:pass => /^\+{4,}$/,
|
411
|
-
|
412
432
|
# inline passthrough macros
|
413
433
|
# +++text+++
|
414
434
|
# $$text$$
|
@@ -424,22 +444,13 @@ module Asciidoctor
|
|
424
444
|
:pass_lit => /(^|[^`\w])(\\?`([^`\s]|[^`\s].*?\S)`)(?![`\w])/m,
|
425
445
|
|
426
446
|
# placeholder for extracted passthrough text
|
427
|
-
:pass_placeholder => /\
|
428
|
-
|
429
|
-
# ____
|
430
|
-
#:quote => /^_{4,}$/,
|
447
|
+
:pass_placeholder => /\e(\d+)\e/,
|
431
448
|
|
432
449
|
# The document revision info line the appears immediately following the
|
433
450
|
# document title author info line, if present
|
434
451
|
# v1.0, 2013-01-01: Ring in the new year release
|
435
452
|
:revision_info => /^(?:\D*(.*?),)?(?:\s*(?!:)(.*?))(?:\s*(?!^):\s*(.*))?$/,
|
436
453
|
|
437
|
-
# '''
|
438
|
-
#:ruler => /^'{3,}$/,
|
439
|
-
|
440
|
-
# ****
|
441
|
-
#:sidebar_blk => /^\*{4,}$/,
|
442
|
-
|
443
454
|
# \' within a word
|
444
455
|
:single_quote_esc => /(\w)\\'(\w)/,
|
445
456
|
# an alternative if our backend generated single-quoted html/xml attributes
|
@@ -448,16 +459,6 @@ module Asciidoctor
|
|
448
459
|
# used for sanitizing attribute names
|
449
460
|
:illegal_attr_name_chars => /[^\w\-]/,
|
450
461
|
|
451
|
-
# |===
|
452
|
-
# |table
|
453
|
-
# |===
|
454
|
-
#:table => /^\|={3,}$/,
|
455
|
-
|
456
|
-
# !===
|
457
|
-
# !table
|
458
|
-
# !===
|
459
|
-
#:table_nested => /^!={3,}$/,
|
460
|
-
|
461
462
|
# 1*h,2*,^3e
|
462
463
|
:table_colspec => /^(?:(\d+)\*)?([<^>](?:\.[<^>]?)?|(?:[<^>]?\.)?[<^>])?(\d+)?([a-z])?$/,
|
463
464
|
|
@@ -490,7 +491,7 @@ module Asciidoctor
|
|
490
491
|
# match[1] is the delimiter, whose length determines the level
|
491
492
|
# match[2] is the title itself
|
492
493
|
# match[3] is an inline anchor, which becomes the section id
|
493
|
-
:section_title => /^(
|
494
|
+
:section_title => /^((?:=|#){1,6})\s+(\S.*?)(?:\s*\[\[([^\[]+)\]\])?(?:\s+\1)?$/,
|
494
495
|
|
495
496
|
# does not begin with a dot and has at least one alphanumeric character
|
496
497
|
:section_name => /^((?=.*\w+.*)[^.].*?)$/,
|
@@ -664,8 +665,9 @@ module Asciidoctor
|
|
664
665
|
# Document object.
|
665
666
|
#
|
666
667
|
# input - the AsciiDoc source as a IO, String or Array.
|
667
|
-
# options - a Hash of options to control processing (default: {})
|
668
|
-
#
|
668
|
+
# options - a String, Array or Hash of options to control processing (default: {})
|
669
|
+
# String and Array values are converted into a Hash.
|
670
|
+
# See Asciidoctor::Document#initialize for details about options.
|
669
671
|
# block - a callback block for handling include::[] directives
|
670
672
|
#
|
671
673
|
# returns the Asciidoctor::Document
|
@@ -674,10 +676,31 @@ module Asciidoctor
|
|
674
676
|
start = Time.now
|
675
677
|
end
|
676
678
|
|
679
|
+
attrs = (options[:attributes] ||= {})
|
680
|
+
if attrs.is_a? Hash
|
681
|
+
# all good; placed here as optimization
|
682
|
+
elsif attrs.is_a? Array
|
683
|
+
attrs = options[:attributes] = attrs.inject({}) do |accum, entry|
|
684
|
+
k, v = entry.split '=', 2
|
685
|
+
accum[k] = v || ''
|
686
|
+
accum
|
687
|
+
end
|
688
|
+
elsif attrs.is_a? String
|
689
|
+
# convert non-escaped spaces into null character, so we split on the
|
690
|
+
# correct spaces chars, and restore escaped spaces
|
691
|
+
attrs = attrs.gsub(REGEXP[:space_delim], "\\1\0").gsub(REGEXP[:escaped_space], '\1')
|
692
|
+
|
693
|
+
attrs = options[:attributes] = attrs.split("\0").inject({}) do |accum, entry|
|
694
|
+
k, v = entry.split '=', 2
|
695
|
+
accum[k] = v || ''
|
696
|
+
accum
|
697
|
+
end
|
698
|
+
else
|
699
|
+
raise ArgumentError, 'illegal type for attributes option'
|
700
|
+
end
|
701
|
+
|
677
702
|
lines = nil
|
678
|
-
if input.is_a?
|
679
|
-
options[:attributes] ||= {}
|
680
|
-
attrs = options[:attributes]
|
703
|
+
if input.is_a? File
|
681
704
|
lines = input.readlines
|
682
705
|
input_mtime = input.mtime
|
683
706
|
input_path = File.expand_path(input.path)
|
@@ -721,8 +744,9 @@ module Asciidoctor
|
|
721
744
|
# attributes on the Document.
|
722
745
|
#
|
723
746
|
# input - the String AsciiDoc source filename
|
724
|
-
# options - a Hash of options to control processing (default: {})
|
725
|
-
#
|
747
|
+
# options - a String, Array or Hash of options to control processing (default: {})
|
748
|
+
# String and Array values are converted into a Hash.
|
749
|
+
# See Asciidoctor::Document#initialize for details about options.
|
726
750
|
# block - a callback block for handling include::[] directives
|
727
751
|
#
|
728
752
|
# returns the Asciidoctor::Document
|
@@ -753,8 +777,9 @@ module Asciidoctor
|
|
753
777
|
# default and the rendered output is returned.
|
754
778
|
#
|
755
779
|
# input - the String AsciiDoc source filename
|
756
|
-
# options - a Hash of options to control processing (default: {})
|
757
|
-
#
|
780
|
+
# options - a String, Array or Hash of options to control processing (default: {})
|
781
|
+
# String and Array values are converted into a Hash.
|
782
|
+
# See Asciidoctor::Document#initialize for details about options.
|
758
783
|
# block - a callback block for handling include::[] directives
|
759
784
|
#
|
760
785
|
# returns the Document object if the rendered result String is written to a
|
@@ -785,7 +810,7 @@ module Asciidoctor
|
|
785
810
|
elsif write_in_place
|
786
811
|
to_file = File.join(File.dirname(input.path), "#{doc.attributes['docname']}#{doc.attributes['outfilesuffix']}")
|
787
812
|
elsif !stream_output && write_to_target
|
788
|
-
working_dir = options.has_key?(:base_dir) ? File.expand_path(
|
813
|
+
working_dir = options.has_key?(:base_dir) ? File.expand_path(options[:base_dir]) : File.expand_path(Dir.pwd)
|
789
814
|
# QUESTION should the jail be the working_dir or doc.base_dir???
|
790
815
|
jail = doc.safe >= SafeMode::SAFE ? working_dir : nil
|
791
816
|
if to_dir
|
@@ -841,14 +866,16 @@ module Asciidoctor
|
|
841
866
|
end
|
842
867
|
|
843
868
|
# NOTE document cannot control this behavior if safe >= SafeMode::SERVER
|
844
|
-
if !stream_output && doc.attr?('copycss') &&
|
869
|
+
if !stream_output && doc.attr?('basebackend-html') && doc.attr?('copycss') &&
|
845
870
|
doc.attr?('linkcss') && DEFAULT_STYLESHEET_KEYS.include?(doc.attr('stylesheet'))
|
846
871
|
Helpers.require_library 'fileutils'
|
847
872
|
outdir = doc.attr('outdir')
|
848
873
|
stylesdir = doc.normalize_system_path(doc.attr('stylesdir'), outdir,
|
849
874
|
doc.safe >= SafeMode::SAFE ? outdir : nil)
|
850
|
-
|
851
|
-
|
875
|
+
Helpers.mkdir_p stylesdir
|
876
|
+
File.open(File.join(stylesdir, DEFAULT_STYLESHEET_NAME), 'w') {|f|
|
877
|
+
f.write Asciidoctor::HTML5.default_asciidoctor_stylesheet
|
878
|
+
}
|
852
879
|
end
|
853
880
|
doc
|
854
881
|
else
|
@@ -860,8 +887,9 @@ module Asciidoctor
|
|
860
887
|
# and render it to the specified backend format
|
861
888
|
#
|
862
889
|
# input - the String AsciiDoc source filename
|
863
|
-
# options - a Hash of options to control processing (default: {})
|
864
|
-
#
|
890
|
+
# options - a String, Array or Hash of options to control processing (default: {})
|
891
|
+
# String and Array values are converted into a Hash.
|
892
|
+
# See Asciidoctor::Document#initialize for details about options.
|
865
893
|
# block - a callback block for handling include::[] directives
|
866
894
|
#
|
867
895
|
# returns the Document object if the rendered result String is written to a
|
@@ -870,14 +898,6 @@ module Asciidoctor
|
|
870
898
|
Asciidoctor.render(File.new(filename), options, &block)
|
871
899
|
end
|
872
900
|
|
873
|
-
# NOTE still contemplating this method
|
874
|
-
#def self.parse_document_header(input, options = {})
|
875
|
-
# document = Document.new [], options
|
876
|
-
# reader = Reader.new input, document, true
|
877
|
-
# Lexer.parse_document_header reader, document
|
878
|
-
# document
|
879
|
-
#end
|
880
|
-
|
881
901
|
# modules
|
882
902
|
require 'asciidoctor/debug'
|
883
903
|
require 'asciidoctor/substituters'
|
@@ -9,11 +9,15 @@ class AbstractBlock < AbstractNode
|
|
9
9
|
# Public: Set the String block title.
|
10
10
|
attr_writer :title
|
11
11
|
|
12
|
+
# Public: Get/Set the caption for this block
|
13
|
+
attr_accessor :caption
|
14
|
+
|
12
15
|
def initialize(parent, context)
|
13
16
|
super(parent, context)
|
14
17
|
@blocks = []
|
15
18
|
@id = nil
|
16
19
|
@title = nil
|
20
|
+
@caption = nil
|
17
21
|
if context == :document
|
18
22
|
@level = 0
|
19
23
|
elsif !parent.nil? && !self.is_a?(Section)
|
@@ -63,7 +67,7 @@ class AbstractBlock < AbstractNode
|
|
63
67
|
# whether this Block *can* have block content
|
64
68
|
# that should be the option 'sectionbody'
|
65
69
|
def blocks?
|
66
|
-
|
70
|
+
!@blocks.empty?
|
67
71
|
end
|
68
72
|
|
69
73
|
# Public: Get the element at i in the array of blocks.
|
@@ -219,7 +223,7 @@ class AbstractBlock < AbstractNode
|
|
219
223
|
if @document.attributes.has_key?(caption_key)
|
220
224
|
caption_title = @document.attributes["#{key}-caption"]
|
221
225
|
caption_num = @document.counter_increment("#{key}-number", self)
|
222
|
-
@caption =
|
226
|
+
@caption = "#{caption_title} #{caption_num}. "
|
223
227
|
end
|
224
228
|
else
|
225
229
|
@caption = caption
|
@@ -43,14 +43,17 @@ class AbstractNode
|
|
43
43
|
# Document node and return the value of the attribute if found. Otherwise,
|
44
44
|
# return the default value, which defaults to nil.
|
45
45
|
#
|
46
|
-
# name - the name of the attribute to lookup
|
47
|
-
# default - the value to return if the attribute is not found (default: nil)
|
46
|
+
# name - the String or Symbol name of the attribute to lookup
|
47
|
+
# default - the Object value to return if the attribute is not found (default: nil)
|
48
|
+
# inherit - a Boolean indicating whether to check for the attribute on the
|
49
|
+
# AsciiDoctor::Document if not found on this node (default: false)
|
48
50
|
#
|
49
51
|
# return the value of the attribute or the default value if the attribute
|
50
52
|
# is not found in the attributes of this node or the document node
|
51
|
-
def attr(name, default = nil)
|
53
|
+
def attr(name, default = nil, inherit = true)
|
52
54
|
name = name.to_s if name.is_a?(Symbol)
|
53
|
-
if self == @document
|
55
|
+
inherit = false if self == @document
|
56
|
+
if !inherit
|
54
57
|
default.nil? ? @attributes[name] : @attributes.fetch(name, default)
|
55
58
|
else
|
56
59
|
default.nil? ? @attributes.fetch(name, @document.attr(name)) :
|
@@ -59,26 +62,29 @@ class AbstractNode
|
|
59
62
|
end
|
60
63
|
|
61
64
|
# Public: Check if the attribute is defined, optionally performing a
|
62
|
-
# comparison of its value
|
65
|
+
# comparison of its value if expected is not nil
|
63
66
|
#
|
64
67
|
# Check if the attribute is defined. First look in the attributes on this
|
65
68
|
# node. If not found, and this node is a child of the Document node, look in
|
66
69
|
# the attributes of the Document node. If the attribute is found and a
|
67
|
-
# comparison value is specified, return whether the two values match.
|
70
|
+
# comparison value is specified (not nil), return whether the two values match.
|
68
71
|
# Otherwise, return whether the attribute was found.
|
69
72
|
#
|
70
|
-
# name
|
71
|
-
# expect
|
73
|
+
# name - the String or Symbol name of the attribute to lookup
|
74
|
+
# expect - the expected Object value of the attribute (default: nil)
|
75
|
+
# inherit - a Boolean indicating whether to check for the attribute on the
|
76
|
+
# AsciiDoctor::Document if not found on this node (default: false)
|
72
77
|
#
|
73
78
|
# return a Boolean indicating whether the attribute exists and, if a
|
74
79
|
# comparison value is specified, whether the value of the attribute matches
|
75
80
|
# the comparison value
|
76
|
-
def attr?(name, expect = nil)
|
81
|
+
def attr?(name, expect = nil, inherit = true)
|
77
82
|
name = name.to_s if name.is_a?(Symbol)
|
83
|
+
inherit = false if self == @document
|
78
84
|
if expect.nil?
|
79
85
|
if @attributes.has_key? name
|
80
86
|
true
|
81
|
-
elsif
|
87
|
+
elsif inherit
|
82
88
|
@document.attributes.has_key? name
|
83
89
|
else
|
84
90
|
false
|
@@ -86,7 +92,7 @@ class AbstractNode
|
|
86
92
|
else
|
87
93
|
if @attributes.has_key? name
|
88
94
|
@attributes[name] == expect
|
89
|
-
elsif
|
95
|
+
elsif inherit && @document.attributes.has_key?(name)
|
90
96
|
@document.attributes[name] == expect
|
91
97
|
else
|
92
98
|
false
|
@@ -251,7 +257,9 @@ class AbstractNode
|
|
251
257
|
def generate_data_uri(target_image, asset_dir_key = nil)
|
252
258
|
Helpers.require_library 'base64'
|
253
259
|
|
254
|
-
|
260
|
+
ext = File.extname(target_image)[1..-1]
|
261
|
+
mimetype = 'image/' + ext
|
262
|
+
mimetype = "#{mimetype}+xml" if ext == 'svg'
|
255
263
|
if asset_dir_key
|
256
264
|
#asset_dir_path = normalize_system_path(@document.attr(asset_dir_key), nil, nil, :target_name => asset_dir_key)
|
257
265
|
#image_path = normalize_system_path(target_image, asset_dir_path, nil, :target_name => 'image')
|
@@ -287,7 +295,7 @@ class AbstractNode
|
|
287
295
|
# if the file does not exist.
|
288
296
|
def read_asset(path, warn_on_failure = false)
|
289
297
|
if File.readable? path
|
290
|
-
File.read
|
298
|
+
File.read(path).chomp
|
291
299
|
else
|
292
300
|
puts "asciidoctor: WARNING: file does not exist or cannot be read: #{path}" if warn_on_failure
|
293
301
|
nil
|