maiku 0.6.1.maiku
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.
- data/lib/maruku.rb +141 -0
- data/lib/maruku/attributes.rb +175 -0
- data/lib/maruku/defaults.rb +71 -0
- data/lib/maruku/errors_management.rb +92 -0
- data/lib/maruku/ext/div.rb +133 -0
- data/lib/maruku/ext/math.rb +41 -0
- data/lib/maruku/ext/math/elements.rb +27 -0
- data/lib/maruku/ext/math/latex_fix.rb +12 -0
- data/lib/maruku/ext/math/mathml_engines/blahtex.rb +107 -0
- data/lib/maruku/ext/math/mathml_engines/itex2mml.rb +29 -0
- data/lib/maruku/ext/math/mathml_engines/none.rb +20 -0
- data/lib/maruku/ext/math/mathml_engines/ritex.rb +24 -0
- data/lib/maruku/ext/math/parsing.rb +119 -0
- data/lib/maruku/ext/math/to_html.rb +187 -0
- data/lib/maruku/ext/math/to_latex.rb +26 -0
- data/lib/maruku/helpers.rb +260 -0
- data/lib/maruku/input/charsource.rb +326 -0
- data/lib/maruku/input/extensions.rb +69 -0
- data/lib/maruku/input/html_helper.rb +189 -0
- data/lib/maruku/input/linesource.rb +111 -0
- data/lib/maruku/input/parse_block.rb +616 -0
- data/lib/maruku/input/parse_doc.rb +232 -0
- data/lib/maruku/input/parse_span_better.rb +746 -0
- data/lib/maruku/input/rubypants.rb +225 -0
- data/lib/maruku/input/type_detection.rb +147 -0
- data/lib/maruku/input_textile2/t2_parser.rb +163 -0
- data/lib/maruku/maruku.rb +33 -0
- data/lib/maruku/output/s5/fancy.rb +756 -0
- data/lib/maruku/output/s5/to_s5.rb +138 -0
- data/lib/maruku/output/to_html.rb +991 -0
- data/lib/maruku/output/to_latex.rb +590 -0
- data/lib/maruku/output/to_latex_entities.rb +367 -0
- data/lib/maruku/output/to_latex_strings.rb +64 -0
- data/lib/maruku/output/to_markdown.rb +164 -0
- data/lib/maruku/output/to_s.rb +56 -0
- data/lib/maruku/string_utils.rb +201 -0
- data/lib/maruku/structures.rb +167 -0
- data/lib/maruku/structures_inspect.rb +87 -0
- data/lib/maruku/structures_iterators.rb +61 -0
- data/lib/maruku/textile2.rb +1 -0
- data/lib/maruku/toc.rb +199 -0
- data/lib/maruku/usage/example1.rb +33 -0
- data/lib/maruku/version.rb +39 -0
- metadata +167 -0
@@ -0,0 +1,138 @@
|
|
1
|
+
# This module groups all functions related to HTML export.
|
2
|
+
module MaRuKu
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rexml/formatters/pretty'
|
6
|
+
require 'rexml/formatters/default'
|
7
|
+
$rexml_new_version = true
|
8
|
+
rescue LoadError
|
9
|
+
$rexml_new_version = false
|
10
|
+
end
|
11
|
+
|
12
|
+
class MDDocument
|
13
|
+
|
14
|
+
def s5_theme
|
15
|
+
html_escape(self.attributes[:slide_theme] || "default")
|
16
|
+
end
|
17
|
+
|
18
|
+
def html_escape(string)
|
19
|
+
string.gsub( /&/, "&" ).
|
20
|
+
gsub( /</, "<" ).
|
21
|
+
gsub( />/, ">" ).
|
22
|
+
gsub( /'/, "'" ).
|
23
|
+
gsub( /"/, """ )
|
24
|
+
end
|
25
|
+
|
26
|
+
# Render as an HTML fragment (no head, just the content of BODY). (returns a string)
|
27
|
+
def to_s5(context={})
|
28
|
+
indent = context[:indent] || -1
|
29
|
+
ie_hack = !context[:ie_hack].kind_of?(FalseClass)
|
30
|
+
content_only = !context[:content_only].kind_of?(FalseClass)
|
31
|
+
|
32
|
+
doc = Document.new(nil,{:respect_whitespace =>:all})
|
33
|
+
|
34
|
+
if content_only
|
35
|
+
body = Element.new('div', doc)
|
36
|
+
else
|
37
|
+
html = Element.new('html', doc)
|
38
|
+
html.add_namespace('http://www.w3.org/1999/xhtml')
|
39
|
+
html.add_namespace('svg', "http://www.w3.org/2000/svg" )
|
40
|
+
|
41
|
+
head = Element.new('head', html)
|
42
|
+
me = Element.new 'meta', head
|
43
|
+
me.attributes['http-equiv'] = 'Content-type'
|
44
|
+
me.attributes['content'] = 'text/html;charset=utf-8'
|
45
|
+
|
46
|
+
# Create title element
|
47
|
+
doc_title = self.attributes[:title] || self.attributes[:subject] || ""
|
48
|
+
title = Element.new 'title', head
|
49
|
+
title << Text.new(doc_title)
|
50
|
+
body = Element.new('body', html)
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
slide_header = self.attributes[:slide_header]
|
55
|
+
slide_footer = self.attributes[:slide_footer]
|
56
|
+
slide_subfooter = self.attributes[:slide_subfooter]
|
57
|
+
slide_topleft = self.attributes[:slide_topleft]
|
58
|
+
slide_topright = self.attributes[:slide_topright]
|
59
|
+
slide_bottomleft = self.attributes[:slide_bottomleft]
|
60
|
+
slide_bottomright = self.attributes[:slide_bottomright]
|
61
|
+
|
62
|
+
dummy_layout_slide =
|
63
|
+
"
|
64
|
+
<div class='layout'>
|
65
|
+
<div id='controls'> </div>
|
66
|
+
<div id='currentSlide'> </div>
|
67
|
+
<div id='header'> #{slide_header}</div>
|
68
|
+
<div id='footer'>
|
69
|
+
<h1>#{slide_footer}</h1>
|
70
|
+
<h2>#{slide_subfooter}</h2>
|
71
|
+
</div>
|
72
|
+
<div class='topleft'> #{slide_topleft}</div>
|
73
|
+
<div class='topright'> #{slide_topright}</div>
|
74
|
+
<div class='bottomleft'> #{slide_bottomleft}</div>
|
75
|
+
<div class='bottomright'> #{slide_bottomright}</div>
|
76
|
+
</div>
|
77
|
+
"
|
78
|
+
body.add_element Document.new(dummy_layout_slide, {:respect_whitespace =>:all}).root
|
79
|
+
|
80
|
+
presentation = Element.new 'div', body
|
81
|
+
presentation.attributes['class'] = 'presentation'
|
82
|
+
|
83
|
+
first_slide="
|
84
|
+
<div class='slide'>
|
85
|
+
<h1> #{self.attributes[:title] ||context[:title]}</h1>
|
86
|
+
<h2> #{self.attributes[:subtitle] ||context[:subtitle]}</h2>
|
87
|
+
<h3> #{self.attributes[:author] ||context[:author]}</h3>
|
88
|
+
<h4> #{self.attributes[:company] ||context[:company]}</h4>
|
89
|
+
</div>
|
90
|
+
"
|
91
|
+
presentation.add_element Document.new(first_slide).root
|
92
|
+
|
93
|
+
slide_num = 0
|
94
|
+
self.toc.section_children.each do |slide|
|
95
|
+
slide_num += 1
|
96
|
+
@doc.attributes[:doc_prefix] = "s#{slide_num}"
|
97
|
+
|
98
|
+
puts "Slide #{slide_num}: " + slide.header_element.to_s
|
99
|
+
div = Element.new('div', presentation)
|
100
|
+
div.attributes['class'] = 'slide'
|
101
|
+
|
102
|
+
h1 = Element.new 'h1', div
|
103
|
+
slide.header_element.children_to_html.each do |e| h1 << e; end
|
104
|
+
|
105
|
+
array_to_html(slide.immediate_children).each do |e| div << e end
|
106
|
+
|
107
|
+
# render footnotes
|
108
|
+
if @doc.footnotes_order.size > 0
|
109
|
+
div << render_footnotes
|
110
|
+
@doc.footnotes_order = []
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
xml = ""
|
115
|
+
if (content_only)
|
116
|
+
if $rexml_new_version
|
117
|
+
formatter = REXML::Formatters::Default.new(ie_hack)
|
118
|
+
formatter.write(body, xml)
|
119
|
+
else
|
120
|
+
body.write(xml,indent,transitive=true,ie_hack);
|
121
|
+
end
|
122
|
+
else
|
123
|
+
doc2 = Document.new("<div>"+S5_external+"</div>",{:respect_whitespace =>:all})
|
124
|
+
doc2.root.children.each{ |child| head << child }
|
125
|
+
|
126
|
+
add_css_to(head)
|
127
|
+
|
128
|
+
# REXML Bug? if indent!=-1 whitespace is not respected for 'pre' elements
|
129
|
+
# containing code.
|
130
|
+
html.write(xml,indent,transitive=true,ie_hack);
|
131
|
+
Xhtml11_mathml2_svg11 + xml
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
end
|
@@ -0,0 +1,991 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
3
|
+
#
|
4
|
+
# This file is part of Maruku.
|
5
|
+
#
|
6
|
+
# Maruku is free software; you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation; either version 2 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# Maruku is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with Maruku; if not, write to the Free Software
|
18
|
+
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
19
|
+
#++
|
20
|
+
|
21
|
+
require 'rexml/document'
|
22
|
+
|
23
|
+
begin
|
24
|
+
require 'rexml/formatters/pretty'
|
25
|
+
require 'rexml/formatters/default'
|
26
|
+
$rexml_new_version = true
|
27
|
+
rescue LoadError
|
28
|
+
$rexml_new_version = false
|
29
|
+
end
|
30
|
+
|
31
|
+
class String
|
32
|
+
# A string is rendered into HTML by creating
|
33
|
+
# a REXML::Text node. REXML takes care of all the encoding.
|
34
|
+
def to_html
|
35
|
+
REXML::Text.new(self)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
# This module groups all functions related to HTML export.
|
41
|
+
module MaRuKu; module Out; module HTML
|
42
|
+
include REXML
|
43
|
+
|
44
|
+
# Render as an HTML fragment (no head, just the content of BODY). (returns a string)
|
45
|
+
def to_html(context={})
|
46
|
+
indent = context[:indent] || -1
|
47
|
+
ie_hack = context[:ie_hack] || true
|
48
|
+
|
49
|
+
div = Element.new 'dummy'
|
50
|
+
children_to_html.each do |e|
|
51
|
+
div << e
|
52
|
+
end
|
53
|
+
|
54
|
+
# render footnotes
|
55
|
+
if @doc.footnotes_order.size > 0
|
56
|
+
div << render_footnotes
|
57
|
+
end
|
58
|
+
|
59
|
+
doc = Document.new(nil,{:respect_whitespace =>:all})
|
60
|
+
doc << div
|
61
|
+
|
62
|
+
# REXML Bug? if indent!=-1 whitespace is not respected for 'pre' elements
|
63
|
+
# containing code.
|
64
|
+
xml =""
|
65
|
+
|
66
|
+
if $rexml_new_version
|
67
|
+
formatter = if indent > -1
|
68
|
+
REXML::Formatters::Pretty.new( indent, ie_hack )
|
69
|
+
else
|
70
|
+
REXML::Formatters::Default.new( ie_hack )
|
71
|
+
end
|
72
|
+
formatter.write( div, xml)
|
73
|
+
else
|
74
|
+
div.write(xml,indent,transitive=true,ie_hack)
|
75
|
+
end
|
76
|
+
|
77
|
+
xml.gsub!(/\A<dummy>\s*/,'')
|
78
|
+
xml.gsub!(/\s*<\/dummy>\Z/,'')
|
79
|
+
xml.gsub!(/\A<dummy\s*\/>/,'')
|
80
|
+
xml
|
81
|
+
end
|
82
|
+
|
83
|
+
# Render to a complete HTML document (returns a string)
|
84
|
+
def to_html_document(context={})
|
85
|
+
indent = context[:indent] || -1
|
86
|
+
ie_hack = context[:ie_hack] ||true
|
87
|
+
doc = to_html_document_tree
|
88
|
+
xml = ""
|
89
|
+
|
90
|
+
# REXML Bug? if indent!=-1 whitespace is not respected for 'pre' elements
|
91
|
+
# containing code.
|
92
|
+
doc.write(xml,indent,transitive=true,ie_hack);
|
93
|
+
|
94
|
+
Xhtml11_mathml2_svg11 + xml
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
Xhtml10strict =
|
99
|
+
"<?xml version='1.0' encoding='utf-8'?>
|
100
|
+
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN'
|
101
|
+
'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>\n"
|
102
|
+
|
103
|
+
Xhtml11strict_mathml2 = '<?xml version="1.0" encoding="utf-8"?>
|
104
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN"
|
105
|
+
"http://www.w3.org/TR/MathML2/dtd/xhtml-math11-f.dtd" [
|
106
|
+
<!ENTITY mathml "http://www.w3.org/1998/Math/MathML">
|
107
|
+
]>
|
108
|
+
'
|
109
|
+
|
110
|
+
Xhtml11_mathml2_svg11 =
|
111
|
+
'<?xml version="1.0" encoding="utf-8"?>
|
112
|
+
<!DOCTYPE html PUBLIC
|
113
|
+
"-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN"
|
114
|
+
"http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd">
|
115
|
+
'
|
116
|
+
|
117
|
+
|
118
|
+
def xml_newline() Text.new("\n") end
|
119
|
+
|
120
|
+
|
121
|
+
=begin maruku_doc
|
122
|
+
Attribute: title
|
123
|
+
Scope: document
|
124
|
+
|
125
|
+
Sets the title of the document.
|
126
|
+
If a title is not specified, the first header will be used.
|
127
|
+
|
128
|
+
These should be equivalent:
|
129
|
+
|
130
|
+
Title: my document
|
131
|
+
|
132
|
+
Content
|
133
|
+
|
134
|
+
and
|
135
|
+
|
136
|
+
my document
|
137
|
+
===========
|
138
|
+
|
139
|
+
Content
|
140
|
+
|
141
|
+
In both cases, the title is set to "my document".
|
142
|
+
=end
|
143
|
+
|
144
|
+
=begin maruku_doc
|
145
|
+
Attribute: doc_prefix
|
146
|
+
Scope: document
|
147
|
+
|
148
|
+
String to disambiguate footnote links.
|
149
|
+
=end
|
150
|
+
|
151
|
+
|
152
|
+
=begin maruku_doc
|
153
|
+
Attribute: subject
|
154
|
+
Scope: document
|
155
|
+
|
156
|
+
Synonim for `title`.
|
157
|
+
=end
|
158
|
+
|
159
|
+
|
160
|
+
# Render to an HTML fragment (returns a REXML document tree)
|
161
|
+
def to_html_tree
|
162
|
+
div = Element.new 'div'
|
163
|
+
div.attributes['class'] = 'maruku_wrapper_div'
|
164
|
+
children_to_html.each do |e|
|
165
|
+
div << e
|
166
|
+
end
|
167
|
+
|
168
|
+
# render footnotes
|
169
|
+
if @doc.footnotes_order.size > 0
|
170
|
+
div << render_footnotes
|
171
|
+
end
|
172
|
+
|
173
|
+
doc = Document.new(nil,{:respect_whitespace =>:all})
|
174
|
+
doc << div
|
175
|
+
end
|
176
|
+
|
177
|
+
=begin maruku_doc
|
178
|
+
Attribute: css
|
179
|
+
Scope: document
|
180
|
+
Output: HTML
|
181
|
+
Summary: Activates CSS stylesheets for HTML.
|
182
|
+
|
183
|
+
`css` should be a space-separated list of urls.
|
184
|
+
|
185
|
+
Example:
|
186
|
+
|
187
|
+
CSS: style.css math.css
|
188
|
+
|
189
|
+
=end
|
190
|
+
|
191
|
+
METAS = %w{description keywords author revised}
|
192
|
+
|
193
|
+
# Render to a complete HTML document (returns a REXML document tree)
|
194
|
+
def to_html_document_tree
|
195
|
+
doc = Document.new(nil,{:respect_whitespace =>:all})
|
196
|
+
# doc << XMLDecl.new
|
197
|
+
|
198
|
+
root = Element.new('html', doc)
|
199
|
+
root.add_namespace('http://www.w3.org/1999/xhtml')
|
200
|
+
root.add_namespace('svg', "http://www.w3.org/2000/svg" )
|
201
|
+
lang = self.attributes[:lang] || 'en'
|
202
|
+
root.attributes['xml:lang'] = lang
|
203
|
+
|
204
|
+
root << xml_newline
|
205
|
+
head = Element.new 'head', root
|
206
|
+
|
207
|
+
#<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
|
208
|
+
me = Element.new 'meta', head
|
209
|
+
me.attributes['http-equiv'] = 'Content-type'
|
210
|
+
# me.attributes['content'] = 'text/html;charset=utf-8'
|
211
|
+
me.attributes['content'] = 'application/xhtml+xml;charset=utf-8'
|
212
|
+
|
213
|
+
METAS.each do |m|
|
214
|
+
if value = self.attributes[m.to_sym]
|
215
|
+
meta = Element.new 'meta', head
|
216
|
+
meta.attributes['name'] = m
|
217
|
+
meta.attributes['content'] = value.to_s
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
|
222
|
+
self.attributes.each do |k,v|
|
223
|
+
if k.to_s =~ /\Ameta-(.*)\Z/
|
224
|
+
meta = Element.new 'meta', head
|
225
|
+
meta.attributes['name'] = $1
|
226
|
+
meta.attributes['content'] = v.to_s
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
|
231
|
+
|
232
|
+
# Create title element
|
233
|
+
doc_title = self.attributes[:title] || self.attributes[:subject] || ""
|
234
|
+
title = Element.new 'title', head
|
235
|
+
title << Text.new(doc_title)
|
236
|
+
|
237
|
+
add_css_to(head)
|
238
|
+
|
239
|
+
|
240
|
+
root << xml_newline
|
241
|
+
|
242
|
+
body = Element.new 'body'
|
243
|
+
|
244
|
+
children_to_html.each do |e|
|
245
|
+
body << e
|
246
|
+
end
|
247
|
+
|
248
|
+
# render footnotes
|
249
|
+
if @doc.footnotes_order.size > 0
|
250
|
+
body << render_footnotes
|
251
|
+
end
|
252
|
+
|
253
|
+
# When we are rendering a whole document, we add a signature
|
254
|
+
# at the bottom.
|
255
|
+
if get_setting(:maruku_signature)
|
256
|
+
body << maruku_html_signature
|
257
|
+
end
|
258
|
+
|
259
|
+
root << body
|
260
|
+
|
261
|
+
doc
|
262
|
+
end
|
263
|
+
|
264
|
+
def add_css_to(head)
|
265
|
+
if css_list = self.attributes[:css]
|
266
|
+
css_list.split.each do |css|
|
267
|
+
# <link type="text/css" rel="stylesheet" href="..." />
|
268
|
+
link = Element.new 'link'
|
269
|
+
link.attributes['type'] = 'text/css'
|
270
|
+
link.attributes['rel'] = 'stylesheet'
|
271
|
+
link.attributes['href'] = css
|
272
|
+
head << link
|
273
|
+
head << xml_newline
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
# returns "st","nd","rd" or "th" as appropriate
|
279
|
+
def day_suffix(day)
|
280
|
+
s = {
|
281
|
+
1 => 'st',
|
282
|
+
2 => 'nd',
|
283
|
+
3 => 'rd',
|
284
|
+
21 => 'st',
|
285
|
+
22 => 'nd',
|
286
|
+
23 => 'rd',
|
287
|
+
31 => 'st'
|
288
|
+
}
|
289
|
+
return s[day] || 'th';
|
290
|
+
end
|
291
|
+
|
292
|
+
# formats a nice date
|
293
|
+
def nice_date
|
294
|
+
t = Time.now
|
295
|
+
t.strftime(" at %H:%M on ")+
|
296
|
+
t.strftime("%A, %B %d")+
|
297
|
+
day_suffix(t.day)+
|
298
|
+
t.strftime(", %Y")
|
299
|
+
end
|
300
|
+
|
301
|
+
def maruku_html_signature
|
302
|
+
div = Element.new 'div'
|
303
|
+
div.attributes['class'] = 'maruku_signature'
|
304
|
+
Element.new 'hr', div
|
305
|
+
span = Element.new 'span', div
|
306
|
+
span.attributes['style'] = 'font-size: small; font-style: italic'
|
307
|
+
span << Text.new('Created by ')
|
308
|
+
a = Element.new('a', span)
|
309
|
+
a.attributes['href'] = 'http://maruku.rubyforge.org'
|
310
|
+
a.attributes['title'] = 'Maruku: a Markdown-superset interpreter for Ruby'
|
311
|
+
a << Text.new('Maruku')
|
312
|
+
span << Text.new(nice_date+".")
|
313
|
+
div
|
314
|
+
end
|
315
|
+
|
316
|
+
def render_footnotes()
|
317
|
+
div = Element.new 'div'
|
318
|
+
div.attributes['class'] = 'footnotes'
|
319
|
+
div << Element.new('hr')
|
320
|
+
ol = Element.new 'ol'
|
321
|
+
@doc.footnotes_order.each_with_index do |fid, i| num = i+1
|
322
|
+
f = self.footnotes[fid]
|
323
|
+
if f
|
324
|
+
li = f.wrap_as_element('li')
|
325
|
+
li.attributes['id'] = "#{get_setting(:doc_prefix)}fn:#{num}"
|
326
|
+
|
327
|
+
a = Element.new 'a'
|
328
|
+
a.attributes['href'] = "\##{get_setting(:doc_prefix)}fnref:#{num}"
|
329
|
+
a.attributes['rev'] = 'footnote'
|
330
|
+
a<< Text.new('↩', true, nil, true)
|
331
|
+
li.insert_after(li.children.last, a)
|
332
|
+
ol << li
|
333
|
+
else
|
334
|
+
maruku_error "Could not find footnote id '#{fid}' among ["+
|
335
|
+
self.footnotes.keys.map{|s|"'"+s+"'"}.join(', ')+"]."
|
336
|
+
end
|
337
|
+
end
|
338
|
+
div << ol
|
339
|
+
div
|
340
|
+
end
|
341
|
+
|
342
|
+
|
343
|
+
def to_html_hrule; create_html_element 'hr' end
|
344
|
+
def to_html_linebreak; Element.new 'br' end
|
345
|
+
|
346
|
+
# renders children as html and wraps into an element of given name
|
347
|
+
#
|
348
|
+
# Sets 'id' if meta is set
|
349
|
+
def wrap_as_element(name, attributes_to_copy=[])
|
350
|
+
m = create_html_element(name, attributes_to_copy)
|
351
|
+
children_to_html.each do |e| m << e; end
|
352
|
+
|
353
|
+
# m << Comment.new( "{"+self.al.to_md+"}") if not self.al.empty?
|
354
|
+
# m << Comment.new( @attributes.inspect) if not @attributes.empty?
|
355
|
+
m
|
356
|
+
end
|
357
|
+
|
358
|
+
=begin maruku_doc
|
359
|
+
Attribute: id
|
360
|
+
Scope: element
|
361
|
+
Output: LaTeX, HTML
|
362
|
+
|
363
|
+
It is copied as a standard HTML attribute.
|
364
|
+
|
365
|
+
Moreover, it used as a label name for hyperlinks in both HTML and
|
366
|
+
in PDF.
|
367
|
+
|
368
|
+
=end
|
369
|
+
|
370
|
+
=begin maruku_doc
|
371
|
+
Attribute: class
|
372
|
+
Scope: element
|
373
|
+
Output: HTML
|
374
|
+
|
375
|
+
It is copied as a standard HTML attribute.
|
376
|
+
=end
|
377
|
+
|
378
|
+
=begin maruku_doc
|
379
|
+
Attribute: style
|
380
|
+
Scope: element
|
381
|
+
Output: HTML
|
382
|
+
|
383
|
+
It is copied as a standard HTML attribute.
|
384
|
+
=end
|
385
|
+
|
386
|
+
|
387
|
+
|
388
|
+
|
389
|
+
|
390
|
+
HTML4Attributes = {}
|
391
|
+
|
392
|
+
coreattrs = [:id, :class, :style, :title]
|
393
|
+
i18n = [:lang, 'xml:lang'.to_sym]
|
394
|
+
events = [
|
395
|
+
:onclick, :ondblclick, :onmousedown, :onmouseup, :onmouseover,
|
396
|
+
:onmousemove, :onmouseout,
|
397
|
+
:onkeypress, :onkeydown, :onkeyup]
|
398
|
+
attrs = coreattrs + i18n + events
|
399
|
+
cellhalign = [:align, :char, :charoff]
|
400
|
+
cellvalign = [:valign]
|
401
|
+
[
|
402
|
+
['body', attrs + [:onload, :onunload]],
|
403
|
+
['address', attrs],
|
404
|
+
['div', attrs],
|
405
|
+
['a', attrs+[:charset, :type, :name, :rel, :rev, :accesskey, :shape, :coords, :tabindex,
|
406
|
+
:onfocus,:onblur]],
|
407
|
+
['img', attrs + [:longdesc, :name, :height, :width, :alt] ],
|
408
|
+
['p', attrs],
|
409
|
+
[['h1','h2','h3','h4','h5','h6'], attrs],
|
410
|
+
[['pre'], attrs],
|
411
|
+
[['q', 'blockquote'], attrs+[:cite]],
|
412
|
+
[['ins','del'], attrs+[:cite,:datetime]],
|
413
|
+
[['ol','ul','li'], attrs],
|
414
|
+
['table',attrs+[:summary, :width, :frame, :rules, :border, :cellspacing, :cellpadding]],
|
415
|
+
['caption',attrs],
|
416
|
+
[['colgroup','col'],attrs+[:span, :width]+cellhalign+cellvalign],
|
417
|
+
[['thead','tbody','tfoot'], attrs+cellhalign+cellvalign],
|
418
|
+
[['td','td','th'], attrs+[:abbr, :axis, :headers, :scope, :rowspan, :colspan, :cellvalign, :cellhalign]],
|
419
|
+
|
420
|
+
# altri
|
421
|
+
[['em','code','strong','hr','span','dl','dd','dt'], attrs]
|
422
|
+
].each do |el, a| [*el].each do |e| HTML4Attributes[e] = a end end
|
423
|
+
|
424
|
+
|
425
|
+
def create_html_element(name, attributes_to_copy=[])
|
426
|
+
m = Element.new name
|
427
|
+
if atts = HTML4Attributes[name] then
|
428
|
+
atts.each do |att|
|
429
|
+
if v = @attributes[att] then
|
430
|
+
m.attributes[att.to_s] = v.to_s
|
431
|
+
end
|
432
|
+
end
|
433
|
+
else
|
434
|
+
# puts "not atts for #{name.inspect}"
|
435
|
+
end
|
436
|
+
m
|
437
|
+
end
|
438
|
+
|
439
|
+
|
440
|
+
def to_html_ul
|
441
|
+
if @attributes[:toc]
|
442
|
+
# render toc
|
443
|
+
html_toc = @doc.toc.to_html
|
444
|
+
return html_toc
|
445
|
+
else
|
446
|
+
add_ws wrap_as_element('ul')
|
447
|
+
end
|
448
|
+
end
|
449
|
+
|
450
|
+
|
451
|
+
def to_html_paragraph; add_ws wrap_as_element('p') end
|
452
|
+
def to_html_ol; add_ws wrap_as_element('ol') end
|
453
|
+
def to_html_li; add_ws wrap_as_element('li') end
|
454
|
+
def to_html_li_span; add_ws wrap_as_element('li') end
|
455
|
+
def to_html_quote; add_ws wrap_as_element('blockquote') end
|
456
|
+
def to_html_strong; wrap_as_element('strong') end
|
457
|
+
def to_html_emphasis; wrap_as_element('em') end
|
458
|
+
|
459
|
+
=begin maruku_doc
|
460
|
+
Attribute: use_numbered_headers
|
461
|
+
Scope: document
|
462
|
+
Summary: Activates the numbering of headers.
|
463
|
+
|
464
|
+
If `true`, section headers will be numbered.
|
465
|
+
|
466
|
+
In LaTeX export, the numbering of headers is managed
|
467
|
+
by Maruku, to have the same results in both HTML and LaTeX.
|
468
|
+
=end
|
469
|
+
|
470
|
+
# nil if not applicable, else string
|
471
|
+
def section_number
|
472
|
+
return nil if not get_setting(:use_numbered_headers)
|
473
|
+
|
474
|
+
n = @attributes[:section_number]
|
475
|
+
if n && (not n.empty?)
|
476
|
+
n.join('.')+". "
|
477
|
+
else
|
478
|
+
nil
|
479
|
+
end
|
480
|
+
end
|
481
|
+
|
482
|
+
# nil if not applicable, else SPAN element
|
483
|
+
def render_section_number
|
484
|
+
# if we are bound to a section, add section number
|
485
|
+
if num = section_number
|
486
|
+
span = Element.new 'span'
|
487
|
+
span.attributes['class'] = 'maruku_section_number'
|
488
|
+
span << Text.new(section_number)
|
489
|
+
span
|
490
|
+
else
|
491
|
+
nil
|
492
|
+
end
|
493
|
+
end
|
494
|
+
|
495
|
+
def to_html_header
|
496
|
+
element_name = "h#{self.level}"
|
497
|
+
h = wrap_as_element element_name
|
498
|
+
|
499
|
+
if span = render_section_number
|
500
|
+
h.insert_before(h.children.first, span)
|
501
|
+
end
|
502
|
+
add_ws h
|
503
|
+
end
|
504
|
+
|
505
|
+
def source2html(source)
|
506
|
+
# source = source.gsub(/&/,'&')
|
507
|
+
source = Text.normalize(source)
|
508
|
+
source = source.gsub(/\'/,''') # IE bug
|
509
|
+
source = source.gsub(/'/,''') # IE bug
|
510
|
+
Text.new(source, true, nil, true )
|
511
|
+
end
|
512
|
+
|
513
|
+
=begin maruku_doc
|
514
|
+
Attribute: html_use_syntax
|
515
|
+
Scope: global, document, element
|
516
|
+
Output: HTML
|
517
|
+
Summary: Enables the use of the `syntax` package.
|
518
|
+
Related: lang, code_lang
|
519
|
+
Default: <?mrk md_code(Globals[:html_use_syntax].to_s) ?>
|
520
|
+
|
521
|
+
If true, the `syntax` package is used. It supports the `ruby` and `xml`
|
522
|
+
languages. Remember to set the `lang` attribute of the code block.
|
523
|
+
|
524
|
+
Examples:
|
525
|
+
|
526
|
+
require 'maruku'
|
527
|
+
{:lang=ruby html_use_syntax=true}
|
528
|
+
|
529
|
+
and
|
530
|
+
|
531
|
+
<div style="text-align:center">Div</div>
|
532
|
+
{:lang=html html_use_syntax=true}
|
533
|
+
|
534
|
+
produces:
|
535
|
+
|
536
|
+
require 'maruku'
|
537
|
+
{:lang=ruby html_use_syntax=true}
|
538
|
+
|
539
|
+
and
|
540
|
+
|
541
|
+
<div style="text-align:center">Div</div>
|
542
|
+
{:lang=html html_use_syntax=true}
|
543
|
+
|
544
|
+
=end
|
545
|
+
|
546
|
+
$syntax_loaded = false
|
547
|
+
def to_html_code;
|
548
|
+
source = self.raw_code
|
549
|
+
|
550
|
+
lang = self.attributes[:lang] || @doc.attributes[:code_lang]
|
551
|
+
|
552
|
+
lang = 'xml' if lang=='html'
|
553
|
+
|
554
|
+
use_syntax = get_setting :html_use_syntax
|
555
|
+
|
556
|
+
element =
|
557
|
+
if use_syntax && lang
|
558
|
+
begin
|
559
|
+
if not $syntax_loaded
|
560
|
+
require 'rubygems'
|
561
|
+
require 'syntax'
|
562
|
+
require 'syntax/convertors/html'
|
563
|
+
$syntax_loaded = true
|
564
|
+
end
|
565
|
+
convertor = Syntax::Convertors::HTML.for_syntax lang
|
566
|
+
|
567
|
+
# eliminate trailing newlines otherwise Syntax crashes
|
568
|
+
source = source.gsub(/\n*\Z/,'')
|
569
|
+
|
570
|
+
html = convertor.convert( source )
|
571
|
+
html = html.gsub(/\'/,''') # IE bug
|
572
|
+
html = html.gsub(/'/,''') # IE bug
|
573
|
+
# html = html.gsub(/&/,'&')
|
574
|
+
|
575
|
+
code = Document.new(html, {:respect_whitespace =>:all}).root
|
576
|
+
code.name = 'code'
|
577
|
+
code.attributes['class'] = lang
|
578
|
+
code.attributes['lang'] = lang
|
579
|
+
|
580
|
+
pre = Element.new 'pre'
|
581
|
+
pre << code
|
582
|
+
pre
|
583
|
+
rescue LoadError => e
|
584
|
+
maruku_error "Could not load package 'syntax'.\n"+
|
585
|
+
"Please install it, for example using 'gem install syntax'."
|
586
|
+
to_html_code_using_pre(source)
|
587
|
+
rescue Object => e
|
588
|
+
maruku_error"Error while using the syntax library for code:\n#{source.inspect}"+
|
589
|
+
"Lang is #{lang} object is: \n"+
|
590
|
+
self.inspect +
|
591
|
+
"\nException: #{e.class}: #{e.message}\n\t#{e.backtrace.join("\n\t")}"
|
592
|
+
|
593
|
+
tell_user("Using normal PRE because the syntax library did not work.")
|
594
|
+
to_html_code_using_pre(source)
|
595
|
+
end
|
596
|
+
else
|
597
|
+
to_html_code_using_pre(source)
|
598
|
+
end
|
599
|
+
|
600
|
+
color = get_setting(:code_background_color)
|
601
|
+
if color != Globals[:code_background_color]
|
602
|
+
element.attributes['style'] = "background-color: #{color};"
|
603
|
+
end
|
604
|
+
add_ws element
|
605
|
+
end
|
606
|
+
|
607
|
+
=begin maruku_doc
|
608
|
+
Attribute: code_background_color
|
609
|
+
Scope: global, document, element
|
610
|
+
Summary: Background color for code blocks.
|
611
|
+
|
612
|
+
The format is either a named color (`green`, `red`) or a CSS color
|
613
|
+
of the form `#ff00ff`.
|
614
|
+
|
615
|
+
* for **HTML output**, the value is put straight in the `background-color` CSS
|
616
|
+
property of the block.
|
617
|
+
|
618
|
+
* for **LaTeX output**, if it is a named color, it must be a color accepted
|
619
|
+
by the LaTeX `color` packages. If it is of the form `#ff00ff`, Maruku
|
620
|
+
defines a color using the `\color[rgb]{r,g,b}` macro.
|
621
|
+
|
622
|
+
For example, for `#0000ff`, the macro is called as: `\color[rgb]{0,0,1}`.
|
623
|
+
|
624
|
+
=end
|
625
|
+
|
626
|
+
|
627
|
+
def to_html_code_using_pre(source)
|
628
|
+
pre = create_html_element 'pre'
|
629
|
+
code = Element.new 'code', pre
|
630
|
+
s = source
|
631
|
+
|
632
|
+
# s = s.gsub(/&/,'&')
|
633
|
+
s = Text.normalize(s)
|
634
|
+
s = s.gsub(/\'/,''') # IE bug
|
635
|
+
s = s.gsub(/'/,''') # IE bug
|
636
|
+
|
637
|
+
if get_setting(:code_show_spaces)
|
638
|
+
# 187 = raquo
|
639
|
+
# 160 = nbsp
|
640
|
+
# 172 = not
|
641
|
+
s.gsub!(/\t/,'»'+' '*3)
|
642
|
+
s.gsub!(/ /,'¬')
|
643
|
+
end
|
644
|
+
|
645
|
+
text = Text.new(s, respect_ws=true, parent=nil, raw=true )
|
646
|
+
|
647
|
+
if lang = self.attributes[:lang]
|
648
|
+
code.attributes['lang'] = lang
|
649
|
+
code.attributes['class'] = lang
|
650
|
+
end
|
651
|
+
code << text
|
652
|
+
pre
|
653
|
+
end
|
654
|
+
|
655
|
+
def to_html_inline_code;
|
656
|
+
pre = create_html_element 'code'
|
657
|
+
source = self.raw_code
|
658
|
+
pre << source2html(source)
|
659
|
+
|
660
|
+
color = get_setting(:code_background_color)
|
661
|
+
if color != Globals[:code_background_color]
|
662
|
+
pre.attributes['style'] = "background-color: #{color};"+(pre.attributes['style']||"")
|
663
|
+
end
|
664
|
+
|
665
|
+
pre
|
666
|
+
end
|
667
|
+
|
668
|
+
def add_class_to(el, cl)
|
669
|
+
el.attributes['class'] =
|
670
|
+
if already = el.attributes['class']
|
671
|
+
already + " " + cl
|
672
|
+
else
|
673
|
+
cl
|
674
|
+
end
|
675
|
+
end
|
676
|
+
|
677
|
+
def add_class_to_link(a)
|
678
|
+
return # not ready yet
|
679
|
+
|
680
|
+
# url = a.attributes['href']
|
681
|
+
# return if not url
|
682
|
+
#
|
683
|
+
# if url =~ /^#/
|
684
|
+
# add_class_to(a, 'maruku-link-samedoc')
|
685
|
+
# elsif url =~ /^http:/
|
686
|
+
# add_class_to(a, 'maruku-link-external')
|
687
|
+
# else
|
688
|
+
# add_class_to(a, 'maruku-link-local')
|
689
|
+
# end
|
690
|
+
#
|
691
|
+
# puts a.attributes['class']
|
692
|
+
end
|
693
|
+
|
694
|
+
|
695
|
+
def to_html_immediate_link
|
696
|
+
a = create_html_element 'a'
|
697
|
+
url = self.url
|
698
|
+
text = url.gsub(/^mailto:/,'') # don't show mailto
|
699
|
+
a << Text.new(text)
|
700
|
+
a.attributes['href'] = url
|
701
|
+
add_class_to_link(a)
|
702
|
+
a
|
703
|
+
end
|
704
|
+
|
705
|
+
def to_html_link
|
706
|
+
a = wrap_as_element 'a'
|
707
|
+
id = self.ref_id
|
708
|
+
|
709
|
+
if ref = @doc.refs[id]
|
710
|
+
url = ref[:url]
|
711
|
+
title = ref[:title]
|
712
|
+
a.attributes['href'] = url if url
|
713
|
+
a.attributes['title'] = title if title
|
714
|
+
else
|
715
|
+
maruku_error "Could not find ref_id = #{id.inspect} for #{self.inspect}\n"+
|
716
|
+
"Available refs are #{@doc.refs.keys.inspect}"
|
717
|
+
tell_user "Not creating a link for ref_id = #{id.inspect}."
|
718
|
+
return wrap_as_element('span')
|
719
|
+
end
|
720
|
+
|
721
|
+
# add_class_to_link(a)
|
722
|
+
return a
|
723
|
+
end
|
724
|
+
|
725
|
+
def to_html_im_link
|
726
|
+
if url = self.url
|
727
|
+
title = self.title
|
728
|
+
a = wrap_as_element 'a'
|
729
|
+
a.attributes['href'] = url
|
730
|
+
a.attributes['title'] = title if title
|
731
|
+
return a
|
732
|
+
else
|
733
|
+
maruku_error"Could not find url in #{self.inspect}"
|
734
|
+
tell_user "Not creating a link for ref_id = #{id.inspect}."
|
735
|
+
return wrap_as_element('span')
|
736
|
+
end
|
737
|
+
end
|
738
|
+
|
739
|
+
def add_ws(e)
|
740
|
+
[Text.new("\n"), e, Text.new("\n")]
|
741
|
+
end
|
742
|
+
##### Email address
|
743
|
+
|
744
|
+
def obfuscate(s)
|
745
|
+
res = ''
|
746
|
+
s.each_byte do |char|
|
747
|
+
res += "&#%03d;" % char
|
748
|
+
end
|
749
|
+
res
|
750
|
+
end
|
751
|
+
|
752
|
+
def to_html_email_address
|
753
|
+
email = self.email
|
754
|
+
a = create_html_element 'a'
|
755
|
+
#a.attributes['href'] = Text.new("mailto:"+obfuscate(email),false,nil,true)
|
756
|
+
#a.attributes.add Attribute.new('href',Text.new(
|
757
|
+
#"mailto:"+obfuscate(email),false,nil,true))
|
758
|
+
# Sorry, for the moment it doesn't work
|
759
|
+
a.attributes['href'] = "mailto:#{email}"
|
760
|
+
|
761
|
+
a << Text.new(obfuscate(email),false,nil,true)
|
762
|
+
a
|
763
|
+
end
|
764
|
+
|
765
|
+
##### Images
|
766
|
+
|
767
|
+
def to_html_image
|
768
|
+
a = create_html_element 'img'
|
769
|
+
id = self.ref_id
|
770
|
+
if ref = @doc.refs[id]
|
771
|
+
url = ref[:url]
|
772
|
+
title = ref[:title]
|
773
|
+
a.attributes['src'] = url.to_s
|
774
|
+
a.attributes['alt'] = children_to_s
|
775
|
+
else
|
776
|
+
maruku_error"Could not find id = #{id.inspect} for\n #{self.inspect}"
|
777
|
+
tell_user "Could not create image with ref_id = #{id.inspect};"+
|
778
|
+
" Using SPAN element as replacement."
|
779
|
+
return wrap_as_element('span')
|
780
|
+
end
|
781
|
+
return a
|
782
|
+
end
|
783
|
+
|
784
|
+
def to_html_im_image
|
785
|
+
if not url = self.url
|
786
|
+
maruku_error "Image with no url: #{self.inspect}"
|
787
|
+
tell_user "Could not create image with ref_id = #{id.inspect};"+
|
788
|
+
" Using SPAN element as replacement."
|
789
|
+
return wrap_as_element('span')
|
790
|
+
end
|
791
|
+
title = self.title
|
792
|
+
a = create_html_element 'img'
|
793
|
+
a.attributes['src'] = url.to_s
|
794
|
+
a.attributes['alt'] = children_to_s
|
795
|
+
return a
|
796
|
+
end
|
797
|
+
|
798
|
+
=begin maruku_doc
|
799
|
+
Attribute: filter_html
|
800
|
+
Scope: document
|
801
|
+
|
802
|
+
If true, raw HTML is discarded from the output.
|
803
|
+
|
804
|
+
=end
|
805
|
+
|
806
|
+
def to_html_raw_html
|
807
|
+
return [] if get_setting(:filter_html)
|
808
|
+
|
809
|
+
raw_html = self.raw_html
|
810
|
+
if rexml_doc = @parsed_html
|
811
|
+
root = rexml_doc.root
|
812
|
+
if root.nil?
|
813
|
+
s = "Bug in REXML: root() of Document is nil: \n#{rexml_doc.inspect}\n"+
|
814
|
+
"Raw HTML:\n#{raw_html.inspect}"
|
815
|
+
maruku_error s
|
816
|
+
tell_user 'The REXML version you have has a bug, omitting HTML'
|
817
|
+
div = Element.new 'div'
|
818
|
+
#div << Text.new(s)
|
819
|
+
return div
|
820
|
+
end
|
821
|
+
|
822
|
+
# copies the @children array (FIXME is it deep?)
|
823
|
+
elements = root.to_a
|
824
|
+
return elements
|
825
|
+
else # invalid
|
826
|
+
# Creates red box with offending HTML
|
827
|
+
tell_user "Wrapping bad html in a PRE with class 'markdown-html-error'\n"+
|
828
|
+
add_tabs(raw_html,1,'|')
|
829
|
+
pre = Element.new('pre')
|
830
|
+
pre.attributes['style'] = 'border: solid 3px red; background-color: pink'
|
831
|
+
pre.attributes['class'] = 'markdown-html-error'
|
832
|
+
pre << Text.new("REXML could not parse this XML/HTML: \n#{raw_html}", true)
|
833
|
+
return pre
|
834
|
+
end
|
835
|
+
end
|
836
|
+
|
837
|
+
def to_html_abbr
|
838
|
+
abbr = Element.new 'abbr'
|
839
|
+
abbr << Text.new(children[0])
|
840
|
+
abbr.attributes['title'] = self.title if self.title
|
841
|
+
abbr
|
842
|
+
end
|
843
|
+
|
844
|
+
def to_html_footnote_reference
|
845
|
+
id = self.footnote_id
|
846
|
+
|
847
|
+
# save the order of used footnotes
|
848
|
+
order = @doc.footnotes_order
|
849
|
+
|
850
|
+
if order.include? id
|
851
|
+
# footnote has already been used
|
852
|
+
return []
|
853
|
+
end
|
854
|
+
|
855
|
+
if not @doc.footnotes[id]
|
856
|
+
return []
|
857
|
+
end
|
858
|
+
|
859
|
+
# take next number
|
860
|
+
order << id
|
861
|
+
|
862
|
+
#num = order.size;
|
863
|
+
num = order.index(id) + 1
|
864
|
+
|
865
|
+
sup = Element.new 'sup'
|
866
|
+
sup.attributes['id'] = "#{get_setting(:doc_prefix)}fnref:#{num}"
|
867
|
+
a = Element.new 'a'
|
868
|
+
a << Text.new(num.to_s)
|
869
|
+
a.attributes['href'] = "\##{get_setting(:doc_prefix)}fn:#{num}"
|
870
|
+
a.attributes['rel'] = 'footnote'
|
871
|
+
sup << a
|
872
|
+
|
873
|
+
sup
|
874
|
+
end
|
875
|
+
|
876
|
+
## Definition lists ###
|
877
|
+
def to_html_definition_list() add_ws wrap_as_element('dl') end
|
878
|
+
def to_html_definition() children_to_html end
|
879
|
+
def to_html_definition_term() add_ws wrap_as_element('dt') end
|
880
|
+
def to_html_definition_data() add_ws wrap_as_element('dd') end
|
881
|
+
|
882
|
+
# FIXME: Ugly code
|
883
|
+
def to_html_table
|
884
|
+
align = self.align
|
885
|
+
num_columns = align.size
|
886
|
+
|
887
|
+
head = @children.slice(0, num_columns)
|
888
|
+
rows = []
|
889
|
+
i = num_columns
|
890
|
+
while i<@children.size
|
891
|
+
rows << @children.slice(i, num_columns)
|
892
|
+
i += num_columns
|
893
|
+
end
|
894
|
+
|
895
|
+
table = create_html_element 'table'
|
896
|
+
thead = Element.new 'thead'
|
897
|
+
tr = Element.new 'tr'
|
898
|
+
array_to_html(head).each do |x| tr<<x end
|
899
|
+
thead << tr
|
900
|
+
table << thead
|
901
|
+
|
902
|
+
tbody = Element.new 'tbody'
|
903
|
+
rows.each do |row|
|
904
|
+
tr = Element.new 'tr'
|
905
|
+
array_to_html(row).each_with_index do |x,i|
|
906
|
+
x.attributes['style'] ="text-align: #{align[i].to_s};"
|
907
|
+
tr<<x
|
908
|
+
end
|
909
|
+
|
910
|
+
tbody << tr << Text.new("\n")
|
911
|
+
end
|
912
|
+
table << tbody
|
913
|
+
table
|
914
|
+
end
|
915
|
+
|
916
|
+
def to_html_head_cell; wrap_as_element('th') end
|
917
|
+
def to_html_cell
|
918
|
+
if @attributes[:scope]
|
919
|
+
wrap_as_element('th', [:scope])
|
920
|
+
else
|
921
|
+
wrap_as_element('td')
|
922
|
+
end
|
923
|
+
end
|
924
|
+
|
925
|
+
def to_html_entity
|
926
|
+
MaRuKu::Out::Latex.need_entity_table
|
927
|
+
|
928
|
+
entity_name = self.entity_name
|
929
|
+
|
930
|
+
if (e = MaRuKu::Out::Latex::ENTITY_TABLE[entity_name]) && e.html_num
|
931
|
+
entity_name = e.html_num
|
932
|
+
end
|
933
|
+
|
934
|
+
# Fix for Internet Explorer
|
935
|
+
if entity_name == 'apos'
|
936
|
+
entity_name = 39
|
937
|
+
end
|
938
|
+
|
939
|
+
|
940
|
+
if entity_name.kind_of? Fixnum
|
941
|
+
# Entity.new(entity_name)
|
942
|
+
Text.new('&#%d;' % [entity_name], false, nil, true)
|
943
|
+
else
|
944
|
+
Text.new('&%s;' % [entity_name], false, nil, true)
|
945
|
+
end
|
946
|
+
end
|
947
|
+
|
948
|
+
def to_html_xml_instr
|
949
|
+
target = self.target || ''
|
950
|
+
code = self.code || ''
|
951
|
+
REXML::Instruction.new(target, code)
|
952
|
+
end
|
953
|
+
|
954
|
+
# Convert each child to html
|
955
|
+
def children_to_html
|
956
|
+
array_to_html(@children)
|
957
|
+
end
|
958
|
+
|
959
|
+
def array_to_html(array)
|
960
|
+
e = []
|
961
|
+
array.each do |c|
|
962
|
+
method = c.kind_of?(MDElement) ?
|
963
|
+
"to_html_#{c.node_type}" : "to_html"
|
964
|
+
|
965
|
+
if not c.respond_to?(method)
|
966
|
+
#raise "Object does not answer to #{method}: #{c.class} #{c.inspect}"
|
967
|
+
next
|
968
|
+
end
|
969
|
+
|
970
|
+
h = c.send(method)
|
971
|
+
|
972
|
+
if h.nil?
|
973
|
+
raise "Nil html created by method #{method}:\n#{h.inspect}\n"+
|
974
|
+
" for object #{c.inspect[0,300]}"
|
975
|
+
end
|
976
|
+
|
977
|
+
if h.kind_of?Array
|
978
|
+
e = e + h #h.each do |hh| e << hh end
|
979
|
+
else
|
980
|
+
e << h
|
981
|
+
end
|
982
|
+
end
|
983
|
+
e
|
984
|
+
end
|
985
|
+
|
986
|
+
def to_html_ref_definition; [] end
|
987
|
+
def to_latex_ref_definition; [] end
|
988
|
+
|
989
|
+
end # HTML
|
990
|
+
end # out
|
991
|
+
end # MaRuKu
|