asciidoctor 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +10 -0
  3. data/Guardfile +18 -0
  4. data/LICENSE +1 -1
  5. data/README.adoc +65 -21
  6. data/Rakefile +10 -0
  7. data/asciidoctor.gemspec +17 -35
  8. data/compat/asciidoc.conf +130 -13
  9. data/lib/asciidoctor.rb +107 -87
  10. data/lib/asciidoctor/abstract_block.rb +6 -2
  11. data/lib/asciidoctor/abstract_node.rb +21 -13
  12. data/lib/asciidoctor/attribute_list.rb +2 -5
  13. data/{stylesheets/asciidoctor.css → lib/asciidoctor/backends/_stylesheets.rb} +96 -46
  14. data/lib/asciidoctor/backends/base_template.rb +9 -4
  15. data/lib/asciidoctor/backends/docbook45.rb +246 -138
  16. data/lib/asciidoctor/backends/html5.rb +580 -381
  17. data/lib/asciidoctor/block.rb +2 -50
  18. data/lib/asciidoctor/cli/options.rb +9 -8
  19. data/lib/asciidoctor/document.rb +35 -45
  20. data/lib/asciidoctor/helpers.rb +10 -0
  21. data/lib/asciidoctor/lexer.rb +456 -148
  22. data/lib/asciidoctor/list_item.rb +0 -21
  23. data/lib/asciidoctor/path_resolver.rb +18 -12
  24. data/lib/asciidoctor/reader.rb +71 -26
  25. data/lib/asciidoctor/renderer.rb +2 -19
  26. data/lib/asciidoctor/section.rb +0 -1
  27. data/lib/asciidoctor/substituters.rb +150 -36
  28. data/lib/asciidoctor/table.rb +30 -24
  29. data/lib/asciidoctor/version.rb +1 -1
  30. data/man/asciidoctor.1 +22 -16
  31. data/man/asciidoctor.ad +24 -16
  32. data/test/attributes_test.rb +50 -0
  33. data/test/blocks_test.rb +660 -9
  34. data/test/document_test.rb +191 -14
  35. data/test/fixtures/encoding.asciidoc +8 -0
  36. data/test/invoker_test.rb +47 -0
  37. data/test/lexer_test.rb +172 -0
  38. data/test/links_test.rb +28 -0
  39. data/test/lists_test.rb +172 -13
  40. data/test/options_test.rb +29 -2
  41. data/test/paragraphs_test.rb +105 -47
  42. data/test/paths_test.rb +3 -3
  43. data/test/reader_test.rb +46 -0
  44. data/test/sections_test.rb +365 -12
  45. data/test/substitutions_test.rb +127 -11
  46. data/test/tables_test.rb +81 -14
  47. data/test/test_helper.rb +18 -7
  48. data/test/text_test.rb +17 -5
  49. metadata +9 -36
@@ -1,147 +1,171 @@
1
+ require 'asciidoctor/backends/_stylesheets'
2
+
1
3
  module Asciidoctor
2
4
  class BaseTemplate
3
5
 
4
6
  # create template matter to insert a style class from the role attribute if specified
5
7
  def role_class
6
- attrvalue(:role)
8
+ attrvalue('role')
7
9
  end
8
10
 
9
11
  # create template matter to insert a style class from the style attribute if specified
10
12
  def style_class(sibling = true)
11
- attrvalue(:style, sibling)
13
+ attrvalue('style', sibling, false)
12
14
  end
13
15
 
14
16
  def title_div(opts = {})
