asciidoctor 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of asciidoctor might be problematic. Click here for more details.
- data/LICENSE +21 -0
- data/README.md +69 -0
- data/Rakefile +150 -0
- data/asciidoctor.gemspec +93 -0
- data/bin/asciidoctor +8 -0
- data/lib/asciidoctor.rb +152 -0
- data/lib/asciidoctor/block.rb +188 -0
- data/lib/asciidoctor/debug.rb +6 -0
- data/lib/asciidoctor/document.rb +717 -0
- data/lib/asciidoctor/errors.rb +5 -0
- data/lib/asciidoctor/list_item.rb +19 -0
- data/lib/asciidoctor/render_templates.rb +219 -0
- data/lib/asciidoctor/renderer.rb +62 -0
- data/lib/asciidoctor/section.rb +224 -0
- data/lib/asciidoctor/string.rb +12 -0
- data/lib/asciidoctor/version.rb +3 -0
- data/noof.rb +16 -0
- data/test/document_test.rb +23 -0
- data/test/fixtures/asciidoc.txt +105 -0
- data/test/fixtures/asciidoc_index.txt +507 -0
- data/test/fixtures/ascshort.txt +32 -0
- data/test/fixtures/list_elements.asciidoc +10 -0
- data/test/headers_test.rb +47 -0
- data/test/list_elements_test.rb +55 -0
- data/test/paragraphs_test.rb +38 -0
- data/test/test_helper.rb +143 -0
- data/test/text_test.rb +71 -0
- metadata +167 -0
@@ -0,0 +1,19 @@
|
|
1
|
+
# Public: Methods for managing items for Asciidoc olists, ulist, and dlists.
|
2
|
+
class Asciidoctor::ListItem
|
3
|
+
# Public: Get the Array of Blocks from the list item's continuation.
|
4
|
+
attr_reader :blocks
|
5
|
+
|
6
|
+
# Public: Get/Set the String content.
|
7
|
+
attr_accessor :content
|
8
|
+
|
9
|
+
# Public: Get/Set the String list item anchor name.
|
10
|
+
attr_accessor :anchor
|
11
|
+
|
12
|
+
# Public: Initialize an Asciidoctor::ListItem object.
|
13
|
+
#
|
14
|
+
# content - the String content (default '')
|
15
|
+
def initialize(content='')
|
16
|
+
@content = content
|
17
|
+
@blocks = []
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,219 @@
|
|
1
|
+
class BaseTemplate
|
2
|
+
def initialize
|
3
|
+
end
|
4
|
+
|
5
|
+
def self.inherited(klass)
|
6
|
+
@template_classes ||= []
|
7
|
+
@template_classes << klass
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.template_classes
|
11
|
+
@template_classes
|
12
|
+
end
|
13
|
+
|
14
|
+
# We're ignoring locals for now. Shut up.
|
15
|
+
def render(obj = Object.new, locals = {})
|
16
|
+
output = template.result(obj.instance_eval {binding})
|
17
|
+
end
|
18
|
+
|
19
|
+
def template
|
20
|
+
raise "You chilluns need to make your own template"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class DocumentTemplate < BaseTemplate
|
25
|
+
def template
|
26
|
+
@template ||= ::ERB.new <<-EOF
|
27
|
+
<div class='man-page'>
|
28
|
+
<div id='header'>
|
29
|
+
<% if header %>
|
30
|
+
<h1><%= header.name %></h1>
|
31
|
+
<div class='sectionbody'><%= header.content %></div>
|
32
|
+
<% elsif preamble %>
|
33
|
+
<div class=preamble'>
|
34
|
+
<div class='sectionbody'>
|
35
|
+
<%= preamble.content %>
|
36
|
+
</div>
|
37
|
+
</div>
|
38
|
+
<% end %>
|
39
|
+
</div>
|
40
|
+
|
41
|
+
<%= content %>
|
42
|
+
|
43
|
+
</div>
|
44
|
+
EOF
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class SectionTemplate < BaseTemplate
|
49
|
+
def template
|
50
|
+
@template ||= ERB.new <<-EOF
|
51
|
+
<div class='sect<%= level %>'>
|
52
|
+
<% if !anchor.nil? %>
|
53
|
+
<a name='<%= anchor %>'></a>
|
54
|
+
<% end %>
|
55
|
+
<h<%= level + 1 %> id='<%= section_id %>'><%= name %></h<%= level + 1 %>>
|
56
|
+
<% if level == 1 %>
|
57
|
+
<div class='sectionbody'><%= content %></div>
|
58
|
+
<% else %>
|
59
|
+
<%= content %>
|
60
|
+
<% end %>
|
61
|
+
</div>
|
62
|
+
EOF
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class SectionAnchorTemplate < BaseTemplate
|
67
|
+
def template
|
68
|
+
@template ||= ERB.new <<-EOF
|
69
|
+
<a name='<%= content %>'></a>
|
70
|
+
EOF
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class SectionDlistTemplate < BaseTemplate
|
75
|
+
def template
|
76
|
+
@template ||= ERB.new <<-EOF
|
77
|
+
<div class='dlist'>
|
78
|
+
<dl>
|
79
|
+
<% content.each do |dt, dd| %>
|
80
|
+
<dt class='hdlist1'><%= dt %></dt>
|
81
|
+
<% unless dd.nil? || dd.empty? %>
|
82
|
+
<dd><%= dd %></dd>
|
83
|
+
<% end %>
|
84
|
+
<% end %>
|
85
|
+
</dl>
|
86
|
+
</div>
|
87
|
+
EOF
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
class SectionListingTemplate < BaseTemplate
|
92
|
+
def template
|
93
|
+
@template ||= ERB.new <<-EOF
|
94
|
+
<div class='listingblock'>
|
95
|
+
<div class='content'>
|
96
|
+
<div class='highlight'>
|
97
|
+
<pre><%= content %></pre>
|
98
|
+
</div>
|
99
|
+
</div>
|
100
|
+
</div>
|
101
|
+
EOF
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
class SectionLiteralTemplate < BaseTemplate
|
106
|
+
def template
|
107
|
+
@template ||= ERB.new <<-EOF
|
108
|
+
<div class='literalblock'>
|
109
|
+
<div class='content'>
|
110
|
+
<pre><tt><%= content %></tt></pre>
|
111
|
+
</div>
|
112
|
+
</div>
|
113
|
+
EOF
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
class SectionNoteTemplate < BaseTemplate
|
118
|
+
def template
|
119
|
+
@template ||= ERB.new <<-EOF
|
120
|
+
<div class='admonitionblock'>
|
121
|
+
<table>
|
122
|
+
<tr>
|
123
|
+
<td class='icon'></td>
|
124
|
+
<td class='content'>
|
125
|
+
<% if !title.nil? %>
|
126
|
+
<div class='title'><%= title %></div>
|
127
|
+
<% end %>
|
128
|
+
<%= content %>
|
129
|
+
</td>
|
130
|
+
</tr>
|
131
|
+
</table>
|
132
|
+
</div>
|
133
|
+
EOF
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
class SectionParagraphTemplate < BaseTemplate
|
138
|
+
def template
|
139
|
+
@template ||= ERB.new <<-EOF
|
140
|
+
<div class='paragraph'>
|
141
|
+
<% if !title.nil? %>
|
142
|
+
<div class='title'><%= title %></div>
|
143
|
+
<% end %>
|
144
|
+
<p><%= content %></p>
|
145
|
+
</div>
|
146
|
+
EOF
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
class SectionSidebarTemplate < BaseTemplate
|
151
|
+
def template
|
152
|
+
@template ||= ERB.new <<-EOF
|
153
|
+
<div class='sidebarblock'>
|
154
|
+
<div class='content'>
|
155
|
+
<p><%= content %></p>
|
156
|
+
</div>
|
157
|
+
</div>
|
158
|
+
EOF
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
class SectionUlistTemplate < BaseTemplate
|
163
|
+
def template
|
164
|
+
@template ||= ERB.new <<-EOF
|
165
|
+
<div class='ulist'>
|
166
|
+
<ul>
|
167
|
+
<% content.each do |li| %>
|
168
|
+
<li><p><%= li %></p></li>
|
169
|
+
<% end %>
|
170
|
+
</ul>
|
171
|
+
</div>
|
172
|
+
EOF
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
=begin
|
177
|
+
../gitscm-next/templates/section_colist.html.erb
|
178
|
+
<div class='colist arabic'>
|
179
|
+
<ol>
|
180
|
+
<% content.each do |li| %>
|
181
|
+
<li><p><%= li %></p></li>
|
182
|
+
<% end %>
|
183
|
+
</ol>
|
184
|
+
</div>
|
185
|
+
../gitscm-next/templates/section_example.html.erb
|
186
|
+
<div class='exampleblock'>
|
187
|
+
<div class='content'>
|
188
|
+
<div class='literalblock'>
|
189
|
+
<div class='content'>
|
190
|
+
<pre><tt><%= content %></tt></pre>
|
191
|
+
</div>
|
192
|
+
</div>
|
193
|
+
</div>
|
194
|
+
</div>
|
195
|
+
../gitscm-next/templates/section_oblock.html.erb
|
196
|
+
<div class='openblock'>
|
197
|
+
<div class='content'>
|
198
|
+
<%= content %>
|
199
|
+
</div>
|
200
|
+
</div>
|
201
|
+
../gitscm-next/templates/section_olist.html.erb
|
202
|
+
<div class='olist arabic'>
|
203
|
+
<ol class='arabic'>
|
204
|
+
<% content.each do |li| %>
|
205
|
+
<li><p><%= li %></p></li>
|
206
|
+
<% end %>
|
207
|
+
</ol>
|
208
|
+
</div>
|
209
|
+
../gitscm-next/templates/section_quote.html.erb
|
210
|
+
<div class='quoteblock'>
|
211
|
+
<div class='content'>
|
212
|
+
<%= content %>
|
213
|
+
</div>
|
214
|
+
</div>
|
215
|
+
../gitscm-next/templates/section_verse.html.erb
|
216
|
+
<div class='verseblock'>
|
217
|
+
<pre class='content'><%= content %></pre>
|
218
|
+
</div>
|
219
|
+
=end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# Public: Methods for rendering Asciidoc Documents, Sections, and Blocks
|
2
|
+
# using erb templates.
|
3
|
+
class Asciidoctor::Renderer
|
4
|
+
# Public: Initialize an Asciidoctor::Renderer object.
|
5
|
+
#
|
6
|
+
def initialize(options={})
|
7
|
+
@debug = !!options[:debug]
|
8
|
+
|
9
|
+
@views = {}
|
10
|
+
|
11
|
+
# Load up all the template classes that we know how to render
|
12
|
+
BaseTemplate.template_classes.each do |tc|
|
13
|
+
view = tc.to_s.underscore.gsub(/_template$/, '')
|
14
|
+
@views[view] = tc.new
|
15
|
+
end
|
16
|
+
|
17
|
+
@render_stack = []
|
18
|
+
end
|
19
|
+
|
20
|
+
# Public: Render an Asciidoc object with a specified view template.
|
21
|
+
#
|
22
|
+
# view - the String view template name.
|
23
|
+
# object - the Object to be used as an evaluation scope.
|
24
|
+
# locals - the optional Hash of locals to be passed to Tilt (default {}) (also ignored, really)
|
25
|
+
def render(view, object, locals = {})
|
26
|
+
@render_stack.push([view, object])
|
27
|
+
if @views[view].nil?
|
28
|
+
raise "Couldn't find a view in @views for #{view}"
|
29
|
+
else
|
30
|
+
Asciidoctor.debug "View for #{view} is #{@views[view]}, object is #{object}"
|
31
|
+
end
|
32
|
+
ret = @views[view].render(object, locals)
|
33
|
+
|
34
|
+
if @debug
|
35
|
+
prefix = ''
|
36
|
+
STDERR.puts '=' * 80
|
37
|
+
STDERR.puts "Rendering:"
|
38
|
+
@render_stack.each do |stack_view, stack_obj|
|
39
|
+
obj_info = case stack_obj
|
40
|
+
when Section; "SECTION #{stack_obj.name}"
|
41
|
+
when Block;
|
42
|
+
if stack_obj.context == :dlist
|
43
|
+
dt_list = stack_obj.buffer.map{|dt,dd| dt.content.strip}.join(', ')
|
44
|
+
"BLOCK :dlist (#{dt_list})"
|
45
|
+
else
|
46
|
+
"BLOCK #{stack_obj.context.inspect}"
|
47
|
+
end
|
48
|
+
else stack_obj.class
|
49
|
+
end
|
50
|
+
STDERR.puts "#{prefix}#{stack_view}: #{obj_info}"
|
51
|
+
prefix << ' '
|
52
|
+
end
|
53
|
+
STDERR.puts '-' * 80
|
54
|
+
STDERR.puts ret.inspect
|
55
|
+
STDERR.puts '=' * 80
|
56
|
+
STDERR.puts
|
57
|
+
end
|
58
|
+
|
59
|
+
@render_stack.pop
|
60
|
+
ret
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,224 @@
|
|
1
|
+
# Public: Methods for managing sections of Asciidoc content in a document.
|
2
|
+
# The section responds as an Array of content blocks by delegating
|
3
|
+
# block-related methods to its @blocks Array.
|
4
|
+
#
|
5
|
+
# Examples
|
6
|
+
#
|
7
|
+
# section = Asciidoctor::Section.new
|
8
|
+
# section.name = 'DESCRIPTION'
|
9
|
+
# section.anchor = 'DESCRIPTION'
|
10
|
+
#
|
11
|
+
# section.size
|
12
|
+
# => 0
|
13
|
+
#
|
14
|
+
# section.section_id
|
15
|
+
# => "_description"
|
16
|
+
#
|
17
|
+
# section << new_block
|
18
|
+
# section.size
|
19
|
+
# => 1
|
20
|
+
class Asciidoctor::Section
|
21
|
+
# Public: Get/Set the Integer section level.
|
22
|
+
attr_accessor :level
|
23
|
+
|
24
|
+
# Public: Set the String section name.
|
25
|
+
attr_writer :name
|
26
|
+
|
27
|
+
# Public: Get/Set the String section title.
|
28
|
+
attr_accessor :title
|
29
|
+
|
30
|
+
# Public: Get/Set the String section caption.
|
31
|
+
attr_accessor :caption
|
32
|
+
|
33
|
+
# Public: Get/Set the String section anchor name.
|
34
|
+
attr_accessor :anchor
|
35
|
+
|
36
|
+
# Public: Get the Array of section blocks.
|
37
|
+
attr_reader :blocks
|
38
|
+
|
39
|
+
# Public: Initialize an Asciidoctor::Section object.
|
40
|
+
#
|
41
|
+
# parent - The parent Asciidoc Object.
|
42
|
+
def initialize(parent)
|
43
|
+
@parent = parent
|
44
|
+
@blocks = []
|
45
|
+
end
|
46
|
+
|
47
|
+
# Public: Get the String section name with intrinsics converted
|
48
|
+
#
|
49
|
+
# Examples
|
50
|
+
#
|
51
|
+
# section.name = "git-web{litdd}browse(1) Manual Page"
|
52
|
+
# section.name
|
53
|
+
# => "git-web--browse(1) Manual Page"
|
54
|
+
#
|
55
|
+
# Returns the String section name
|
56
|
+
def name
|
57
|
+
@name &&
|
58
|
+
@name.gsub(/(^|[^\\])\{(\w[\w\-]+\w)\}/) { $1 + Asciidocs::INTRINSICS[$2] }.
|
59
|
+
gsub( /`([^`]+)`/, '<tt>\1</tt>' )
|
60
|
+
end
|
61
|
+
|
62
|
+
# Public: Get the String section id
|
63
|
+
#
|
64
|
+
# Examples
|
65
|
+
#
|
66
|
+
# section = Section.new
|
67
|
+
# section.name = "Foo"
|
68
|
+
# section.section_id
|
69
|
+
# => "_foo"
|
70
|
+
def section_id
|
71
|
+
"_#{name && name.downcase.gsub(' ','_')}"
|
72
|
+
end
|
73
|
+
|
74
|
+
# Public: Get the Asciidoctor::Document instance to which this Block belongs
|
75
|
+
def document
|
76
|
+
@parent.is_a?(Asciidoctor::Document) ? @parent : @parent.document
|
77
|
+
end
|
78
|
+
|
79
|
+
# Public: Get the Asciidoctor::Renderer instance being used for the ancestor
|
80
|
+
# Asciidoctor::Document instance.
|
81
|
+
def renderer
|
82
|
+
Asciidoctor.debug "Section#renderer: Looking for my renderer up in #{@parent}"
|
83
|
+
@parent.renderer
|
84
|
+
end
|
85
|
+
|
86
|
+
# Public: Get the rendered String content for this Section and all its child
|
87
|
+
# Blocks.
|
88
|
+
def render
|
89
|
+
Asciidoctor.debug "Now rendering section for #{self}"
|
90
|
+
renderer.render('section', self)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Public: Get the String section content by aggregating rendered section blocks.
|
94
|
+
#
|
95
|
+
# Examples
|
96
|
+
#
|
97
|
+
# section = Section.new
|
98
|
+
# section << 'foo'
|
99
|
+
# section << 'bar'
|
100
|
+
# section << 'baz'
|
101
|
+
# section.content
|
102
|
+
# "<div class=\"paragraph\"><p>foo</p></div>\n<div class=\"paragraph\"><p>bar</p></div>\n<div class=\"paragraph\"><p>baz</p></div>"
|
103
|
+
def content
|
104
|
+
@blocks.map do |block|
|
105
|
+
Asciidoctor.debug "Begin rendering block #{block.is_a?(Asciidoctor::Section) ? block.name : 'n/a'} #{block} (context: #{block.is_a?(Asciidoctor::Block) ? block.context : 'n/a' })"
|
106
|
+
poo = block.render
|
107
|
+
Asciidoctor.debug "===> Done rendering block #{block.is_a?(Asciidoctor::Section) ? block.name : 'n/a'} #{block} (context: #{block.is_a?(Asciidoctor::Block) ? block.context : 'n/a' })"
|
108
|
+
poo
|
109
|
+
end.join
|
110
|
+
end
|
111
|
+
|
112
|
+
# Public: Get the Integer number of blocks in the section.
|
113
|
+
#
|
114
|
+
# Examples
|
115
|
+
#
|
116
|
+
# section = Section.new
|
117
|
+
#
|
118
|
+
# section.size
|
119
|
+
# => 0
|
120
|
+
#
|
121
|
+
# section << 'foo'
|
122
|
+
# section << 'bar'
|
123
|
+
# section.size
|
124
|
+
# => 2
|
125
|
+
def size
|
126
|
+
@blocks.size
|
127
|
+
end
|
128
|
+
|
129
|
+
# Public: Get the element at i in the array of section blocks.
|
130
|
+
#
|
131
|
+
# i - The Integer array index number.
|
132
|
+
#
|
133
|
+
# section = Section.new
|
134
|
+
#
|
135
|
+
# section << 'foo'
|
136
|
+
# section << 'bar'
|
137
|
+
# section[1]
|
138
|
+
# => "bar"
|
139
|
+
def [](i)
|
140
|
+
@blocks[i]
|
141
|
+
end
|
142
|
+
|
143
|
+
# Public: Delete the element at i in the array of section blocks,
|
144
|
+
# returning that element or nil if i is out of range.
|
145
|
+
#
|
146
|
+
# i - The Integer array index number.
|
147
|
+
#
|
148
|
+
# section = Section.new
|
149
|
+
#
|
150
|
+
# section << 'foo'
|
151
|
+
# section << 'bar'
|
152
|
+
# section.delete_at(1)
|
153
|
+
# => "bar"
|
154
|
+
#
|
155
|
+
# section.blocks
|
156
|
+
# => ["foo"]
|
157
|
+
def delete_at(i)
|
158
|
+
@blocks.delete_at(i)
|
159
|
+
end
|
160
|
+
|
161
|
+
# Public: Append a content block to this section's list of blocks.
|
162
|
+
#
|
163
|
+
# block - The new section block.
|
164
|
+
#
|
165
|
+
# section = Section.new
|
166
|
+
#
|
167
|
+
# section << 'foo'
|
168
|
+
# section << 'bar'
|
169
|
+
# section.blocks
|
170
|
+
# => ["foo", "bar"]
|
171
|
+
def <<(block)
|
172
|
+
@blocks << block
|
173
|
+
end
|
174
|
+
|
175
|
+
# Public: Clear this Section's list of blocks.
|
176
|
+
#
|
177
|
+
# section = Section.new
|
178
|
+
#
|
179
|
+
# section << 'foo'
|
180
|
+
# section << 'bar'
|
181
|
+
# section.blocks
|
182
|
+
# => ["foo", "bar"]
|
183
|
+
# section.clear_blocks
|
184
|
+
# section.blocks
|
185
|
+
# => []
|
186
|
+
def clear_blocks
|
187
|
+
@blocks = []
|
188
|
+
end
|
189
|
+
|
190
|
+
# Public: Insert a content block at the specified index in this section's
|
191
|
+
# list of blocks.
|
192
|
+
#
|
193
|
+
# i - The Integer array index number.
|
194
|
+
# val = The content block to insert.
|
195
|
+
#
|
196
|
+
# section = Section.new
|
197
|
+
#
|
198
|
+
# section << 'foo'
|
199
|
+
# section << 'baz'
|
200
|
+
# section.insert(1, 'bar')
|
201
|
+
# section.blocks
|
202
|
+
# ["foo", "bar", "baz"]
|
203
|
+
def insert(i, block)
|
204
|
+
@blocks.insert(i, block)
|
205
|
+
end
|
206
|
+
|
207
|
+
# Public: Get the Integer index number of the first content block element
|
208
|
+
# for which the provided block returns true. Returns nil if no match is
|
209
|
+
# found.
|
210
|
+
#
|
211
|
+
# block - A block that can be used to determine whether a supplied element
|
212
|
+
# is a match.
|
213
|
+
#
|
214
|
+
# section = Section.new
|
215
|
+
#
|
216
|
+
# section << 'foo'
|
217
|
+
# section << 'bar'
|
218
|
+
# section << 'baz'
|
219
|
+
# section.index{|el| el =~ /^ba/}
|
220
|
+
# => 1
|
221
|
+
def index(&block)
|
222
|
+
@blocks.index(&block)
|
223
|
+
end
|
224
|
+
end
|