amp-front 0.1.0
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/.document +5 -0
- data/.gitignore +24 -0
- data/Ampfile +3 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +36 -0
- data/LICENSE +20 -0
- data/README.md +50 -0
- data/Rakefile +64 -0
- data/VERSION +1 -0
- data/design_docs/commands.md +91 -0
- data/design_docs/dependencies.md +35 -0
- data/design_docs/plugins.md +47 -0
- data/features/amp.feature +8 -0
- data/features/amp_help.feature +36 -0
- data/features/amp_plugin_list.feature +10 -0
- data/features/step_definitions/amp-front_steps.rb +23 -0
- data/features/support/env.rb +4 -0
- data/lib/amp-front.rb +30 -0
- data/lib/amp-front/dispatch/commands/base.rb +158 -0
- data/lib/amp-front/dispatch/commands/builtin/help.rb +23 -0
- data/lib/amp-front/dispatch/commands/builtin/plugin.rb +24 -0
- data/lib/amp-front/dispatch/commands/validations.rb +171 -0
- data/lib/amp-front/dispatch/runner.rb +86 -0
- data/lib/amp-front/help/entries/__default__.erb +31 -0
- data/lib/amp-front/help/entries/ampfiles.md +42 -0
- data/lib/amp-front/help/entries/commands.erb +6 -0
- data/lib/amp-front/help/entries/new-commands.md +81 -0
- data/lib/amp-front/help/help.rb +312 -0
- data/lib/amp-front/plugins/base.rb +87 -0
- data/lib/amp-front/support/module_extensions.rb +92 -0
- data/lib/amp-front/third_party/maruku.rb +136 -0
- data/lib/amp-front/third_party/maruku/attributes.rb +227 -0
- data/lib/amp-front/third_party/maruku/defaults.rb +71 -0
- data/lib/amp-front/third_party/maruku/errors_management.rb +92 -0
- data/lib/amp-front/third_party/maruku/helpers.rb +260 -0
- data/lib/amp-front/third_party/maruku/input/charsource.rb +326 -0
- data/lib/amp-front/third_party/maruku/input/extensions.rb +69 -0
- data/lib/amp-front/third_party/maruku/input/html_helper.rb +189 -0
- data/lib/amp-front/third_party/maruku/input/linesource.rb +111 -0
- data/lib/amp-front/third_party/maruku/input/parse_block.rb +615 -0
- data/lib/amp-front/third_party/maruku/input/parse_doc.rb +234 -0
- data/lib/amp-front/third_party/maruku/input/parse_span_better.rb +746 -0
- data/lib/amp-front/third_party/maruku/input/rubypants.rb +225 -0
- data/lib/amp-front/third_party/maruku/input/type_detection.rb +147 -0
- data/lib/amp-front/third_party/maruku/input_textile2/t2_parser.rb +163 -0
- data/lib/amp-front/third_party/maruku/maruku.rb +33 -0
- data/lib/amp-front/third_party/maruku/output/to_ansi.rb +223 -0
- data/lib/amp-front/third_party/maruku/output/to_html.rb +991 -0
- data/lib/amp-front/third_party/maruku/output/to_markdown.rb +164 -0
- data/lib/amp-front/third_party/maruku/output/to_s.rb +56 -0
- data/lib/amp-front/third_party/maruku/string_utils.rb +191 -0
- data/lib/amp-front/third_party/maruku/structures.rb +167 -0
- data/lib/amp-front/third_party/maruku/structures_inspect.rb +87 -0
- data/lib/amp-front/third_party/maruku/structures_iterators.rb +61 -0
- data/lib/amp-front/third_party/maruku/textile2.rb +1 -0
- data/lib/amp-front/third_party/maruku/toc.rb +199 -0
- data/lib/amp-front/third_party/maruku/usage/example1.rb +33 -0
- data/lib/amp-front/third_party/maruku/version.rb +40 -0
- data/lib/amp-front/third_party/trollop.rb +766 -0
- data/spec/amp-front_spec.rb +25 -0
- data/spec/command_specs/base_spec.rb +123 -0
- data/spec/command_specs/command_spec.rb +97 -0
- data/spec/command_specs/help_spec.rb +33 -0
- data/spec/command_specs/spec_helper.rb +37 -0
- data/spec/command_specs/validations_spec.rb +267 -0
- data/spec/dispatch_specs/runner_spec.rb +116 -0
- data/spec/dispatch_specs/spec_helper.rb +15 -0
- data/spec/help_specs/help_entry_spec.rb +78 -0
- data/spec/help_specs/help_registry_spec.rb +77 -0
- data/spec/help_specs/spec_helper.rb +15 -0
- data/spec/plugin_specs/base_spec.rb +36 -0
- data/spec/plugin_specs/spec_helper.rb +15 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +33 -0
- data/spec/support_specs/module_extensions_spec.rb +104 -0
- data/spec/support_specs/spec_helper.rb +15 -0
- data/test/third_party_tests/test_trollop.rb +1181 -0
- metadata +192 -0
|
@@ -0,0 +1,33 @@
|
|
|
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
|
+
|
|
22
|
+
# The Maruku class is the public interface
|
|
23
|
+
#
|
|
24
|
+
|
|
25
|
+
class Maruku
|
|
26
|
+
def initialize(s=nil, meta={})
|
|
27
|
+
super(nil)
|
|
28
|
+
self.attributes.merge! meta
|
|
29
|
+
if s
|
|
30
|
+
parse_doc(s)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
class String
|
|
4
|
+
# escapes special characters
|
|
5
|
+
def to_ansi
|
|
6
|
+
self
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
class String
|
|
11
|
+
##
|
|
12
|
+
# Returns the string, encoded for a tty terminal with the given color code.
|
|
13
|
+
#
|
|
14
|
+
# @param [String] color_code a TTY color code
|
|
15
|
+
# @return [String] the string wrapped in non-printing characters to make the text
|
|
16
|
+
# appear in a given color
|
|
17
|
+
def colorize(color_code, closing_tag = 39)
|
|
18
|
+
"\e[#{color_code}m#{self}\e[#{closing_tag}m"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
[:black, :red, :green, :yellow, :blue, :magenta, :cyan, :white].tap do |list|
|
|
22
|
+
list.each_with_index do |arg, idx|
|
|
23
|
+
define_method(arg) { colorize(30 + idx, 39) }
|
|
24
|
+
define_method("on_#{arg}") { colorize(40 + idx, 49) }
|
|
25
|
+
end
|
|
26
|
+
define_method :color do |*args|
|
|
27
|
+
result = self
|
|
28
|
+
args.each do |arg|
|
|
29
|
+
if arg.to_s[0,3] == "on_"
|
|
30
|
+
then base = 40; arg = arg.to_s[3..-1].to_sym
|
|
31
|
+
else base = 30
|
|
32
|
+
end
|
|
33
|
+
result = result.colorize(base + list.index(arg), base + 9)
|
|
34
|
+
end
|
|
35
|
+
result
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Returns the string, colored red.
|
|
40
|
+
def bold; colorize(1, 22); end
|
|
41
|
+
def underline; colorize(4, 24); end
|
|
42
|
+
def blink; colorize(5, 25); end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
module MaRuKu
|
|
46
|
+
class MDDocument
|
|
47
|
+
# Render as a LaTeX fragment
|
|
48
|
+
def to_ansi
|
|
49
|
+
children_to_ansi
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
module MaRuKu
|
|
55
|
+
module Out
|
|
56
|
+
module Ansi
|
|
57
|
+
|
|
58
|
+
def to_ansi_hrule
|
|
59
|
+
"\n#{'-' * 40}\n"
|
|
60
|
+
end
|
|
61
|
+
def to_ansi_linebreak
|
|
62
|
+
"\n "
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def to_ansi_paragraph
|
|
66
|
+
children_to_ansi+"\n\n"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def latex_color(s, command='color')
|
|
70
|
+
if s =~ /^\#(\w\w)(\w\w)(\w\w)$/
|
|
71
|
+
r = $1.hex; g = $2.hex; b=$3.hex
|
|
72
|
+
# convert from 0-255 to 0.0-1.0
|
|
73
|
+
r = r / 255.0; g = g / 255.0; b = b / 255.0;
|
|
74
|
+
"\\#{command}[rgb]{%0.2f,%0.2f,%0.2f}" % [r,g,b]
|
|
75
|
+
elsif s =~ /^\#(\w)(\w)(\w)$/
|
|
76
|
+
r = $1.hex; g = $2.hex; b=$3.hex
|
|
77
|
+
# convert from 0-15 to 0.0-1.0
|
|
78
|
+
r = r / 15.0; g = g / 15.0; b = b / 15.0;
|
|
79
|
+
"\\#{command}[rgb]{%0.2f,%0.2f,%0.2f}" % [r,g,b]
|
|
80
|
+
else
|
|
81
|
+
"\\#{command}{#{s}}"
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def to_ansi_code
|
|
86
|
+
source = self.raw_code
|
|
87
|
+
return source.to_s.black.on_green+"\n\n"
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def to_ansi_header
|
|
92
|
+
level = self.level
|
|
93
|
+
title = children_to_ansi
|
|
94
|
+
length = title.size
|
|
95
|
+
|
|
96
|
+
if level == 1 || level == 3 then title = title.bold end
|
|
97
|
+
if level == 1 || level == 2 then title = title.underline end
|
|
98
|
+
|
|
99
|
+
%{#{title}\n\n}
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def to_ansi_ul
|
|
103
|
+
children_to_ansi + "\n"
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def to_ansi_quote
|
|
107
|
+
wrap_as_environment('quote')
|
|
108
|
+
end
|
|
109
|
+
def to_ansi_ol
|
|
110
|
+
wrap_as_environment('enumerate')
|
|
111
|
+
end
|
|
112
|
+
def to_ansi_li
|
|
113
|
+
"* #{children_to_ansi}\n"
|
|
114
|
+
end
|
|
115
|
+
def to_ansi_li_span
|
|
116
|
+
"* #{children_to_ansi}\n"
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def to_ansi_strong
|
|
120
|
+
"#{children_to_ansi}".bold
|
|
121
|
+
end
|
|
122
|
+
def to_ansi_emphasis
|
|
123
|
+
"#{children_to_ansi}".underline
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def wrap_as_span(c)
|
|
127
|
+
"{#{c} #{children_to_ansi}}"
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def to_ansi_inline_code
|
|
131
|
+
source = self.raw_code
|
|
132
|
+
return source.to_s.black.on_green
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def to_ansi_immediate_link
|
|
136
|
+
url = self.url
|
|
137
|
+
text = url.gsub(/^mailto:/,'') # don't show mailto
|
|
138
|
+
# gsub('~','$\sim$')
|
|
139
|
+
text = latex_escape(text)
|
|
140
|
+
if url[0,1] == '#'
|
|
141
|
+
url = url[1,url.size]
|
|
142
|
+
return "\\hyperlink{#{url}}{#{text}}"
|
|
143
|
+
else
|
|
144
|
+
return "\\href{#{url}}{#{text}}"
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def to_ansi_im_link
|
|
149
|
+
url = self.url
|
|
150
|
+
|
|
151
|
+
if url[0,1] == '#'
|
|
152
|
+
url = url[1,url.size]
|
|
153
|
+
return "#{children_to_ansi} (#{url})"
|
|
154
|
+
else
|
|
155
|
+
return "#{children_to_ansi} (#{url})"
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def to_ansi_link
|
|
160
|
+
id = self.ref_id
|
|
161
|
+
ref = @doc.refs[id]
|
|
162
|
+
if not ref
|
|
163
|
+
$stderr.puts "Could not find id = '#{id}'"
|
|
164
|
+
return children_to_ansi
|
|
165
|
+
else
|
|
166
|
+
url = ref[:url]
|
|
167
|
+
#title = ref[:title] || 'no title'
|
|
168
|
+
|
|
169
|
+
if url[0,1] == '#'
|
|
170
|
+
url = url[1,url.size]
|
|
171
|
+
return "\\hyperlink{#{url}}{#{children_to_ansi}}"
|
|
172
|
+
else
|
|
173
|
+
return "\\href{#{url}}{#{children_to_ansi}}"
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def to_ansi_email_address
|
|
180
|
+
"#{self.email}"
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def to_ansi_raw_html
|
|
184
|
+
#'{\bf Raw HTML removed in ansi version }'
|
|
185
|
+
""
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def to_ansi_abbr
|
|
189
|
+
children_to_ansi
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# Convert each child to html
|
|
193
|
+
def children_to_ansi
|
|
194
|
+
array_to_ansi(@children)
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def array_to_ansi(array, join_char='')
|
|
198
|
+
e = []
|
|
199
|
+
array.each do |c|
|
|
200
|
+
method = c.kind_of?(MDElement) ? "to_ansi_#{c.node_type}" : "to_ansi"
|
|
201
|
+
|
|
202
|
+
if not c.respond_to?(method)
|
|
203
|
+
next
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
h = c.send(method)
|
|
207
|
+
|
|
208
|
+
if h.nil?
|
|
209
|
+
raise "Nil ansi for #{c.inspect} created with method #{method}"
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
if h.kind_of?Array
|
|
213
|
+
e = e + h
|
|
214
|
+
else
|
|
215
|
+
e << h
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
e.join(join_char)
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
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
|