maruku 0.6.1 → 0.7.0.beta1

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.
Files changed (263) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/MIT-LICENSE.txt +20 -0
  5. data/bin/maruku +153 -152
  6. data/bin/marutex +2 -29
  7. data/data/entities.xml +261 -0
  8. data/docs/math.md +14 -18
  9. data/lib/maruku.rb +65 -77
  10. data/lib/maruku/attributes.rb +109 -214
  11. data/lib/maruku/defaults.rb +45 -67
  12. data/lib/maruku/document.rb +43 -0
  13. data/lib/maruku/element.rb +112 -0
  14. data/lib/maruku/errors.rb +71 -0
  15. data/lib/maruku/ext/div.rb +105 -113
  16. data/lib/maruku/ext/fenced_code.rb +97 -0
  17. data/lib/maruku/ext/math.rb +22 -26
  18. data/lib/maruku/ext/math/elements.rb +20 -26
  19. data/lib/maruku/ext/math/mathml_engines/blahtex.rb +92 -104
  20. data/lib/maruku/ext/math/mathml_engines/itex2mml.rb +33 -26
  21. data/lib/maruku/ext/math/mathml_engines/none.rb +11 -19
  22. data/lib/maruku/ext/math/mathml_engines/ritex.rb +2 -4
  23. data/lib/maruku/ext/math/parsing.rb +107 -113
  24. data/lib/maruku/ext/math/to_html.rb +184 -187
  25. data/lib/maruku/ext/math/to_latex.rb +30 -21
  26. data/lib/maruku/helpers.rb +158 -257
  27. data/lib/maruku/html.rb +254 -0
  28. data/lib/maruku/input/charsource.rb +272 -319
  29. data/lib/maruku/input/extensions.rb +62 -63
  30. data/lib/maruku/input/html_helper.rb +220 -189
  31. data/lib/maruku/input/linesource.rb +90 -110
  32. data/lib/maruku/input/mdline.rb +129 -0
  33. data/lib/maruku/input/parse_block.rb +618 -612
  34. data/lib/maruku/input/parse_doc.rb +145 -215
  35. data/lib/maruku/input/parse_span.rb +658 -0
  36. data/lib/maruku/input/rubypants.rb +200 -128
  37. data/lib/maruku/inspect_element.rb +60 -0
  38. data/lib/maruku/maruku.rb +10 -31
  39. data/lib/maruku/output/entity_table.rb +33 -0
  40. data/lib/maruku/output/s5/fancy.rb +462 -462
  41. data/lib/maruku/output/s5/to_s5.rb +115 -135
  42. data/lib/maruku/output/to_html.rb +898 -983
  43. data/lib/maruku/output/to_latex.rb +561 -560
  44. data/lib/maruku/output/to_markdown.rb +207 -162
  45. data/lib/maruku/output/to_s.rb +11 -52
  46. data/lib/maruku/string_utils.rb +129 -179
  47. data/lib/maruku/toc.rb +185 -196
  48. data/lib/maruku/version.rb +33 -38
  49. data/spec/block_docs/abbrev.md +776 -0
  50. data/{tests/unittest → spec/block_docs}/abbreviations.md +11 -20
  51. data/{tests/unittest → spec/block_docs}/alt.md +2 -14
  52. data/{tests/unittest/pending → spec/block_docs}/amps.md +1 -13
  53. data/{tests/unittest → spec/block_docs}/attributes/att2.md +0 -12
  54. data/{tests/unittest → spec/block_docs}/attributes/att3.md +2 -14
  55. data/{tests/unittest → spec/block_docs}/attributes/attributes.md +12 -16
  56. data/{tests/unittest → spec/block_docs}/attributes/circular.md +0 -12
  57. data/{tests/unittest → spec/block_docs}/attributes/default.md +1 -13
  58. data/{tests/unittest → spec/block_docs}/blank.md +0 -12
  59. data/{tests/unittest → spec/block_docs}/blanks_in_code.md +16 -15
  60. data/{tests/unittest/loss.md → spec/block_docs/bug_def.md} +6 -18
  61. data/{tests/unittest → spec/block_docs}/bug_table.md +3 -15
  62. data/{tests/unittest → spec/block_docs}/code.md +7 -14
  63. data/{tests/unittest → spec/block_docs}/code2.md +4 -14
  64. data/{tests/unittest → spec/block_docs}/code3.md +12 -16
  65. data/{tests/unittest → spec/block_docs}/data_loss.md +2 -14
  66. data/{tests/unittest → spec/block_docs}/divs/div1.md +0 -12
  67. data/{tests/unittest → spec/block_docs}/divs/div2.md +0 -12
  68. data/{tests/unittest → spec/block_docs}/divs/div3_nest.md +3 -15
  69. data/{tests/unittest → spec/block_docs}/easy.md +1 -13
  70. data/spec/block_docs/email.md +29 -0
  71. data/{tests/unittest/pending → spec/block_docs}/empty_cells.md +3 -15
  72. data/{tests/unittest → spec/block_docs}/encoding/iso-8859-1.md +1 -14
  73. data/{tests/unittest → spec/block_docs}/encoding/utf-8.md +0 -12
  74. data/{tests/unittest → spec/block_docs}/entities.md +27 -29
  75. data/{tests/unittest/notyet → spec/block_docs}/escape.md +2 -14
  76. data/{tests/unittest → spec/block_docs}/escaping.md +11 -22
  77. data/{tests/unittest → spec/block_docs}/extra_dl.md +2 -13
  78. data/{tests/unittest → spec/block_docs}/extra_header_id.md +14 -20
  79. data/{tests/unittest → spec/block_docs}/extra_table1.md +3 -15
  80. data/spec/block_docs/fenced_code_blocks.md +66 -0
  81. data/spec/block_docs/fenced_code_blocks_highlighted.md +18 -0
  82. data/{tests/unittest → spec/block_docs}/footnotes.md +12 -24
  83. data/spec/block_docs/footnotes2.md +78 -0
  84. data/spec/block_docs/hard.md +25 -0
  85. data/spec/block_docs/header_after_par.md +62 -0
  86. data/{tests/unittest → spec/block_docs}/headers.md +10 -18
  87. data/{tests/unittest → spec/block_docs}/hex_entities.md +7 -18
  88. data/{tests/unittest → spec/block_docs}/hrule.md +5 -12
  89. data/{tests/unittest → spec/block_docs}/html3.md +1 -13
  90. data/{tests/unittest → spec/block_docs}/html4.md +2 -14
  91. data/{tests/unittest → spec/block_docs}/html5.md +2 -14
  92. data/spec/block_docs/html_block_in_para.md +22 -0
  93. data/spec/block_docs/html_inline.md +25 -0
  94. data/spec/block_docs/html_trailing.md +31 -0
  95. data/spec/block_docs/ie.md +62 -0
  96. data/spec/block_docs/iframe.md +29 -0
  97. data/{tests/unittest → spec/block_docs}/images.md +22 -28
  98. data/{tests/unittest → spec/block_docs}/images2.md +7 -17
  99. data/{tests/unittest → spec/block_docs}/inline_html.md +37 -67
  100. data/{tests/unittest → spec/block_docs}/inline_html2.md +1 -13
  101. data/spec/block_docs/inline_html_beginning.md +10 -0
  102. data/spec/block_docs/issue20.md +9 -0
  103. data/spec/block_docs/issue26.md +22 -0
  104. data/spec/block_docs/issue29.md +9 -0
  105. data/spec/block_docs/issue30.md +30 -0
  106. data/spec/block_docs/issue31.md +25 -0
  107. data/spec/block_docs/issue40.md +40 -0
  108. data/spec/block_docs/issue64.md +55 -0
  109. data/spec/block_docs/issue67.md +19 -0
  110. data/spec/block_docs/issue70.md +11 -0
  111. data/spec/block_docs/issue72.md +17 -0
  112. data/spec/block_docs/issue74.md +38 -0
  113. data/spec/block_docs/issue79.md +15 -0
  114. data/spec/block_docs/issue83.md +13 -0
  115. data/spec/block_docs/issue85.md +25 -0
  116. data/spec/block_docs/issue88.md +19 -0
  117. data/spec/block_docs/issue89.md +12 -0
  118. data/spec/block_docs/issue90.md +38 -0
  119. data/{tests/unittest/pending → spec/block_docs}/link.md +21 -18
  120. data/{tests/unittest → spec/block_docs}/links.md +33 -32
  121. data/spec/block_docs/links2.md +21 -0
  122. data/{tests/unittest → spec/block_docs}/list1.md +0 -12
  123. data/{tests/unittest → spec/block_docs}/list12.md +2 -14
  124. data/{tests/unittest → spec/block_docs}/list2.md +2 -14
  125. data/spec/block_docs/list_multipara.md +42 -0
  126. data/{tests/unittest → spec/block_docs}/lists.md +28 -29
  127. data/{tests/unittest → spec/block_docs}/lists10.md +2 -14
  128. data/spec/block_docs/lists11.md +23 -0
  129. data/spec/block_docs/lists12.md +43 -0
  130. data/spec/block_docs/lists13.md +55 -0
  131. data/spec/block_docs/lists14.md +61 -0
  132. data/spec/block_docs/lists15.md +36 -0
  133. data/spec/block_docs/lists6.md +88 -0
  134. data/spec/block_docs/lists7b.md +58 -0
  135. data/spec/block_docs/lists9.md +53 -0
  136. data/{tests/unittest → spec/block_docs}/lists_after_paragraph.md +19 -25
  137. data/spec/block_docs/lists_blank.md +35 -0
  138. data/{tests/unittest/list3.md → spec/block_docs/lists_blockquote_code.md} +2 -14
  139. data/{tests/unittest/list4.md → spec/block_docs/lists_need_blank_line.md} +50 -21
  140. data/spec/block_docs/lists_nested.md +44 -0
  141. data/spec/block_docs/lists_nested_blankline.md +28 -0
  142. data/spec/block_docs/lists_nested_deep.md +43 -0
  143. data/{tests/unittest → spec/block_docs}/lists_ol.md +37 -54
  144. data/spec/block_docs/lists_paraindent.md +47 -0
  145. data/spec/block_docs/lists_tab.md +54 -0
  146. data/spec/block_docs/loss.md +17 -0
  147. data/spec/block_docs/math-blahtex/equations.md +30 -0
  148. data/spec/block_docs/math-blahtex/inline.md +48 -0
  149. data/spec/block_docs/math-blahtex/math2.md +45 -0
  150. data/spec/block_docs/math-blahtex/table.md +25 -0
  151. data/spec/block_docs/math/embedded_invalid_svg.md +79 -0
  152. data/spec/block_docs/math/embedded_svg.md +97 -0
  153. data/spec/block_docs/math/equations.md +44 -0
  154. data/{tests/unittest → spec/block_docs}/math/inline.md +7 -19
  155. data/spec/block_docs/math/math2.md +45 -0
  156. data/{tests/unittest → spec/block_docs}/math/notmath.md +0 -12
  157. data/spec/block_docs/math/raw_mathml.md +87 -0
  158. data/spec/block_docs/math/table.md +25 -0
  159. data/{tests/unittest → spec/block_docs}/math/table2.md +5 -17
  160. data/{tests/unittest → spec/block_docs}/misc_sw.md +181 -118
  161. data/{tests/unittest → spec/block_docs}/olist.md +6 -18
  162. data/{tests/unittest → spec/block_docs}/one.md +0 -12
  163. data/{tests/unittest → spec/block_docs}/paragraph.md +0 -12
  164. data/{tests/unittest → spec/block_docs}/paragraph_rules/dont_merge_ref.md +4 -12
  165. data/{tests/unittest → spec/block_docs}/paragraph_rules/tab_is_blank.md +0 -12
  166. data/{tests/unittest → spec/block_docs}/paragraphs.md +1 -13
  167. data/{tests/unittest → spec/block_docs}/recover/recover_links.md +4 -16
  168. data/{tests/unittest/pending/ref.md → spec/block_docs/ref_with_period.md} +7 -16
  169. data/spec/block_docs/ref_with_title.md +22 -0
  170. data/{tests/unittest → spec/block_docs}/references/long_example.md +16 -23
  171. data/{tests/unittest → spec/block_docs}/references/spaces_and_numbers.md +0 -12
  172. data/{tests/unittest → spec/block_docs}/smartypants.md +24 -31
  173. data/{tests/unittest → spec/block_docs}/syntax_hl.md +13 -17
  174. data/{tests/unittest → spec/block_docs}/table_attributes.md +2 -14
  175. data/spec/block_docs/tables.md +58 -0
  176. data/{tests/unittest → spec/block_docs}/test.md +1 -13
  177. data/{tests/unittest/notyet → spec/block_docs}/ticks.md +1 -13
  178. data/spec/block_docs/toc.md +87 -0
  179. data/{tests/unittest/notyet → spec/block_docs}/triggering.md +14 -25
  180. data/{tests/unittest → spec/block_docs}/underscore_in_words.md +0 -12
  181. data/{tests/unittest → spec/block_docs}/wrapping.md +4 -16
  182. data/spec/block_docs/xml.md +33 -0
  183. data/{tests/unittest → spec/block_docs}/xml2.md +0 -12
  184. data/spec/block_docs/xml3.md +24 -0
  185. data/{tests/unittest → spec/block_docs}/xml_instruction.md +9 -20
  186. data/spec/block_spec.rb +110 -0
  187. data/spec/cli_spec.rb +8 -0
  188. data/spec/span_spec.rb +256 -0
  189. data/spec/spec_helper.rb +2 -0
  190. data/spec/to_html_utf8_spec.rb +13 -0
  191. metadata +205 -243
  192. metadata.gz.sig +3 -0
  193. data/Rakefile +0 -48
  194. data/bin/marudown +0 -29
  195. data/bin/marutest +0 -345
  196. data/docs/changelog.md +0 -334
  197. data/lib/maruku/errors_management.rb +0 -92
  198. data/lib/maruku/ext/math/latex_fix.rb +0 -12
  199. data/lib/maruku/input/parse_span_better.rb +0 -746
  200. data/lib/maruku/input/type_detection.rb +0 -147
  201. data/lib/maruku/output/to_latex_entities.rb +0 -367
  202. data/lib/maruku/output/to_latex_strings.rb +0 -64
  203. data/lib/maruku/structures.rb +0 -167
  204. data/lib/maruku/structures_inspect.rb +0 -87
  205. data/lib/maruku/structures_iterators.rb +0 -61
  206. data/lib/maruku/tests/benchmark.rb +0 -82
  207. data/lib/maruku/tests/new_parser.rb +0 -373
  208. data/lib/maruku/tests/tests.rb +0 -136
  209. data/lib/maruku/usage/example1.rb +0 -33
  210. data/tests/bugs/code_in_links.md +0 -101
  211. data/tests/bugs/complex_escaping.md +0 -38
  212. data/tests/math/syntax.md +0 -46
  213. data/tests/math_usage/document.md +0 -13
  214. data/tests/others/abbreviations.md +0 -11
  215. data/tests/others/blank.md +0 -4
  216. data/tests/others/code.md +0 -5
  217. data/tests/others/code2.md +0 -8
  218. data/tests/others/code3.md +0 -16
  219. data/tests/others/email.md +0 -4
  220. data/tests/others/entities.md +0 -19
  221. data/tests/others/escaping.md +0 -16
  222. data/tests/others/extra_dl.md +0 -101
  223. data/tests/others/extra_header_id.md +0 -13
  224. data/tests/others/extra_table1.md +0 -40
  225. data/tests/others/footnotes.md +0 -17
  226. data/tests/others/headers.md +0 -10
  227. data/tests/others/hrule.md +0 -10
  228. data/tests/others/images.md +0 -20
  229. data/tests/others/inline_html.md +0 -42
  230. data/tests/others/links.md +0 -38
  231. data/tests/others/list1.md +0 -4
  232. data/tests/others/list2.md +0 -5
  233. data/tests/others/list3.md +0 -8
  234. data/tests/others/lists.md +0 -32
  235. data/tests/others/lists_after_paragraph.md +0 -44
  236. data/tests/others/lists_ol.md +0 -39
  237. data/tests/others/misc_sw.md +0 -105
  238. data/tests/others/one.md +0 -1
  239. data/tests/others/paragraphs.md +0 -13
  240. data/tests/others/sss06.md +0 -352
  241. data/tests/others/test.md +0 -4
  242. data/tests/s5/s5profiling.md +0 -48
  243. data/tests/unittest/bug_def.md +0 -28
  244. data/tests/unittest/email.md +0 -32
  245. data/tests/unittest/html2.md +0 -34
  246. data/tests/unittest/ie.md +0 -61
  247. data/tests/unittest/links2.md +0 -34
  248. data/tests/unittest/lists11.md +0 -28
  249. data/tests/unittest/lists6.md +0 -53
  250. data/tests/unittest/lists9.md +0 -76
  251. data/tests/unittest/math/equations.md +0 -86
  252. data/tests/unittest/math/math2.md +0 -57
  253. data/tests/unittest/math/table.md +0 -37
  254. data/tests/unittest/notyet/header_after_par.md +0 -70
  255. data/tests/unittest/red_tests/abbrev.md +0 -1388
  256. data/tests/unittest/red_tests/lists7.md +0 -68
  257. data/tests/unittest/red_tests/lists7b.md +0 -128
  258. data/tests/unittest/red_tests/lists8.md +0 -76
  259. data/tests/unittest/red_tests/xml.md +0 -70
  260. data/tests/unittest/xml3.md +0 -38
  261. data/tests/utf8-files/simple.md +0 -1
  262. data/unit_test_block.sh +0 -5
  263. data/unit_test_span.sh +0 -3
