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.

Files changed (47) hide show
  1. data/Gemfile +2 -0
  2. data/README.asciidoc +35 -26
  3. data/Rakefile +9 -6
  4. data/asciidoctor.gemspec +27 -8
  5. data/bin/asciidoctor +1 -1
  6. data/lib/asciidoctor.rb +351 -63
  7. data/lib/asciidoctor/abstract_block.rb +218 -0
  8. data/lib/asciidoctor/abstract_node.rb +249 -0
  9. data/lib/asciidoctor/attribute_list.rb +211 -0
  10. data/lib/asciidoctor/backends/base_template.rb +99 -0
  11. data/lib/asciidoctor/backends/docbook45.rb +510 -0
  12. data/lib/asciidoctor/backends/html5.rb +585 -0
  13. data/lib/asciidoctor/block.rb +27 -254
  14. data/lib/asciidoctor/callouts.rb +117 -0
  15. data/lib/asciidoctor/debug.rb +7 -4
  16. data/lib/asciidoctor/document.rb +229 -77
  17. data/lib/asciidoctor/inline.rb +29 -0
  18. data/lib/asciidoctor/lexer.rb +1330 -502
  19. data/lib/asciidoctor/list_item.rb +33 -34
  20. data/lib/asciidoctor/reader.rb +305 -142
  21. data/lib/asciidoctor/renderer.rb +115 -19
  22. data/lib/asciidoctor/section.rb +100 -189
  23. data/lib/asciidoctor/substituters.rb +468 -0
  24. data/lib/asciidoctor/table.rb +499 -0
  25. data/lib/asciidoctor/version.rb +1 -1
  26. data/test/attributes_test.rb +301 -87
  27. data/test/blocks_test.rb +568 -0
  28. data/test/document_test.rb +221 -24
  29. data/test/fixtures/dot.gif +0 -0
  30. data/test/fixtures/encoding.asciidoc +1 -0
  31. data/test/fixtures/include-file.asciidoc +1 -0
  32. data/test/fixtures/tip.gif +0 -0
  33. data/test/headers_test.rb +411 -43
  34. data/test/lexer_test.rb +265 -45
  35. data/test/links_test.rb +144 -3
  36. data/test/lists_test.rb +2252 -74
  37. data/test/paragraphs_test.rb +21 -30
  38. data/test/preamble_test.rb +24 -0
  39. data/test/reader_test.rb +248 -12
  40. data/test/renderer_test.rb +22 -0
  41. data/test/substitutions_test.rb +414 -0
  42. data/test/tables_test.rb +484 -0
  43. data/test/test_helper.rb +70 -6
  44. data/test/text_test.rb +30 -6
  45. metadata +64 -10
  46. data/lib/asciidoctor/render_templates.rb +0 -317
  47. 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