reverse_adoc 0.2.3
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/.github/workflows/macos.yml +27 -0
- data/.github/workflows/ubuntu.yml +27 -0
- data/.github/workflows/windows.yml +30 -0
- data/.hound.yml +3 -0
- data/.rubocop.yml +10 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +25 -0
- data/README.adoc +290 -0
- data/Rakefile +14 -0
- data/bin/reverse_adoc +67 -0
- data/bin/w2a +85 -0
- data/lib/reverse_asciidoctor.rb +70 -0
- data/lib/reverse_asciidoctor/cleaner.rb +90 -0
- data/lib/reverse_asciidoctor/config.rb +53 -0
- data/lib/reverse_asciidoctor/converters.rb +33 -0
- data/lib/reverse_asciidoctor/converters/a.rb +38 -0
- data/lib/reverse_asciidoctor/converters/aside.rb +14 -0
- data/lib/reverse_asciidoctor/converters/audio.rb +34 -0
- data/lib/reverse_asciidoctor/converters/base.rb +24 -0
- data/lib/reverse_asciidoctor/converters/blockquote.rb +18 -0
- data/lib/reverse_asciidoctor/converters/br.rb +11 -0
- data/lib/reverse_asciidoctor/converters/bypass.rb +77 -0
- data/lib/reverse_asciidoctor/converters/code.rb +15 -0
- data/lib/reverse_asciidoctor/converters/div.rb +14 -0
- data/lib/reverse_asciidoctor/converters/drop.rb +18 -0
- data/lib/reverse_asciidoctor/converters/em.rb +18 -0
- data/lib/reverse_asciidoctor/converters/figure.rb +21 -0
- data/lib/reverse_asciidoctor/converters/h.rb +19 -0
- data/lib/reverse_asciidoctor/converters/head.rb +18 -0
- data/lib/reverse_asciidoctor/converters/hr.rb +11 -0
- data/lib/reverse_asciidoctor/converters/ignore.rb +12 -0
- data/lib/reverse_asciidoctor/converters/img.rb +80 -0
- data/lib/reverse_asciidoctor/converters/li.rb +24 -0
- data/lib/reverse_asciidoctor/converters/mark.rb +12 -0
- data/lib/reverse_asciidoctor/converters/math.rb +20 -0
- data/lib/reverse_asciidoctor/converters/ol.rb +46 -0
- data/lib/reverse_asciidoctor/converters/p.rb +17 -0
- data/lib/reverse_asciidoctor/converters/pass_through.rb +9 -0
- data/lib/reverse_asciidoctor/converters/pre.rb +38 -0
- data/lib/reverse_asciidoctor/converters/q.rb +12 -0
- data/lib/reverse_asciidoctor/converters/strong.rb +17 -0
- data/lib/reverse_asciidoctor/converters/sub.rb +12 -0
- data/lib/reverse_asciidoctor/converters/sup.rb +12 -0
- data/lib/reverse_asciidoctor/converters/table.rb +64 -0
- data/lib/reverse_asciidoctor/converters/td.rb +67 -0
- data/lib/reverse_asciidoctor/converters/text.rb +65 -0
- data/lib/reverse_asciidoctor/converters/th.rb +16 -0
- data/lib/reverse_asciidoctor/converters/tr.rb +22 -0
- data/lib/reverse_asciidoctor/converters/video.rb +36 -0
- data/lib/reverse_asciidoctor/errors.rb +10 -0
- data/lib/reverse_asciidoctor/version.rb +3 -0
- data/reverse_adoc.gemspec +35 -0
- data/spec/assets/anchors.html +22 -0
- data/spec/assets/basic.html +58 -0
- data/spec/assets/code.html +22 -0
- data/spec/assets/escapables.html +15 -0
- data/spec/assets/from_the_wild.html +23 -0
- data/spec/assets/full_example.html +49 -0
- data/spec/assets/html_fragment.html +3 -0
- data/spec/assets/lists.html +137 -0
- data/spec/assets/minimum.html +4 -0
- data/spec/assets/paragraphs.html +24 -0
- data/spec/assets/quotation.html +12 -0
- data/spec/assets/tables.html +99 -0
- data/spec/assets/unknown_tags.html +9 -0
- data/spec/components/anchors_spec.rb +21 -0
- data/spec/components/basic_spec.rb +49 -0
- data/spec/components/code_spec.rb +28 -0
- data/spec/components/escapables_spec.rb +23 -0
- data/spec/components/from_the_wild_spec.rb +17 -0
- data/spec/components/html_fragment_spec.rb +11 -0
- data/spec/components/lists_spec.rb +86 -0
- data/spec/components/paragraphs_spec.rb +15 -0
- data/spec/components/quotation_spec.rb +12 -0
- data/spec/components/tables_spec.rb +31 -0
- data/spec/components/unknown_tags_spec.rb +39 -0
- data/spec/lib/reverse_asciidoctor/cleaner_spec.rb +157 -0
- data/spec/lib/reverse_asciidoctor/config_spec.rb +26 -0
- data/spec/lib/reverse_asciidoctor/converters/aside_spec.rb +12 -0
- data/spec/lib/reverse_asciidoctor/converters/audio_spec.rb +18 -0
- data/spec/lib/reverse_asciidoctor/converters/blockquote_spec.rb +24 -0
- data/spec/lib/reverse_asciidoctor/converters/br_spec.rb +9 -0
- data/spec/lib/reverse_asciidoctor/converters/code_spec.rb +18 -0
- data/spec/lib/reverse_asciidoctor/converters/div_spec.rb +18 -0
- data/spec/lib/reverse_asciidoctor/converters/figure_spec.rb +13 -0
- data/spec/lib/reverse_asciidoctor/converters/img_spec.rb +28 -0
- data/spec/lib/reverse_asciidoctor/converters/li_spec.rb +13 -0
- data/spec/lib/reverse_asciidoctor/converters/mark_spec.rb +10 -0
- data/spec/lib/reverse_asciidoctor/converters/p_spec.rb +12 -0
- data/spec/lib/reverse_asciidoctor/converters/pre_spec.rb +45 -0
- data/spec/lib/reverse_asciidoctor/converters/q_spec.rb +10 -0
- data/spec/lib/reverse_asciidoctor/converters/strong_spec.rb +20 -0
- data/spec/lib/reverse_asciidoctor/converters/text_spec.rb +62 -0
- data/spec/lib/reverse_asciidoctor/converters/video_spec.rb +18 -0
- data/spec/lib/reverse_asciidoctor/converters_spec.rb +19 -0
- data/spec/lib/reverse_asciidoctor_spec.rb +37 -0
- data/spec/spec_helper.rb +21 -0
- metadata +299 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Unless run with ReverseAsciidoctor.config.mathml2asciimath,
|
|
2
|
+
# this is cheating: we're injecting MathML into Asciidoctor, but
|
|
3
|
+
# Asciidoctor only understands AsciiMath or LaTeX
|
|
4
|
+
|
|
5
|
+
require "mathml2asciimath"
|
|
6
|
+
|
|
7
|
+
module ReverseAsciidoctor
|
|
8
|
+
module Converters
|
|
9
|
+
class Math < Base
|
|
10
|
+
def convert(node, state = {})
|
|
11
|
+
stem = node.to_s.gsub(/\n/, " ")
|
|
12
|
+
stem = MathML2AsciiMath.m2a(stem) if ReverseAsciidoctor.config.mathml2asciimath
|
|
13
|
+
stem = stem.gsub(/\[/, "\\[").gsub(/\]/, "\\]").gsub(/\(\(([^\)]+)\)\)/, "(\\1)") unless stem.nil?
|
|
14
|
+
" stem:[" << stem << "] "
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
register :math, Math.new
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
module ReverseAsciidoctor
|
|
2
|
+
module Converters
|
|
3
|
+
class Ol < Base
|
|
4
|
+
def convert(node, state = {})
|
|
5
|
+
id = node['id']
|
|
6
|
+
anchor = id ? "[[#{id}]]\n" : ""
|
|
7
|
+
ol_count = state.fetch(:ol_count, 0) + 1
|
|
8
|
+
attrs = ol_attrs(node)
|
|
9
|
+
"\n#{anchor}#{attrs}" << treat_children(node, state.merge(ol_count: ol_count))
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def number_style(node)
|
|
13
|
+
style = case node["style"]
|
|
14
|
+
when "1" then "arabic"
|
|
15
|
+
when "A" then "upperalpha"
|
|
16
|
+
when "a" then "loweralpha"
|
|
17
|
+
when "I" then "upperroman"
|
|
18
|
+
when "i" then "lowerroman"
|
|
19
|
+
else
|
|
20
|
+
nil
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def ol_attrs(node)
|
|
25
|
+
style = number_style(node)
|
|
26
|
+
reversed = "%reversed" if node["reversed"]
|
|
27
|
+
start = "start=#{node['start']}" if node["start"]
|
|
28
|
+
type = "type=#{node['type']}" if node["type"]
|
|
29
|
+
attrs = []
|
|
30
|
+
attrs << style if style
|
|
31
|
+
attrs << reversed if reversed
|
|
32
|
+
attrs << start if start
|
|
33
|
+
attrs << type if type
|
|
34
|
+
if attrs.empty?
|
|
35
|
+
""
|
|
36
|
+
else
|
|
37
|
+
"[#{attrs.join(',')}]\n"
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
register :ol, Ol.new
|
|
43
|
+
register :ul, Ol.new
|
|
44
|
+
register :dir, Ol.new
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module ReverseAsciidoctor
|
|
2
|
+
module Converters
|
|
3
|
+
class P < Base
|
|
4
|
+
def convert(node, state = {})
|
|
5
|
+
id = node['id']
|
|
6
|
+
anchor = id ? "[[#{id}]]\n" : ""
|
|
7
|
+
if state[:tdsinglepara]
|
|
8
|
+
"#{anchor}" << treat_children(node, state).strip
|
|
9
|
+
else
|
|
10
|
+
"\n\n#{anchor}" << treat_children(node, state).strip << "\n\n"
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
register :p, P.new
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module ReverseAsciidoctor
|
|
2
|
+
module Converters
|
|
3
|
+
class Pre < Base
|
|
4
|
+
def convert(node, state = {})
|
|
5
|
+
id = node['id']
|
|
6
|
+
anchor = id ? "[[#{id}]]\n" : ""
|
|
7
|
+
lang = language(node)
|
|
8
|
+
content = treat_children(node, state)
|
|
9
|
+
if lang
|
|
10
|
+
"\n\n#{anchor}[source,#{lang}]\n----\n" << content.lines.to_a.join("") << "\n----\n\n"
|
|
11
|
+
else
|
|
12
|
+
"\n\n#{anchor}....\n" << content.lines.to_a.join("") << "\n....\n\n"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def treat(node, state)
|
|
19
|
+
node.to_s
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def language(node)
|
|
23
|
+
lang = language_from_highlight_class(node)
|
|
24
|
+
lang || language_from_confluence_class(node)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def language_from_highlight_class(node)
|
|
28
|
+
node.parent['class'].to_s[/highlight-([a-zA-Z0-9]+)/, 1]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def language_from_confluence_class(node)
|
|
32
|
+
node['class'].to_s[/brush:\s?(:?.*);/, 1]
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
register :pre, Pre.new
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module ReverseAsciidoctor
|
|
2
|
+
module Converters
|
|
3
|
+
class Strong < Base
|
|
4
|
+
def convert(node, state = {})
|
|
5
|
+
content = treat_children(node, state.merge(already_strong: true))
|
|
6
|
+
if content.strip.empty? || state[:already_strong]
|
|
7
|
+
content
|
|
8
|
+
else
|
|
9
|
+
"#{content[/^\s*/]}*#{content.strip}*#{content[/\s*$/]}"
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
register :strong, Strong.new
|
|
15
|
+
register :b, Strong.new
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
module ReverseAsciidoctor
|
|
2
|
+
module Converters
|
|
3
|
+
class Table < Base
|
|
4
|
+
def convert(node, state = {})
|
|
5
|
+
id = node['id']
|
|
6
|
+
anchor = id ? "[[#{id}]]\n" : ""
|
|
7
|
+
title = extract_title(node)
|
|
8
|
+
title = ".#{title}\n" unless title.empty?
|
|
9
|
+
attrs = style(node)
|
|
10
|
+
"\n\n#{anchor}#{attrs}#{title}|===\n" << treat_children(node, state) << "\n|===\n"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def extract_title(node)
|
|
14
|
+
title = node.at("./caption")
|
|
15
|
+
return "" if title.nil?
|
|
16
|
+
treat_children(title, {})
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def frame(node)
|
|
20
|
+
case node["frame"]
|
|
21
|
+
when "void"
|
|
22
|
+
"frame=none"
|
|
23
|
+
when "hsides"
|
|
24
|
+
"frame=topbot"
|
|
25
|
+
when "vsides"
|
|
26
|
+
"frame=sides"
|
|
27
|
+
when "box", "border"
|
|
28
|
+
"frame=all"
|
|
29
|
+
else
|
|
30
|
+
nil
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def rules(node)
|
|
35
|
+
case node["rules"]
|
|
36
|
+
when "all"
|
|
37
|
+
"rules=all"
|
|
38
|
+
when "rows"
|
|
39
|
+
"rules=rows"
|
|
40
|
+
when "cols"
|
|
41
|
+
"rules=cols"
|
|
42
|
+
when "none"
|
|
43
|
+
"rules=none"
|
|
44
|
+
else
|
|
45
|
+
nil
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def style(node)
|
|
50
|
+
width = "width=#{node['width']}" if node['width']
|
|
51
|
+
attrs = []
|
|
52
|
+
frame_attr = frame(node)
|
|
53
|
+
rules_attr = rules(node)
|
|
54
|
+
attrs << width if width
|
|
55
|
+
attrs << frame_attr if frame_attr
|
|
56
|
+
attrs << rules_attr if rules_attr
|
|
57
|
+
return "" if attrs.empty?
|
|
58
|
+
"[#{attrs.join(',')}]\n"
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
register :table, Table.new
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
module ReverseAsciidoctor
|
|
2
|
+
module Converters
|
|
3
|
+
class Td < Base
|
|
4
|
+
def convert(node, state = {})
|
|
5
|
+
id = node['id']
|
|
6
|
+
anchor = id ? "[[#{id}]]" : ""
|
|
7
|
+
colrowattr = colrow(node['colspan'], node['rowspan'])
|
|
8
|
+
alignattr = alignstyle(node)
|
|
9
|
+
style = cellstyle(node)
|
|
10
|
+
singlepara = node.elements.size == 1 && node.elements.first.name == "p"
|
|
11
|
+
state[:tdsinglepara] = singlepara if singlepara
|
|
12
|
+
adoccell = node.at(".//ul | .//ol | .//pre | .//blockquote | .//br | .//hr") ||
|
|
13
|
+
node.at(".//p") && !singlepara
|
|
14
|
+
style = "a" if adoccell
|
|
15
|
+
delim = adoccell ? "\n" : " "
|
|
16
|
+
content = treat_children(node, state)
|
|
17
|
+
"#{colrowattr}#{alignattr}#{style}| #{anchor}#{content}#{delim}"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def cellstyle(node)
|
|
21
|
+
""
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def colrow(colspan, rowspan)
|
|
25
|
+
if colspan && rowspan
|
|
26
|
+
"#{colspan}.#{rowspan}+"
|
|
27
|
+
elsif colspan
|
|
28
|
+
"#{colspan}+"
|
|
29
|
+
elsif rowspan
|
|
30
|
+
".#{rowspan}+"
|
|
31
|
+
else
|
|
32
|
+
""
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def alignstyle(node)
|
|
37
|
+
align = node["align"]
|
|
38
|
+
valign = node["valign"]
|
|
39
|
+
a = case align
|
|
40
|
+
when "left" then "<"
|
|
41
|
+
when "center" then "^"
|
|
42
|
+
when "right" then ">"
|
|
43
|
+
else
|
|
44
|
+
""
|
|
45
|
+
end
|
|
46
|
+
v = case valign
|
|
47
|
+
when "top" then "<"
|
|
48
|
+
when "middle" then "^"
|
|
49
|
+
when "bottom" then ">"
|
|
50
|
+
else
|
|
51
|
+
""
|
|
52
|
+
end
|
|
53
|
+
if align && valign
|
|
54
|
+
"#{a}.#{v}"
|
|
55
|
+
elsif align
|
|
56
|
+
a
|
|
57
|
+
elsif valign
|
|
58
|
+
".#{v}"
|
|
59
|
+
else
|
|
60
|
+
""
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
register :td, Td.new
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
module ReverseAsciidoctor
|
|
2
|
+
module Converters
|
|
3
|
+
class Text < Base
|
|
4
|
+
def convert(node, state = {})
|
|
5
|
+
if node.text.strip.empty?
|
|
6
|
+
treat_empty(node, state)
|
|
7
|
+
else
|
|
8
|
+
treat_text(node)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def treat_empty(node, state)
|
|
15
|
+
parent = node.parent.name.to_sym
|
|
16
|
+
if [:ol, :ul].include?(parent) # Otherwise the identation is broken
|
|
17
|
+
''
|
|
18
|
+
elsif state[:tdsinglepara]
|
|
19
|
+
''
|
|
20
|
+
elsif node.text == ' ' # Regular whitespace text node
|
|
21
|
+
' '
|
|
22
|
+
else
|
|
23
|
+
''
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def treat_text(node)
|
|
28
|
+
text = node.text
|
|
29
|
+
text = preserve_nbsp(text)
|
|
30
|
+
text = remove_border_newlines(text)
|
|
31
|
+
text = remove_inner_newlines(text)
|
|
32
|
+
text = escape_keychars(text)
|
|
33
|
+
|
|
34
|
+
text = preserve_keychars_within_backticks(text)
|
|
35
|
+
text = preserve_tags(text)
|
|
36
|
+
|
|
37
|
+
text
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def preserve_nbsp(text)
|
|
41
|
+
text.gsub(/\u00A0/, " ")
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def preserve_tags(text)
|
|
45
|
+
text.gsub(/[<>]/, '>' => '\>', '<' => '\<')
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def remove_border_newlines(text)
|
|
49
|
+
text.gsub(/\A\n+/, '').gsub(/\n+\z/, '')
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def remove_inner_newlines(text)
|
|
53
|
+
text.tr("\n\t", ' ').squeeze(' ')
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def preserve_keychars_within_backticks(text)
|
|
57
|
+
text.gsub(/`.*?`/) do |match|
|
|
58
|
+
match.gsub('\_', '_').gsub('\*', '*')
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
register :text, Text.new
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module ReverseAsciidoctor
|
|
2
|
+
module Converters
|
|
3
|
+
class Tr < Base
|
|
4
|
+
def convert(node, state = {})
|
|
5
|
+
content = treat_children(node, state).rstrip
|
|
6
|
+
result = "#{content}\n"
|
|
7
|
+
table_header_row?(node) ? result + underline_for(node) : result
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def table_header_row?(node)
|
|
11
|
+
# node.element_children.all? {|child| child.name.to_sym == :th}
|
|
12
|
+
node.previous_element.nil?
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def underline_for(node)
|
|
16
|
+
"\n"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
register :tr, Tr.new
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
module ReverseAsciidoctor
|
|
2
|
+
module Converters
|
|
3
|
+
class Video < Base
|
|
4
|
+
def convert(node, state = {})
|
|
5
|
+
autoplay = node['autoplay']
|
|
6
|
+
loop_attr = node['loop']
|
|
7
|
+
controls = node['controls']
|
|
8
|
+
src = node['src']
|
|
9
|
+
id = node['id']
|
|
10
|
+
anchor = id ? "[[#{id}]]\n" : ""
|
|
11
|
+
title = extract_title(node)
|
|
12
|
+
title = ".#{title}\n" unless title.empty?
|
|
13
|
+
[anchor, title, "video::", src, "[", options(node), "]"].join("")
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def options(node)
|
|
17
|
+
autoplay = node['autoplay']
|
|
18
|
+
loop_attr = node['loop']
|
|
19
|
+
controls = node['controls']
|
|
20
|
+
width = node['width']
|
|
21
|
+
ret = ""
|
|
22
|
+
if autoplay || loop_attr || controls
|
|
23
|
+
out = []
|
|
24
|
+
out << "autoplay" if autoplay
|
|
25
|
+
out << "loop" if loop_attr
|
|
26
|
+
out << "controls" if controls
|
|
27
|
+
out << "width=#{width}" if width
|
|
28
|
+
ret = %{options="#{out.join(',')}"}
|
|
29
|
+
end
|
|
30
|
+
ret
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
register :video, Video.new
|
|
35
|
+
end
|
|
36
|
+
end
|