@@ -1,33 +1,13 @@
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
- # NOTA BENE:
23
- #
24
- # The following algorithm is a rip-off of RubyPants written by
25
- # Christian Neukirchen.
1
+ #
2
+ # NOTA BENE:
3
+ #
4
+ # The following algorithm is a rip-off of RubyPants written by
5
+ # Christian Neukirchen.
26
6
  #
27
7
  # RubyPants is a Ruby port of SmartyPants written by John Gruber.
28
8
  #
29
- # This file is distributed under the GPL, which I guess is compatible
30
- # with the terms of the RubyPants license.
9
+ # This file is distributed under the MIT license, which is compatible
10
+ # with the terms of the RubyPants license (3-clause BSD).
31
11
  #
32
12
  # -- Andrea Censi
33
13
 
@@ -51,39 +31,39 @@
51
31
  # [snip]
52
32
  #
53
33
  # == Authors
54
- #
34
+ #
55
35
  # John Gruber did all of the hard work of writing this software in
56
36
  # Perl for Movable Type and almost all of this useful documentation.
57
37
  # Chad Miller ported it to Python to use with Pyblosxom.
58
38
  #
59
39
  # Christian Neukirchen provided the Ruby port, as a general-purpose
60
40
  # library that follows the *Cloth API.
61
- #
41
+ #
62
42
  #
