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
@@ -22,38 +22,31 @@ module Asciidoctor
|
|
22
22
|
# => {'style' => 'quote', 'attribution' => 'Famous Person', 'citetitle' => 'Famous Book (2001)'}
|
23
23
|
#
|
24
24
|
class AttributeList
|
25
|
-
|
26
|
-
# FIXME Opal not inheriting constants from parent scope
|
27
|
-
# NOTE can't use ::RUBY_ENGINE_OPAL here either
|
28
|
-
if ::RUBY_ENGINE == 'opal'
|
29
|
-
CG_BLANK = '[ \\t]'
|
30
|
-
CC_WORD = 'a-zA-Z0-9_'
|
31
|
-
CG_WORD = '[a-zA-Z0-9_]'
|
32
|
-
end
|
25
|
+
BACKSLASH = '\\'
|
33
26
|
|
34
27
|
# Public: Regular expressions for detecting the boundary of a value
|
35
28
|
BoundaryRxs = {
|
36
29
|
'"' => /.*?[^\\](?=")/,
|
37
30
|
'\'' => /.*?[^\\](?=')/,
|
38
|
-
',' => /.*?(
|
31
|
+
',' => /.*?(?=[ \t]*(,|$))/
|
39
32
|
}
|
40
33
|
|
41
34
|
# Public: Regular expressions for unescaping quoted characters
|
42
|
-
|
43
|
-
'"' =>
|
44
|
-
'\'' =>
|
35
|
+
EscapedQuotes = {
|
36
|
+
'"' => '\\"',
|
37
|
+
'\'' => '\\\''
|
45
38
|
}
|
46
39
|
|
47
40
|
# Public: A regular expression for an attribute name (approx. name token from XML)
|
48
41
|
# TODO named attributes cannot contain dash characters
|
49
42
|
NameRx = /#{CG_WORD}[#{CC_WORD}\-.]*/
|
50
43
|
|
51
|
-
BlankRx =
|
44
|
+
BlankRx = /[ \t]+/
|
52
45
|
|
53
46
|
# Public: Regular expressions for skipping blanks and delimiters
|
54
47
|
SkipRxs = {
|
55
48
|
:blank => BlankRx,
|
56
|
-
',' =>
|
49
|
+
',' => /[ \t]*(,|$)/
|
57
50
|
}
|
58
51
|
|
59
52
|
def initialize source, block = nil, delimiter = ','
|
@@ -162,16 +155,27 @@ class AttributeList
|
|
162
155
|
# opts is an alias for options
|
163
156
|
case name
|
164
157
|
when 'options', 'opts'
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
158
|
+
if value.include? ','
|
159
|
+
value = value.delete ' ' if value.include? ' '
|
160
|
+
(value.split ',').each {|opt| @attributes[%(#{opt}-option)] = '' unless opt.empty? }
|
161
|
+
else
|
162
|
+
@attributes[%(#{value = value.strip}-option)] = ''
|
163
|
+
end
|
164
|
+
@attributes['options'] = value
|
170
165
|
else
|
171
|
-
|
166
|
+
if single_quoted_value && @block
|
167
|
+
case name
|
168
|
+
when 'title', 'reftext'
|
169
|
+
@attributes[name] = value
|
170
|
+
else
|
171
|
+
@attributes[name] = @block.apply_subs value
|
172
|
+
end
|
173
|
+
else
|
174
|
+
@attributes[name] = value
|
175
|
+
end
|
172
176
|
end
|
173
177
|
else
|
174
|
-
resolved_name = single_quoted_value &&
|
178
|
+
resolved_name = single_quoted_value && @block ? (@block.apply_subs name) : name
|
175
179
|
if (pos_name = pos_attrs[index])
|
176
180
|
@attributes[pos_name] = resolved_name
|
177
181
|
end
|
@@ -193,7 +197,11 @@ class AttributeList
|
|
193
197
|
|
194
198
|
if (value = scan_to_quote quote)
|
195
199
|
@scanner.get_byte
|
196
|
-
value.
|
200
|
+
if value.include? BACKSLASH
|
201
|
+
value.gsub EscapedQuotes[quote], quote
|
202
|
+
else
|
203
|
+
value
|
204
|
+
end
|
197
205
|
else
|
198
206
|
%(#{quote}#{scan_to_delimiter})
|
199
207
|
end
|
data/lib/asciidoctor/block.rb
CHANGED
@@ -24,7 +24,7 @@ class Block < AbstractBlock
|
|
24
24
|
}).default = :simple
|
25
25
|
|
26
26
|
# Public: Create alias for context to be consistent w/ AsciiDoc
|
27
|
-
alias
|
27
|
+
alias blockname context
|
28
28
|
|
29
29
|
# Public: Get/Set the original Array content for this block, if applicable
|
30
30
|
attr_accessor :lines
|
@@ -74,14 +74,14 @@ class Block < AbstractBlock
|
|
74
74
|
lock_in_subs
|
75
75
|
# e.g., :subs => nil
|
76
76
|
else
|
77
|
-
@subs
|
77
|
+
# NOTE @subs is initialized as empty array by super constructor
|
78
78
|
# prevent subs from being resolved
|
79
79
|
@default_subs = []
|
80
80
|
@attributes.delete 'subs'
|
81
81
|
end
|
82
82
|
# defer subs resolution; subs attribute is honored
|
83
83
|
else
|
84
|
-
@subs
|
84
|
+
# NOTE @subs is initialized as empty array by super constructor
|
85
85
|
# QUESTION should we honor :default_subs option (i.e., @default_subs = opts[:default_subs])?
|
86
86
|
@default_subs = nil
|
87
87
|
end
|
@@ -109,9 +109,9 @@ class Block < AbstractBlock
|
|
109
109
|
when :compound
|
110
110
|
super
|
111
111
|
when :simple
|
112
|
-
apply_subs
|
112
|
+
apply_subs @lines * LF, @subs
|
113
113
|
when :verbatim, :raw
|
114
|
-
#((apply_subs @lines
|
114
|
+
#((apply_subs @lines * LF, @subs).sub StripLineWiseRx, '\1')
|
115
115
|
|
116
116
|
# QUESTION could we use strip here instead of popping empty lines?
|
117
117
|
# maybe apply_subs can know how to strip whitespace?
|
@@ -121,7 +121,7 @@ class Block < AbstractBlock
|
|
121
121
|
else
|
122
122
|
result.shift while (first = result[0]) && first.rstrip.empty?
|
123
123
|
result.pop while (last = result[-1]) && last.rstrip.empty?
|
124
|
-
result *
|
124
|
+
result * LF
|
125
125
|
end
|
126
126
|
else
|
127
127
|
warn %(Unknown content model '#{@content_model}' for block: #{to_s}) unless @content_model == :empty
|
@@ -134,7 +134,7 @@ class Block < AbstractBlock
|
|
134
134
|
# Returns the a String containing the lines joined together or nil if there
|
135
135
|
# are no lines
|
136
136
|
def source
|
137
|
-
@lines *
|
137
|
+
@lines * LF
|
138
138
|
end
|
139
139
|
|
140
140
|
def to_s
|
@@ -7,7 +7,7 @@ module Asciidoctor
|
|
7
7
|
attr_reader :documents
|
8
8
|
attr_reader :code
|
9
9
|
|
10
|
-
def initialize
|
10
|
+
def initialize *options
|
11
11
|
@documents = []
|
12
12
|
@out = nil
|
13
13
|
@err = nil
|
@@ -33,19 +33,12 @@ module Asciidoctor
|
|
33
33
|
return unless @options
|
34
34
|
|
35
35
|
old_verbose = $VERBOSE
|
36
|
-
case @options[:verbose]
|
37
|
-
when 0
|
38
|
-
$VERBOSE = nil
|
39
|
-
when 1
|
40
|
-
$VERBOSE = false
|
41
|
-
when 2
|
42
|
-
$VERBOSE = true
|
43
|
-
end
|
44
|
-
|
45
36
|
opts = {}
|
46
37
|
infiles = []
|
47
38
|
outfile = nil
|
48
|
-
|
39
|
+
err = @err || $stderr
|
40
|
+
show_timings = false
|
41
|
+
|
49
42
|
@options.map do |key, val|
|
50
43
|
case key
|
51
44
|
when :input_files
|
@@ -57,55 +50,75 @@ module Asciidoctor
|
|
57
50
|
when :attributes
|
58
51
|
# NOTE processor will dup attributes internally
|
59
52
|
opts[:attributes] = val
|
53
|
+
when :timings
|
54
|
+
show_timings = val
|
60
55
|
when :trace
|
61
|
-
# currently
|
56
|
+
# currently does nothing
|
57
|
+
when :verbose
|
58
|
+
case val
|
59
|
+
when 0
|
60
|
+
$VERBOSE = nil
|
61
|
+
when 1
|
62
|
+
$VERBOSE = false
|
63
|
+
when 2
|
64
|
+
$VERBOSE = true
|
65
|
+
end
|
62
66
|
else
|
63
67
|
opts[key] = val unless val.nil?
|
64
68
|
end
|
65
69
|
end
|
66
70
|
|
67
|
-
if infiles.size == 1
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
71
|
+
stdin = if infiles.size == 1
|
72
|
+
if (infile0 = infiles[0]) == '-'
|
73
|
+
outfile ||= infile0
|
74
|
+
true
|
75
|
+
elsif ::File.pipe? infile0
|
76
|
+
outfile ||= '-'
|
77
|
+
nil
|
78
|
+
end
|
72
79
|
end
|
73
80
|
|
74
|
-
|
75
|
-
|
76
|
-
tofile = (@out || $stdout)
|
81
|
+
tofile = if outfile == '-'
|
82
|
+
@out || $stdout
|
77
83
|
elsif outfile
|
78
|
-
tofile = outfile
|
79
84
|
opts[:mkdirs] = true
|
85
|
+
outfile
|
80
86
|
else
|
81
|
-
# automatically calculate outfile based on infile unless to_dir is set
|
82
|
-
tofile = nil
|
83
87
|
opts[:mkdirs] = true
|
88
|
+
nil # automatically calculate outfile based on infile
|
84
89
|
end
|
85
90
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
input_opts =
|
91
|
+
if stdin
|
92
|
+
# allows use of block to supply stdin, particularly useful for tests
|
93
|
+
input = block_given? ? yield : STDIN
|
94
|
+
input_opts = opts.merge :to_file => tofile
|
90
95
|
if show_timings
|
91
|
-
timings = Timings.new
|
92
|
-
|
93
|
-
timings.print_report((@err || $stderr), ((input.respond_to? :path) ? input.path : '-'))
|
96
|
+
@documents << (::Asciidoctor.convert input, (input_opts.merge :timings => (timings = Timings.new)))
|
97
|
+
timings.print_report err, '-'
|
94
98
|
else
|
95
|
-
@documents << ::Asciidoctor.convert
|
99
|
+
@documents << (::Asciidoctor.convert input, input_opts)
|
100
|
+
end
|
101
|
+
else
|
102
|
+
infiles.each do |infile|
|
103
|
+
input_opts = opts.merge :to_file => tofile
|
104
|
+
if show_timings
|
105
|
+
@documents << (::Asciidoctor.convert_file infile, (input_opts.merge :timings => (timings = Timings.new)))
|
106
|
+
timings.print_report err, infile
|
107
|
+
else
|
108
|
+
@documents << (::Asciidoctor.convert_file infile, input_opts)
|
109
|
+
end
|
96
110
|
end
|
97
111
|
end
|
98
112
|
rescue ::Exception => e
|
99
113
|
if ::SignalException === e
|
100
114
|
@code = e.signo
|
101
115
|
# add extra endline if Ctrl+C is used
|
102
|
-
|
116
|
+
err.puts if ::Interrupt === e
|
103
117
|
else
|
104
118
|
@code = (e.respond_to? :status) ? e.status : 1
|
105
119
|
if @options[:trace]
|
106
120
|
raise e
|
107
121
|
else
|
108
|
-
err = (@err || $stderr)
|
109
122
|
if ::RuntimeError === e
|
110
123
|
err.puts %(#{e.message} (#{e.class}))
|
111
124
|
else
|
@@ -123,7 +136,7 @@ module Asciidoctor
|
|
123
136
|
@documents[0]
|
124
137
|
end
|
125
138
|
|
126
|
-
def redirect_streams
|
139
|
+
def redirect_streams out, err = nil
|
127
140
|
@out = out
|
128
141
|
@err = err
|
129
142
|
end
|
@@ -56,14 +56,14 @@ Example: asciidoctor -b html5 source.asciidoc
|
|
56
56
|
end
|
57
57
|
opts.on('--safe',
|
58
58
|
'set safe mode level to safe (default: unsafe)',
|
59
|
-
'enables include
|
59
|
+
'enables include directives, but prevents access to ancestor paths of source file',
|
60
60
|
'provided for compatibility with the asciidoc command') do
|
61
61
|
self[:safe] = SafeMode::SAFE
|
62
62
|
end
|
63
|
-
opts.on('-S', '--safe-mode SAFE_MODE', (safe_mode_names = SafeMode.
|
63
|
+
opts.on('-S', '--safe-mode SAFE_MODE', (safe_mode_names = SafeMode.names),
|
64
64
|
%(set safe mode level explicitly: [#{safe_mode_names * ', '}] (default: unsafe)),
|
65
|
-
'disables potentially dangerous macros in source files, such as include::[]') do |
|
66
|
-
self[:safe] = SafeMode.
|
65
|
+
'disables potentially dangerous macros in source files, such as include::[]') do |name|
|
66
|
+
self[:safe] = SafeMode.value_for_name name
|
67
67
|
end
|
68
68
|
opts.on('-s', '--no-header-footer', 'suppress output of header and footer (default: false)') do
|
69
69
|
self[:header_footer] = false
|
@@ -84,7 +84,7 @@ Example: asciidoctor -b html5 source.asciidoc
|
|
84
84
|
val = val ? (FORCE_ENCODING ? (val.force_encoding ::Encoding::UTF_8) : val) : ''
|
85
85
|
# move leading ! to end for internal processing
|
86
86
|
#if !val && key.start_with?('!')
|
87
|
-
# key =
|
87
|
+
# key = %(#{key[1..-1]}!)
|
88
88
|
#end
|
89
89
|
self[:attributes][key] = val
|
90
90
|
end
|
@@ -93,7 +93,7 @@ Example: asciidoctor -b html5 source.asciidoc
|
|
93
93
|
if self[:template_dirs].nil?
|
94
94
|
self[:template_dirs] = [template_dir]
|
95
95
|
elsif ::Array === self[:template_dirs]
|
96
|
-
self[:template_dirs]
|
96
|
+
self[:template_dirs] << template_dir
|
97
97
|
else
|
98
98
|
self[:template_dirs] = [self[:template_dirs], template_dir]
|
99
99
|
end
|
@@ -128,8 +128,19 @@ Example: asciidoctor -b html5 source.asciidoc
|
|
128
128
|
self[:timings] = true
|
129
129
|
end
|
130
130
|
|
131
|
-
opts.on_tail('-h', '--help', '
|
132
|
-
|
131
|
+
opts.on_tail('-h', '--help [TOPIC]', 'print the help message',
|
132
|
+
'show the command usage if TOPIC is not specified (or not recognized)',
|
133
|
+
'dump the Asciidoctor man page (in troff/groff format) if TOPIC is manpage') do |topic|
|
134
|
+
if topic == 'manpage'
|
135
|
+
if ::File.exist?(manpage_path = (::File.join ::Asciidoctor::ROOT_PATH, 'man', 'asciidoctor.1'))
|
136
|
+
$stdout.puts(::IO.read manpage_path)
|
137
|
+
else
|
138
|
+
$stderr.puts 'asciidoctor: FAILED: man page not found; try `man asciidoctor`'
|
139
|
+
return 1
|
140
|
+
end
|
141
|
+
else
|
142
|
+
$stdout.puts opts
|
143
|
+
end
|
133
144
|
return 0
|
134
145
|
end
|
135
146
|
|
@@ -153,12 +164,12 @@ Example: asciidoctor -b html5 source.asciidoc
|
|
153
164
|
|
154
165
|
# shave off the file to process so that options errors appear correctly
|
155
166
|
if args.size == 1 && args[0] == '-'
|
156
|
-
infiles
|
167
|
+
infiles << args.pop
|
157
168
|
elsif
|
158
169
|
args.each do |file|
|
159
170
|
if file == '-' || (file.start_with? '-')
|
160
171
|
# warn, but don't panic; we may have enough to proceed, so we won't force a failure
|
161
|
-
$stderr.puts
|
172
|
+
$stderr.puts %(asciidoctor: WARNING: extra arguments detected (unparsed arguments: '#{args * "', '"}') or incorrect usage of stdin)
|
162
173
|
else
|
163
174
|
if ::File.readable? file
|
164
175
|
matches = [file]
|
@@ -179,7 +190,7 @@ Example: asciidoctor -b html5 source.asciidoc
|
|
179
190
|
end
|
180
191
|
|
181
192
|
infiles.each do |file|
|
182
|
-
unless file == '-' || (::File.file? file)
|
193
|
+
unless file == '-' || (::File.file? file) || (::File.pipe? file)
|
183
194
|
if ::File.readable? file
|
184
195
|
$stderr.puts %(asciidoctor: FAILED: input path #{file} is a #{(::File.stat file).ftype}, not a file)
|
185
196
|
else
|
@@ -184,7 +184,7 @@ module Asciidoctor
|
|
184
184
|
end
|
185
185
|
|
186
186
|
# Alias for backward compatibility.
|
187
|
-
alias
|
187
|
+
alias convert_with_options convert
|
188
188
|
end
|
189
189
|
|
190
190
|
# A module that can be used to mix the {#write} method into a {Converter}
|
@@ -202,9 +202,9 @@ module Asciidoctor
|
|
202
202
|
if target.respond_to? :write
|
203
203
|
target.write output.chomp
|
204
204
|
# ensure there's a trailing endline to be nice to terminals
|
205
|
-
target.write
|
205
|
+
target.write LF
|
206
206
|
else
|
207
|
-
::
|
207
|
+
::IO.write target, output
|
208
208
|
end
|
209
209
|
nil
|
210
210
|
end
|
@@ -34,7 +34,7 @@ module Asciidoctor
|
|
34
34
|
opts.empty? ? (send transform, node) : (send transform, node, opts)
|
35
35
|
end
|
36
36
|
|
37
|
-
alias
|
37
|
+
alias handles? respond_to?
|
38
38
|
|
39
39
|
# Public: Returns the converted content of the {AbstractNode}.
|
40
40
|
#
|
@@ -43,7 +43,7 @@ module Asciidoctor
|
|
43
43
|
node.content
|
44
44
|
end
|
45
45
|
|
46
|
-
alias
|
46
|
+
alias pass content
|
47
47
|
|
48
48
|
# Public: Skips conversion of the {AbstractNode}.
|
49
49
|
#
|
@@ -29,7 +29,7 @@ module Asciidoctor
|
|
29
29
|
result << '</listitem>'
|
30
30
|
end
|
31
31
|
result << %(</orderedlist>)
|
32
|
-
result *
|
32
|
+
result * LF
|
33
33
|
end
|
34
34
|
|
35
35
|
def inline_anchor node
|
@@ -66,7 +66,7 @@ module Asciidoctor
|
|
66
66
|
result << %(<email>#{doc.attr email_key}</email>) if doc.attr? email_key
|
67
67
|
result << '</author>'
|
68
68
|
|
69
|
-
result *
|
69
|
+
result * LF
|
70
70
|
end
|
71
71
|
|
72
72
|
def common_attributes id, role = nil, reftext = nil
|
@@ -4,6 +4,8 @@ module Asciidoctor
|
|
4
4
|
# similar to the docbook45 backend from AsciiDoc Python, but migrated to the
|
5
5
|
# DocBook 5 specification.
|
6
6
|
class Converter::DocBook5Converter < Converter::BuiltIn
|
7
|
+
ImageMacroRx = /^image::?(.+?)\[(.*?)\]$/
|
8
|
+
|
7
9
|
def document node
|
8
10
|
result = []
|
9
11
|
if (root_tag_name = node.doctype) == 'manpage'
|
@@ -29,34 +31,25 @@ module Asciidoctor
|
|
29
31
|
end
|
30
32
|
lang_attribute = (node.attr? 'nolang') ? nil : %( #{lang_attribute_name}="#{node.attr 'lang', 'en'}")
|
31
33
|
result << %(<#{root_tag_name}#{document_ns_attributes node}#{lang_attribute}>)
|
32
|
-
result << (document_info_element node, root_tag_name)
|
34
|
+
result << (document_info_element node, root_tag_name) unless node.noheader
|
33
35
|
result << node.content if node.blocks?
|
34
36
|
unless (footer_docinfo = node.docinfo :footer).empty?
|
35
37
|
result << footer_docinfo
|
36
38
|
end
|
37
39
|
result << %(</#{root_tag_name}>)
|
38
40
|
|
39
|
-
result *
|
41
|
+
result * LF
|
40
42
|
end
|
41
43
|
|
42
|
-
alias
|
44
|
+
alias embedded content
|
45
|
+
|
46
|
+
MANPAGE_SECTION_TAGS = { 'section' => 'refsection', 'synopsis' => 'refsynopsisdiv' }
|
43
47
|
|
44
48
|
def section node
|
45
|
-
|
46
|
-
|
47
|
-
if (tag_name = node.sectname).start_with? 'sect'
|
48
|
-
# a normal child section of a special section
|
49
|
-
tag_name = 'section'
|
50
|
-
end
|
49
|
+
if node.document.doctype == 'manpage'
|
50
|
+
tag_name = MANPAGE_SECTION_TAGS[tag_name = node.sectname] || tag_name
|
51
51
|
else
|
52
|
-
tag_name =
|
53
|
-
end
|
54
|
-
if doctype == 'manpage'
|
55
|
-
if tag_name == 'section'
|
56
|
-
tag_name = 'refsection'
|
57
|
-
elsif tag_name == 'synopsis'
|
58
|
-
tag_name = 'refsynopsisdiv'
|
59
|
-
end
|
52
|
+
tag_name = node.sectname
|
60
53
|
end
|
61
54
|
%(<#{tag_name}#{common_attributes node.id, node.role, node.reftext}>
|
62
55
|
<title>#{node.title}</title>
|
@@ -70,7 +63,7 @@ module Asciidoctor
|
|
70
63
|
</#{tag_name}>)
|
71
64
|
end
|
72
65
|
|
73
|
-
alias
|
66
|
+
alias audio skip
|
74
67
|
|
75
68
|
def colist node
|
76
69
|
result = []
|
@@ -83,16 +76,10 @@ module Asciidoctor
|
|
83
76
|
result << '</callout>'
|
84
77
|
end
|
85
78
|
result << %(</calloutlist>)
|
86
|
-
result *
|
79
|
+
result * LF
|
87
80
|
end
|
88
81
|
|
89
82
|
(DLIST_TAGS = {
|
90
|
-
'labeled' => {
|
91
|
-
:list => 'variablelist',
|
92
|
-
:entry => 'varlistentry',
|
93
|
-
:term => 'term',
|
94
|
-
:item => 'listitem'
|
95
|
-
},
|
96
83
|
'qanda' => {
|
97
84
|
:list => 'qandaset',
|
98
85
|
:entry => 'qandaentry',
|
@@ -106,7 +93,7 @@ module Asciidoctor
|
|
106
93
|
:term => 'glossterm',
|
107
94
|
:item => 'glossdef'
|
108
95
|
}
|
109
|
-
}).default = { # default
|
96
|
+
}).default = { # default is variable
|
110
97
|
:list => 'variablelist',
|
111
98
|
:entry => 'varlistentry',
|
112
99
|
:term => 'term',
|
@@ -172,7 +159,7 @@ module Asciidoctor
|
|
172
159
|
result << %(</#{list_tag}>) if list_tag
|
173
160
|
end
|
174
161
|
|
175
|
-
result *
|
162
|
+
result * LF
|
176
163
|
end
|
177
164
|
|
178
165
|
def example node
|
@@ -193,19 +180,29 @@ module Asciidoctor
|
|
193
180
|
end
|
194
181
|
|
195
182
|
def image node
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
183
|
+
# NOTE according to the DocBook spec, content area, scaling, and scaling to fit are mutually exclusive
|
184
|
+
# See http://tdg.docbook.org/tdg/4.5/imagedata-x.html#d0e79635
|
185
|
+
if node.attr? 'scaledwidth'
|
186
|
+
width_attribute = %( width="#{node.attr 'scaledwidth'}")
|
187
|
+
depth_attribute = nil
|
188
|
+
scale_attribute = nil
|
189
|
+
elsif node.attr? 'scale'
|
190
|
+
# QUESTION should we set the viewport using width and depth? (the scaled image would be contained within this box)
|
191
|
+
#width_attribute = (node.attr? 'width') ? %( width="#{node.attr 'width'}") : nil
|
192
|
+
#depth_attribute = (node.attr? 'height') ? %( depth="#{node.attr 'height'}") : nil
|
193
|
+
scale_attribute = %( scale="#{node.attr 'scale'}")
|
194
|
+
else
|
195
|
+
width_attribute = (node.attr? 'width') ? %( contentwidth="#{node.attr 'width'}") : nil
|
196
|
+
depth_attribute = (node.attr? 'height') ? %( contentdepth="#{node.attr 'height'}") : nil
|
197
|
+
scale_attribute = nil
|
198
|
+
end
|
202
199
|
align_attribute = (node.attr? 'align') ? %( align="#{node.attr 'align'}") : nil
|
203
200
|
|
204
201
|
mediaobject = %(<mediaobject>
|
205
202
|
<imageobject>
|
206
|
-
<imagedata fileref="#{node.image_uri(node.attr 'target')}"#{width_attribute}#{depth_attribute}#{
|
203
|
+
<imagedata fileref="#{node.image_uri(node.attr 'target')}"#{width_attribute}#{depth_attribute}#{scale_attribute}#{align_attribute}/>
|
207
204
|
</imageobject>
|
208
|
-
<textobject><phrase>#{node.
|
205
|
+
<textobject><phrase>#{node.alt}</phrase></textobject>
|
209
206
|
</mediaobject>)
|
210
207
|
|
211
208
|
if node.title?
|
@@ -224,7 +221,7 @@ module Asciidoctor
|
|
224
221
|
informal = !node.title?
|
225
222
|
listing_attributes = (common_attributes node.id, node.role, node.reftext)
|
226
223
|
if node.style == 'source' && (node.attr? 'language')
|
227
|
-
numbering = (node.attr? 'linenums') ? 'numbered' : 'unnumbered'
|
224
|
+
numbering = (node.attr? 'linenums', nil, false) ? 'numbered' : 'unnumbered'
|
228
225
|
listing_content = %(<programlisting#{informal ? listing_attributes : nil} language="#{node.attr 'language', nil, false}" linenumbering="#{numbering}">#{node.content}</programlisting>)
|
229
226
|
else
|
230
227
|
listing_content = %(<screen#{informal ? listing_attributes : nil}>#{node.content}</screen>)
|
@@ -256,10 +253,12 @@ module Asciidoctor
|
|
256
253
|
|
257
254
|
def stem node
|
258
255
|
if (idx = node.subs.index :specialcharacters)
|
259
|
-
node.subs.
|
256
|
+
node.subs.delete_at idx
|
257
|
+
equation = node.content
|
258
|
+
idx > 0 ? (node.subs.insert idx, :specialcharacters) : (node.subs.unshift :specialcharacters)
|
259
|
+
else
|
260
|
+
equation = node.content
|
260
261
|
end
|
261
|
-
equation = node.content
|
262
|
-
node.subs.insert idx, :specialcharacters if idx
|
263
262
|
if node.style == 'asciimath'
|
264
263
|
if ((defined? ::AsciiMath) || ((defined? @asciimath_available) ? @asciimath_available :
|
265
264
|
(@asciimath_available = Helpers.require_library 'asciimath', true, :warn)))
|
@@ -299,13 +298,13 @@ module Asciidoctor
|
|
299
298
|
result << '</listitem>'
|
300
299
|
end
|
301
300
|
result << %(</orderedlist>)
|
302
|
-
result *
|
301
|
+
result * LF
|
303
302
|
end
|
304
303
|
|
305
304
|
def open node
|
306
305
|
case node.style
|
307
306
|
when 'abstract'
|
308
|
-
if node.parent == node.document && node.document.
|
307
|
+
if node.parent == node.document && node.document.doctype == 'book'
|
309
308
|
warn 'asciidoctor: WARNING: abstract block cannot be used in a document without a title when doctype is book. Excluding block content.'
|
310
309
|
''
|
311
310
|
else
|
@@ -368,7 +367,7 @@ module Asciidoctor
|
|
368
367
|
end
|
369
368
|
result << (resolve_content node)
|
370
369
|
result << '</blockquote>'
|
371
|
-
result *
|
370
|
+
result * LF
|
372
371
|
end
|
373
372
|
|
374
373
|
def thematic_break node
|
@@ -382,7 +381,6 @@ module Asciidoctor
|
|
382
381
|
end
|
383
382
|
|
384
383
|
TABLE_PI_NAMES = ['dbhtml', 'dbfo', 'dblatex']
|
385
|
-
TABLE_SECTIONS = [:head, :foot, :body]
|
386
384
|
|
387
385
|
def table node
|
388
386
|
has_body = false
|
@@ -407,10 +405,11 @@ module Asciidoctor
|
|
407
405
|
node.columns.each do |col|
|
408
406
|
result << %(<colspec colname="col_#{col.attr 'colnumber'}" colwidth="#{col.attr col_width_key}*"/>)
|
409
407
|
end
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
408
|
+
node.rows.by_section.each do |tsec, rows|
|
409
|
+
next if rows.empty?
|
410
|
+
has_body = true if tsec == :body
|
411
|
+
result << %(<t#{tsec}>)
|
412
|
+
rows.each do |row|
|
414
413
|
result << '<row>'
|
415
414
|
row.each do |cell|
|
416
415
|
halign_attribute = (cell.attr? 'halign') ? %( align="#{cell.attr 'halign'}") : nil
|
@@ -419,20 +418,20 @@ module Asciidoctor
|
|
419
418
|
rowspan_attribute = cell.rowspan ? %( morerows="#{cell.rowspan - 1}") : nil
|
420
419
|
# NOTE <entry> may not have whitespace (e.g., line breaks) as a direct descendant according to DocBook rules
|
421
420
|
entry_start = %(<entry#{halign_attribute}#{valign_attribute}#{colspan_attribute}#{rowspan_attribute}>)
|
422
|
-
|
423
|
-
cell.text
|
421
|
+
if tsec == :head
|
422
|
+
cell_content = cell.text
|
424
423
|
else
|
425
424
|
case cell.style
|
426
425
|
when :asciidoc
|
427
|
-
cell.content
|
426
|
+
cell_content = cell.content
|
428
427
|
when :verse
|
429
|
-
%(<literallayout>#{cell.text}</literallayout>)
|
428
|
+
cell_content = %(<literallayout>#{cell.text}</literallayout>)
|
430
429
|
when :literal
|
431
|
-
%(<literallayout class="monospaced">#{cell.text}</literallayout>)
|
430
|
+
cell_content = %(<literallayout class="monospaced">#{cell.text}</literallayout>)
|
432
431
|
when :header
|
433
|
-
cell.content.
|
432
|
+
cell_content = (cell_content = cell.content).empty? ? '' : %(<simpara><emphasis role="strong">#{cell_content * '</emphasis></simpara><simpara><emphasis role="strong">'}</emphasis></simpara>)
|
434
433
|
else
|
435
|
-
cell.content.
|
434
|
+
cell_content = (cell_content = cell.content).empty? ? '' : %(<simpara>#{cell_content * '</simpara><simpara>'}</simpara>)
|
436
435
|
end
|
437
436
|
end
|
438
437
|
entry_end = (node.document.attr? 'cellbgcolor') ? %(<?dbfo bgcolor="#{node.document.attr 'cellbgcolor'}"?></entry>) : '</entry>'
|
@@ -440,16 +439,16 @@ module Asciidoctor
|
|
440
439
|
end
|
441
440
|
result << '</row>'
|
442
441
|
end
|
443
|
-
result << %(</t#{
|
442
|
+
result << %(</t#{tsec}>)
|
444
443
|
end
|
445
444
|
result << '</tgroup>'
|
446
445
|
result << %(</#{tag_name}>)
|
447
446
|
|
448
447
|
warn 'asciidoctor: WARNING: tables must have at least one body row' unless has_body
|
449
|
-
result *
|
448
|
+
result * LF
|
450
449
|
end
|
451
450
|
|
452
|
-
alias
|
451
|
+
alias toc skip
|
453
452
|
|
454
453
|
def ulist node
|
455
454
|
result = []
|
@@ -482,7 +481,7 @@ module Asciidoctor
|
|
482
481
|
result << '</itemizedlist>'
|
483
482
|
end
|
484
483
|
|
485
|
-
result *
|
484
|
+
result * LF
|
486
485
|
end
|
487
486
|
|
488
487
|
def verse node
|
@@ -501,15 +500,15 @@ module Asciidoctor
|
|
501
500
|
end
|
502
501
|
result << %(<literallayout>#{node.content}</literallayout>)
|
503
502
|
result << '</blockquote>'
|
504
|
-
result *
|
503
|
+
result * LF
|
505
504
|
end
|
506
505
|
|
507
|
-
alias
|
506
|
+
alias video skip
|
508
507
|
|
509
508
|
def inline_anchor node
|
510
509
|
case node.type
|
511
510
|
when :ref
|
512
|
-
%(<anchor#{common_attributes node.
|
511
|
+
%(<anchor#{common_attributes((id = node.id), nil, node.reftext || %([#{id}]))}/>)
|
513
512
|
when :xref
|
514
513
|
if (path = node.attributes['path'])
|
515
514
|
# QUESTION should we use refid as fallback text instead? (like the html5 backend?)
|
@@ -521,8 +520,8 @@ module Asciidoctor
|
|
521
520
|
when :link
|
522
521
|
%(<link xl:href="#{node.target}">#{node.text}</link>)
|
523
522
|
when :bibref
|
524
|
-
|
525
|
-
%(<anchor#{common_attributes
|
523
|
+
# NOTE technically node.text should be node.reftext, but subs have already been applied to text
|
524
|
+
%(<anchor#{common_attributes node.id, nil, (text = node.text)}/>#{text})
|
526
525
|
else
|
527
526
|
warn %(asciidoctor: WARNING: unknown anchor type: #{node.type.inspect})
|
528
527
|
end
|
@@ -555,7 +554,7 @@ module Asciidoctor
|
|
555
554
|
<imageobject>
|
556
555
|
<imagedata fileref="#{node.type == 'icon' ? (node.icon_uri node.target) : (node.image_uri node.target)}"#{width_attribute}#{depth_attribute}/>
|
557
556
|
</imageobject>
|
558
|
-
<textobject><phrase>#{node.
|
557
|
+
<textobject><phrase>#{node.alt}</phrase></textobject>
|
559
558
|
</inlinemediaobject>)
|
560
559
|
end
|
561
560
|
|
@@ -578,7 +577,7 @@ module Asciidoctor
|
|
578
577
|
result << %(<indexterm>
|
579
578
|
<primary>#{terms[-1]}</primary>
|
580
579
|
</indexterm>)
|
581
|
-
result *
|
580
|
+
result * LF
|
582
581
|
end
|
583
582
|
end
|
584
583
|
|
@@ -586,32 +585,33 @@ module Asciidoctor
|
|
586
585
|
if (keys = node.attr 'keys').size == 1
|
587
586
|
%(<keycap>#{keys[0]}</keycap>)
|
588
587
|
else
|
589
|
-
%(<keycombo>#{keys
|
588
|
+
%(<keycombo><keycap>#{keys * '</keycap><keycap>'}</keycap></keycombo>)
|
590
589
|
end
|
591
590
|
end
|
592
591
|
|
593
592
|
def inline_menu node
|
594
593
|
menu = node.attr 'menu'
|
595
|
-
if
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
594
|
+
if (submenus = node.attr 'submenus').empty?
|
595
|
+
if (menuitem = node.attr 'menuitem', nil, false)
|
596
|
+
%(<menuchoice><guimenu>#{menu}</guimenu> <guimenuitem>#{menuitem}</guimenuitem></menuchoice>)
|
597
|
+
else
|
598
|
+
%(<guimenu>#{menu}</guimenu>)
|
599
|
+
end
|
600
600
|
else
|
601
|
-
%(<guimenu>#{menu}</guimenu>)
|
601
|
+
%(<menuchoice><guimenu>#{menu}</guimenu> <guisubmenu>#{submenus * '</guisubmenu> <guisubmenu>'}</guisubmenu> <guimenuitem>#{node.attr 'menuitem'}</guimenuitem></menuchoice>)
|
602
602
|
end
|
603
603
|
end
|
604
604
|
|
605
605
|
(QUOTE_TAGS = {
|
606
|
+
:monospaced => ['<literal>', '</literal>', false],
|
606
607
|
:emphasis => ['<emphasis>', '</emphasis>', true],
|
607
608
|
:strong => ['<emphasis role="strong">', '</emphasis>', true],
|
608
|
-
:monospaced => ['<literal>', '</literal>', false],
|
609
|
-
:superscript => ['<superscript>', '</superscript>', false],
|
610
|
-
:subscript => ['<subscript>', '</subscript>', false],
|
611
609
|
:double => ['“', '”', true],
|
612
610
|
:single => ['‘', '’', true],
|
613
|
-
:mark => ['<emphasis role="marked">', '</emphasis>', false]
|
614
|
-
|
611
|
+
:mark => ['<emphasis role="marked">', '</emphasis>', false],
|
612
|
+
:superscript => ['<superscript>', '</superscript>', false],
|
613
|
+
:subscript => ['<subscript>', '</subscript>', false]
|
614
|
+
}).default = ['', '', true]
|
615
615
|
|
616
616
|
def inline_quoted node
|
617
617
|
if (type = node.type) == :asciimath
|
@@ -628,11 +628,11 @@ module Asciidoctor
|
|
628
628
|
else
|
629
629
|
open, close, supports_phrase = QUOTE_TAGS[type]
|
630
630
|
text = node.text
|
631
|
-
if
|
631
|
+
if node.role
|
632
632
|
if supports_phrase
|
633
|
-
quoted_text = %(#{open}<phrase role="#{role}">#{text}</phrase>#{close})
|
633
|
+
quoted_text = %(#{open}<phrase role="#{node.role}">#{text}</phrase>#{close})
|
634
634
|
else
|
635
|
-
quoted_text = %(#{open.chop} role="#{role}">#{text}#{close})
|
635
|
+
quoted_text = %(#{open.chop} role="#{node.role}">#{text}#{close})
|
636
636
|
end
|
637
637
|
else
|
638
638
|
quoted_text = %(#{open}#{text}#{close})
|
@@ -658,14 +658,20 @@ module Asciidoctor
|
|
658
658
|
result << %(<email>#{doc.attr email_key}</email>) if doc.attr? email_key
|
659
659
|
result << '</author>'
|
660
660
|
|
661
|
-
result *
|
661
|
+
result * LF
|
662
662
|
end
|
663
663
|
|
664
664
|
def common_attributes id, role = nil, reftext = nil
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
665
|
+
attrs = id ? %( xml:id="#{id}") : ''
|
666
|
+
attrs = %(#{attrs} role="#{role}") if role
|
667
|
+
if reftext
|
668
|
+
if (reftext.include? '<') && ((reftext = reftext.gsub XmlSanitizeRx, '').include? ' ')
|
669
|
+
reftext = (reftext.squeeze ' ').strip
|
670
|
+
end
|
671
|
+
reftext = (reftext.gsub '"', '"') if reftext.include? '"'
|
672
|
+
attrs = %(#{attrs} xreflabel="#{reftext}")
|
673
|
+
end
|
674
|
+
attrs
|
669
675
|
end
|
670
676
|
|
671
677
|
def doctype_declaration root_tag_name
|
@@ -673,7 +679,7 @@ module Asciidoctor
|
|
673
679
|
end
|
674
680
|
|
675
681
|
def document_info_element doc, info_tag_prefix, use_info_tag_prefix = false
|
676
|
-
info_tag_prefix =
|
682
|
+
info_tag_prefix = nil unless use_info_tag_prefix
|
677
683
|
result = []
|
678
684
|
result << %(<#{info_tag_prefix}info>)
|
679
685
|
result << document_title_tags(doc.doctitle :partition => true, :use_fallback => true) unless doc.notitle
|
@@ -703,6 +709,16 @@ module Asciidoctor
|
|
703
709
|
result << %(</revision>
|
704
710
|
</revhistory>)
|
705
711
|
end
|
712
|
+
unless use_info_tag_prefix
|
713
|
+
if (doc.attr? 'front-cover-image') || (doc.attr? 'back-cover-image')
|
714
|
+
if (back_cover_tag = cover_tag doc, 'back')
|
715
|
+
result << (cover_tag doc, 'front', true)
|
716
|
+
result << back_cover_tag
|
717
|
+
elsif (front_cover_tag = cover_tag doc, 'front')
|
718
|
+
result << front_cover_tag
|
719
|
+
end
|
720
|
+
end
|
721
|
+
end
|
706
722
|
unless (head_docinfo = doc.docinfo).empty?
|
707
723
|
result << head_docinfo
|
708
724
|
end
|
@@ -721,7 +737,7 @@ module Asciidoctor
|
|
721
737
|
result << '</refnamediv>'
|
722
738
|
end
|
723
739
|
|
724
|
-
result *
|
740
|
+
result * LF
|
725
741
|
end
|
726
742
|
|
727
743
|
def document_ns_attributes doc
|
@@ -749,5 +765,34 @@ module Asciidoctor
|
|
749
765
|
def title_tag node, optional = true
|
750
766
|
!optional || node.title? ? %(<title>#{node.title}</title>\n) : nil
|
751
767
|
end
|
768
|
+
|
769
|
+
def cover_tag doc, face, use_placeholder = false
|
770
|
+
if (cover_image = doc.attr %(#{face}-cover-image))
|
771
|
+
width_attr = nil
|
772
|
+
depth_attr = nil
|
773
|
+
if (cover_image.include? ':') && ImageMacroRx =~ cover_image
|
774
|
+
cover_image = doc.image_uri $1
|
775
|
+
unless $2.empty?
|
776
|
+
attrs = (AttributeList.new $2).parse ['alt', 'width', 'height']
|
777
|
+
if attrs.key? 'scaledwidth'
|
778
|
+
# NOTE scalefit="1" is the default in this case
|
779
|
+
width_attr = %( width="#{attrs['scaledwidth']}")
|
780
|
+
else
|
781
|
+
width_attr = %( contentwidth="#{attrs['width']}") if attrs.key? 'width'
|
782
|
+
depth_attr = %( contentdepth="#{attrs['height']}") if attrs.key? 'height'
|
783
|
+
end
|
784
|
+
end
|
785
|
+
end
|
786
|
+
%(<cover role="#{face}">
|
787
|
+
<mediaobject>
|
788
|
+
<imageobject>
|
789
|
+
<imagedata fileref="#{cover_image}"#{width_attr}#{depth_attr}/>
|
790
|
+
</imageobject>
|
791
|
+
</mediaobject>
|
792
|
+
</cover>)
|
793
|
+
elsif use_placeholder
|
794
|
+
%(<cover role="#{face}"/>)
|
795
|
+
end
|
796
|
+
end
|
752
797
|
end
|
753
798
|
end
|