15
- %(<% if title? %><div class="title">#{opts.has_key?(:caption) ? '<%= @caption %>' : ''}<%= title %></div><% end %>)
17
+ if opts.has_key? :caption
18
+ %q(<% if title? %><div class="title"><%= @caption %><%= title %></div><% end %>)
19
+ else
20
+ %q(<% if title? %><div class="title"><%= title %></div><% end %>)
21
+ end
16
22
  end
17
23
  end
18
24
 
19
25
  module HTML5
26
+
20
27
  class DocumentTemplate < BaseTemplate
21
28
  def self.outline(node, to_depth = 2)
22
29
  toc_level = nil
23
30
  sections = node.sections
24
31
  unless sections.empty?
25
- toc_level, indent = ''
26
- nested = true
27
- unless node.is_a?(Document)
28
- if node.document.doctype == 'book'
29
- indent = ' ' * node.level unless node.level == 0
30
- nested = node.level > 0
31
- else
32
- indent = ' ' * node.level
33
- end
32
+ # FIXME the level for special sections should be set correctly in the model
33
+ # sec_level will only be 0 if we have a book doctype with parts
34
+ sec_level = sections.first.level
35
+ if sec_level == 0 && sections.first.special
36
+ sec_level = 1
34
37
  end
35
- toc_level << "#{indent}<ol>\n" if nested
38
+ toc_level = %(<ol type="none" class="sectlevel#{sec_level}">\n)
39
+ numbered = node.document.attr? 'numbered'
36
40
  sections.each do |section|
37
- toc_level << "#{indent} <li><a href=\"##{section.id}\">#{!section.special && section.level > 0 ? "#{section.sectnum} " : ''}#{section.attr('caption')}#{section.title}</a></li>\n"
38
- if section.level < to_depth && (child_toc_level = outline(section, to_depth))
39
- if section.document.doctype != 'book' || section.level > 0
40
- toc_level << "#{indent} <li>\n#{child_toc_level}\n#{indent} </li>\n"
41
- else
42
- toc_level << "#{indent}#{child_toc_level}\n"
41
+ # need to check playback attributes for change in numbered setting
42
+ # FIXME encapsulate me
43
+ if section.attributes.has_key? :attribute_entries
44
+ if (numbered_override = section.attributes[:attribute_entries].find {|entry| entry.name == 'numbered'})
45
+ numbered = numbered_override.negate ? false : true
43
46
  end
44
47
  end
48
+ section_num = numbered && !section.special && section.level > 0 && section.level < 4 ? %(#{section.sectnum} ) : nil
49
+ toc_level = %(#{toc_level}<li><a href=\"##{section.id}\">#{section_num}#{section.caption}#{section.title}</a></li>\n)
50
+ if section.level < to_depth && (child_toc_level = outline(section, to_depth))
51
+ toc_level = %(#{toc_level}<li>\n#{child_toc_level}\n</li>\n)
52
+ end
45
53
  end
46
- toc_level << "#{indent}</ol>" if nested
54
+ toc_level = %(#{toc_level}</ol>)
47
55
  end
48
56
  toc_level
49
57
  end
50
58
 
51
- # Internal: Generate the default stylesheet for CodeRay
52
- #
53
- # returns the default CodeRay stylesheet as a String
54
- def self.default_coderay_stylesheet
55
- Helpers.require_library 'coderay'
56
- ::CodeRay::Encoders[:html]::CSS.new(:default).stylesheet
57
- end
58
-
59
59
  def template
60
60
  @template ||= @eruby.new <<-EOS
61
61
  <%#encoding:UTF-8%><!DOCTYPE html>
62
- <html<% unless attr? :nolang %> lang="<%= attr :lang, 'en' %>"<% end %>>
63
- <head>
64
- <meta http-equiv="Content-Type" content="text/html; charset=<%= attr :encoding %>">
65
- <meta name="generator" content="Asciidoctor <%= attr 'asciidoctor-version' %>">
66
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
67
- <% if attr? :description %>
68
- <meta name="description" content="<%= attr :description %>">
69
- <% end %>
70
- <% if attr? :keywords %>
71
- <meta name="keywords" content="<%= attr :keywords %>">
72
- <% end %>
73
- <title><%= doctitle %></title>
74
- <% if DEFAULT_STYLESHEET_KEYS.include?(attr 'stylesheet') %>
75
- <% if @safe >= SafeMode::SECURE || (attr? 'linkcss') %>
76
- <link rel="stylesheet" href="<%= normalize_web_path(DEFAULT_STYLESHEET_NAME, (attr :stylesdir, '')) %>">
77
- <% else %>
78
- <style>
79
- <%= read_asset DEFAULT_STYLESHEET_PATH %>
80
- </style>
81
- <% end %>
82
- <% elsif attr? :stylesheet %>
83
- <% if attr? 'linkcss' %>
84
- <link rel="stylesheet" href="<%= normalize_web_path((attr :stylesheet), attr(:stylesdir, '')) %>">
85
- <% else %>
86
- <style>
87
- <%= read_asset normalize_system_path(attr(:stylesheet), attr(:stylesdir, '')), true %>
88
- </style>
89
- <% end %>
90
- <% end %>
91
- <% case attr 'source-highlighter' %><%
92
- when 'coderay' %>
93
- <% if (attr 'coderay-css', 'class') == 'class' %>
94
- <style>
95
- <%= template.class.default_coderay_stylesheet %>
96
- </style>
97
- <% end %><%
98
- when 'highlightjs' %>
99
- <link rel="stylesheet" href="<%= (attr :highlightjsdir, 'http://cdnjs.cloudflare.com/ajax/libs/highlight.js/7.3') %>/styles/<%= (attr 'highlightjs-theme', 'default') %>.min.css">
100
- <script src="<%= (attr :highlightjsdir, 'http://cdnjs.cloudflare.com/ajax/libs/highlight.js/7.3') %>/highlight.min.js"></script>
101
- <script>hljs.initHighlightingOnLoad()</script>
102
- <% end %>
103
- <%= docinfo %>
104
- </head>
105
- <body#{id} class="<%= doctype %>"<% if attr? 'max-width' %> style="max-width: <%= attr 'max-width' %>;"<% end %>>
106
- <% unless noheader %>
107
- <div id="header">
108
- <% if has_header? %>
109
- <% unless notitle %>
110
- <h1><%= @header.title %></h1>
111
- <% end %>
112
- <% if attr? :author %><span id="author"><%= attr :author %></span><br>
113
- <% if attr? :email %><span id="email"><%= sub_macros(attr :email) %></span><br><% end %><% end %>
114
- <% if attr? :revnumber %><span id="revnumber">version <%= attr :revnumber %><%= attr?(:revdate) ? ',' : '' %></span><% end %>
115
- <% if attr? :revdate %><span id="revdate"><%= attr :revdate %></span><% end %>
116
- <% if attr? :revremark %><br><span id="revremark"><%= attr :revremark %></span><% end %>
117
- <% end %>
118
- <% if (attr? :toc) && (attr? 'toc-placement', 'auto') %>
119
- <div id="toc" class="<%= attr 'toc-class', 'toc' %>">
120
- <div id="toctitle"><%= attr 'toc-title' %></div>
62
+ <html<%= !(attr? 'nolang') ? %( lang="\#{attr 'lang', 'en'}") : nil %>>
63
+ <head>
64
+ <meta http-equiv="Content-Type" content="text/html; charset=<%= attr :encoding %>">
65
+ <meta name="generator" content="Asciidoctor <%= attr 'asciidoctor-version' %>">
66
+ <meta name="viewport" content="width=device-width, initial-scale=1.0"><%
67
+ if attr? :description %>
68
+ <meta name="description" content="<%= attr :description %>"><%
69
+ end
70
+ if attr? :keywords %>
71
+ <meta name="keywords" content="<%= attr :keywords %>"><%
72
+ end %>
73
+ <title><%= doctitle %></title><%
74
+ if DEFAULT_STYLESHEET_KEYS.include?(attr 'stylesheet')
75
+ if @safe >= SafeMode::SECURE || (attr? 'linkcss') %>
76
+ <link rel="stylesheet" href="<%= normalize_web_path(DEFAULT_STYLESHEET_NAME, (attr :stylesdir, '')) %>"><%
77
+ else %>
78
+ <style>
79
+ <%= ::Asciidoctor::HTML5.default_asciidoctor_stylesheet %>
80
+ </style><%
81
+ end
82
+ elsif attr? :stylesheet
83
+ if attr? 'linkcss' %>
84
+ <link rel="stylesheet" href="<%= normalize_web_path((attr :stylesheet), (attr :stylesdir, '')) %>"><%
85
+ else %>
86
+ <style>
87
+ <%= read_asset normalize_system_path((attr :stylesheet), (attr :stylesdir, '')), true %>
88
+ </style><%
89
+ end
90
+ end
91
+ if attr? 'icons', 'font'
92
+ if !(attr 'iconfont-remote', '').nil? %>
93
+ <link rel="stylesheet" href="<%= attr 'iconfont-cdn', 'http://cdnjs.cloudflare.com/ajax/libs/font-awesome/3.1.0/css' %>/<%= attr 'iconfont-name', 'font-awesome' %>.min.css"><%
94
+ else %>
95
+ <link rel="stylesheet" href="<%= normalize_web_path(%(\#{attr 'iconfont-name', 'font-awesome'}.css), (attr 'stylesdir', '')) %>"><%
96
+ end
97
+ end
98
+ case attr 'source-highlighter'
99
+ when 'coderay'
100
+ if (attr 'coderay-css', 'class') == 'class' %>
101
+ <style>
102
+ <%= ::Asciidoctor::HTML5.default_coderay_stylesheet %>
103
+ </style><%
104
+ end
105
+ when 'highlightjs', 'highlight.js' %>
106
+ <link rel="stylesheet" href="<%= attr :highlightjsdir, 'http://cdnjs.cloudflare.com/ajax/libs/highlight.js/7.3' %>/styles/<%= attr 'highlightjs-theme', 'default' %>.min.css">
107
+ <script src="<%= attr :highlightjsdir, 'http://cdnjs.cloudflare.com/ajax/libs/highlight.js/7.3' %>/highlight.min.js"></script>
108
+ <script>hljs.initHighlightingOnLoad()</script><%
109
+ when 'prettify' %>
110
+ <link rel="stylesheet" href="<%= attr 'prettifydir', 'http://cdnjs.cloudflare.com/ajax/libs/prettify/r298' %>/<%= attr 'prettify-theme', 'prettify' %>.min.css">
111
+ <script src="<%= attr 'prettifydir', 'http://cdnjs.cloudflare.com/ajax/libs/prettify/r298' %>/prettify.min.js"></script>
112
+ <script>document.addEventListener('DOMContentLoaded', prettyPrint)</script><%
113
+ end %><%= (docinfo_content = docinfo).empty? ? nil : %(
114
+ \#{docinfo_content}) %>
115
+ </head>
116
+ <body#{id} class="<%= doctype %><%= (attr? 'toc-class') && (attr? 'toc') && (attr? 'toc-placement', 'auto') ? %( \#{attr 'toc-class'}) : nil %>"<%= (attr? 'max-width') ? %( style="max-width: \#{attr 'max-width'};") : nil %>><%
117
+ unless noheader %>
118
+ <div id="header"><%
119
+ if has_header?
120
+ unless notitle %>
121
+ <h1><%= @header.title %></h1><%
122
+ end %><%
123
+ if attr? :author %>
124
+ <span id="author"><%= attr :author %></span><br><%
125
+ if attr? :email %>
126
+ <span id="email"><%= sub_macros(attr :email) %></span><br><%
127
+ end
128
+ end
129
+ if attr? :revnumber %>
130
+ <span id="revnumber">version <%= attr :revnumber %><%= (attr? :revdate) ? ',' : '' %></span><%
131
+ end
132
+ if attr? :revdate %>
133
+ <span id="revdate"><%= attr :revdate %></span><%
134
+ end
135
+ if attr? :revremark %>
136
+ <br><span id="revremark"><%= attr :revremark %></span><%
137
+ end
138
+ end
139
+ if (attr? :toc) && (attr? 'toc-placement', 'auto') %>
140
+ <div id="toc" class="<%= attr 'toc-class', 'toc' %>">
141
+ <div id="toctitle"><%= attr 'toc-title' %></div>
121
142
  <%= template.class.outline(self, (attr :toclevels, 2).to_i) %>
122
- </div>
123
- <% end %>
124
- </div>
125
- <% end %>
126
- <div id="content">
143
+ </div><%
144
+ end %>
145
+ </div><%
146
+ end %>
147
+ <div id="content">
127
148
  <%= content %>
128
- </div>
129
- <% unless !footnotes? || attr?(:nofootnotes) %><div id="footnotes">
130
- <hr>
131
- <% footnotes.each do |fn| %>
132
- <div class="footnote" id="_footnote_<%= fn.index %>">
133
- <a href="#_footnoteref_<%= fn.index %>"><%= fn.index %></a>. <%= fn.text %>
134
- </div>
135
- <% end %>
136
- </div>
137
- <% end %>
138
- <div id="footer">
139
- <div id="footer-text">
140
- <% if attr? :revnumber %>Version <%= attr :revnumber %><br><% end %>
141
- Last updated <%= attr :docdatetime %>
142
- </div>
143
- </div>
144
- </body>
149
+ </div><%
150
+ unless !footnotes? || (attr? :nofootnotes) %>
151
+ <div id="footnotes">
152
+ <hr><%
153
+ footnotes.each do |fn| %>
154
+ <div class="footnote" id="_footnote_<%= fn.index %>">
155
+ <a href="#_footnoteref_<%= fn.index %>"><%= fn.index %></a>. <%= fn.text %>
156
+ </div><%
157
+ end %>
158
+ </div><%
159
+ end %>
160
+ <div id="footer">
161
+ <div id="footer-text"><%
162
+ if attr? :revnumber %>
163
+ Version <%= attr :revnumber %><br><%
164
+ end %>
165
+ Last updated <%= attr :docdatetime %>
166
+ </div>
167
+ </div>
168
+ </body>
145
169
  </html>
146
170
  EOS
147
171
  end
@@ -152,7 +176,7 @@ class EmbeddedTemplate < BaseTemplate
152
176
  @template ||= @eruby.new <<-EOS
153
177
  <%#encoding:UTF-8%><% unless notitle || !has_header? %><h1#{id}><%= header.title %></h1>
154
178
  <% end %><%= content %>
155
- <% unless !footnotes? || attr?(:nofootnotes) %><div id="footnotes">
179
+ <% unless !footnotes? || (attr? :nofootnotes) %><div id="footnotes">
156
180
  <hr>
157
181
  <% footnotes.each do |fn| %>
158
182
  <div class="footnote" id="_footnote_<%= fn.index %>">
@@ -168,12 +192,12 @@ class BlockTocTemplate < BaseTemplate
168
192
  def result(node)
169
193
  doc = node.document
170
194
 
171
- return '' unless doc.attr?('toc')
195
+ return '' unless (doc.attr? 'toc')
172
196
 
173
197
  if node.id
174
198
  id_attr = %( id="#{node.id}")
175
199
  title_id_attr = ''
176
- elsif doc.embedded? || !doc.attr?('toc-placement', 'auto')
200
+ elsif doc.embedded? || !(doc.attr? 'toc-placement')
177
201
  id_attr = ' id="toc"'
178
202
  title_id_attr = ' id="toctitle"'
179
203
  else
@@ -181,13 +205,13 @@ class BlockTocTemplate < BaseTemplate
181
205
  title_id_attr = ''
182
206
  end
183
207
  title = node.title? ? node.title : (doc.attr 'toc-title')
184
- levels = node.attr?('levels') ? node.attr('levels').to_i : doc.attr('toclevels', 2).to_i
185
- role = node.attr?('role') ? node.attr('role') : doc.attr('toc-class', 'toc')
208
+ levels = (node.attr? 'levels') ? (node.attr 'levels').to_i : (doc.attr 'toclevels', 2).to_i
209
+ role = (node.attr? 'role') ? (node.attr 'role') : (doc.attr 'toc-class', 'toc')
186
210
 
187
- %(\n<div#{id_attr} class="#{role}">
211
+ %(<div#{id_attr} class="#{role}">
188
212
  <div#{title_id_attr} class="title">#{title}</div>
189
213
  #{DocumentTemplate.outline(doc, levels)}
190
- </div>)
214
+ </div>\n)
191
215
  end
192
216
 
193
217
  def template
@@ -196,12 +220,23 @@ class BlockTocTemplate < BaseTemplate
196
220
  end
197
221
 
198
222
  class BlockPreambleTemplate < BaseTemplate
223
+ def toc(node)
224
+ if (node.attr? 'toc') && (node.attr? 'toc-placement', 'preamble')
225
+ %(\n<div id="toc" class="#{node.attr 'toc-class', 'toc'}">
226
+ <div id="toctitle">#{node.attr 'toc-title'}</div>
227
+ #{DocumentTemplate.outline(node.document, (node.attr 'toclevels', 2).to_i)}
228
+ </div>)
229
+ else
230
+ ''
231
+ end
232
+ end
233
+
199
234
  def template
200
235
  @template ||= @eruby.new <<-EOS
201
236
  <%#encoding:UTF-8%><div id="preamble">
202
- <div class="sectionbody">
237
+ <div class="sectionbody">
203
238
  <%= content %>
204
- </div>
239
+ </div><%= template.toc(self) %>
205
240
  </div>
206
241
  EOS
207
242
  end
@@ -215,30 +250,43 @@ class SectionTemplate < BaseTemplate
215
250
  slevel = 1
216
251
  end
217
252
  htag = "h#{slevel + 1}"
218
- id = sec.id && " id=\"#{sec.id}\""
253
+ id = anchor = link_start = link_end = nil
254
+ if sec.id
255
+ id = %( id="#{sec.id}")
256
+ if sec.document.attr? 'sectanchors'
257
+ #if sec.document.attr? 'icons', 'font'
258
+ # anchor = %(<a class="anchor" href="##{sec.id}"><i class="icon-anchor"></i></a>)
259
+ #else
260
+ anchor = %(<a class="anchor" href="##{sec.id}"></a>)
261
+ #end
262
+ elsif sec.document.attr? 'sectlinks'
263
+ link_start = %(<a class="link" href="##{sec.id}">)
264
+ link_end = '</a>'
265
+ end
266
+ end
219
267
 
220
268
  if slevel == 0
221
- %(<h1#{id}>#{sec.title}</h1>
222
- #{sec.content})
269
+ %(<h1#{id} class="sect0">#{anchor}#{link_start}#{sec.title}#{link_end}</h1>
270
+ #{sec.content}\n)
223
271
  else
224
- role = sec.attr?('role') ? " #{sec.attr('role')}" : nil
225
- if !sec.special && (sec.attr? 'numbered') && slevel < 4
272
+ role = (sec.attr? 'role') ? " #{sec.attr 'role'}" : nil
273
+ if !sec.special && (sec.document.attr? 'numbered') && slevel < 4
226
274
  sectnum = "#{sec.sectnum} "
227
275
  else
228
276
  sectnum = nil
229
277
  end
230
278
 
231
279
  if slevel == 1
232
- content = %( <div class="sectionbody">
280
+ content = %(<div class="sectionbody">
233
281
  #{sec.content}
234
- </div>)
282
+ </div>)
235
283
  else
236
284
  content = sec.content
237
285
  end
238
286
  %(<div class="sect#{slevel}#{role}">
239
- <#{htag}#{id}>#{sectnum}#{sec.attr 'caption'}#{sec.title}</#{htag}>
287
+ <#{htag}#{id}>#{anchor}#{link_start}#{sectnum}#{sec.caption}#{sec.title}#{link_end}</#{htag}>
240
288
  #{content}
241
- </div>)
289
+ </div>\n)
242
290
  end
243
291
  end
244
292
 
@@ -259,69 +307,103 @@ class BlockDlistTemplate < BaseTemplate
259
307
  def template
260
308
  @template ||= @eruby.new <<-EOS
261
309
  <%#encoding:UTF-8%><%
262
- if attr? :style, 'qanda' %>
263
- <div#{id} class="qlist#{style_class}#{role_class}">
264
- #{title_div}
265
- <ol>
266
- <% content.each do |dt, dd| %>
267
- <li>
268
- <p><em><%= dt.text %></em></p>
269
- <% unless dd.nil? %>
270
- <% if dd.text? %>
271
- <p><%= dd.text %></p>
272
- <% end %>
273
- <% if dd.blocks? %>
274
- <%= dd.content %>
275
- <% end %>
276
- <% end %>
277
- </li>
278
- <% end %>
279
- </ol>
280
- </div>
281
- <% elsif attr? :style, 'horizontal' %>
282
- <div#{id} class="hdlist#{role_class}">
283
- #{title_div}
284
- <table>
285
- <colgroup>
286
- <col<% if attr? :labelwidth %> style="width:<%= attr :labelwidth %>%;"<% end %>>
287
- <col<% if attr? :itemwidth %> style="width:<%= attr :itemwidth %>%;"<% end %>>
288
- </colgroup>
289
- <% content.each do |dt, dd| %>
290
- <tr>
291
- <td class="hdlist1<% if attr? 'strong-option' %> strong<% end %>">
292
- <%= dt.text %>
293
- <br>
294
- </td>
295
- <td class="hdlist2"><% unless dd.nil? %><% if dd.text? %>
296
- <p style="margin-top: 0;"><%= dd.text %></p><% end %><% if dd.blocks? %>
297
- <%= dd.content %><% end %><% end %>
298
- </td>
299
- </tr>
300
- <% end %>
301
- </table>
302
- </div>
303
- <% else %>
304
- <div#{id} class="dlist#{style_class}#{role_class}">
305
- #{title_div}
306
- <dl>
307
- <% content.each do |dt, dd| %>
308
- <dt<% if !(attr? :style) %> class="hdlist1"<% end %>>
309
- <%= dt.text %>
310
- </dt>
311
- <% unless dd.nil? %>
312
- <dd>
313
- <% if dd.text? %>
314
- <p><%= dd.text %></p>
315
- <% end %>
316
- <% if dd.blocks? %>
317
- <%= dd.content %>
318
- <% end %>
319
- </dd>
320
- <% end %>
321
- <% end %>
322
- </dl>
323
- </div>
324
- <% end %>
310
+ continuing = false
311
+ entries = content
312
+ last_index = entries.length - 1
313
+ if attr? 'style', 'qanda', false
314
+ %><div#{id} class="qlist#{style_class}#{role_class}"><%
315
+ if title? %>
316
+ <div class="title"><%= title %></div><%
317
+ end %>
318
+ <ol><%
319
+ entries.each_with_index do |(dt, dd), index|
320
+ last = (index == last_index)
321
+ unless continuing %>
322
+ <li><%
323
+ end %>
324
+ <p><em><%= dt.text %></em></p><%
325
+ if !last && dd.nil?
326
+ continuing = true
327
+ next
328
+ else
329
+ continuing = false
330
+ end
331
+ unless dd.nil?
332
+ if dd.text? %>
333
+ <p><%= dd.text %></p><%
334
+ end
335
+ if dd.blocks? %>
336
+ <%= dd.content %><%
337
+ end
338
+ end %>
339
+ </li><%
340
+ end %>
341
+ </ol>
342
+ </div><%
343
+ elsif attr? 'style', 'horizontal', false
344
+ %><div#{id} class="hdlist#{role_class}"><%
345
+ if title? %>
346
+ <div class="title"><%= title %></div><%
347
+ end %>
348
+ <table><%
349
+ if (attr? :labelwidth) || (attr? :itemwidth) %>
350
+ <colgroup>
351
+ <col<% if attr? :labelwidth %> style="width:<%= (attr :labelwidth).chomp('%') %>%;"<% end %>>
352
+ <col<% if attr? :itemwidth %> style="width:<%= (attr :itemwidth).chomp('%') %>%;"<% end %>>
353
+ </colgroup><%
354
+ end %><%
355
+ entries.each_with_index do |(dt, dd), index|
356
+ last = (index == last_index)
357
+ unless continuing %>
358
+ <tr>
359
+ <td class="hdlist1<%= (attr? 'strong-option') ? 'strong' : nil %>"><%
360
+ end %>
361
+ <%= dt.text %>
362
+ <br><%
363
+ if !last && dd.nil?
364
+ continuing = true
365
+ next
366
+ else
367
+ continuing = false
368
+ end %>
369
+ </td>
370
+ <td class="hdlist2"><%
371
+ unless dd.nil?
372
+ if dd.text? %>
373
+ <p><%= dd.text %></p><%
374
+ end
375
+ if dd.blocks? %>
376
+ <%= dd.content %><%
377
+ end
378
+ end %>
379
+ </td>
380
+ </tr><%
381
+ end %>
382
+ </table>
383
+ </div><%
384
+ else
385
+ %><div#{id} class="dlist#{style_class}#{role_class}"><%
386
+ if title? %>
387
+ <div class="title"><%= title %></div><%
388
+ end %>
389
+ <dl><%
390
+ entries.each_with_index do |(dt, dd), index|
391
+ last = (index == last_index) %>
392
+ <dt<%= !(attr? 'style', nil, false) ? %( class="hdlist1") : nil %>><%= dt.text %></dt><%
393
+ unless dd.nil? %>
394
+ <dd><%
395
+ if dd.text? %>
396
+ <p><%= dd.text %></p><%
397
+ end %><%
398
+ if dd.blocks? %>
399
+ <%= dd.content %><%
400
+ end %>
401
+ </dd><%
402
+ end
403
+ end %>
404
+ </dl>
405
+ </div><%
406
+ end %>
325
407
  EOS
326
408
  end
327
409
  end
@@ -330,14 +412,30 @@ class BlockListingTemplate < BaseTemplate
330
412
  def template
331
413
  @template ||= @eruby.new <<-EOS
332
414
  <%#encoding:UTF-8%><div#{id} class="listingblock#{role_class}">
333
- #{title_div :caption => true}
334
- <div class="content monospaced">
335
- <% if attr? :style, 'source' %>
336
- <pre class="highlight<% if attr? 'source-highlighter', 'coderay' %> CodeRay<% end %>"><code#{attribute('class', :language)}><%= template.preserve_endlines(content, self) %></code></pre>
337
- <% else %>
338
- <pre><%= template.preserve_endlines(content, self) %></pre>
339
- <% end %>
340
- </div>
415
+ #{title_div :caption => true}
416
+ <div class="content monospaced"><%
417
+ if attr? 'style', 'source', false
418
+ language = (language = (attr 'language')) ? %(\#{language} language-\#{language}) : nil
419
+ case attr 'source-highlighter'
420
+ when 'coderay'
421
+ pre_class = ' class="CodeRay"'
422
+ code_class = language ? %( class="\#{language}") : nil
423
+ when 'highlightjs', 'highlight.js'
424
+ pre_class = ' class="highlight"'
425
+ code_class = language ? %( class="\#{language}") : nil
426
+ when 'prettify'
427
+ pre_class = %( class="prettyprint\#{(attr? 'linenums') ? ' linenums' : nil})
428
+ pre_class = language ? %(\#{pre_class} \#{language}") : %(\#{pre_class}")
429
+ code_class = nil
430
+ else
431
+ pre_class = ' class="highlight"'
432
+ code_class = language ? %( class="\#{language}") : nil
433
+ end %>
434
+ <pre<%= pre_class %>><code<%= code_class %>><%= template.preserve_endlines(content, self) %></code></pre><%
435
+ else %>
436
+ <pre><%= template.preserve_endlines(content, self) %></pre><%
437
+ end %>
438
+ </div>
341
439
  </div>
342
440
  EOS
343
441
  end
@@ -347,10 +445,10 @@ class BlockLiteralTemplate < BaseTemplate
347
445
  def template
348
446
  @template ||= @eruby.new <<-EOS
349
447
  <%#encoding:UTF-8%><div#{id} class="literalblock#{role_class}">
350
- #{title_div}
351
- <div class="content monospaced">
352
- <pre><%= template.preserve_endlines(content, self) %></pre>
353
- </div>
448
+ #{title_div}
449
+ <div class="content monospaced">
450
+ <pre><%= template.preserve_endlines(content, self) %></pre>
451
+ </div>
354
452
  </div>
355
453
  EOS
356
454
  end
@@ -360,21 +458,23 @@ class BlockAdmonitionTemplate < BaseTemplate
360
458
  def template
361
459
  @template ||= @eruby.new <<-EOS
362
460
  <%#encoding:UTF-8%><div#{id} class="admonitionblock <%= attr :name %>#{role_class}">
363
- <table>
364
- <tr>
365
- <td class="icon">
366
- <% if attr? :icons %>
367
- <img src="<%= icon_uri(attr :name) %>" alt="<%= attr :caption %>">
368
- <% else %>
369
- <div class="title"><%= attr :caption %></div>
370
- <% end %>
371
- </td>
372
- <td class="content">
373
- #{title_div}
374
- <%= content %>
375
- </td>
376
- </tr>
377
- </table>
461
+ <table>
462
+ <tr>
463
+ <td class="icon"><%
464
+ if attr? 'icons', 'font' %>
465
+ <i class="icon-<%= attr :name %>" title="<%= @caption %>"></i><%
466
+ elsif attr? 'icons' %>
467
+ <img src="<%= icon_uri(attr :name) %>" alt="<%= @caption %>"><%
468
+ else %>
469
+ <div class="title"><%= @caption %></div><%
470
+ end %>
471
+ </td>
472
+ <td class="content">
473
+ #{title_div}
474
+ <%= content %>
475
+ </td>
476
+ </tr>
477
+ </table>
378
478
  </div>
379
479
  EOS
380
480
  end
@@ -382,14 +482,14 @@ end
382
482
 
383
483
  class BlockParagraphTemplate < BaseTemplate
384
484
  def paragraph(id, role, title, content)
385
- %(<div#{id && " id=\"#{id}\""} class=\"paragraph#{role && " #{role}"}\">#{title && "
386
- <div class=\"title\">#{title}</div>"}
387
- <p>#{content}</p>
388
- </div>)
485
+ %(<div#{id && " id=\"#{id}\""} class="paragraph#{role && " #{role}"}">#{title && "
486
+ <div class=\"title\">#{title}</div>"}
487
+ <p>#{content}</p>
488
+ </div>\n)
389
489
  end
390
490
 
391
491
  def result(node)
392
- paragraph(node.id, node.attr('role'), (node.title? ? node.title : nil), node.content)
492
+ paragraph(node.id, (node.attr 'role'), (node.title? ? node.title : nil), node.content)
393
493
  end
394
494
 
395
495
  def template
@@ -401,10 +501,10 @@ class BlockSidebarTemplate < BaseTemplate
401
501
  def template
402
502
  @template ||= @eruby.new <<-EOS
403
503
  <%#encoding:UTF-8%><div#{id} class="sidebarblock#{role_class}">
404
- <div class="content">
405
- #{title_div}
504
+ <div class="content">
505
+ #{title_div}
406
506
  <%= content %>
407
- </div>
507
+ </div>
408
508
  </div>
409
509
  EOS
410
510
  end
@@ -414,25 +514,48 @@ class BlockExampleTemplate < BaseTemplate
414
514
  def template
415
515
  @template ||= @eruby.new <<-EOS
416
516
  <%#encoding:UTF-8%><div#{id} class="exampleblock#{role_class}">
417
- #{title_div :caption => true}
418
- <div class="content">
517
+ #{title_div :caption => true}
518
+ <div class="content">
419
519
  <%= content %>
420
- </div>
520
+ </div>
421
521
  </div>
422
522
  EOS
423
523
  end
424
524
  end
425
525
 
426
526
  class BlockOpenTemplate < BaseTemplate
427
- def template
428
- @template ||= @eruby.new <<-EOS
429
- <%#encoding:UTF-8%><div#{id} class="openblock#{role_class}">
430
- #{title_div}
431
- <div class="content">
432
- <%= content %>
433
- </div>
527
+ def result(node)
528
+ open_block(node, node.id, (node.attr 'style', nil, false), (node.attr 'role'), node.title? ? node.title : nil, node.content)
529
+ end
530
+
531
+ def open_block(node, id, style, role, title, content)
532
+ if style == 'abstract'
533
+ if node.parent == node.document && node.document.attr?('doctype', 'book')
534
+ puts 'asciidoctor: WARNING: abstract block cannot be used in a document without a title when doctype is book. Excluding block content.'
535
+ ''
536
+ else
537
+ %(<div#{id && " id=\"#{id}\""} class="quoteblock abstract#{role && " #{role}"}">#{title &&
538
+ "<div class=\"title\">#{title}</div>"}
539
+ <blockquote>
540
+ #{content}
541
+ </blockquote>
542
+ </div>\n)
543
+ end
544
+ elsif style == 'partintro' && (!node.document.attr?('doctype', 'book') || !node.parent.is_a?(Asciidoctor::Section) || node.level != 0)
545
+ puts 'asciidoctor: ERROR: partintro block can only be used when doctype is book and it\'s a child of a book part. Excluding block content.'
546
+ ''
547
+ else
548
+ %(<div#{id && " id=\"#{id}\""} class="openblock#{style != 'open' ? " #{style}" : ''}#{role && " #{role}"}">#{title &&
549
+ "<div class=\"title\">#{title}</div>"}
550
+ <div class="content">
551
+ #{content}
434
552
  </div>
435
- EOS
553
+ </div>\n)
554
+ end
555
+ end
556
+
557
+ def template
558
+ :invoke_result
436
559
  end
437
560
  end
438
561
 
@@ -446,21 +569,23 @@ class BlockQuoteTemplate < BaseTemplate
446
569
  def template
447
570
  @template ||= @eruby.new <<-EOS
448
571
  <%#encoding:UTF-8%><div#{id} class="quoteblock#{role_class}">
449
- #{title_div}
450
- <blockquote>
572
+ #{title_div}
573
+ <blockquote>
451
574
  <%= content %>
452
- </blockquote>
453
- <div class="attribution">
454
- <% if attr? :citetitle %>
455
- <cite><%= attr :citetitle %></cite>
456
- <% end %>
457
- <% if attr? :attribution %>
458
- <% if attr? :citetitle %>
459
- <br>
460
- <% end %>
461
- <%= "&#8212; \#{attr :attribution}" %>
462
- <% end %>
463
- </div>
575
+ </blockquote><%
576
+ if (attr? :attribution) || (attr? :citetitle) %>
577
+ <div class="attribution"><%
578
+ if attr? :citetitle %>
579
+ <cite><%= attr :citetitle %></cite><%
580
+ end
581
+ if attr? :attribution
582
+ if attr? :citetitle %>
583
+ <br><%
584
+ end %>
585
+ <%= "&#8212; \#{attr :attribution}" %><%
586
+ end %>
587
+ </div><%
588
+ end %>
464
589
  </div>
465
590
  EOS
466
591
  end
@@ -470,19 +595,21 @@ class BlockVerseTemplate < BaseTemplate
470
595
  def template
471
596
  @template ||= @eruby.new <<-EOS
472
597
  <%#encoding:UTF-8%><div#{id} class="verseblock#{role_class}">
473
- #{title_div}
474
- <pre class="content"><%= template.preserve_endlines(content, self) %></pre>
475
- <div class="attribution">
476
- <% if attr? :citetitle %>
477
- <cite><%= attr :citetitle %></cite>
478
- <% end %>
479
- <% if attr? :attribution %>
480
- <% if attr? :citetitle %>
481
- <br>
482
- <% end %>
483
- <%= "&#8212; \#{attr :attribution}" %>
484
- <% end %>
485
- </div>
598
+ #{title_div}
599
+ <pre class="content"><%= template.preserve_endlines(content, self) %></pre><%
600
+ if (attr? :attribution) || (attr? :citetitle) %>
601
+ <div class="attribution"><%
602
+ if attr? :citetitle %>
603
+ <cite><%= attr :citetitle %></cite><%
604
+ end
605
+ if attr? :attribution
606
+ if attr? :citetitle %>
607
+ <br><%
608
+ end %>
609
+ <%= "&#8212; \#{attr :attribution}" %><%
610
+ end %>
611
+ </div><%
612
+ end %>
486
613
  </div>
487
614
  EOS
488
615
  end
@@ -492,37 +619,38 @@ class BlockUlistTemplate < BaseTemplate
492
619
  def template
493
620
  @template ||= @eruby.new <<-EOS
494
621
  <%#encoding:UTF-8%><div#{id} class="ulist#{style_class}#{role_class}">
495
- #{title_div}
496
- <ul>
497
- <% content.each do |item| %>
498
- <li>
499
- <p><%= item.text %></p>
500
- <% if item.blocks? %>
501
- <%= item.content %>
502
- <% end %>
503
- </li>
504
- <% end %>
505
- </ul>
622
+ #{title_div}
623
+ <ul><%
624
+ content.each do |item| %>
625
+ <li>
626
+ <p><%= item.text %></p><%
627
+ if item.blocks? %>
628
+ <%= item.content %><%
629
+ end %>
630
+ </li><%
631
+ end %>
632
+ </ul>
506
633
  </div>
507
634
  EOS
508
635
  end
509
636
  end
510
637
 
511
638
  class BlockOlistTemplate < BaseTemplate
639
+
512
640
  def template
513
641
  @template ||= @eruby.new <<-EOS
514
- <%#encoding:UTF-8%><div#{id} class="olist#{style_class}#{role_class}">
515
- #{title_div}
516
- <ol class="<%= attr :style %>"#{attribute('start', :start)}>
517
- <% content.each do |item| %>
518
- <li>
519
- <p><%= item.text %></p>
520
- <% if item.blocks? %>
521
- <%= item.content %>
522
- <% end %>
523
- </li>
524
- <% end %>
525
- </ol>
642
+ <%#encoding:UTF-8%><% style = attr 'style', nil, false %><div#{id} class="olist#{style_class}#{role_class}">
643
+ #{title_div}
644
+ <ol class="<%= style %>"<%= (type = ::Asciidoctor::ORDERED_LIST_KEYWORDS[style]) ? %( type="\#{type}") : nil %>#{attribute('start', :start)}><%
645
+ content.each do |item| %>
646
+ <li>
647
+ <p><%= item.text %></p><%
648
+ if item.blocks? %>
649
+ <%= item.content %><%
650
+ end %>
651
+ </li><%
652
+ end %>
653
+ </ol>
526
654
  </div>
527
655
  EOS
528
656
  end
@@ -532,25 +660,28 @@ class BlockColistTemplate < BaseTemplate
532
660
  def template
533
661
  @template ||= @eruby.new <<-EOS
534
662
  <%#encoding:UTF-8%><div#{id} class="colist#{style_class}#{role_class}">
535
- #{title_div}
536
- <% if attr? :icons %>
537
- <table>
538
- <% content.each_with_index do |item, i| %>
539
- <tr>
540
- <td><img src="<%= icon_uri("callouts/\#{i + 1}") %>" alt="<%= i + 1 %>"></td>
541
- <td><%= item.text %></td>
542
- </tr>
543
- <% end %>
544
- </table>
545
- <% else %>
546
- <ol>
547
- <% content.each do |item| %>
548
- <li>
549
- <p><%= item.text %></p>
550
- </li>
551
- <% end %>
552
- </ol>
553
- <% end %>
663
+ #{title_div}<%
664
+ if attr? :icons %>
665
+ <table><%
666
+ content.each_with_index do |item, i| %>
667
+ <tr>
668
+ <td><%
669
+ if attr? :icons, 'font' %><i class="conum"><%= i + 1 %></i><%
670
+ else %><img src="<%= icon_uri("callouts/\#{i + 1}") %>" alt="<%= i + 1 %>"><%
671
+ end %></td>
672
+ <td><%= item.text %></td>
673
+ </tr><%
674
+ end %>
675
+ </table><%
676
+ else %>
677
+ <ol><%
678
+ content.each do |item| %>
679
+ <li>
680
+ <p><%= item.text %></p>
681
+ </li><%
682
+ end %>
683
+ </ol><%
684
+ end %>
554
685
  </div>
555
686
  EOS
556
687
  end
@@ -561,42 +692,56 @@ class BlockTableTemplate < BaseTemplate
561
692
  @template ||= @eruby.new <<-EOS
562
693
  <%#encoding:UTF-8%><table#{id} class="tableblock frame-<%= attr :frame, 'all' %> grid-<%= attr :grid, 'all'%>#{role_class}" style="<%
563
694
  if !(attr? 'autowidth-option') %>width:<%= attr :tablepcwidth %>%; <% end %><%
564
- if attr? :float %>float: <%= attr :float %>; <% end %>">
565
- <% if title? %>
566
- <caption class="title"><% unless @caption.nil? %><%= @caption %><% end %><%= title %></caption>
567
- <% end %>
568
- <% if (attr :rowcount) >= 0 %>
569
- <colgroup>
570
- <% if attr? 'autowidth-option' %>
571
- <% @columns.each do %>
572
- <col>
573
- <% end %>
574
- <% else %>
575
- <% @columns.each do |col| %>
576
- <col style="width:<%= col.attr :colpcwidth %>%;">
577
- <% end %>
578
- <% end %>
579
- </colgroup>
580
- <% [:head, :foot, :body].select {|tsec| !@rows[tsec].empty? }.each do |tsec| %>
581
- <t<%= tsec %>>
582
- <% @rows[tsec].each do |row| %>
583
- <tr>
584
- <% row.each do |cell| %>
585
- <<%= tsec == :head ? 'th' : 'td' %> class="tableblock halign-<%= cell.attr :halign %> valign-<%= cell.attr :valign %>"#{attribute('colspan', 'cell.colspan')}#{attribute('rowspan', 'cell.rowspan')}><%
586
- if tsec == :head %><%= cell.text %><% else %><%
587
- case cell.attr(:style)
588
- when :asciidoc %><div><%= cell.content %></div><%
589
- when :verse %><div class="verse"><%= template.preserve_endlines(cell.text, self) %></div><%
590
- when :literal %><div class="literal monospaced"><pre><%= template.preserve_endlines(cell.text, self) %></pre></div><%
591
- when :header %><% cell.content.each do |text| %><p class="tableblock header"><%= text %></p><% end %><%
592
- else %><% cell.content.each do |text| %><p class="tableblock"><%= text %></p><% end %><%
593
- end %><% end %></<%= tsec == :head ? 'th' : 'td' %>>
594
- <% end %>
595
- </tr>
596
- <% end %>
597
- </t<%= tsec %>>
598
- <% end %>
599
- <% end %>
695
+ if attr? :float %>float: <%= attr :float %>; <% end %>"><%
696
+ if title? %>
697
+ <caption class="title"><% unless @caption.nil? %><%= @caption %><% end %><%= title %></caption><%
698
+ end
699
+ if (attr :rowcount) >= 0 %>
700
+ <colgroup><%
701
+ if attr? 'autowidth-option'
702
+ @columns.each do %>
703
+ <col><%
704
+ end
705
+ else
706
+ @columns.each do |col| %>
707
+ <col style="width:<%= col.attr :colpcwidth %>%;"><%
708
+ end
709
+ end %>
710
+ </colgroup><%
711
+ [:head, :foot, :body].select {|tsec| !@rows[tsec].empty? }.each do |tsec| %>
712
+ <t<%= tsec %>><%
713
+ @rows[tsec].each do |row| %>
714
+ <tr><%
715
+ row.each do |cell| %>
716
+ <<%= tsec == :head ? 'th' : 'td' %> class="tableblock halign-<%= cell.attr :halign %> valign-<%= cell.attr :valign %>"#{attribute('colspan', 'cell.colspan')}#{attribute('rowspan', 'cell.rowspan')}<%
717
+ cell_content = ''
718
+ if tsec == :head
719
+ cell_content = cell.text
720
+ else
721
+ case (cell.attr 'style', nil, false)
722
+ when :asciidoc
723
+ cell_content = %(<div>\#{cell.content}</div>)
724
+ when :verse
725
+ cell_content = %(<div class="verse">\#{template.preserve_endlines(cell.text, self)}</div>)
726
+ when :literal
727
+ cell_content = %(<div class="literal monospaced"><pre>\#{template.preserve_endlines(cell.text, self)}</pre></div>)
728
+ when :header
729
+ cell.content.each do |text|
730
+ cell_content = %(\#{cell_content}<p class="tableblock header">\#{text}</p>)
731
+ end
732
+ else
733
+ cell.content.each do |text|
734
+ cell_content = %(\#{cell_content}<p class="tableblock">\#{text}</p>)
735
+ end
736
+ end
737
+ end %><%= (@document.attr? 'cellbgcolor') ? %( style="background-color:\#{@document.attr 'cellbgcolor'};") : nil
738
+ %>><%= cell_content %></<%= tsec == :head ? 'th' : 'td' %>><%
739
+ end %>
740
+ </tr><%
741
+ end %>
742
+ </t<%= tsec %>><%
743
+ end
744
+ end %>
600
745
  </table>
601
746
  EOS
602
747
  end
@@ -605,17 +750,18 @@ end
605
750
  class BlockImageTemplate < BaseTemplate
606
751
  def template
607
752
  @template ||= @eruby.new <<-EOS
608
- <%#encoding:UTF-8%><div#{id} class="imageblock#{style_class}#{role_class}"<% if (attr? :align) || (attr? :float)
609
- %> style="<% if attr? :align %>text-align: <%= attr :align %><% if attr? :float %>; <% end %><% end %><% if attr? :float %>float: <%= attr :float %><% end %>"<% end
610
- %>>
611
- <div class="content">
612
- <% if attr? :link %>
613
- <a class="image" href="<%= attr :link %>"><img src="<%= image_uri(attr :target) %>" alt="<%= attr :alt %>"#{attribute('width', :width)}#{attribute('height', :height)}></a>
614
- <% else %>
615
- <img src="<%= image_uri(attr :target) %>" alt="<%= attr :alt %>"#{attribute('width', :width)}#{attribute('height', :height)}>
616
- <% end %>
617
- </div>
618
- #{title_div :caption => true}
753
+ <%#encoding:UTF-8%><div#{id} class="imageblock#{style_class}#{role_class}"<%
754
+ if (attr? :align) || (attr? :float) %> style="<%
755
+ if attr? :align %>text-align: <%= attr :align %><% if attr? :float %>; <% end %><% end %><% if attr? :float %>float: <%= attr :float %><% end %>"<%
756
+ end %>>
757
+ <div class="content"><%
758
+ if attr? :link %>
759
+ <a class="image" href="<%= attr :link %>"><img src="<%= image_uri(attr :target) %>" alt="<%= attr :alt %>"#{attribute('width', :width)}#{attribute('height', :height)}></a><%
760
+ else %>
761
+ <img src="<%= image_uri(attr :target) %>" alt="<%= attr :alt %>"#{attribute('width', :width)}#{attribute('height', :height)}><%
762
+ end %>
763
+ </div>
764
+ #{title_div :caption => true}
619
765
  </div>
620
766
  EOS
621
767
  end
@@ -625,15 +771,15 @@ class BlockAudioTemplate < BaseTemplate
625
771
  def template
626
772
  @template ||= @eruby.new <<-EOS
627
773
  <%#encoding:UTF-8%><div#{id} class="audioblock#{style_class}#{role_class}">
628
- #{title_div :caption => true}
629
- <div class="content">
630
- <audio src="<%= media_uri(attr :target) %>"<% if
631
- attr? 'autoplay-option' %> autoplay<% end %><%
632
- unless attr? 'nocontrols-option' %> controls<% end %><%
633
- if attr? 'loop-option' %> loop<% end %>>
634
- Your browser does not support the audio tag.
635
- </audio>
636
- </div>
774
+ #{title_div :caption => true}
775
+ <div class="content">
776
+ <audio src="<%= media_uri(attr :target) %>"<%
777
+ if attr? 'autoplay-option' %> autoplay<% end %><%
778
+ unless attr? 'nocontrols-option' %> controls<% end %><%
779
+ if attr? 'loop-option' %> loop<% end %>>
780
+ Your browser does not support the audio tag.
781
+ </audio>
782
+ </div>
637
783
  </div>
638
784
  EOS
639
785
  end
@@ -643,16 +789,16 @@ class BlockVideoTemplate < BaseTemplate
643
789
  def template
644
790
  @template ||= @eruby.new <<-EOS
645
791
  <%#encoding:UTF-8%><div#{id} class="videoblock#{style_class}#{role_class}">
646
- #{title_div :caption => true}
647
- <div class="content">
648
- <video src="<%= media_uri(attr :target) %>"#{attribute('width', :width)}#{attribute('height', :height)}<%
649
- if attr? 'poster' %> poster="<%= media_uri(attr :poster) %>"<% end %><%
650
- if attr? 'autoplay-option' %> autoplay<% end %><%
651
- unless attr? 'nocontrols-option' %> controls<% end %><%
652
- if attr? 'loop-option' %> loop<% end %>>
653
- Your browser does not support the video tag.
654
- </video>
655
- </div>
792
+ #{title_div :caption => true}
793
+ <div class="content">
794
+ <video src="<%= media_uri(attr :target) %>"#{attribute('width', :width)}#{attribute('height', :height)}<%
795
+ if attr? 'poster' %> poster="<%= media_uri(attr :poster) %>"<% end %><%
796
+ if attr? 'autoplay-option' %> autoplay<% end %><%
797
+ unless attr? 'nocontrols-option' %> controls<% end %><%
798
+ if attr? 'loop-option' %> loop<% end %>>
799
+ Your browser does not support the video tag.
800
+ </video>
801
+ </div>
656
802
  </div>
657
803
  EOS
658
804
  end
@@ -670,7 +816,7 @@ end
670
816
 
671
817
  class BlockPageBreakTemplate < BaseTemplate
672
818
  def result(node)
673
- '<div style="page-break-after: always;"></div>'
819
+ %(<div style="page-break-after: always;"></div>\n)
674
820
  end
675
821
 
676
822
  def template
@@ -680,7 +826,7 @@ end
680
826
 
681
827
  class InlineBreakTemplate < BaseTemplate
682
828
  def result(node)
683
- "#{node.text}<br>"
829
+ %(#{node.text}<br>\n)
684
830
  end
685
831
 
686
832
  def template
@@ -690,7 +836,9 @@ end
690
836
 
691
837
  class InlineCalloutTemplate < BaseTemplate
692
838
  def result(node)
693
- if node.attr? 'icons'
839
+ if node.attr? 'icons', 'font'
840
+ %(<i class="conum">#{node.text}</i>)
841
+ elsif node.attr? 'icons'
694
842
  src = node.icon_uri("callouts/#{node.text}")
695
843
  %(<img src="#{src}" alt="#{node.text}">)
696
844
  else
@@ -706,7 +854,7 @@ end
706
854
  class InlineQuotedTemplate < BaseTemplate
707
855
  NO_TAGS = ['', '']
708
856
 
709
- QUOTED_TAGS = {
857
+ QUOTE_TAGS = {
710
858
  :emphasis => ['<em>', '</em>'],
711
859
  :strong => ['<strong>', '</strong>'],
712
860
  :monospaced => ['<code>', '</code>'],
@@ -717,16 +865,67 @@ class InlineQuotedTemplate < BaseTemplate
717
865
  }
718
866
 
719
867
  def quote_text(text, type, role)
720
- start_tag, end_tag = QUOTED_TAGS[type] || NO_TAGS
868
+ start_tag, end_tag = QUOTE_TAGS[type] || NO_TAGS
721
869
  if role
722
- "#{start_tag}<span class=\"#{role}\">#{text}</span>#{end_tag}"
870
+ if start_tag.start_with? '<'
871
+ %(#{start_tag.chop} class="#{role}">#{text}#{end_tag})
872
+ else
873
+ %(#{start_tag}<span class="#{role}">#{text}</span>#{end_tag})
874
+ end
723
875
  else
724
876
  "#{start_tag}#{text}#{end_tag}"
725
877
  end
726
878
  end
727
879
 
728
880
  def result(node)
729
- quote_text(node.text, node.type, node.attr('role'))
881
+ quote_text(node.text, node.type, (node.attr 'role'))
882
+ end
883
+
884
+ def template
885
+ :invoke_result
886
+ end
887
+ end
888
+
889
+ class InlineButtonTemplate < BaseTemplate
890
+ def result(node)
891
+ %(<b class="button">#{node.text}</b>)
892
+ end
893
+
894
+ def template
895
+ :invoke_result
896
+ end
897
+ end
898
+
899
+ class InlineKbdTemplate < BaseTemplate
900
+ def result(node)
901
+ keys = node.attr 'keys'
902
+ if keys.size == 1
903
+ %(<kbd>#{keys.first}</kbd>)
904
+ else
905
+ key_combo = keys.map{|key| %(<kbd>#{key}</kbd>+) }.join.chop
906
+ %(<kbd class="keyseq">#{key_combo}</kbd>)
907
+ end
908
+ end
909
+
910
+ def template
911
+ :invoke_result
912
+ end
913
+ end
914
+
915
+ class InlineMenuTemplate < BaseTemplate
916
+ def menu(menu, submenus, menuitem)
917
+ if !submenus.empty?
918
+ submenu_path = submenus.map{|submenu| %(<span class="submenu">#{submenu}</span>&#160;&#9656; ) }.join.chop
919
+ %(<span class="menuseq"><span class="menu">#{menu}</span>&#160;&#9656; #{submenu_path} <span class="menuitem">#{menuitem}</span></span>)
920
+ elsif !menuitem.nil?
921
+ %(<span class="menuseq"><span class="menu">#{menu}</span>&#160;&#9656; <span class="menuitem">#{menuitem}</span></span>)
922
+ else
923
+ %(<span class="menu">#{menu}</span>)
924
+ end
925
+ end
926
+
927
+ def result(node)
928
+ menu(node.attr('menu'), node.attr('submenus'), node.attr('menuitem'))
730
929
  end
731
930
 
732
931
  def template
@@ -735,7 +934,7 @@ class InlineQuotedTemplate < BaseTemplate
735
934
  end
736
935
 
737
936
  class InlineAnchorTemplate < BaseTemplate
738
- def anchor(target, text, type, document, window = nil)
937
+ def anchor(target, text, type, document, node)
739
938
  case type
740
939
  when :xref
741
940
  text = document.references[:ids].fetch(target, "[#{target}]") if text.nil?
@@ -743,14 +942,14 @@ class InlineAnchorTemplate < BaseTemplate
743
942
  when :ref
744
943
  %(<a id="#{target}"></a>)
745
944
  when :link
746
- %(<a href="#{target}"#{window && " target=\"#{window}\""}>#{text}</a>)
945
+ %(<a href="#{target}"#{(node.attr? 'role') ? " class=\"#{node.attr 'role'}\"" : nil}#{(node.attr? 'window') ? " target=\"#{node.attr 'window'}\"" : nil}>#{text}</a>)
747
946
  when :bibref
748
947
  %(<a id="#{target}"></a>[#{target}])
749
948
  end
750
949
  end
751
950
 
752
951
  def result(node)
753
- anchor(node.target, node.text, node.type, node.document, (node.type == :link ? node.attr('window') : nil))
952
+ anchor(node.target, node.text, node.type, node.document, node)
754
953
  end
755
954
 
756
955
  def template