63
43
  # == Copyright and License
64
- #
44
+ #
65
45
  # === SmartyPants license:
66
- #
46
+ #
67
47
  # Copyright (c) 2003 John Gruber
68
48
  # (http://daringfireball.net)
69
49
  # All rights reserved.
70
- #
50
+ #
71
51
  # Redistribution and use in source and binary forms, with or without
72
52
  # modification, are permitted provided that the following conditions
73
53
  # are met:
74
- #
54
+ #
75
55
  # * Redistributions of source code must retain the above copyright
76
56
  # notice, this list of conditions and the following disclaimer.
77
- #
57
+ #
78
58
  # * Redistributions in binary form must reproduce the above copyright
79
59
  # notice, this list of conditions and the following disclaimer in
80
60
  # the documentation and/or other materials provided with the
81
61
  # distribution.
82
- #
62
+ #
83
63
  # * Neither the name "SmartyPants" nor the names of its contributors
84
64
  # may be used to endorse or promote products derived from this
85
65
  # software without specific prior written permission.
86
- #
66
+ #
87
67
  # This software is provided by the copyright holders and contributors
88
68
  # "as is" and any express or implied warranties, including, but not
89
69
  # limited to, the implied warranties of merchantability and fitness
@@ -96,23 +76,23 @@
96
76
  # liability, or tort (including negligence or otherwise) arising in
