nronn 0.10.1.pre2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/AUTHORS +8 -0
- data/CHANGES +230 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +72 -0
- data/INSTALLING.md +92 -0
- data/LICENSE.txt +12 -0
- data/README.md +131 -0
- data/Rakefile +153 -0
- data/bin/ronn +253 -0
- data/completion/bash/ronn +32 -0
- data/completion/zsh/_ronn +24 -0
- data/config.ru +15 -0
- data/lib/ronn/document.rb +530 -0
- data/lib/ronn/index.rb +180 -0
- data/lib/ronn/roff.rb +393 -0
- data/lib/ronn/server.rb +67 -0
- data/lib/ronn/template/80c.css +6 -0
- data/lib/ronn/template/dark.css +18 -0
- data/lib/ronn/template/darktoc.css +17 -0
- data/lib/ronn/template/default.html +41 -0
- data/lib/ronn/template/man.css +100 -0
- data/lib/ronn/template/print.css +5 -0
- data/lib/ronn/template/screen.css +105 -0
- data/lib/ronn/template/toc.css +27 -0
- data/lib/ronn/template.rb +173 -0
- data/lib/ronn/utils.rb +57 -0
- data/lib/ronn.rb +47 -0
- data/man/index.html +78 -0
- data/man/index.txt +15 -0
- data/man/ronn-format.7 +145 -0
- data/man/ronn-format.7.ronn +157 -0
- data/man/ronn.1 +227 -0
- data/man/ronn.1.ronn +316 -0
- data/nronn.gemspec +136 -0
- data/test/angle_bracket_syntax.html +27 -0
- data/test/angle_bracket_syntax.roff +24 -0
- data/test/angle_bracket_syntax.ronn +22 -0
- data/test/backticks.html +14 -0
- data/test/backticks.ronn +10 -0
- data/test/basic_document.html +8 -0
- data/test/basic_document.ronn +4 -0
- data/test/circumflexes.ronn +1 -0
- data/test/code_blocks.html +38 -0
- data/test/code_blocks.roff +38 -0
- data/test/code_blocks.ronn +41 -0
- data/test/code_blocks_regression +19 -0
- data/test/code_blocks_regression.html +38 -0
- data/test/code_blocks_regression.ronn +40 -0
- data/test/contest.rb +70 -0
- data/test/custom_title_document.html +6 -0
- data/test/custom_title_document.ronn +5 -0
- data/test/definition_list_syntax.html +25 -0
- data/test/definition_list_syntax.roff +19 -0
- data/test/definition_list_syntax.ronn +18 -0
- data/test/dots_at_line_start_test.roff +19 -0
- data/test/dots_at_line_start_test.ronn +12 -0
- data/test/ellipses.roff +7 -0
- data/test/ellipses.ronn +7 -0
- data/test/entity_encoding_test.html +42 -0
- data/test/entity_encoding_test.roff +51 -0
- data/test/entity_encoding_test.ronn +34 -0
- data/test/index.txt +8 -0
- data/test/markdown_syntax.html +954 -0
- data/test/markdown_syntax.roff +907 -0
- data/test/markdown_syntax.ronn +881 -0
- data/test/middle_paragraph.html +14 -0
- data/test/middle_paragraph.roff +9 -0
- data/test/middle_paragraph.ronn +10 -0
- data/test/missing_spaces.roff +7 -0
- data/test/missing_spaces.ronn +2 -0
- data/test/nested_list.ronn +19 -0
- data/test/nested_list_with_code.html +14 -0
- data/test/nested_list_with_code.roff +11 -0
- data/test/nested_list_with_code.ronn +6 -0
- data/test/ordered_list.html +28 -0
- data/test/ordered_list.roff +25 -0
- data/test/ordered_list.ronn +21 -0
- data/test/page.with.periods.in.name.5.ronn +4 -0
- data/test/pre_block_with_quotes.roff +8 -0
- data/test/pre_block_with_quotes.ronn +6 -0
- data/test/section_reference_links.html +16 -0
- data/test/section_reference_links.roff +7 -0
- data/test/section_reference_links.ronn +12 -0
- data/test/single_quotes.html +11 -0
- data/test/single_quotes.roff +5 -0
- data/test/single_quotes.ronn +9 -0
- data/test/tables.ronn +24 -0
- data/test/test_ronn.rb +124 -0
- data/test/test_ronn_document.rb +186 -0
- data/test/test_ronn_index.rb +73 -0
- data/test/titleless_document.html +9 -0
- data/test/titleless_document.ronn +3 -0
- data/test/underline_spacing_test.roff +13 -0
- data/test/underline_spacing_test.ronn +11 -0
- metadata +309 -0
data/lib/ronn/roff.rb
ADDED
@@ -0,0 +1,393 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require 'ronn/utils'
|
3
|
+
|
4
|
+
module Ronn
|
5
|
+
# Filter for converting HTML to ROFF
|
6
|
+
class RoffFilter
|
7
|
+
include Ronn::Utils
|
8
|
+
|
9
|
+
# Convert Ronn HTML to roff.
|
10
|
+
# The html input is an HTML fragment, not a complete document
|
11
|
+
def initialize(html_fragment, name, section, tagline, manual = nil,
|
12
|
+
version = nil, date = nil)
|
13
|
+
@buf = []
|
14
|
+
title_heading name, section, tagline, manual, version, date
|
15
|
+
doc = Nokogiri::HTML.fragment(html_fragment)
|
16
|
+
remove_extraneous_elements! doc
|
17
|
+
normalize_whitespace! doc
|
18
|
+
block_filter doc
|
19
|
+
write "\n"
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_s
|
23
|
+
@buf.join.gsub(/[ \t]+$/, '')
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
def previous(node)
|
29
|
+
return unless node.respond_to?(:previous)
|
30
|
+
prev = node.previous
|
31
|
+
prev = prev.previous until prev.nil? || prev.elem?
|
32
|
+
prev
|
33
|
+
end
|
34
|
+
|
35
|
+
def title_heading(name, section, _tagline, manual, version, date)
|
36
|
+
comment "generated with nRonn/v#{Ronn.version}"
|
37
|
+
comment "https://github.com/n-ronn/nronn/tree/#{Ronn.revision}"
|
38
|
+
return if name.nil?
|
39
|
+
if manual
|
40
|
+
macro 'TH', %("#{escape(name.upcase)}" "#{section}" "#{date.strftime('%B %Y')}" "#{version}" "#{manual}")
|
41
|
+
else
|
42
|
+
macro 'TH', %("#{escape(name.upcase)}" "#{section}" "#{date.strftime('%B %Y')}" "#{version}")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def remove_extraneous_elements!(doc)
|
47
|
+
doc.traverse do |node|
|
48
|
+
node.parent.children.delete(node) if node.comment?
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def normalize_whitespace!(node)
|
53
|
+
if node.is_a?(Array) || node.is_a?(Nokogiri::XML::NodeSet)
|
54
|
+
node.to_a.dup.each { |ch| normalize_whitespace! ch }
|
55
|
+
elsif node.text?
|
56
|
+
preceding = node.previous
|
57
|
+
following = node.next
|
58
|
+
content = node.content.gsub(/[\n ]+/m, ' ')
|
59
|
+
if preceding.nil? || block_element?(preceding.name) ||
|
60
|
+
preceding.name == 'br'
|
61
|
+
content.lstrip!
|
62
|
+
end
|
63
|
+
if following.nil? || block_element?(following.name) ||
|
64
|
+
following.name == 'br'
|
65
|
+
content.rstrip!
|
66
|
+
end
|
67
|
+
if content.empty?
|
68
|
+
node.remove
|
69
|
+
else
|
70
|
+
node.content = content
|
71
|
+
end
|
72
|
+
elsif node.elem? && node.name == 'pre'
|
73
|
+
# stop traversing
|
74
|
+
elsif node.elem? && node.children
|
75
|
+
normalize_whitespace! node.children
|
76
|
+
elsif node.elem?
|
77
|
+
# element has no children
|
78
|
+
elsif node.document? || node.fragment?
|
79
|
+
normalize_whitespace! node.children
|
80
|
+
elsif node.is_a?(Nokogiri::XML::DTD) || node.is_a?(Nokogiri::XML::Comment)
|
81
|
+
# ignore
|
82
|
+
nop
|
83
|
+
else
|
84
|
+
warn 'unexpected node during whitespace normalization: %p', node
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def block_filter(node)
|
89
|
+
return if node.nil?
|
90
|
+
|
91
|
+
if node.is_a?(Array) || node.is_a?(Nokogiri::XML::NodeSet)
|
92
|
+
node.each { |ch| block_filter(ch) }
|
93
|
+
|
94
|
+
elsif node.document? || node.fragment?
|
95
|
+
block_filter(node.children)
|
96
|
+
|
97
|
+
elsif node.text?
|
98
|
+
# This hack is necessary to support mixed-child-type dd's
|
99
|
+
inline_filter(node)
|
100
|
+
|
101
|
+
elsif node.elem?
|
102
|
+
case node.name
|
103
|
+
when 'html', 'body'
|
104
|
+
block_filter(node.children)
|
105
|
+
when 'div'
|
106
|
+
block_filter(node.children)
|
107
|
+
when 'h1'
|
108
|
+
# discard
|
109
|
+
nop
|
110
|
+
when 'h2'
|
111
|
+
macro 'SH', quote(escape(node.inner_html))
|
112
|
+
when 'h3'
|
113
|
+
macro 'SS', quote(escape(node.inner_html))
|
114
|
+
when 'h4', 'h5', 'h6'
|
115
|
+
# Ronn discourages use of this many heading levels, but if they are used,
|
116
|
+
# we should make them legible instead of ignoring them.
|
117
|
+
macro 'SS', quote(escape(node.inner_html))
|
118
|
+
|
119
|
+
when 'p'
|
120
|
+
prev = previous(node)
|
121
|
+
if prev && %w[dd li blockquote].include?(node.parent.name)
|
122
|
+
macro 'IP'
|
123
|
+
elsif prev && !%w[h1 h2 h3].include?(prev.name)
|
124
|
+
macro 'P'
|
125
|
+
elsif node.previous&.text?
|
126
|
+
macro 'IP'
|
127
|
+
end
|
128
|
+
inline_filter(node.children)
|
129
|
+
|
130
|
+
when 'blockquote'
|
131
|
+
prev = previous(node)
|
132
|
+
indent = prev.nil? || !%w[h1 h2 h3].include?(prev.name)
|
133
|
+
macro 'IP', %w["" 4] if indent
|
134
|
+
block_filter(node.children)
|
135
|
+
macro 'IP', %w["" 0] if indent
|
136
|
+
|
137
|
+
when 'pre'
|
138
|
+
prev = previous(node)
|
139
|
+
indent = prev.nil? || !%w[h1 h2 h3].include?(prev.name)
|
140
|
+
macro 'IP', %w["" 4] if indent
|
141
|
+
macro 'nf'
|
142
|
+
# HACK: strip an initial \n to avoid extra spacing
|
143
|
+
if node.children && node.children[0].text?
|
144
|
+
text = node.children[0].to_s
|
145
|
+
node.children[0].replace(text[1..-1]) if text.start_with? "\n"
|
146
|
+
end
|
147
|
+
inline_filter(node.children)
|
148
|
+
macro 'fi'
|
149
|
+
macro 'IP', %w["" 0] if indent
|
150
|
+
|
151
|
+
when 'dl'
|
152
|
+
macro 'TP'
|
153
|
+
block_filter(node.children)
|
154
|
+
when 'dt'
|
155
|
+
prev = previous(node)
|
156
|
+
macro 'TP' unless prev.nil?
|
157
|
+
inline_filter(node.children)
|
158
|
+
write "\n"
|
159
|
+
when 'dd'
|
160
|
+
if node.at('p')
|
161
|
+
block_filter(node.children)
|
162
|
+
else
|
163
|
+
inline_filter(node.children)
|
164
|
+
end
|
165
|
+
write "\n"
|
166
|
+
|
167
|
+
when 'ol', 'ul'
|
168
|
+
block_filter(node.children)
|
169
|
+
macro 'IP', %w["" 0]
|
170
|
+
when 'li'
|
171
|
+
case node.parent.name
|
172
|
+
when 'ol'
|
173
|
+
macro 'IP', %W["#{node.parent.children.index(node) + 1}." 4]
|
174
|
+
when 'ul'
|
175
|
+
macro 'IP', ['"\(bu"', '4']
|
176
|
+
else
|
177
|
+
raise "List element found as a child of non-list parent element: #{node.inspect}"
|
178
|
+
end
|
179
|
+
if node.at('p,ol,ul,dl,div')
|
180
|
+
block_filter(node.children)
|
181
|
+
else
|
182
|
+
inline_filter(node.children)
|
183
|
+
end
|
184
|
+
write "\n"
|
185
|
+
|
186
|
+
when 'span', 'code', 'b', 'strong', 'kbd', 'samp', 'var', 'em', 'i',
|
187
|
+
'u', 'br', 'a'
|
188
|
+
inline_filter(node)
|
189
|
+
|
190
|
+
when 'table'
|
191
|
+
macro 'TS'
|
192
|
+
write "allbox;\n"
|
193
|
+
block_filter(node.children)
|
194
|
+
macro 'TE'
|
195
|
+
when 'thead'
|
196
|
+
# Convert to format section and first row
|
197
|
+
tr = node.children[0]
|
198
|
+
header_contents = []
|
199
|
+
cell_formats = []
|
200
|
+
tr.children.each do |th|
|
201
|
+
style = th['style']
|
202
|
+
cell_format = case style
|
203
|
+
when 'text-align:left;'
|
204
|
+
'l'
|
205
|
+
when 'text-align:right;'
|
206
|
+
'r'
|
207
|
+
when 'text-align:center;'
|
208
|
+
'c'
|
209
|
+
else
|
210
|
+
'l'
|
211
|
+
end
|
212
|
+
header_contents << th.inner_html
|
213
|
+
cell_formats << cell_format
|
214
|
+
end
|
215
|
+
write cell_formats.join(' ') + ".\n"
|
216
|
+
write header_contents.join("\t") + "\n"
|
217
|
+
when 'th'
|
218
|
+
raise 'internal error: unexpected <th> element'
|
219
|
+
when 'tbody'
|
220
|
+
# Let the 'tr' handle it
|
221
|
+
block_filter(node.children)
|
222
|
+
when 'tr'
|
223
|
+
# Convert to a table data row
|
224
|
+
node.children.each do |child|
|
225
|
+
block_filter(child)
|
226
|
+
write "\t"
|
227
|
+
end
|
228
|
+
write "\n"
|
229
|
+
when 'td'
|
230
|
+
inline_filter(node.children)
|
231
|
+
|
232
|
+
else
|
233
|
+
warn 'unrecognized block tag: %p', node.name
|
234
|
+
end
|
235
|
+
|
236
|
+
elsif node.is_a?(Nokogiri::XML::DTD)
|
237
|
+
# Ignore
|
238
|
+
nop
|
239
|
+
elsif node.is_a?(Nokogiri::XML::Comment)
|
240
|
+
# Ignore
|
241
|
+
nop
|
242
|
+
else
|
243
|
+
raise "unexpected node: #{node.inspect}"
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
def inline_filter(node)
|
248
|
+
return unless node # is an empty node
|
249
|
+
|
250
|
+
if node.is_a?(Array) || node.is_a?(Nokogiri::XML::NodeSet)
|
251
|
+
node.each { |ch| inline_filter(ch) }
|
252
|
+
|
253
|
+
elsif node.text?
|
254
|
+
text = node.to_html.dup
|
255
|
+
write escape(text)
|
256
|
+
|
257
|
+
elsif node.comment?
|
258
|
+
# ignore HTML comments
|
259
|
+
|
260
|
+
elsif node.elem?
|
261
|
+
case node.name
|
262
|
+
when 'span'
|
263
|
+
inline_filter(node.children)
|
264
|
+
|
265
|
+
when 'code'
|
266
|
+
if child_of?(node, 'pre')
|
267
|
+
inline_filter(node.children)
|
268
|
+
else
|
269
|
+
write '\fB'
|
270
|
+
inline_filter(node.children)
|
271
|
+
write '\fR'
|
272
|
+
end
|
273
|
+
|
274
|
+
when 'b', 'strong', 'kbd', 'samp'
|
275
|
+
write '\fB'
|
276
|
+
inline_filter(node.children)
|
277
|
+
write '\fR'
|
278
|
+
|
279
|
+
when 'var', 'em', 'i', 'u'
|
280
|
+
write '\fI'
|
281
|
+
inline_filter(node.children)
|
282
|
+
write '\fR'
|
283
|
+
|
284
|
+
when 'br'
|
285
|
+
macro 'br'
|
286
|
+
|
287
|
+
when 'a'
|
288
|
+
if node.classes.include?('man-ref')
|
289
|
+
inline_filter(node.children)
|
290
|
+
elsif node.has_attribute?('data-bare-link')
|
291
|
+
write '\fI'
|
292
|
+
inline_filter(node.children)
|
293
|
+
write '\fR'
|
294
|
+
else
|
295
|
+
inline_filter(node.children)
|
296
|
+
write ' '
|
297
|
+
write '\fI'
|
298
|
+
write escape(node.attributes['href'].content)
|
299
|
+
write '\fR'
|
300
|
+
end
|
301
|
+
|
302
|
+
when 'sup'
|
303
|
+
# This superscript equivalent is a big ugly hack.
|
304
|
+
write '^('
|
305
|
+
inline_filter(node.children)
|
306
|
+
write ')'
|
307
|
+
|
308
|
+
else
|
309
|
+
warn 'unrecognized inline tag: %p', node.name
|
310
|
+
end
|
311
|
+
|
312
|
+
else
|
313
|
+
raise "unexpected node: #{node.inspect}"
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
def maybe_new_line
|
318
|
+
write "\n" if @buf.last && @buf.last[-1] != "\n"
|
319
|
+
end
|
320
|
+
|
321
|
+
def macro(name, value = nil)
|
322
|
+
maybe_new_line
|
323
|
+
writeln ".#{[name, value].compact.join(' ')}"
|
324
|
+
end
|
325
|
+
|
326
|
+
HTML_ROFF_ENTITIES = {
|
327
|
+
'•' => '\(bu',
|
328
|
+
'<' => '<',
|
329
|
+
'>' => '>',
|
330
|
+
' ' => '\~', # That's a literal non-breaking space character there
|
331
|
+
'©' => '\(co',
|
332
|
+
'”' => '\(rs',
|
333
|
+
'—' => '\(em',
|
334
|
+
'®' => '\(rg',
|
335
|
+
'§' => '\(sc',
|
336
|
+
'≥' => '\(>=',
|
337
|
+
'≤' => '\(<=',
|
338
|
+
'≠' => '\(!=',
|
339
|
+
'≡' => '\(=='
|
340
|
+
}.freeze
|
341
|
+
|
342
|
+
def escape(text)
|
343
|
+
return text.to_s if text.nil? || text.empty?
|
344
|
+
ent = HTML_ROFF_ENTITIES
|
345
|
+
text = text.dup
|
346
|
+
text.gsub!(/&#x([0-9A-Fa-f]+);/) { $1.to_i(16).chr } # hex entities
|
347
|
+
text.gsub!(/&#(\d+);/) { $1.to_i.chr } # dec entities
|
348
|
+
text.gsub!('\\', '\e') # backslash
|
349
|
+
text.gsub!('...', '\|.\|.\|.') # ellipses
|
350
|
+
text.gsub!(/[.-]/) { |m| "\\#{m}" } # control chars
|
351
|
+
ent.each do |key, val|
|
352
|
+
text.gsub!(key, val)
|
353
|
+
end
|
354
|
+
text.gsub!('&', '&') # amps
|
355
|
+
text
|
356
|
+
end
|
357
|
+
|
358
|
+
def quote(text)
|
359
|
+
"\"#{text.gsub(/"/, '\\"')}\""
|
360
|
+
end
|
361
|
+
|
362
|
+
# write text to output buffer
|
363
|
+
def write(text)
|
364
|
+
return if text.nil? || text.empty?
|
365
|
+
# lines cannot start with a '.' or "'". insert zero-width character before.
|
366
|
+
text = text.gsub(/\n\\\./, "\n\\\\&\\.")
|
367
|
+
text = text.gsub(/\n'/, "\n\\&\\'")
|
368
|
+
buf_ends_in_newline = @buf.last && @buf.last[-1] == "\n"
|
369
|
+
@buf << '\&' if text[0, 2] == '\.' && buf_ends_in_newline
|
370
|
+
@buf << '\&' if text[0, 1] == "'" && buf_ends_in_newline
|
371
|
+
@buf << text
|
372
|
+
end
|
373
|
+
|
374
|
+
# write text to output buffer on a new line.
|
375
|
+
def writeln(text)
|
376
|
+
maybe_new_line
|
377
|
+
write text
|
378
|
+
write "\n"
|
379
|
+
end
|
380
|
+
|
381
|
+
def comment(text)
|
382
|
+
writeln %(.\\" #{text})
|
383
|
+
end
|
384
|
+
|
385
|
+
def warn(text, *args)
|
386
|
+
Kernel.warn format("warn: #{text}", args)
|
387
|
+
end
|
388
|
+
|
389
|
+
def nop
|
390
|
+
# Do nothing
|
391
|
+
end
|
392
|
+
end
|
393
|
+
end
|
data/lib/ronn/server.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'ronn'
|
2
|
+
require 'rack'
|
3
|
+
require 'sinatra/base'
|
4
|
+
|
5
|
+
module Ronn
|
6
|
+
# Ronn HTTP server. Serves a list of .ronn files as HTML. The options Hash is
|
7
|
+
# passed to Ronn::Document.new on each invocation.
|
8
|
+
#
|
9
|
+
# Use Ronn::Server.new to create a Rack app. See the config.ru file in the
|
10
|
+
# root of the Ronn distribution for example usage.
|
11
|
+
#
|
12
|
+
# Ronn::Server.run starts a server on port 1207.
|
13
|
+
module Server
|
14
|
+
def self.new(files, options = {})
|
15
|
+
files = Dir[files] if files.respond_to?(:to_str)
|
16
|
+
raise ArgumentError, 'no files' if files.empty?
|
17
|
+
Sinatra.new do
|
18
|
+
set :show_exceptions, true
|
19
|
+
set :public_dir, File.expand_path(__FILE__, '../templates')
|
20
|
+
set :static, false
|
21
|
+
set :views, File.expand_path(__FILE__, '../templates')
|
22
|
+
|
23
|
+
get '/' do
|
24
|
+
files.map do |f|
|
25
|
+
base = File.basename(f, '.ronn')
|
26
|
+
"<li><a href='./#{base}.html'>#{escape_html(base)}</a></li>"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
options[:styles] ||= options[:style]
|
31
|
+
my_styles = if options[:styles].respond_to?(:to_ary)
|
32
|
+
options[:styles]
|
33
|
+
elsif options[:styles]
|
34
|
+
options[:styles].split(/[, ]+/)
|
35
|
+
else
|
36
|
+
[]
|
37
|
+
end
|
38
|
+
|
39
|
+
files.each do |file|
|
40
|
+
basename = File.basename(file, '.ronn')
|
41
|
+
|
42
|
+
get "/#{basename}.html" do
|
43
|
+
options = options.merge(styles: my_styles)
|
44
|
+
%w[date manual organization].each do |attribute|
|
45
|
+
next unless params[attribute]
|
46
|
+
options[attribute] = params[attribute]
|
47
|
+
end
|
48
|
+
Ronn::Document.new(file, options).to_html
|
49
|
+
end
|
50
|
+
get "/#{basename}.roff" do
|
51
|
+
content_type 'text/plain+roff'
|
52
|
+
Ronn::Document.new(file, options.dup).to_roff
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.run(files, options = {})
|
59
|
+
port_number = options['port'] || 1207
|
60
|
+
new(files, options).run!(
|
61
|
+
server: %w[mongrel thin webrick],
|
62
|
+
port: port_number,
|
63
|
+
logging: true
|
64
|
+
)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
.mp, body#manpage {
|
2
|
+
background:#080706;
|
3
|
+
color:#888;
|
4
|
+
}
|
5
|
+
.mp, .mp code, .mp pre,
|
6
|
+
.mp pre code, .mp tt, .mp kbd,
|
7
|
+
.mp samp { color:#aaa }
|
8
|
+
.mp h1, .mp h2, .mp h3, .mp h4 { color:#fff }
|
9
|
+
.man-decor, .man-decor ol li { color:#666 }
|
10
|
+
.mp code, .mp strong, .mp b { color:#fff }
|
11
|
+
|
12
|
+
.mp em, .mp var, .mp u { color:#ddd }
|
13
|
+
|
14
|
+
.mp pre code { color:#ddd }
|
15
|
+
|
16
|
+
.mp a, .mp a:link, .mp a:hover,
|
17
|
+
.mp a code, .mp a pre, .mp a tt,
|
18
|
+
.mp a kbd, .mp a samp { color:#fff }
|
@@ -0,0 +1,17 @@
|
|
1
|
+
/* darktoc.css - enable table of contents */
|
2
|
+
|
3
|
+
.man-navigation {
|
4
|
+
border-left:2px solid #222;
|
5
|
+
background-color:#131211;
|
6
|
+
}
|
7
|
+
.man-navigation a,
|
8
|
+
.man-navigation a:hover,
|
9
|
+
.man-navigation a:link,
|
10
|
+
.man-navigation a:visited {
|
11
|
+
color:#777;
|
12
|
+
text-decoration:none;
|
13
|
+
}
|
14
|
+
.man-navigation a:hover {
|
15
|
+
color:#fff;
|
16
|
+
text-decoration:underline;
|
17
|
+
}
|
@@ -0,0 +1,41 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta http-equiv='content-type' content='text/html;charset=utf8'>
|
5
|
+
<meta name='generator' content='{{ generator }}'>
|
6
|
+
<title>{{ title }}</title>
|
7
|
+
{{{ stylesheet_tags }}}
|
8
|
+
</head>
|
9
|
+
<!--
|
10
|
+
The following styles are deprecated and will be removed at some point:
|
11
|
+
div#man, div#man ol.man, div#man ol.head, div#man ol.man.
|
12
|
+
|
13
|
+
The .man-page, .man-decor, .man-head, .man-foot, .man-title, and
|
14
|
+
.man-navigation should be used instead.
|
15
|
+
-->
|
16
|
+
<body id='manpage'>
|
17
|
+
<div class='mp' id='man'>
|
18
|
+
|
19
|
+
<div class='man-navigation' style='display:none'>
|
20
|
+
{{#section_heads}}
|
21
|
+
<a href="#{{id}}">{{text}}</a>
|
22
|
+
{{/section_heads}}
|
23
|
+
</div>
|
24
|
+
|
25
|
+
<ol class='man-decor man-head man head'>
|
26
|
+
<li class='tl'>{{ page_name }}</li>
|
27
|
+
<li class='tc'>{{ manual }}</li>
|
28
|
+
<li class='tr'>{{ page_name }}</li>
|
29
|
+
</ol>
|
30
|
+
|
31
|
+
{{{ html }}}
|
32
|
+
|
33
|
+
<ol class='man-decor man-foot man foot'>
|
34
|
+
<li class='tl'>{{ organization }}</li>
|
35
|
+
<li class='tc'>{{ date }}</li>
|
36
|
+
<li class='tr'>{{ page_name }}</li>
|
37
|
+
</ol>
|
38
|
+
|
39
|
+
</div>
|
40
|
+
</body>
|
41
|
+
</html>
|
@@ -0,0 +1,100 @@
|
|
1
|
+
/* man.css - core manpage styles */
|
2
|
+
|
3
|
+
/* STRUCTURE, INDENT, MARGINS */
|
4
|
+
|
5
|
+
body#manpage { margin:0 }
|
6
|
+
.mp {
|
7
|
+
max-width:100ex;
|
8
|
+
padding:0 9ex 1ex 4ex;
|
9
|
+
}
|
10
|
+
|
11
|
+
.mp p, .mp pre,
|
12
|
+
.mp ul, .mp ol, .mp dl { margin:0 0 20px 0 }
|
13
|
+
.mp h2 { margin:10px 0 0 0 }
|
14
|
+
|
15
|
+
.mp > p, .mp > pre, .mp > ul,
|
16
|
+
.mp > ol, .mp > dl { margin-left:8ex }
|
17
|
+
.mp h3 { margin:0 0 0 4ex }
|
18
|
+
|
19
|
+
.mp dt { margin:0; clear:left }
|
20
|
+
.mp dt.flush { float:left; width:8ex }
|
21
|
+
.mp dd { margin:0 0 0 9ex }
|
22
|
+
.mp h1, .mp h2, .mp h3, .mp h4 { clear:left }
|
23
|
+
|
24
|
+
.mp pre { margin-bottom:20px }
|
25
|
+
.mp pre+h2, .mp pre+h3 { margin-top:22px }
|
26
|
+
.mp h2+pre, .mp h3+pre { margin-top:5px }
|
27
|
+
|
28
|
+
.mp img { display:block;margin:auto }
|
29
|
+
.mp h1.man-title { display:none }
|
30
|
+
|
31
|
+
/* FONTS */
|
32
|
+
|
33
|
+
.mp, .mp code, .mp pre, .mp tt,
|
34
|
+
.mp kbd, .mp samp, .mp h3, .mp h4 {
|
35
|
+
font-family:monospace;
|
36
|
+
font-size:14px;
|
37
|
+
line-height:1.42857142857143;
|
38
|
+
}
|
39
|
+
.mp h2 {
|
40
|
+
font-size:16px;
|
41
|
+
line-height:1.25;
|
42
|
+
}
|
43
|
+
.mp h1 {
|
44
|
+
font-size:20px;
|
45
|
+
line-height:2;
|
46
|
+
}
|
47
|
+
|
48
|
+
/* TEXT STYLES */
|
49
|
+
|
50
|
+
.mp {
|
51
|
+
text-align:justify;
|
52
|
+
background:#fff;
|
53
|
+
}
|
54
|
+
.mp, .mp code, .mp pre,
|
55
|
+
.mp pre code, .mp tt, .mp kbd,
|
56
|
+
.mp samp { color:#131211 }
|
57
|
+
.mp h1, .mp h2, .mp h3, .mp h4 { color:#030201 }
|
58
|
+
.mp u { text-decoration:underline; }
|
59
|
+
|
60
|
+
.mp code, .mp strong, .mp b {
|
61
|
+
font-weight:bold;
|
62
|
+
color:#131211;
|
63
|
+
}
|
64
|
+
|
65
|
+
.mp em, .mp var {
|
66
|
+
font-style:italic;
|
67
|
+
color:#232221;
|
68
|
+
text-decoration:none;
|
69
|
+
}
|
70
|
+
|
71
|
+
/* LINKS */
|
72
|
+
|
73
|
+
.mp a, .mp a:link, .mp a:hover,
|
74
|
+
.mp a code, .mp a pre, .mp a tt,
|
75
|
+
.mp a kbd, .mp a samp { color:#0000ff }
|
76
|
+
|
77
|
+
.mp b.man-ref { font-weight:normal;color:#434241 }
|
78
|
+
|
79
|
+
/* PREFORMATTED BLOCKS */
|
80
|
+
|
81
|
+
.mp pre { padding:0 4ex }
|
82
|
+
.mp pre code { font-weight:normal;color:#434241 }
|
83
|
+
.mp h2+pre, h3+pre { padding-left:0 }
|
84
|
+
|
85
|
+
/* DOCUMENT HEADER AND FOOTER AREAS */
|
86
|
+
|
87
|
+
ol.man-decor, ol.man-decor li {
|
88
|
+
margin:3px 0 10px 0;
|
89
|
+
padding:0;
|
90
|
+
float:left;
|
91
|
+
width:33%;
|
92
|
+
list-style-type:none;
|
93
|
+
text-transform:uppercase;
|
94
|
+
color:#999;
|
95
|
+
letter-spacing:1px;
|
96
|
+
}
|
97
|
+
ol.man-decor { width:100% }
|
98
|
+
ol.man-decor li.tl { text-align:left }
|
99
|
+
ol.man-decor li.tc { text-align:center; letter-spacing:4px }
|
100
|
+
ol.man-decor li.tr { text-align:right; float:right }
|