asciidoctor 0.0.7 → 0.0.9
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.
- data/Gemfile +2 -0
- data/README.asciidoc +35 -26
- data/Rakefile +9 -6
- data/asciidoctor.gemspec +27 -8
- data/bin/asciidoctor +1 -1
- data/lib/asciidoctor.rb +351 -63
- data/lib/asciidoctor/abstract_block.rb +218 -0
- data/lib/asciidoctor/abstract_node.rb +249 -0
- data/lib/asciidoctor/attribute_list.rb +211 -0
- data/lib/asciidoctor/backends/base_template.rb +99 -0
- data/lib/asciidoctor/backends/docbook45.rb +510 -0
- data/lib/asciidoctor/backends/html5.rb +585 -0
- data/lib/asciidoctor/block.rb +27 -254
- data/lib/asciidoctor/callouts.rb +117 -0
- data/lib/asciidoctor/debug.rb +7 -4
- data/lib/asciidoctor/document.rb +229 -77
- data/lib/asciidoctor/inline.rb +29 -0
- data/lib/asciidoctor/lexer.rb +1330 -502
- data/lib/asciidoctor/list_item.rb +33 -34
- data/lib/asciidoctor/reader.rb +305 -142
- data/lib/asciidoctor/renderer.rb +115 -19
- data/lib/asciidoctor/section.rb +100 -189
- data/lib/asciidoctor/substituters.rb +468 -0
- data/lib/asciidoctor/table.rb +499 -0
- data/lib/asciidoctor/version.rb +1 -1
- data/test/attributes_test.rb +301 -87
- data/test/blocks_test.rb +568 -0
- data/test/document_test.rb +221 -24
- data/test/fixtures/dot.gif +0 -0
- data/test/fixtures/encoding.asciidoc +1 -0
- data/test/fixtures/include-file.asciidoc +1 -0
- data/test/fixtures/tip.gif +0 -0
- data/test/headers_test.rb +411 -43
- data/test/lexer_test.rb +265 -45
- data/test/links_test.rb +144 -3
- data/test/lists_test.rb +2252 -74
- data/test/paragraphs_test.rb +21 -30
- data/test/preamble_test.rb +24 -0
- data/test/reader_test.rb +248 -12
- data/test/renderer_test.rb +22 -0
- data/test/substitutions_test.rb +414 -0
- data/test/tables_test.rb +484 -0
- data/test/test_helper.rb +70 -6
- data/test/text_test.rb +30 -6
- metadata +64 -10
- data/lib/asciidoctor/render_templates.rb +0 -317
- data/lib/asciidoctor/string.rb +0 -12
@@ -0,0 +1,211 @@
|
|
1
|
+
# Public: Handles parsing AsciiDoc attribute lists into a Hash of key/value
|
2
|
+
# pairs. By default, attributes must each be separated by a comma and quotes
|
3
|
+
# may be used around the value. If a key is not detected, the value is assigned
|
4
|
+
# to a 1-based positional key, The positional attributes can be "rekeyed" when
|
5
|
+
# given a posattrs array either during parsing or after the fact.
|
6
|
+
#
|
7
|
+
# Examples
|
8
|
+
#
|
9
|
+
# attrlist = Asciidoctor::AttributeList.new('astyle')
|
10
|
+
#
|
11
|
+
# attrlist.parse
|
12
|
+
# => {0 => 'astyle'}
|
13
|
+
#
|
14
|
+
# attrlist.rekey(['style'])
|
15
|
+
# => {'style' => 'astyle'}
|
16
|
+
#
|
17
|
+
# attrlist = Asciidoctor::AttributeList.new('quote, Famous Person, Famous Book (2001)')
|
18
|
+
#
|
19
|
+
# attrlist.parse(['style', 'attribution', 'citetitle'])
|
20
|
+
# => {'style' => 'quote', 'attribution' => 'Famous Person', 'citetitle' => 'Famous Book (2001)'}
|
21
|
+
#
|
22
|
+
class Asciidoctor::AttributeList
|
23
|
+
|
24
|
+
# Public: Regular expressions for detecting the boundary of a value
|
25
|
+
BOUNDARY_PATTERNS = {
|
26
|
+
'"' => /.*?[^\\](?=")/,
|
27
|
+
'\'' => /.*?[^\\](?=')/,
|
28
|
+
',' => /.*?(?=[ \t]*(,|$))/
|
29
|
+
}
|
30
|
+
|
31
|
+
# Public: Regular expressions for unescaping quoted characters
|
32
|
+
UNESCAPE_PATTERNS = {
|
33
|
+
'\\"' => /\\"/,
|
34
|
+
'\\\'' => /\\'/
|
35
|
+
}
|
36
|
+
|
37
|
+
# Public: Regular expressions for skipping blanks and delimiters
|
38
|
+
SKIP_PATTERNS = {
|
39
|
+
:blank => /[ \t]+/,
|
40
|
+
',' => /[ \t]*(,|$)/
|
41
|
+
}
|
42
|
+
|
43
|
+
# Public: A regular expression for an attribute name
|
44
|
+
# TODO named attributes cannot contain dash characters
|
45
|
+
NAME_PATTERN = /[A-Za-z:_][A-Za-z:_\-\.]*/
|
46
|
+
|
47
|
+
# Public: A regular expression for splitting a comma-separated string
|
48
|
+
CSV_SPLIT_PATTERN = /[ \t]*,[ \t]*/
|
49
|
+
|
50
|
+
def initialize(source, block = nil, quotes = ['\'', '"'], delimiter = ',', escape_char = '\\')
|
51
|
+
@scanner = ::StringScanner.new source
|
52
|
+
@block = block
|
53
|
+
@quotes = quotes
|
54
|
+
@escape_char = escape_char
|
55
|
+
@delimiter = delimiter
|
56
|
+
@attributes = nil
|
57
|
+
end
|
58
|
+
|
59
|
+
def parse_into(attributes, posattrs = [])
|
60
|
+
attributes.update(parse(posattrs))
|
61
|
+
end
|
62
|
+
|
63
|
+
def parse(posattrs = [])
|
64
|
+
return @attributes unless @attributes.nil?
|
65
|
+
|
66
|
+
@attributes = {}
|
67
|
+
# not sure if I want this assignment or not
|
68
|
+
#attributes[0] = @scanner.string
|
69
|
+
index = 0
|
70
|
+
|
71
|
+
while parse_attribute(index, posattrs)
|
72
|
+
break if @scanner.eos?
|
73
|
+
skip_delimiter
|
74
|
+
index += 1
|
75
|
+
end
|
76
|
+
|
77
|
+
@attributes
|
78
|
+
end
|
79
|
+
|
80
|
+
def rekey(posattrs)
|
81
|
+
AttributeList.rekey(@attributes, posattrs)
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.rekey(attributes, pos_attrs)
|
85
|
+
pos_attrs.each_with_index do |key, index|
|
86
|
+
pos = index + 1
|
87
|
+
unless (val = attributes[pos]).nil?
|
88
|
+
attributes[key] = val
|
89
|
+
#QUESTION should we delete the positional key?
|
90
|
+
#attributes.delete pos
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
attributes
|
95
|
+
end
|
96
|
+
|
97
|
+
def parse_attribute(index = 0, pos_attrs = [])
|
98
|
+
single_quoted_value = false
|
99
|
+
skip_blank
|
100
|
+
first = @scanner.peek(1)
|
101
|
+
# example: "quote" || 'quote'
|
102
|
+
if @quotes.include? first
|
103
|
+
value = nil
|
104
|
+
name = parse_attribute_value @scanner.get_byte
|
105
|
+
if first == '\''
|
106
|
+
single_quoted_value = true
|
107
|
+
end
|
108
|
+
else
|
109
|
+
name = scan_name
|
110
|
+
|
111
|
+
skipped = 0
|
112
|
+
c = nil
|
113
|
+
if @scanner.eos?
|
114
|
+
if name.nil?
|
115
|
+
return false
|
116
|
+
end
|
117
|
+
else
|
118
|
+
skipped = skip_blank || 0
|
119
|
+
c = @scanner.get_byte
|
120
|
+
end
|
121
|
+
|
122
|
+
# example: quote
|
123
|
+
if c.nil? || c == @delimiter
|
124
|
+
value = nil
|
125
|
+
# example: Sherlock Holmes || =foo=
|
126
|
+
elsif c != '=' || name.nil?
|
127
|
+
remainder = scan_to_delimiter
|
128
|
+
name = '' if name.nil?
|
129
|
+
name += ' ' * skipped + c
|
130
|
+
name += remainder unless remainder.nil?
|
131
|
+
value = nil
|
132
|
+
else
|
133
|
+
skip_blank
|
134
|
+
# example: foo=,
|
135
|
+
if @scanner.peek(1) == @delimiter
|
136
|
+
value = nil
|
137
|
+
else
|
138
|
+
c = @scanner.get_byte
|
139
|
+
|
140
|
+
# example: foo="bar" || foo='bar' || foo="ba\"zaar" || foo='ba\'zaar' || foo='ba"zaar' (all spaces ignored)
|
141
|
+
if @quotes.include? c
|
142
|
+
value = parse_attribute_value c
|
143
|
+
if c == '\''
|
144
|
+
single_quoted_value = true
|
145
|
+
end
|
146
|
+
# example: foo=bar (all spaces ignored)
|
147
|
+
elsif !c.nil?
|
148
|
+
value = c + scan_to_delimiter
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
if value.nil?
|
155
|
+
resolved_name = single_quoted_value && !@block.nil? ? @block.apply_normal_subs(name) : name
|
156
|
+
if !(pos_name = pos_attrs[index]).nil?
|
157
|
+
@attributes[pos_name] = resolved_name
|
158
|
+
else
|
159
|
+
#@attributes[index + 1] = resolved_name
|
160
|
+
end
|
161
|
+
# not sure if we want to always assign the positional key
|
162
|
+
@attributes[index + 1] = resolved_name
|
163
|
+
# not sure if I want this assignment or not
|
164
|
+
#@attributes[resolved_name] = nil
|
165
|
+
else
|
166
|
+
resolved_value = value
|
167
|
+
# example: options="opt1,opt2,opt3"
|
168
|
+
if name == 'options'
|
169
|
+
resolved_value.split(CSV_SPLIT_PATTERN).each do |o|
|
170
|
+
@attributes[o + '-option'] = nil
|
171
|
+
end
|
172
|
+
elsif single_quoted_value && !@block.nil?
|
173
|
+
resolved_value = @block.apply_normal_subs(value)
|
174
|
+
end
|
175
|
+
@attributes[name] = resolved_value
|
176
|
+
end
|
177
|
+
|
178
|
+
true
|
179
|
+
end
|
180
|
+
|
181
|
+
def parse_attribute_value(quote)
|
182
|
+
value = scan_to_quote quote
|
183
|
+
if value.nil?
|
184
|
+
quote + scan_to_delimiter
|
185
|
+
else
|
186
|
+
@scanner.get_byte
|
187
|
+
value.gsub(UNESCAPE_PATTERNS[@escape_char + quote], quote)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def skip_blank
|
192
|
+
@scanner.skip SKIP_PATTERNS[:blank]
|
193
|
+
end
|
194
|
+
|
195
|
+
def skip_delimiter
|
196
|
+
@scanner.skip SKIP_PATTERNS[@delimiter]
|
197
|
+
end
|
198
|
+
|
199
|
+
def scan_name
|
200
|
+
@scanner.scan NAME_PATTERN
|
201
|
+
end
|
202
|
+
|
203
|
+
def scan_to_delimiter
|
204
|
+
@scanner.scan BOUNDARY_PATTERNS[@delimiter]
|
205
|
+
end
|
206
|
+
|
207
|
+
def scan_to_quote(quote)
|
208
|
+
@scanner.scan BOUNDARY_PATTERNS[quote]
|
209
|
+
end
|
210
|
+
|
211
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# An abstract base class that provides methods for definining and rendering the
|
2
|
+
# backend templates. Concrete subclasses must implement the template method.
|
3
|
+
#
|
4
|
+
# NOTE we must use double quotes for attribute values in the HTML/XML output to
|
5
|
+
# prevent quote processing. This requirement seems hackish, but AsciiDoc has
|
6
|
+
# this same issue.
|
7
|
+
class Asciidoctor::BaseTemplate
|
8
|
+
|
9
|
+
attr_reader :view
|
10
|
+
attr_reader :eruby
|
11
|
+
|
12
|
+
def initialize(view, eruby)
|
13
|
+
@view = view
|
14
|
+
@eruby = eruby
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.inherited(klass)
|
18
|
+
@template_classes ||= []
|
19
|
+
@template_classes << klass
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.template_classes
|
23
|
+
@template_classes
|
24
|
+
end
|
25
|
+
|
26
|
+
# Public: Render this template in the execution context of
|
27
|
+
# the supplied concrete instance of Asciidoctor::AbstractNode.
|
28
|
+
#
|
29
|
+
# This method invokes the template method on this instance to retrieve the
|
30
|
+
# template data and then evaluates that template in the context of the
|
31
|
+
# supplied concrete instance of Asciidoctor::AbstractNode. This instance is
|
32
|
+
# accessible to the template data via the local variable named 'template'.
|
33
|
+
#
|
34
|
+
# If the compact flag on the document's renderer is true and the view context is
|
35
|
+
# document or embedded, then blank lines in the output are compacted. Otherwise,
|
36
|
+
# the rendered output is returned unprocessed.
|
37
|
+
#
|
38
|
+
# node - The concrete instance of AsciiDoctor::AbstractNode to render
|
39
|
+
# locals - A Hash of additional variables. Not currently in use.
|
40
|
+
def render(node = Object.new, locals = {})
|
41
|
+
# this is hot code, so we inline both calls rather than capture output to a local variable
|
42
|
+
if node.renderer.compact && (@view == 'document' || @view == 'embedded')
|
43
|
+
compact(template.result(node.get_binding(self)))
|
44
|
+
else
|
45
|
+
template.result(node.get_binding(self))
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Public: Compact blank lines in the provided text. This method also restores
|
50
|
+
# every HTML line feed entity found with an endline character.
|
51
|
+
#
|
52
|
+
# text - the String to process
|
53
|
+
#
|
54
|
+
# returns the text with blank lines removed and HTML line feed entities
|
55
|
+
# converted to an endline character.
|
56
|
+
def compact(str)
|
57
|
+
str.gsub(Asciidoctor::BLANK_LINES_PATTERN, '').gsub(Asciidoctor::LINE_FEED_ENTITY, "\n")
|
58
|
+
end
|
59
|
+
|
60
|
+
# Public: Preserve endlines by replacing them with the HTML line feed entity.
|
61
|
+
#
|
62
|
+
# If the compact flag on the document's renderer is true, perform the
|
63
|
+
# replacement. Otherwise, return the text unprocessed.
|
64
|
+
#
|
65
|
+
# text - the String to process
|
66
|
+
# node - the concrete instance of Asciidoctor::AbstractNode being rendered
|
67
|
+
def preserve_endlines(str, node)
|
68
|
+
node.renderer.compact ? str.gsub("\n", Asciidoctor::LINE_FEED_ENTITY) : str
|
69
|
+
end
|
70
|
+
|
71
|
+
def template
|
72
|
+
raise "You chilluns need to make your own template"
|
73
|
+
end
|
74
|
+
|
75
|
+
# create template matter to insert an attribute if the variable has a value
|
76
|
+
def attribute(name, key)
|
77
|
+
type = key.is_a?(Symbol) ? :attr : :var
|
78
|
+
key = key.to_s
|
79
|
+
if type == :attr
|
80
|
+
# example: <% if attr? 'foo' %> bar="<%= attr 'foo' %>"<% end %>
|
81
|
+
'<% if attr? \'' + key + '\' %> ' + name + '="<%= attr \'' + key.to_s + '\' %>"<% end %>'
|
82
|
+
else
|
83
|
+
# example: <% if foo %> bar="<%= foo %>"<% end %>
|
84
|
+
'<% if ' + key + ' %> ' + name + '="<%= ' + key + ' %>"<% end %>'
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# create template matter to insert a style class if the variable has a value
|
89
|
+
def attrvalue(key, sibling = true)
|
90
|
+
delimiter = sibling ? ' ' : ''
|
91
|
+
# example: <% if attr? 'foo' %><%= attr 'foo' %><% end %>
|
92
|
+
'<% if attr? \'' + key.to_s + '\' %>' + delimiter + '<%= attr \'' + key.to_s + '\' %><% end %>'
|
93
|
+
end
|
94
|
+
|
95
|
+
# create template matter to insert an id if one is specified for the block
|
96
|
+
def id
|
97
|
+
attribute('id', '@id')
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,510 @@
|
|
1
|
+
class Asciidoctor::BaseTemplate
|
2
|
+
def role
|
3
|
+
attribute('role', :role)
|
4
|
+
end
|
5
|
+
|
6
|
+
def xreflabel
|
7
|
+
attribute('xreflabel', :reftext)
|
8
|
+
end
|
9
|
+
|
10
|
+
def title
|
11
|
+
tag('title', 'title')
|
12
|
+
end
|
13
|
+
|
14
|
+
def tag(name, key)
|
15
|
+
type = key.is_a?(Symbol) ? :attr : :var
|
16
|
+
key = key.to_s
|
17
|
+
if type == :attr
|
18
|
+
# example: <% if attr? 'foo' %><bar><%= attr 'foo' %></bar><% end %>
|
19
|
+
'<% if attr? \'' + key + '\' %><' + name + '><%= attr \'' + key + '\' %></' + name + '><% end %>'
|
20
|
+
else
|
21
|
+
# example: <% unless foo.to_s.empty? %><bar><%= foo %></bar><% end %>
|
22
|
+
'<% unless ' + key + '.to_s.empty? %><' + name + '><%= ' + key + ' %></' + name + '><% end %>'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
module Asciidoctor::DocBook45
|
28
|
+
class DocumentTemplate < ::Asciidoctor::BaseTemplate
|
29
|
+
def docinfo
|
30
|
+
<<-EOF
|
31
|
+
<% if has_header? && !notitle %>
|
32
|
+
#{tag 'title', '@header.name'}
|
33
|
+
<% end %>
|
34
|
+
<% if attr? :revdate %>
|
35
|
+
<date><%= attr :revdate %></date>
|
36
|
+
<% else %>
|
37
|
+
<date><%= attr :docdate %></date>
|
38
|
+
<% end %>
|
39
|
+
<% if has_header? %>
|
40
|
+
<% if attr? :author %>
|
41
|
+
<author>
|
42
|
+
#{tag 'firstname', :firstname}
|
43
|
+
#{tag 'othername', :middlename}
|
44
|
+
#{tag 'surname', :lastname}
|
45
|
+
#{tag 'email', :email}
|
46
|
+
</author>
|
47
|
+
#{tag 'authorinitials', :authorinitials}
|
48
|
+
<% end %>
|
49
|
+
<% if (attr? :revnumber) || (attr? :revremark) %>
|
50
|
+
<revhistory>
|
51
|
+
#{tag 'revision', :revnumber}
|
52
|
+
#{tag 'date', :revdate}
|
53
|
+
#{tag 'authorinitials', :authorinitials}
|
54
|
+
#{tag 'revremark', :revremark}
|
55
|
+
</revhistory>
|
56
|
+
<% end %>
|
57
|
+
<% end %>
|
58
|
+
EOF
|
59
|
+
end
|
60
|
+
|
61
|
+
def template
|
62
|
+
@template ||= @eruby.new <<-EOF
|
63
|
+
<%#encoding:UTF-8%>
|
64
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
65
|
+
<!DOCTYPE <%= doctype %> PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
|
66
|
+
<% if attr? :toc %><?asciidoc-toc?><% end %>
|
67
|
+
<% if attr? :numbered %><?asciidoc-numbered?><% end %>
|
68
|
+
<% if doctype == 'book' %>
|
69
|
+
<book lang="en">
|
70
|
+
<bookinfo>
|
71
|
+
#{docinfo}
|
72
|
+
</bookinfo>
|
73
|
+
<%= content %>
|
74
|
+
</book>
|
75
|
+
<% else %>
|
76
|
+
<article lang="en">
|
77
|
+
<articleinfo>
|
78
|
+
#{docinfo}
|
79
|
+
</articleinfo>
|
80
|
+
<%= content %>
|
81
|
+
</article>
|
82
|
+
<% end %>
|
83
|
+
EOF
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
class EmbeddedTemplate < ::Asciidoctor::BaseTemplate
|
88
|
+
def template
|
89
|
+
@template ||= @eruby.new <<-EOS
|
90
|
+
<%#encoding:UTF-8%>
|
91
|
+
<%= content %>
|
92
|
+
EOS
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
class BlockPreambleTemplate < ::Asciidoctor::BaseTemplate
|
97
|
+
def template
|
98
|
+
@template ||= @eruby.new <<-EOF
|
99
|
+
<%#encoding:UTF-8%>
|
100
|
+
<% if document.doctype == 'book' %>
|
101
|
+
<preface#{id}#{role}#{xreflabel}>
|
102
|
+
<title><%= title %></title>
|
103
|
+
<%= content %>
|
104
|
+
</preface>
|
105
|
+
<% else %>
|
106
|
+
<%= content %>
|
107
|
+
<% end %>
|
108
|
+
EOF
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
class SectionTemplate < ::Asciidoctor::BaseTemplate
|
113
|
+
def template
|
114
|
+
@template ||= @eruby.new <<-EOF
|
115
|
+
<%#encoding:UTF-8%>
|
116
|
+
<<%= document.doctype == 'book' && level <= 1 ? 'chapter' : 'section' %>#{id}#{role}#{xreflabel}>
|
117
|
+
#{title}
|
118
|
+
<%= content %>
|
119
|
+
</<%= document.doctype == 'book' && level <= 1 ? 'chapter' : 'section' %>>
|
120
|
+
EOF
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
class BlockParagraphTemplate < ::Asciidoctor::BaseTemplate
|
125
|
+
def template
|
126
|
+
@template ||= @eruby.new <<-EOF
|
127
|
+
<%#encoding:UTF-8%>
|
128
|
+
<% if !title? %>
|
129
|
+
<simpara#{id}#{role}#{xreflabel}><%= content %></simpara>
|
130
|
+
<% else %>
|
131
|
+
<formalpara#{id}#{role}#{xreflabel}>
|
132
|
+
<title><%= title %></title>
|
133
|
+
<para><%= content %></para>
|
134
|
+
</formalpara>
|
135
|
+
<% end %>
|
136
|
+
EOF
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
class BlockAdmonitionTemplate < ::Asciidoctor::BaseTemplate
|
141
|
+
def template
|
142
|
+
@template ||= @eruby.new <<-EOF
|
143
|
+
<%#encoding:UTF-8%>
|
144
|
+
<<%= attr :name %>#{id}#{role}#{xreflabel}>
|
145
|
+
#{title}
|
146
|
+
<% if blocks? %>
|
147
|
+
<%= content %>
|
148
|
+
<% else %>
|
149
|
+
<simpara><%= content.chomp %></simpara>
|
150
|
+
<% end %>
|
151
|
+
</<%= attr :name %>>
|
152
|
+
EOF
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
class BlockUlistTemplate < ::Asciidoctor::BaseTemplate
|
157
|
+
def template
|
158
|
+
@template ||= @eruby.new <<-EOF
|
159
|
+
<%#encoding:UTF-8%>
|
160
|
+
<itemizedlist#{id}#{role}#{xreflabel}>
|
161
|
+
#{title}
|
162
|
+
<% content.each do |li| %>
|
163
|
+
<listitem>
|
164
|
+
<simpara><%= li.text %></simpara>
|
165
|
+
<% if li.blocks? %>
|
166
|
+
<%= li.content %>
|
167
|
+
<% end %>
|
168
|
+
</listitem>
|
169
|
+
<% end %>
|
170
|
+
</itemizedlist>
|
171
|
+
EOF
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
class BlockOlistTemplate < ::Asciidoctor::BaseTemplate
|
176
|
+
def template
|
177
|
+
@template ||= @eruby.new <<-EOF
|
178
|
+
<%#encoding:UTF-8%>
|
179
|
+
<orderedlist#{id}#{role}#{xreflabel}#{attribute('numeration', :style)}>
|
180
|
+
#{title}
|
181
|
+
<% content.each do |li| %>
|
182
|
+
<listitem>
|
183
|
+
<simpara><%= li.text %></simpara>
|
184
|
+
<% if li.blocks? %>
|
185
|
+
<%= li.content %>
|
186
|
+
<% end %>
|
187
|
+
</listitem>
|
188
|
+
<% end %>
|
189
|
+
</orderedlist>
|
190
|
+
EOF
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
class BlockColistTemplate < ::Asciidoctor::BaseTemplate
|
195
|
+
def template
|
196
|
+
@template ||= @eruby.new <<-EOF
|
197
|
+
<%#encoding:UTF-8%>
|
198
|
+
<calloutlist#{id}#{role}#{xreflabel}>
|
199
|
+
#{title}
|
200
|
+
<% content.each do |li| %>
|
201
|
+
<callout arearefs="<%= li.attr :coids %>">
|
202
|
+
<para><%= li.text %></para>
|
203
|
+
<% if li.blocks? %>
|
204
|
+
<%= li.content %>
|
205
|
+
<% end %>
|
206
|
+
</callout>
|
207
|
+
<% end %>
|
208
|
+
</calloutlist>
|
209
|
+
EOF
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
class BlockDlistTemplate < ::Asciidoctor::BaseTemplate
|
214
|
+
def template
|
215
|
+
@template ||= @eruby.new <<-EOF
|
216
|
+
<%#encoding:UTF-8%>
|
217
|
+
<variablelist#{id}#{role}#{xreflabel}>
|
218
|
+
#{title}
|
219
|
+
<% content.each do |dt, dd| %>
|
220
|
+
<varlistentry>
|
221
|
+
<term>
|
222
|
+
<%= dt.text %>
|
223
|
+
</term>
|
224
|
+
<% unless dd.nil? %>
|
225
|
+
<listitem>
|
226
|
+
<% if dd.text? %>
|
227
|
+
<simpara><%= dd.text %></simpara>
|
228
|
+
<% end %>
|
229
|
+
<% if dd.blocks? %>
|
230
|
+
<%= dd.content %>
|
231
|
+
<% end %>
|
232
|
+
</listitem>
|
233
|
+
<% end %>
|
234
|
+
</varlistentry>
|
235
|
+
<% end %>
|
236
|
+
</variablelist>
|
237
|
+
EOF
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
class BlockOpenTemplate < ::Asciidoctor::BaseTemplate
|
242
|
+
def template
|
243
|
+
@template ||= @eruby.new <<-EOS
|
244
|
+
<%#encoding:UTF-8%>
|
245
|
+
<%= content %>
|
246
|
+
EOS
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
class BlockListingTemplate < ::Asciidoctor::BaseTemplate
|
251
|
+
def template
|
252
|
+
@template ||= @eruby.new <<-EOF
|
253
|
+
<%#encoding:UTF-8%>
|
254
|
+
<% if !title? %>
|
255
|
+
<% if (attr :style) == 'source' %>
|
256
|
+
<programlisting#{id}#{role}#{xreflabel}#{attribute('language', :language)} linenumbering="<%= (attr? :linenums) ? 'numbered' : 'unnumbered' %>"><%= template.preserve_endlines(content, self) %></programlisting>
|
257
|
+
<% else %>
|
258
|
+
<screen#{id}#{role}#{xreflabel}><%= template.preserve_endlines(content, self) %></screen>
|
259
|
+
<% end %>
|
260
|
+
<% else %>
|
261
|
+
<formalpara#{id}#{role}#{xreflabel}>
|
262
|
+
<title><%= title %></title>
|
263
|
+
<para>
|
264
|
+
<% if (attr :style) == 'source' %>
|
265
|
+
<programlisting language="<%= attr :language %>" linenumbering="<%= (attr? :linenums) ? 'numbered' : 'unnumbered' %>"><%= template.preserve_endlines(content, self) %></programlisting>
|
266
|
+
<% else %>
|
267
|
+
<screen><%= template.preserve_endlines(content, self) %></screen>
|
268
|
+
<% end %>
|
269
|
+
</para>
|
270
|
+
</formalpara>
|
271
|
+
<% end %>
|
272
|
+
EOF
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
class BlockLiteralTemplate < ::Asciidoctor::BaseTemplate
|
277
|
+
def template
|
278
|
+
@template ||= @eruby.new <<-EOF
|
279
|
+
<%#encoding:UTF-8%>
|
280
|
+
<% if !title? %>
|
281
|
+
<literallayout#{id}#{role}#{xreflabel} class="monospaced"><%= template.preserve_endlines(content, self) %></literallayout>
|
282
|
+
<% else %>
|
283
|
+
<formalpara#{id}#{role}#{xreflabel}>
|
284
|
+
<title><%= title %></title>
|
285
|
+
<para>
|
286
|
+
<literallayout class="monospaced"><%= template.preserve_endlines(content, self) %></literallayout>
|
287
|
+
</para>
|
288
|
+
</formalpara>
|
289
|
+
<% end %>
|
290
|
+
EOF
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
class BlockExampleTemplate < ::Asciidoctor::BaseTemplate
|
295
|
+
def template
|
296
|
+
@template ||= @eruby.new <<-EOF
|
297
|
+
<%#encoding:UTF-8%>
|
298
|
+
<example#{id}#{role}#{xreflabel}>
|
299
|
+
#{title}
|
300
|
+
<%= content %>
|
301
|
+
</example>
|
302
|
+
EOF
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
class BlockSidebarTemplate < ::Asciidoctor::BaseTemplate
|
307
|
+
def template
|
308
|
+
@template ||= @eruby.new <<-EOF
|
309
|
+
<%#encoding:UTF-8%>
|
310
|
+
<sidebar#{id}#{role}#{xreflabel}>
|
311
|
+
#{title}
|
312
|
+
<%= content %>
|
313
|
+
</sidebar>
|
314
|
+
EOF
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
class BlockQuoteTemplate < ::Asciidoctor::BaseTemplate
|
319
|
+
def template
|
320
|
+
@template ||= @eruby.new <<-EOF
|
321
|
+
<%#encoding:UTF-8%>
|
322
|
+
<blockquote#{id}#{role}#{xreflabel}>
|
323
|
+
#{title}
|
324
|
+
<% if (attr? :attribution) || (attr? :citetitle) %>
|
325
|
+
<attribution>
|
326
|
+
<% if attr? :attribution %>
|
327
|
+
<%= attr(:attribution) %>
|
328
|
+
<% end %>
|
329
|
+
#{tag 'citetitle', :citetitle}
|
330
|
+
</attribution>
|
331
|
+
<% end %>
|
332
|
+
<% if !buffer.nil? %>
|
333
|
+
<simpara><%= content %></simpara>
|
334
|
+
<% else %>
|
335
|
+
<%= content %>
|
336
|
+
<% end %>
|
337
|
+
</blockquote>
|
338
|
+
EOF
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
class BlockVerseTemplate < ::Asciidoctor::BaseTemplate
|
343
|
+
def template
|
344
|
+
@template ||= @eruby.new <<-EOF
|
345
|
+
<%#encoding:UTF-8%>
|
346
|
+
<blockquote#{id}#{role}#{xreflabel}>
|
347
|
+
#{title}
|
348
|
+
<% if (attr? :attribution) || (attr? :citetitle) %>
|
349
|
+
<attribution>
|
350
|
+
<% if attr? :attribution %>
|
351
|
+
<%= attr(:attribution) %>
|
352
|
+
<% end %>
|
353
|
+
#{tag 'citetitle', :citetitle}
|
354
|
+
</attribution>
|
355
|
+
<% end %>
|
356
|
+
<literallayout><%= content %></literallayout>
|
357
|
+
</blockquote>
|
358
|
+
EOF
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
class BlockPassTemplate < ::Asciidoctor::BaseTemplate
|
363
|
+
def template
|
364
|
+
@template ||= @eruby.new <<-EOS
|
365
|
+
<%#encoding:UTF-8%>
|
366
|
+
<%= content %>
|
367
|
+
EOS
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
371
|
+
class BlockTableTemplate < ::Asciidoctor::BaseTemplate
|
372
|
+
def template
|
373
|
+
@template ||= @eruby.new <<-EOS
|
374
|
+
<%#encoding:UTF-8%>
|
375
|
+
<<%= title? ? 'table' : 'informaltable'%>#{id}#{role}#{xreflabel} frame="<%= attr :frame, 'all'%>"
|
376
|
+
rowsep="<%= ['none', 'cols'].include?(attr :grid) ? 0 : 1 %>" colsep="<%= ['none', 'rows'].include?(attr :grid) ? 0 : 1 %>">
|
377
|
+
#{title}
|
378
|
+
<% if attr? :width %>
|
379
|
+
<?dbhtml table-width="<%= attr :width %>"?>
|
380
|
+
<?dbfo table-width="<%= attr :width %>"?>
|
381
|
+
<?dblatex table-width="<%= attr :width %>"?>
|
382
|
+
<% end %>
|
383
|
+
<tgroup cols="<%= attr :colcount %>">
|
384
|
+
<% @columns.each do |col| %>
|
385
|
+
<colspec colname="col_<%= col.attr :colnumber %>" colwidth="<%= col.attr((attr? :width) ? :colabswidth : :colpcwidth) %>*"/>
|
386
|
+
<% end %>
|
387
|
+
<% [:head, :foot, :body].select {|tsec| !rows[tsec].empty? }.each do |tsec| %>
|
388
|
+
<t<%= tsec %>>
|
389
|
+
<% @rows[tsec].each do |row| %>
|
390
|
+
<row>
|
391
|
+
<% row.each do |cell| %>
|
392
|
+
<entry#{attribute('align', 'cell.attr :halign')}#{attribute('valign', 'cell.attr :valign')}<%
|
393
|
+
if cell.colspan %> namest="col_<%= cell.column.attr :colnumber %>" nameend="col_<%= (cell.column.attr :colnumber) + cell.colspan - 1 %>"<%
|
394
|
+
end %><% if cell.rowspan %> morerows="<%= cell.rowspan - 1 %>"<% end %>><%
|
395
|
+
if tsec == :head %><%= cell.text %><%
|
396
|
+
else %><%
|
397
|
+
case cell.attr(:style)
|
398
|
+
when :asciidoc %><%= cell.content %><%
|
399
|
+
when :verse %><literallayout><%= template.preserve_endlines(cell.text, self) %></literallayout><%
|
400
|
+
when :literal %><literallayout class="monospaced"><%= template.preserve_endlines(cell.text, self) %></literallayout><%
|
401
|
+
when :header %><% cell.content.each do |text| %><simpara><emphasis role="strong"><%= text %></emphasis></simpara><% end %><%
|
402
|
+
else %><% cell.content.each do |text| %><simpara><%= text %></simpara><% end %><%
|
403
|
+
%><% end %><% end %></entry>
|
404
|
+
<% end %>
|
405
|
+
</row>
|
406
|
+
<% end %>
|
407
|
+
</t<%= tsec %>>
|
408
|
+
<% end %>
|
409
|
+
</tgroup>
|
410
|
+
</<%= title? ? 'table' : 'informaltable'%>>
|
411
|
+
EOS
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
415
|
+
class BlockImageTemplate < ::Asciidoctor::BaseTemplate
|
416
|
+
def template
|
417
|
+
@template ||= @eruby.new <<-EOF
|
418
|
+
<%#encoding:UTF-8%>
|
419
|
+
<figure#{id}#{role}#{xreflabel}>
|
420
|
+
#{title}
|
421
|
+
<mediaobject>
|
422
|
+
<imageobject>
|
423
|
+
<imagedata fileref="<%= image_uri(attr :target) %>"#{attribute('contentwidth', :width)}#{attribute('contentdepth', :height)}/>
|
424
|
+
</imageobject>
|
425
|
+
<textobject><phrase><%= attr :alt %></phrase></textobject>
|
426
|
+
</mediaobject>
|
427
|
+
</figure>
|
428
|
+
EOF
|
429
|
+
end
|
430
|
+
end
|
431
|
+
|
432
|
+
class BlockRulerTemplate < ::Asciidoctor::BaseTemplate
|
433
|
+
def template
|
434
|
+
@template ||= @eruby.new <<-EOF
|
435
|
+
<simpara><?asciidoc-hr?></simpara>
|
436
|
+
EOF
|
437
|
+
end
|
438
|
+
end
|
439
|
+
|
440
|
+
class InlineBreakTemplate < ::Asciidoctor::BaseTemplate
|
441
|
+
def template
|
442
|
+
@template ||= @eruby.new <<-EOF
|
443
|
+
<%= text %><?asciidoc-br?>
|
444
|
+
EOF
|
445
|
+
end
|
446
|
+
end
|
447
|
+
|
448
|
+
class InlineQuotedTemplate < ::Asciidoctor::BaseTemplate
|
449
|
+
QUOTED_TAGS = {
|
450
|
+
:emphasis => ['<emphasis>', '</emphasis>'],
|
451
|
+
:strong => ['<emphasis role="strong">', '</emphasis>'],
|
452
|
+
:monospaced => ['<literal>', '</literal>'],
|
453
|
+
:superscript => ['<superscript>', '</superscript>'],
|
454
|
+
:subscript => ['<subscript>', '</subscript>'],
|
455
|
+
:double => [Asciidoctor::INTRINSICS['ldquo'], Asciidoctor::INTRINSICS['rdquo']],
|
456
|
+
:single => [Asciidoctor::INTRINSICS['lsquo'], Asciidoctor::INTRINSICS['rsquo']],
|
457
|
+
:none => ['', '']
|
458
|
+
}
|
459
|
+
|
460
|
+
def template
|
461
|
+
@template ||= @eruby.new <<-EOF
|
462
|
+
<% tags = template.class::QUOTED_TAGS[@type] %><%= tags.first %><%
|
463
|
+
if attr? :role %><phrase#{role}><%
|
464
|
+
end %><%= @text %><%
|
465
|
+
if attr? :role %></phrase><%
|
466
|
+
end %><%= tags.last %>
|
467
|
+
EOF
|
468
|
+
end
|
469
|
+
end
|
470
|
+
|
471
|
+
class InlineAnchorTemplate < ::Asciidoctor::BaseTemplate
|
472
|
+
def template
|
473
|
+
@template ||= @eruby.new <<-EOF
|
474
|
+
<% if @type == :xref
|
475
|
+
%><%
|
476
|
+
if @text.nil?
|
477
|
+
%><xref linkend="<%= @target %>"/><%
|
478
|
+
else
|
479
|
+
%><link linkend="<%= @target %>"><%= @text %></link><%
|
480
|
+
end %><%
|
481
|
+
elsif @type == :ref
|
482
|
+
%><anchor id="<%= @target %>" xreflabel="<%= @text %>"/><%
|
483
|
+
else
|
484
|
+
%><ulink url="<%= @target %>"><%= @text %></ulink><%
|
485
|
+
end %>
|
486
|
+
EOF
|
487
|
+
end
|
488
|
+
end
|
489
|
+
|
490
|
+
class InlineImageTemplate < ::Asciidoctor::BaseTemplate
|
491
|
+
def template
|
492
|
+
@template ||= @eruby.new <<-EOF
|
493
|
+
<inlinemediaobject>
|
494
|
+
<imageobject>
|
495
|
+
<imagedata fileref="<%= image_uri(@target) %>"#{attribute('width', :width)}#{attribute('depth', :height)}/>
|
496
|
+
</imageobject>
|
497
|
+
<textobject><phrase><%= attr :alt %></phrase></textobject>
|
498
|
+
</inlinemediaobject>
|
499
|
+
EOF
|
500
|
+
end
|
501
|
+
end
|
502
|
+
|
503
|
+
class InlineCalloutTemplate < ::Asciidoctor::BaseTemplate
|
504
|
+
def template
|
505
|
+
@template ||= @eruby.new <<-EOF
|
506
|
+
<co#{id}/>
|
507
|
+
EOF
|
508
|
+
end
|
509
|
+
end
|
510
|
+
end
|