97
77
  # any way out of the use of this software, even if advised of the
98
78
  # possibility of such damage.
99
- #
79
+ #
100
80
  # === RubyPants license
101
- #
81
+ #
102
82
  # RubyPants is a derivative work of SmartyPants and smartypants.py.
103
- #
83
+ #
104
84
  # Redistribution and use in source and binary forms, with or without
105
85
  # modification, are permitted provided that the following conditions
106
86
  # are met:
107
- #
87
+ #
108
88
  # * Redistributions of source code must retain the above copyright
109
89
  # notice, this list of conditions and the following disclaimer.
110
- #
90
+ #
111
91
  # * Redistributions in binary form must reproduce the above copyright
112
92
  # notice, this list of conditions and the following disclaimer in
113
93
  # the documentation and/or other materials provided with the
114
94
  # distribution.
115
- #
95
+ #
116
96
  # This software is provided by the copyright holders and contributors
117
97
  # "as is" and any express or implied warranties, including, but not
118
98
  # limited to, the implied warranties of merchantability and fitness
@@ -125,7 +105,7 @@
125
105
  # liability, or tort (including negligence or otherwise) arising in
126
106
  # any way out of the use of this software, even if advised of the
127
107
  # possibility of such damage.
128
- #
108
+ #
129
109
  #
