amp 0.5.2 → 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (232) hide show
  1. data/.gitignore +12 -0
  2. data/.hgignore +3 -0
  3. data/AUTHORS +1 -1
  4. data/Manifest.txt +99 -38
  5. data/README.md +3 -3
  6. data/Rakefile +53 -18
  7. data/SCHEDULE.markdown +5 -1
  8. data/TODO.markdown +120 -149
  9. data/ampfile.rb +3 -1
  10. data/bin/amp +4 -1
  11. data/ext/amp/bz2/extconf.rb +1 -1
  12. data/ext/amp/mercurial_patch/extconf.rb +1 -1
  13. data/ext/amp/mercurial_patch/mpatch.c +4 -3
  14. data/ext/amp/priority_queue/extconf.rb +1 -1
  15. data/ext/amp/support/extconf.rb +1 -1
  16. data/ext/amp/support/support.c +1 -1
  17. data/lib/amp.rb +125 -67
  18. data/lib/amp/commands/command.rb +12 -10
  19. data/lib/amp/commands/command_support.rb +8 -1
  20. data/lib/amp/commands/commands/help.rb +2 -20
  21. data/lib/amp/commands/commands/init.rb +14 -2
  22. data/lib/amp/commands/commands/templates.rb +6 -4
  23. data/lib/amp/commands/commands/version.rb +15 -1
  24. data/lib/amp/commands/commands/workflow.rb +3 -3
  25. data/lib/amp/commands/commands/workflows/git/add.rb +3 -3
  26. data/lib/amp/commands/commands/workflows/git/copy.rb +1 -1
  27. data/lib/amp/commands/commands/workflows/git/rm.rb +4 -2
  28. data/lib/amp/commands/commands/workflows/hg/add.rb +1 -1
  29. data/lib/amp/commands/commands/workflows/hg/addremove.rb +2 -2
  30. data/lib/amp/commands/commands/workflows/hg/annotate.rb +8 -2
  31. data/lib/amp/commands/commands/workflows/hg/bisect.rb +253 -0
  32. data/lib/amp/commands/commands/workflows/hg/branch.rb +1 -1
  33. data/lib/amp/commands/commands/workflows/hg/branches.rb +3 -3
  34. data/lib/amp/commands/commands/workflows/hg/bundle.rb +3 -3
  35. data/lib/amp/commands/commands/workflows/hg/clone.rb +4 -5
  36. data/lib/amp/commands/commands/workflows/hg/commit.rb +37 -1
  37. data/lib/amp/commands/commands/workflows/hg/copy.rb +2 -1
  38. data/lib/amp/commands/commands/workflows/hg/debug/index.rb +1 -1
  39. data/lib/amp/commands/commands/workflows/hg/diff.rb +3 -8
  40. data/lib/amp/commands/commands/workflows/hg/forget.rb +5 -4
  41. data/lib/amp/commands/commands/workflows/hg/identify.rb +6 -6
  42. data/lib/amp/commands/commands/workflows/hg/import.rb +1 -1
  43. data/lib/amp/commands/commands/workflows/hg/incoming.rb +2 -2
  44. data/lib/amp/commands/commands/workflows/hg/log.rb +5 -4
  45. data/lib/amp/commands/commands/workflows/hg/merge.rb +1 -1
  46. data/lib/amp/commands/commands/workflows/hg/move.rb +5 -3
  47. data/lib/amp/commands/commands/workflows/hg/outgoing.rb +1 -1
  48. data/lib/amp/commands/commands/workflows/hg/push.rb +6 -7
  49. data/lib/amp/commands/commands/workflows/hg/remove.rb +2 -2
  50. data/lib/amp/commands/commands/workflows/hg/resolve.rb +6 -23
  51. data/lib/amp/commands/commands/workflows/hg/root.rb +1 -2
  52. data/lib/amp/commands/commands/workflows/hg/status.rb +21 -12
  53. data/lib/amp/commands/commands/workflows/hg/tag.rb +2 -2
  54. data/lib/amp/commands/commands/workflows/hg/untrack.rb +12 -0
  55. data/lib/amp/commands/commands/workflows/hg/verify.rb +13 -3
  56. data/lib/amp/commands/commands/workflows/hg/what_changed.rb +18 -0
  57. data/lib/amp/commands/dispatch.rb +12 -13
  58. data/lib/amp/dependencies/amp_support.rb +1 -1
  59. data/lib/amp/dependencies/amp_support/ruby_amp_support.rb +1 -0
  60. data/lib/amp/dependencies/maruku.rb +136 -0
  61. data/lib/amp/dependencies/maruku/attributes.rb +227 -0
  62. data/lib/amp/dependencies/maruku/defaults.rb +71 -0
  63. data/lib/amp/dependencies/maruku/errors_management.rb +92 -0
  64. data/lib/amp/dependencies/maruku/helpers.rb +260 -0
  65. data/lib/amp/dependencies/maruku/input/charsource.rb +326 -0
  66. data/lib/amp/dependencies/maruku/input/extensions.rb +69 -0
  67. data/lib/amp/dependencies/maruku/input/html_helper.rb +189 -0
  68. data/lib/amp/dependencies/maruku/input/linesource.rb +111 -0
  69. data/lib/amp/dependencies/maruku/input/parse_block.rb +615 -0
  70. data/lib/amp/dependencies/maruku/input/parse_doc.rb +234 -0
  71. data/lib/amp/dependencies/maruku/input/parse_span_better.rb +746 -0
  72. data/lib/amp/dependencies/maruku/input/rubypants.rb +225 -0
  73. data/lib/amp/dependencies/maruku/input/type_detection.rb +147 -0
  74. data/lib/amp/dependencies/maruku/input_textile2/t2_parser.rb +163 -0
  75. data/lib/amp/dependencies/maruku/maruku.rb +33 -0
  76. data/lib/amp/dependencies/maruku/output/to_ansi.rb +223 -0
  77. data/lib/amp/dependencies/maruku/output/to_html.rb +991 -0
  78. data/lib/amp/dependencies/maruku/output/to_markdown.rb +164 -0
  79. data/lib/amp/dependencies/maruku/output/to_s.rb +56 -0
  80. data/lib/amp/dependencies/maruku/string_utils.rb +191 -0
  81. data/lib/amp/dependencies/maruku/structures.rb +167 -0
  82. data/lib/amp/dependencies/maruku/structures_inspect.rb +87 -0
  83. data/lib/amp/dependencies/maruku/structures_iterators.rb +61 -0
  84. data/lib/amp/dependencies/maruku/textile2.rb +1 -0
  85. data/lib/amp/dependencies/maruku/toc.rb +199 -0
  86. data/lib/amp/dependencies/maruku/usage/example1.rb +33 -0
  87. data/lib/amp/dependencies/maruku/version.rb +40 -0
  88. data/lib/amp/dependencies/priority_queue.rb +2 -1
  89. data/lib/amp/dependencies/python_config.rb +2 -1
  90. data/lib/amp/graphs/ancestor.rb +2 -1
  91. data/lib/amp/graphs/copies.rb +236 -233
  92. data/lib/amp/help/entries/__default__.erb +31 -0
  93. data/lib/amp/help/entries/commands.erb +6 -0
  94. data/lib/amp/help/entries/mdtest.md +35 -0
  95. data/lib/amp/help/entries/silly +3 -0
  96. data/lib/amp/help/help.rb +288 -0
  97. data/lib/amp/profiling_hacks.rb +5 -3
  98. data/lib/amp/repository/abstract/abstract_changeset.rb +97 -0
  99. data/lib/amp/repository/abstract/abstract_local_repo.rb +181 -0
  100. data/lib/amp/repository/abstract/abstract_staging_area.rb +180 -0
  101. data/lib/amp/repository/abstract/abstract_versioned_file.rb +100 -0
  102. data/lib/amp/repository/abstract/common_methods/changeset.rb +75 -0
  103. data/lib/amp/repository/abstract/common_methods/local_repo.rb +277 -0
  104. data/lib/amp/repository/abstract/common_methods/staging_area.rb +233 -0
  105. data/lib/amp/repository/abstract/common_methods/versioned_file.rb +71 -0
  106. data/lib/amp/repository/generic_repo_picker.rb +78 -0
  107. data/lib/amp/repository/git/repo_format/changeset.rb +336 -0
  108. data/lib/amp/repository/git/repo_format/staging_area.rb +192 -0
  109. data/lib/amp/repository/git/repo_format/versioned_file.rb +119 -0
  110. data/lib/amp/repository/git/repositories/local_repository.rb +164 -0
  111. data/lib/amp/repository/git/repository.rb +41 -0
  112. data/lib/amp/repository/mercurial/encoding/mercurial_diff.rb +382 -0
  113. data/lib/amp/repository/mercurial/encoding/mercurial_patch.rb +1 -0
  114. data/lib/amp/repository/mercurial/encoding/patch.rb +294 -0
  115. data/lib/amp/repository/mercurial/encoding/pure_ruby/ruby_mercurial_patch.rb +124 -0
  116. data/lib/amp/repository/mercurial/merging/merge_ui.rb +327 -0
  117. data/lib/amp/repository/mercurial/merging/simple_merge.rb +452 -0
  118. data/lib/amp/repository/mercurial/repo_format/branch_manager.rb +266 -0
  119. data/lib/amp/repository/mercurial/repo_format/changeset.rb +768 -0
  120. data/lib/amp/repository/mercurial/repo_format/dir_state.rb +716 -0
  121. data/lib/amp/repository/mercurial/repo_format/journal.rb +218 -0
  122. data/lib/amp/repository/mercurial/repo_format/lock.rb +210 -0
  123. data/lib/amp/repository/mercurial/repo_format/merge_state.rb +228 -0
  124. data/lib/amp/repository/mercurial/repo_format/staging_area.rb +367 -0
  125. data/lib/amp/repository/mercurial/repo_format/store.rb +487 -0
  126. data/lib/amp/repository/mercurial/repo_format/tag_manager.rb +322 -0
  127. data/lib/amp/repository/mercurial/repo_format/updatable.rb +543 -0
  128. data/lib/amp/repository/mercurial/repo_format/updater.rb +848 -0
  129. data/lib/amp/repository/mercurial/repo_format/verification.rb +433 -0
  130. data/lib/amp/repository/mercurial/repositories/bundle_repository.rb +216 -0
  131. data/lib/amp/repository/mercurial/repositories/http_repository.rb +386 -0
  132. data/lib/amp/repository/mercurial/repositories/local_repository.rb +2034 -0
  133. data/lib/amp/repository/mercurial/repository.rb +119 -0
  134. data/lib/amp/repository/mercurial/revlogs/bundle_revlogs.rb +249 -0
  135. data/lib/amp/repository/mercurial/revlogs/changegroup.rb +217 -0
  136. data/lib/amp/repository/mercurial/revlogs/changelog.rb +339 -0
  137. data/lib/amp/repository/mercurial/revlogs/file_log.rb +152 -0
  138. data/lib/amp/repository/mercurial/revlogs/index.rb +500 -0
  139. data/lib/amp/repository/mercurial/revlogs/manifest.rb +201 -0
  140. data/lib/amp/repository/mercurial/revlogs/node.rb +20 -0
  141. data/lib/amp/repository/mercurial/revlogs/revlog.rb +1026 -0
  142. data/lib/amp/repository/mercurial/revlogs/revlog_support.rb +129 -0
  143. data/lib/amp/repository/mercurial/revlogs/versioned_file.rb +597 -0
  144. data/lib/amp/repository/repository.rb +11 -88
  145. data/lib/amp/server/extension/amp_extension.rb +3 -3
  146. data/lib/amp/server/fancy_http_server.rb +1 -1
  147. data/lib/amp/server/fancy_views/_browser.haml +1 -1
  148. data/lib/amp/server/fancy_views/_diff_file.haml +1 -8
  149. data/lib/amp/server/fancy_views/changeset.haml +2 -2
  150. data/lib/amp/server/fancy_views/file.haml +1 -1
  151. data/lib/amp/server/fancy_views/file_diff.haml +1 -1
  152. data/lib/amp/support/amp_ui.rb +13 -29
  153. data/lib/amp/support/generator.rb +1 -1
  154. data/lib/amp/support/loaders.rb +1 -2
  155. data/lib/amp/support/logger.rb +10 -16
  156. data/lib/amp/support/match.rb +18 -4
  157. data/lib/amp/support/mercurial/ignore.rb +151 -0
  158. data/lib/amp/support/openers.rb +8 -3
  159. data/lib/amp/support/support.rb +91 -46
  160. data/lib/amp/templates/{blank.commit.erb → mercurial/blank.commit.erb} +0 -0
  161. data/lib/amp/templates/{blank.log.erb → mercurial/blank.log.erb} +0 -0
  162. data/lib/amp/templates/{default.commit.erb → mercurial/default.commit.erb} +0 -0
  163. data/lib/amp/templates/{default.log.erb → mercurial/default.log.erb} +0 -0
  164. data/lib/amp/templates/template.rb +18 -18
  165. data/man/amp.1 +51 -0
  166. data/site/src/about/commands.haml +1 -1
  167. data/site/src/css/amp.css +1 -1
  168. data/site/src/index.haml +3 -3
  169. data/tasks/man.rake +39 -0
  170. data/tasks/stats.rake +1 -10
  171. data/tasks/yard.rake +1 -50
  172. data/test/dirstate_tests/test_dir_state.rb +10 -8
  173. data/test/functional_tests/annotate.out +31 -0
  174. data/test/functional_tests/test_functional.rb +155 -63
  175. data/test/localrepo_tests/ampfile.rb +12 -0
  176. data/test/localrepo_tests/test_local_repo.rb +56 -57
  177. data/test/manifest_tests/test_manifest.rb +3 -5
  178. data/test/merge_tests/test_merge.rb +3 -3
  179. data/test/revlog_tests/test_revlog.rb +14 -6
  180. data/test/store_tests/test_fncache_store.rb +19 -19
  181. data/test/test_19_compatibility.rb +46 -0
  182. data/test/test_base85.rb +2 -2
  183. data/test/test_bdiff.rb +2 -2
  184. data/test/test_changegroup.rb +59 -0
  185. data/test/test_commands.rb +2 -2
  186. data/test/test_difflib.rb +2 -2
  187. data/test/test_generator.rb +34 -0
  188. data/test/test_ignore.rb +203 -0
  189. data/test/test_journal.rb +18 -13
  190. data/test/test_match.rb +2 -2
  191. data/test/test_mdiff.rb +3 -3
  192. data/test/test_mpatch.rb +3 -3
  193. data/test/test_multi_io.rb +40 -0
  194. data/test/test_support.rb +18 -2
  195. data/test/test_templates.rb +38 -0
  196. data/test/test_ui.rb +79 -0
  197. data/test/testutilities.rb +56 -0
  198. metadata +168 -49
  199. data/ext/amp/bz2/mkmf.log +0 -38
  200. data/lib/amp/encoding/mercurial_diff.rb +0 -378
  201. data/lib/amp/encoding/mercurial_patch.rb +0 -1
  202. data/lib/amp/encoding/patch.rb +0 -292
  203. data/lib/amp/encoding/pure_ruby/ruby_mercurial_patch.rb +0 -123
  204. data/lib/amp/merges/merge_state.rb +0 -164
  205. data/lib/amp/merges/merge_ui.rb +0 -322
  206. data/lib/amp/merges/simple_merge.rb +0 -450
  207. data/lib/amp/repository/branch_manager.rb +0 -234
  208. data/lib/amp/repository/dir_state.rb +0 -950
  209. data/lib/amp/repository/journal.rb +0 -203
  210. data/lib/amp/repository/lock.rb +0 -207
  211. data/lib/amp/repository/repositories/bundle_repository.rb +0 -214
  212. data/lib/amp/repository/repositories/http_repository.rb +0 -377
  213. data/lib/amp/repository/repositories/local_repository.rb +0 -2661
  214. data/lib/amp/repository/store.rb +0 -485
  215. data/lib/amp/repository/tag_manager.rb +0 -319
  216. data/lib/amp/repository/updatable.rb +0 -532
  217. data/lib/amp/repository/verification.rb +0 -431
  218. data/lib/amp/repository/versioned_file.rb +0 -475
  219. data/lib/amp/revlogs/bundle_revlogs.rb +0 -246
  220. data/lib/amp/revlogs/changegroup.rb +0 -217
  221. data/lib/amp/revlogs/changelog.rb +0 -338
  222. data/lib/amp/revlogs/changeset.rb +0 -521
  223. data/lib/amp/revlogs/file_log.rb +0 -165
  224. data/lib/amp/revlogs/index.rb +0 -493
  225. data/lib/amp/revlogs/manifest.rb +0 -195
  226. data/lib/amp/revlogs/node.rb +0 -18
  227. data/lib/amp/revlogs/revlog.rb +0 -1045
  228. data/lib/amp/revlogs/revlog_support.rb +0 -126
  229. data/lib/amp/support/ignore.rb +0 -144
  230. data/site/Rakefile +0 -38
  231. data/test/test_amp.rb +0 -9
  232. data/test/test_helper.rb +0 -15
@@ -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('&#8617;', 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(/&/,'&amp;')
507
+ source = Text.normalize(source)
508
+ source = source.gsub(/\&apos;/,'&#39;') # IE bug
509
+ source = source.gsub(/'/,'&#39;') # 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(/\&apos;/,'&#39;') # IE bug
572
+ html = html.gsub(/'/,'&#39;') # IE bug
573
+ # html = html.gsub(/&/,'&amp;')
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(/&/,'&amp;')
633
+ s = Text.normalize(s)
634
+ s = s.gsub(/\&apos;/,'&#39;') # IE bug
635
+ s = s.gsub(/'/,'&#39;') # IE bug
636
+
637
+ if get_setting(:code_show_spaces)
638
+ # 187 = raquo
639
+ # 160 = nbsp
640
+ # 172 = not
641
+ s.gsub!(/\t/,'&#187;'+'&#160;'*3)
642
+ s.gsub!(/ /,'&#172;')
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