asciidoctor 0.0.7 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
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