130
110
  # == Links
131
111
  #
@@ -137,89 +117,181 @@
137
117
  # Christian Neukirchen:: http://kronavita.de/chris
138
118
 
139
119
 
140
- module MaRuKu; module In; module Markdown; module SpanLevelParser
141
- Punct_class = '[!"#\$\%\'()*+,\-.\/:;<=>?\@\[\\\\\]\^_`{|}~]'
142
- Close_class = %![^\ \t\r\n\\[\{\(\-]!
143
-
144
- Rules = [
145
- [/---/, :mdash ],
146
- [/--/, :ndash ],
147
- ['...', :hellip ],
148
- ['. . .', :hellip ],
149
- ["``", :ldquo ],
150
- ["''", :rdquo ],
151
- [/<<\s/, [:laquo, :nbsp] ],
152
- [/\s>>/, [:nbsp, :raquo] ],
153
- [/<</, :laquo ],
154
- [/>>/, :raquo ],
155
-
156
- # def educate_single_backticks(str)
157
- # ["`", :lsquo]
158
- # ["'", :rsquo]
159
-
160
- # Special case if the very first character is a quote followed by
161
- # punctuation at a non-word-break. Close the quotes by brute
162
- # force:
163
- [/^'(?=#{Punct_class}\B)/, :rsquo],
164
- [/^"(?=#{Punct_class}\B)/, :rdquo],
165
- # Special case for double sets of quotes, e.g.:
166
- # <p>He said, "'Quoted' words in a larger quote."</p>
167
- [/"'(?=\w)/, [:ldquo, :lsquo] ],
168
- [/'"(?=\w)/, [:lsquo, :ldquo] ],
169
- # Special case for decade abbreviations (the '80s):
170
- [/'(?=\d\ds)/, :rsquo ],
171
- # Get most opening single quotes:
172
- [/(\s)'(?=\w)/, [:one, :lsquo] ],
173
- # Single closing quotes:
174
- [/(#{Close_class})'/, [:one, :rsquo]],
175
- [/'(\s|s\b|$)/, [:rsquo, :one]],
176
- # Any remaining single quotes should be opening ones:
177
- [/'/, :lsquo],
178
- # Get most opening double quotes:
179
- [/(\s)"(?=\w)/, [:one, :ldquo]],
180
- # Double closing quotes:
181
- [/(#{Close_class})"/, [:one, :rdquo]],
182
- [/"(\s|s\b|$)/, [:rdquo, :one]],
183
- # Any remaining quotes should be opening ones:
184
- [/"/, :ldquo]
185
- ].
186
- map{|reg, subst| # People should do the thinking, machines should do the work.
187
- reg = Regexp.new(Regexp.escape(reg)) if not reg.kind_of? Regexp
188
- subst = [subst] if not subst.kind_of?Array
189
- [reg, subst]}
190
-
191
- # note: input will be destroyed
192
- def apply_one_rule(reg, subst, input)
193
- output = []
194
- while first = input.shift
195
- if first.kind_of?(String) && (m = reg.match(first))
196
- output.push m. pre_match if m. pre_match.size > 0
197
- input.unshift m.post_match if m.post_match.size > 0
198
- subst.reverse.each do |x|
199
- input.unshift( x == :one ? m[1] : md_entity(x.to_s) ) end
200
- else
201
- output.push first
202
- end
203
- end
204
- return output
205
- end
206
-
207
- def educate(elements)
208
- Rules.each do |reg, subst|
209
- elements = apply_one_rule(reg, subst, elements)
210
- end
211
- # strips empty strings
212
- elements.delete_if {|x| x.kind_of?(String) && x.size == 0}
213
- final = []
214
- # join consecutive strings
215
- elements.each do |x|
216
- if x.kind_of?(String) && final.last.kind_of?(String)
217
- final.last << x
218
- else
219
- final << x
220
- end
221
- end
222
- return final
223
- end
120
+ module MaRuKu::In::Markdown::SpanLevelParser
121
+ Punct_class = '[!"#\$\%\'()*+,\-.\/:;<=>?\@\[\\\\\]\^_`{|}~]'
122
+ Close_class = "[^\ \t\r\n\\[\{\(\-]"
123
+
124
+ # A rule to apply a particular pattern (like double quotes)
125
+ # against a list of strings and MDElements, replacing that
126
+ # pattern with the smartypants version.
127
+ class Rule
128
+ # The pattern to search for
129
+ attr_accessor :pattern
130
+
131
+ # The replacement tokens (entities or other instructions)
132
+ attr_accessor :replacement
133
+
134
+ # This is a hack to allow us to build entities.
135
+ attr_accessor :doc
136
+
137
+ def initialize(pattern, replacement)
138
+ @pattern = pattern
139
+ @replacement = replacement
140
+ end
141
+
142
+ private
143
+
144
+ # Add something to the output array. If it's
145
+ # not a string (like an MDElement) just add it direcltly,
146
+ # otherwise attempt to add on to the last element in the
147
+ # output if it's a string.
148
+ def append_to_output(output, str)
149
+ if !str.kind_of?(String)
150
+ output << str
151
+ return
152
+ end
153
+ return if str.empty?
154
+ if output.last.kind_of?(String)
155
+ output.last << str
156
+ else
157
+ output << str
158
+ end
159
+ end
160
+ end
161
+
162
+ # Simple rule that says "Replace this pattern with these entities"
163
+ class ReplaceRule < Rule
164
+ # Replace all matches in the input at once with the
165
+ # same elements from "replacement".
166
+ def apply(first, input, output)
167
+ intersperse(first.split(pattern), replacement).each do |x|
168
+ append_to_output(output, x)
169
+ end
170
+ end
224
171
 
225
- end end end end
172
+ private
173
+
174
+ # Sort of like "join" - places the elements in "elem"
175
+ # between each adjacent element in the array.
176
+ def intersperse(ary, elem)
177
+ return ary if ary.length <= 1
178
+ h, *t = ary
179
+ t.inject([h]) do |r, e|
180
+ entities = elem.map do |el|
181
+ en = el.clone
182
+ en.doc = doc
183
+ en
184
+ end
185
+ r.concat entities
186
+ r << e
187
+ end
188
+ end
189
+ end
190
+
191
+ # A more complex rule that uses a capture group from the
192
+ # pattern in its replacement.
193
+ class CaptureRule < Rule
194
+ # One at a time, replace each match, including
195
+ # some part of the match, and put the rest back into
196
+ # input to be processed next.
197
+ def apply(first, input, output)
198
+ if pattern =~ first
199
+ m = Regexp.last_match
200
+ append_to_output(output, m.pre_match)
201
+ input.unshift m.post_match unless m.post_match.empty?
202
+ replacement.reverse_each do |sub|
203
+ if sub == :one
204
+ input.unshift m[1]
205
+ else
206
+ entity = sub.clone
207
+ sub.doc = doc
208
+ input.unshift entity
209
+ end
210
+ end
211
+ else
212
+ append_to_output(output, first)
213
+ end
214
+ end
215
+ end
216
+
217
+ # All the rules that will be applied (in order) to smarten the document.
218
+ Rules =
219
+ [
220
+ ['---', :mdash ],
221
+ ['--', :ndash ],
222
+ ['...', :hellip ],
223
+ ['. . .', :hellip ],
224
+ ["``", :ldquo ],
225
+ ["''", :rdquo ],
226
+ [/<<\s/, [:laquo, :nbsp] ],
227
+ [/\s>>/, [:nbsp, :raquo] ],
228
+ ['<<', :laquo ],
229
+ ['>>', :raquo ],
230
+
231
+ # Special case if the very first character is a quote followed by
232
+ # punctuation at a non-word-break. Close the quotes by brute
233
+ # force:
234
+ [/\A'(?=#{Punct_class}\B)/, :rsquo],
235
+ [/\A"(?=#{Punct_class}\B)/, :rdquo],
236
+ # Special case for double sets of quotes, e.g.:
237
+ # <p>He said, "'Quoted' words in a larger quote."</p>
238
+ [/"'(?=\w)/, [:ldquo, :lsquo] ],
239
+ [/'"(?=\w)/, [:lsquo, :ldquo] ],
240
+ # Special case for decade abbreviations (the '80s):
241
+ [/'(?=\d\ds)/, :rsquo ],
242
+ # Get most opening single quotes:
243
+ [/(\s)'(?=\w)/, [:one, :lsquo] ],
244
+ # Single closing quotes:
245
+ [/(#{Close_class})'/, [:one, :rsquo]],
246
+ [/'(\s|s\b|$)/, [:rsquo, :one]],
247
+ # Any remaining single quotes should be opening ones:
248
+ ["'", :lsquo],
249
+ # Get most opening double quotes:
250
+ [/(\s)"(?=\w)/, [:one, :ldquo]],
251
+ # Double closing quotes:
252
+ [/(#{Close_class})"/, [:one, :rdquo]],
253
+ [/"(\s|s\b|$)/, [:rdquo, :one]],
254
+ # Any remaining quotes should be opening ones:
255
+ ['"', :ldquo]
256
+ ].
257
+ map do |reg, subst| # People should do the thinking, machines should do the work.
258
+ captures = false
259
+ subst = Array(subst).map do |s|
260
+ if s == :one
261
+ captures = true
262
+ s
263
+ else
264
+ MaRuKu::MDElement.new(:entity, [], { :entity_name => s.to_s.freeze }, nil)
265
+ end
266
+ end.freeze
267
+
268
+ if captures
269
+ CaptureRule.new reg, subst
270
+ else
271
+ ReplaceRule.new reg, subst
272
+ end
273
+ end
274
+
275
+ # Fully apply a single rule to an entire array
276
+ # of elements.
277
+ # note: input will be modified in place
278
+ def apply_one_rule!(rule, input)
279
+ output = []
280
+ while first = input.shift
281
+ if first.kind_of?(String)
282
+ rule.doc = @doc
283
+ rule.apply(first, input, output)
284
+ else
285
+ output << first
286
+ end
287
+ end
288
+ output
289
+ end
290
+
291
+ # Transform elements to have SmartyPants punctuation.
292
+ def educate(elements)
293
+ Rules.inject(elements) do |elems, rule|
294
+ apply_one_rule!(rule, elems)
295
+ end
296
+ end
297
+ end
@@ -0,0 +1,60 @@
1
+ module MaRuKu
2
+ class MDElement
3
+ INSPECT_FORMS = {
4
+ :paragraph => ["par", :children],
5
+ :footnote_reference => ["foot_ref", :footnote_id],
6
+ :entity => ["entity", :entity_name],
7
+ :email_address => ["email", :email],
8
+ :inline_code => ["code", :raw_code],
9
+ :raw_html => ["html", :raw_html],
10
+ :emphasis => ["em", :children],
11
+ :strong => ["strong", :children],
12
+ :immediate_link => ["url", :url],
13
+ :image => ["image", :children, :ref_id],
14
+ :im_image => ["im_image", :children, :url, :title],
15
+ :link => ["link", :children, :ref_id],
16
+ :im_link => ["im_link", :children, :url, :title],
17
+ :ref_definition => ["ref_def", :ref_id, :url, :title],
18
+ :ial => ["ial", :ial],
19
+ :li => ["li", :children, :want_my_paragraph]
20
+ }
21
+
22
+ # Outputs the document AST as calls to document helpers.
23
+ # (this should be `eval`-able to get a copy of the original element).
24
+ def inspect
25
+ if INSPECT_FORMS.has_key? @node_type
26
+ name, *params = INSPECT_FORMS[@node_type]
27
+
28
+ params = params.map do |p|
29
+ if p == :children
30
+ children_inspect
31
+ else
32
+ send(p).inspect
33
+ end
34
+ end
35
+ params << @al.inspect if @al && !@al.empty?
36
+ else
37
+ name = 'el'
38
+ params = [self.node_type.inspect, children_inspect]
39
+ params << @meta_priv.inspect unless @meta_priv.empty? && self.al.empty?
40
+ params << self.al.inspect unless self.al.empty?
41
+ end
42
+
43
+ "md_#{name}(#{params.join(', ')})"
44
+ end
45
+
46
+ private
47
+
48
+ def children_inspect
49
+ kids = @children.map(&:inspect)
50
+ return kids.first if kids.size == 1
51
+
52
+ comma = kids.join(", ")
53
+ if comma.size < 70
54
+ "[#{comma}]"
55
+ else
56
+ "[\n\t#{kids.join(",\n\t")}\n]"
57
+ end
58
+ end
59
+ end
60
+ end