newstile 1.0.1

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 (405) hide show
  1. data/AUTHORS +1 -0
  2. data/CONTRIBUTERS +6 -0
  3. data/COPYING +24 -0
  4. data/ChangeLog +5489 -0
  5. data/GPL +674 -0
  6. data/README +31 -0
  7. data/Rakefile +342 -0
  8. data/VERSION +1 -0
  9. data/benchmark/benchmark.rb +34 -0
  10. data/benchmark/generate_data.rb +112 -0
  11. data/benchmark/historic-jruby-1.4.0.dat +7 -0
  12. data/benchmark/historic-ruby-1.8.6.dat +7 -0
  13. data/benchmark/historic-ruby-1.8.7.dat +7 -0
  14. data/benchmark/historic-ruby-1.9.1p243.dat +7 -0
  15. data/benchmark/historic-ruby-1.9.2dev.dat +7 -0
  16. data/benchmark/mdbasics.text +306 -0
  17. data/benchmark/mdsyntax.text +888 -0
  18. data/benchmark/static-jruby-1.4.0.dat +7 -0
  19. data/benchmark/static-ruby-1.8.6.dat +7 -0
  20. data/benchmark/static-ruby-1.8.7.dat +7 -0
  21. data/benchmark/static-ruby-1.9.1p243.dat +7 -0
  22. data/benchmark/static-ruby-1.9.2dev.dat +7 -0
  23. data/benchmark/testing.sh +9 -0
  24. data/benchmark/timing.sh +10 -0
  25. data/bin/newstile +82 -0
  26. data/data/newstile/document.html +18 -0
  27. data/data/newstile/document.latex +43 -0
  28. data/doc/default.scss.css +519 -0
  29. data/doc/default.template +80 -0
  30. data/doc/documentation.page +72 -0
  31. data/doc/index.page +96 -0
  32. data/doc/installation.page +90 -0
  33. data/doc/links.markdown +6 -0
  34. data/doc/news.feed +10 -0
  35. data/doc/news.page +28 -0
  36. data/doc/quickref.page +564 -0
  37. data/doc/syntax.page +1615 -0
  38. data/doc/tests.page +51 -0
  39. data/doc/virtual +2 -0
  40. data/lib/newstile.rb +23 -0
  41. data/lib/newstile/compatibility.rb +34 -0
  42. data/lib/newstile/converter.rb +43 -0
  43. data/lib/newstile/converter/base.rb +111 -0
  44. data/lib/newstile/converter/html.rb +405 -0
  45. data/lib/newstile/converter/latex.rb +577 -0
  46. data/lib/newstile/converter/markdown.rb +426 -0
  47. data/lib/newstile/converter/newstile.rb +426 -0
  48. data/lib/newstile/document.rb +168 -0
  49. data/lib/newstile/error.rb +27 -0
  50. data/lib/newstile/options.rb +296 -0
  51. data/lib/newstile/parser.rb +39 -0
  52. data/lib/newstile/parser/base.rb +94 -0
  53. data/lib/newstile/parser/html.rb +499 -0
  54. data/lib/newstile/parser/newstile.rb +325 -0
  55. data/lib/newstile/parser/newstile/abbreviation.rb +66 -0
  56. data/lib/newstile/parser/newstile/attribute_list.rb +111 -0
  57. data/lib/newstile/parser/newstile/autolink.rb +54 -0
  58. data/lib/newstile/parser/newstile/blank_line.rb +43 -0
  59. data/lib/newstile/parser/newstile/block_boundary.rb +46 -0
  60. data/lib/newstile/parser/newstile/blockquote.rb +63 -0
  61. data/lib/newstile/parser/newstile/codeblock.rb +60 -0
  62. data/lib/newstile/parser/newstile/codespan.rb +57 -0
  63. data/lib/newstile/parser/newstile/emphasis.rb +70 -0
  64. data/lib/newstile/parser/newstile/eob.rb +39 -0
  65. data/lib/newstile/parser/newstile/escaped_chars.rb +38 -0
  66. data/lib/newstile/parser/newstile/extension.rb +116 -0
  67. data/lib/newstile/parser/newstile/footnote.rb +74 -0
  68. data/lib/newstile/parser/newstile/header.rb +84 -0
  69. data/lib/newstile/parser/newstile/horizontal_rule.rb +39 -0
  70. data/lib/newstile/parser/newstile/html.rb +175 -0
  71. data/lib/newstile/parser/newstile/html_entity.rb +39 -0
  72. data/lib/newstile/parser/newstile/line_break.rb +38 -0
  73. data/lib/newstile/parser/newstile/link.rb +177 -0
  74. data/lib/newstile/parser/newstile/list.rb +239 -0
  75. data/lib/newstile/parser/newstile/math.rb +64 -0
  76. data/lib/newstile/parser/newstile/paragraph.rb +55 -0
  77. data/lib/newstile/parser/newstile/smart_quotes.rb +214 -0
  78. data/lib/newstile/parser/newstile/table.rb +134 -0
  79. data/lib/newstile/parser/newstile/typographic_symbol.rb +54 -0
  80. data/lib/newstile/utils.rb +37 -0
  81. data/lib/newstile/utils/entities.rb +336 -0
  82. data/lib/newstile/utils/html.rb +75 -0
  83. data/lib/newstile/utils/ordered_hash.rb +79 -0
  84. data/lib/newstile/version.rb +28 -0
  85. data/man/man1/newstile.1 +246 -0
  86. data/setup.rb +1585 -0
  87. data/test/run_tests.rb +59 -0
  88. data/test/test_files.rb +162 -0
  89. data/test/testcases/block/01_blank_line/spaces.html +1 -0
  90. data/test/testcases/block/01_blank_line/spaces.text +3 -0
  91. data/test/testcases/block/01_blank_line/tabs.html +1 -0
  92. data/test/testcases/block/01_blank_line/tabs.text +6 -0
  93. data/test/testcases/block/02_eob/beginning.html +1 -0
  94. data/test/testcases/block/02_eob/beginning.text +3 -0
  95. data/test/testcases/block/02_eob/end.html +1 -0
  96. data/test/testcases/block/02_eob/end.text +3 -0
  97. data/test/testcases/block/02_eob/middle.html +1 -0
  98. data/test/testcases/block/02_eob/middle.text +5 -0
  99. data/test/testcases/block/03_paragraph/indented.html +18 -0
  100. data/test/testcases/block/03_paragraph/indented.text +19 -0
  101. data/test/testcases/block/03_paragraph/no_newline_at_end.html +5 -0
  102. data/test/testcases/block/03_paragraph/no_newline_at_end.text +5 -0
  103. data/test/testcases/block/03_paragraph/one_para.html +1 -0
  104. data/test/testcases/block/03_paragraph/one_para.text +1 -0
  105. data/test/testcases/block/03_paragraph/two_para.html +4 -0
  106. data/test/testcases/block/03_paragraph/two_para.text +4 -0
  107. data/test/testcases/block/04_header/atx_header.html +37 -0
  108. data/test/testcases/block/04_header/atx_header.text +34 -0
  109. data/test/testcases/block/04_header/atx_header_no_newline_at_end.html +1 -0
  110. data/test/testcases/block/04_header/atx_header_no_newline_at_end.text +1 -0
  111. data/test/testcases/block/04_header/setext_header.html +30 -0
  112. data/test/testcases/block/04_header/setext_header.html.19 +30 -0
  113. data/test/testcases/block/04_header/setext_header.text +36 -0
  114. data/test/testcases/block/04_header/setext_header_no_newline_at_end.html +1 -0
  115. data/test/testcases/block/04_header/setext_header_no_newline_at_end.text +2 -0
  116. data/test/testcases/block/04_header/with_auto_id_prefix.html +3 -0
  117. data/test/testcases/block/04_header/with_auto_id_prefix.options +2 -0
  118. data/test/testcases/block/04_header/with_auto_id_prefix.text +3 -0
  119. data/test/testcases/block/04_header/with_auto_ids.html +17 -0
  120. data/test/testcases/block/04_header/with_auto_ids.options +1 -0
  121. data/test/testcases/block/04_header/with_auto_ids.text +19 -0
  122. data/test/testcases/block/05_blockquote/indented.html +25 -0
  123. data/test/testcases/block/05_blockquote/indented.text +14 -0
  124. data/test/testcases/block/05_blockquote/lazy.html +34 -0
  125. data/test/testcases/block/05_blockquote/lazy.text +20 -0
  126. data/test/testcases/block/05_blockquote/nested.html +10 -0
  127. data/test/testcases/block/05_blockquote/nested.text +6 -0
  128. data/test/testcases/block/05_blockquote/no_newline_at_end.html +4 -0
  129. data/test/testcases/block/05_blockquote/no_newline_at_end.text +2 -0
  130. data/test/testcases/block/05_blockquote/with_code_blocks.html +15 -0
  131. data/test/testcases/block/05_blockquote/with_code_blocks.text +11 -0
  132. data/test/testcases/block/06_codeblock/error.html +4 -0
  133. data/test/testcases/block/06_codeblock/error.text +4 -0
  134. data/test/testcases/block/06_codeblock/lazy.html +4 -0
  135. data/test/testcases/block/06_codeblock/lazy.text +5 -0
  136. data/test/testcases/block/06_codeblock/no_newline_at_end.html +2 -0
  137. data/test/testcases/block/06_codeblock/no_newline_at_end.text +1 -0
  138. data/test/testcases/block/06_codeblock/no_newline_at_end_1.html +2 -0
  139. data/test/testcases/block/06_codeblock/no_newline_at_end_1.text +2 -0
  140. data/test/testcases/block/06_codeblock/normal.html +13 -0
  141. data/test/testcases/block/06_codeblock/normal.text +10 -0
  142. data/test/testcases/block/06_codeblock/tilde_syntax.html +7 -0
  143. data/test/testcases/block/06_codeblock/tilde_syntax.text +9 -0
  144. data/test/testcases/block/06_codeblock/whitespace.html +3 -0
  145. data/test/testcases/block/06_codeblock/whitespace.text +3 -0
  146. data/test/testcases/block/06_codeblock/with_blank_line.html +13 -0
  147. data/test/testcases/block/06_codeblock/with_blank_line.text +12 -0
  148. data/test/testcases/block/06_codeblock/with_eob_marker.html +6 -0
  149. data/test/testcases/block/06_codeblock/with_eob_marker.text +5 -0
  150. data/test/testcases/block/06_codeblock/with_ial.html +6 -0
  151. data/test/testcases/block/06_codeblock/with_ial.text +5 -0
  152. data/test/testcases/block/07_horizontal_rule/error.html +7 -0
  153. data/test/testcases/block/07_horizontal_rule/error.html.19 +7 -0
  154. data/test/testcases/block/07_horizontal_rule/error.text +7 -0
  155. data/test/testcases/block/07_horizontal_rule/normal.html +17 -0
  156. data/test/testcases/block/07_horizontal_rule/normal.text +17 -0
  157. data/test/testcases/block/07_horizontal_rule/sepspaces.html +3 -0
  158. data/test/testcases/block/07_horizontal_rule/sepspaces.text +3 -0
  159. data/test/testcases/block/07_horizontal_rule/septabs.html +3 -0
  160. data/test/testcases/block/07_horizontal_rule/septabs.text +3 -0
  161. data/test/testcases/block/08_list/escaping.html +17 -0
  162. data/test/testcases/block/08_list/escaping.text +17 -0
  163. data/test/testcases/block/08_list/item_ial.html +7 -0
  164. data/test/testcases/block/08_list/item_ial.text +5 -0
  165. data/test/testcases/block/08_list/lazy.html +39 -0
  166. data/test/testcases/block/08_list/lazy.text +29 -0
  167. data/test/testcases/block/08_list/list_and_hr.html +9 -0
  168. data/test/testcases/block/08_list/list_and_hr.text +5 -0
  169. data/test/testcases/block/08_list/list_and_others.html +40 -0
  170. data/test/testcases/block/08_list/list_and_others.text +26 -0
  171. data/test/testcases/block/08_list/mixed.html +117 -0
  172. data/test/testcases/block/08_list/mixed.text +66 -0
  173. data/test/testcases/block/08_list/nested.html +17 -0
  174. data/test/testcases/block/08_list/nested.text +7 -0
  175. data/test/testcases/block/08_list/other_first_element.html +39 -0
  176. data/test/testcases/block/08_list/other_first_element.text +18 -0
  177. data/test/testcases/block/08_list/simple_ol.html +19 -0
  178. data/test/testcases/block/08_list/simple_ol.text +13 -0
  179. data/test/testcases/block/08_list/simple_ul.html +48 -0
  180. data/test/testcases/block/08_list/simple_ul.text +36 -0
  181. data/test/testcases/block/08_list/single_item.html +3 -0
  182. data/test/testcases/block/08_list/single_item.text +1 -0
  183. data/test/testcases/block/08_list/special_cases.html +55 -0
  184. data/test/testcases/block/08_list/special_cases.text +35 -0
  185. data/test/testcases/block/09_html/comment.html +18 -0
  186. data/test/testcases/block/09_html/comment.text +15 -0
  187. data/test/testcases/block/09_html/content_model/deflists.html +6 -0
  188. data/test/testcases/block/09_html/content_model/deflists.options +1 -0
  189. data/test/testcases/block/09_html/content_model/deflists.text +6 -0
  190. data/test/testcases/block/09_html/content_model/tables.html +14 -0
  191. data/test/testcases/block/09_html/content_model/tables.options +1 -0
  192. data/test/testcases/block/09_html/content_model/tables.text +14 -0
  193. data/test/testcases/block/09_html/html_and_codeblocks.html +15 -0
  194. data/test/testcases/block/09_html/html_and_codeblocks.options +1 -0
  195. data/test/testcases/block/09_html/html_and_codeblocks.text +13 -0
  196. data/test/testcases/block/09_html/html_to_native/code.html +10 -0
  197. data/test/testcases/block/09_html/html_to_native/code.text +9 -0
  198. data/test/testcases/block/09_html/html_to_native/comment.html +7 -0
  199. data/test/testcases/block/09_html/html_to_native/comment.text +8 -0
  200. data/test/testcases/block/09_html/html_to_native/emphasis.html +3 -0
  201. data/test/testcases/block/09_html/html_to_native/emphasis.text +3 -0
  202. data/test/testcases/block/09_html/html_to_native/entity.html +1 -0
  203. data/test/testcases/block/09_html/html_to_native/entity.text +1 -0
  204. data/test/testcases/block/09_html/html_to_native/header.html +6 -0
  205. data/test/testcases/block/09_html/html_to_native/header.options +2 -0
  206. data/test/testcases/block/09_html/html_to_native/header.text +6 -0
  207. data/test/testcases/block/09_html/html_to_native/list_dl.html +8 -0
  208. data/test/testcases/block/09_html/html_to_native/list_dl.text +8 -0
  209. data/test/testcases/block/09_html/html_to_native/list_ol.html +15 -0
  210. data/test/testcases/block/09_html/html_to_native/list_ol.text +17 -0
  211. data/test/testcases/block/09_html/html_to_native/list_ul.html +19 -0
  212. data/test/testcases/block/09_html/html_to_native/list_ul.text +22 -0
  213. data/test/testcases/block/09_html/html_to_native/options +1 -0
  214. data/test/testcases/block/09_html/html_to_native/paragraph.html +3 -0
  215. data/test/testcases/block/09_html/html_to_native/paragraph.text +4 -0
  216. data/test/testcases/block/09_html/html_to_native/table_normal.html +14 -0
  217. data/test/testcases/block/09_html/html_to_native/table_normal.text +12 -0
  218. data/test/testcases/block/09_html/html_to_native/table_simple.html +48 -0
  219. data/test/testcases/block/09_html/html_to_native/table_simple.text +56 -0
  220. data/test/testcases/block/09_html/html_to_native/typography.html +1 -0
  221. data/test/testcases/block/09_html/html_to_native/typography.html.19 +1 -0
  222. data/test/testcases/block/09_html/html_to_native/typography.text +1 -0
  223. data/test/testcases/block/09_html/invalid_html_1.html +5 -0
  224. data/test/testcases/block/09_html/invalid_html_1.text +5 -0
  225. data/test/testcases/block/09_html/invalid_html_2.html +5 -0
  226. data/test/testcases/block/09_html/invalid_html_2.text +5 -0
  227. data/test/testcases/block/09_html/markdown_attr.html +38 -0
  228. data/test/testcases/block/09_html/markdown_attr.text +38 -0
  229. data/test/testcases/block/09_html/not_parsed.html +24 -0
  230. data/test/testcases/block/09_html/not_parsed.text +24 -0
  231. data/test/testcases/block/09_html/parse_as_raw.html +30 -0
  232. data/test/testcases/block/09_html/parse_as_raw.options +1 -0
  233. data/test/testcases/block/09_html/parse_as_raw.text +29 -0
  234. data/test/testcases/block/09_html/parse_as_span.html +12 -0
  235. data/test/testcases/block/09_html/parse_as_span.options +1 -0
  236. data/test/testcases/block/09_html/parse_as_span.text +9 -0
  237. data/test/testcases/block/09_html/parse_block_html.html +21 -0
  238. data/test/testcases/block/09_html/parse_block_html.options +1 -0
  239. data/test/testcases/block/09_html/parse_block_html.text +17 -0
  240. data/test/testcases/block/09_html/processing_instruction.html +13 -0
  241. data/test/testcases/block/09_html/processing_instruction.text +12 -0
  242. data/test/testcases/block/09_html/simple.html +64 -0
  243. data/test/testcases/block/09_html/simple.html.19 +64 -0
  244. data/test/testcases/block/09_html/simple.options +1 -0
  245. data/test/testcases/block/09_html/simple.text +59 -0
  246. data/test/testcases/block/10_ald/simple.html +2 -0
  247. data/test/testcases/block/10_ald/simple.text +8 -0
  248. data/test/testcases/block/11_ial/auto_id_and_ial.html +1 -0
  249. data/test/testcases/block/11_ial/auto_id_and_ial.options +1 -0
  250. data/test/testcases/block/11_ial/auto_id_and_ial.text +2 -0
  251. data/test/testcases/block/11_ial/simple.html +25 -0
  252. data/test/testcases/block/11_ial/simple.text +34 -0
  253. data/test/testcases/block/12_extension/comment.html +8 -0
  254. data/test/testcases/block/12_extension/comment.text +12 -0
  255. data/test/testcases/block/12_extension/ignored.html +8 -0
  256. data/test/testcases/block/12_extension/ignored.text +8 -0
  257. data/test/testcases/block/12_extension/nomarkdown.html +10 -0
  258. data/test/testcases/block/12_extension/nomarkdown.kramdown +20 -0
  259. data/test/testcases/block/12_extension/nomarkdown.latex +13 -0
  260. data/test/testcases/block/12_extension/nomarkdown.text +21 -0
  261. data/test/testcases/block/12_extension/options.html +21 -0
  262. data/test/testcases/block/12_extension/options.text +21 -0
  263. data/test/testcases/block/12_extension/options2.html +10 -0
  264. data/test/testcases/block/12_extension/options2.text +5 -0
  265. data/test/testcases/block/12_extension/options3.html +7 -0
  266. data/test/testcases/block/12_extension/options3.text +7 -0
  267. data/test/testcases/block/13_definition_list/definition_at_beginning.html +1 -0
  268. data/test/testcases/block/13_definition_list/definition_at_beginning.text +1 -0
  269. data/test/testcases/block/13_definition_list/item_ial.html +12 -0
  270. data/test/testcases/block/13_definition_list/item_ial.text +8 -0
  271. data/test/testcases/block/13_definition_list/multiple_terms.html +13 -0
  272. data/test/testcases/block/13_definition_list/multiple_terms.text +10 -0
  273. data/test/testcases/block/13_definition_list/no_def_list.html +2 -0
  274. data/test/testcases/block/13_definition_list/no_def_list.text +2 -0
  275. data/test/testcases/block/13_definition_list/para_wrapping.html +10 -0
  276. data/test/testcases/block/13_definition_list/para_wrapping.text +6 -0
  277. data/test/testcases/block/13_definition_list/separated_by_eob.html +8 -0
  278. data/test/testcases/block/13_definition_list/separated_by_eob.text +5 -0
  279. data/test/testcases/block/13_definition_list/simple.html +8 -0
  280. data/test/testcases/block/13_definition_list/simple.text +7 -0
  281. data/test/testcases/block/13_definition_list/styled_terms.html +4 -0
  282. data/test/testcases/block/13_definition_list/styled_terms.text +2 -0
  283. data/test/testcases/block/13_definition_list/too_much_space.html +3 -0
  284. data/test/testcases/block/13_definition_list/too_much_space.text +4 -0
  285. data/test/testcases/block/13_definition_list/with_blocks.html +38 -0
  286. data/test/testcases/block/13_definition_list/with_blocks.text +24 -0
  287. data/test/testcases/block/14_table/errors.html +8 -0
  288. data/test/testcases/block/14_table/errors.text +9 -0
  289. data/test/testcases/block/14_table/footer.html +65 -0
  290. data/test/testcases/block/14_table/footer.text +25 -0
  291. data/test/testcases/block/14_table/header.html +103 -0
  292. data/test/testcases/block/14_table/header.text +32 -0
  293. data/test/testcases/block/14_table/no_table.html +3 -0
  294. data/test/testcases/block/14_table/no_table.text +3 -0
  295. data/test/testcases/block/14_table/simple.html +139 -0
  296. data/test/testcases/block/14_table/simple.text +38 -0
  297. data/test/testcases/block/15_math/normal.html +26 -0
  298. data/test/testcases/block/15_math/normal.text +28 -0
  299. data/test/testcases/block/16_toc/no_toc_depth.html +33 -0
  300. data/test/testcases/block/16_toc/no_toc_depth.options +1 -0
  301. data/test/testcases/block/16_toc/no_toc_depth.text +16 -0
  302. data/test/testcases/block/16_toc/toc_depth_2.html +24 -0
  303. data/test/testcases/block/16_toc/toc_depth_2.options +1 -0
  304. data/test/testcases/block/16_toc/toc_depth_2.text +16 -0
  305. data/test/testcases/encoding.html +46 -0
  306. data/test/testcases/encoding.text +28 -0
  307. data/test/testcases/span/01_link/empty.html +5 -0
  308. data/test/testcases/span/01_link/empty.text +5 -0
  309. data/test/testcases/span/01_link/image_in_a.html +5 -0
  310. data/test/testcases/span/01_link/image_in_a.text +5 -0
  311. data/test/testcases/span/01_link/imagelinks.html +14 -0
  312. data/test/testcases/span/01_link/imagelinks.text +16 -0
  313. data/test/testcases/span/01_link/inline.html +46 -0
  314. data/test/testcases/span/01_link/inline.html.19 +46 -0
  315. data/test/testcases/span/01_link/inline.text +48 -0
  316. data/test/testcases/span/01_link/link_defs.html +9 -0
  317. data/test/testcases/span/01_link/link_defs.text +26 -0
  318. data/test/testcases/span/01_link/links_with_angle_brackets.html +3 -0
  319. data/test/testcases/span/01_link/links_with_angle_brackets.text +3 -0
  320. data/test/testcases/span/01_link/reference.html +35 -0
  321. data/test/testcases/span/01_link/reference.html.19 +35 -0
  322. data/test/testcases/span/01_link/reference.text +47 -0
  323. data/test/testcases/span/02_emphasis/empty.html +3 -0
  324. data/test/testcases/span/02_emphasis/empty.text +3 -0
  325. data/test/testcases/span/02_emphasis/errors.html +9 -0
  326. data/test/testcases/span/02_emphasis/errors.text +9 -0
  327. data/test/testcases/span/02_emphasis/nesting.html +38 -0
  328. data/test/testcases/span/02_emphasis/nesting.text +33 -0
  329. data/test/testcases/span/02_emphasis/normal.html +46 -0
  330. data/test/testcases/span/02_emphasis/normal.text +46 -0
  331. data/test/testcases/span/03_codespan/empty.html +5 -0
  332. data/test/testcases/span/03_codespan/empty.text +5 -0
  333. data/test/testcases/span/03_codespan/errors.html +1 -0
  334. data/test/testcases/span/03_codespan/errors.text +1 -0
  335. data/test/testcases/span/03_codespan/highlighting.html +1 -0
  336. data/test/testcases/span/03_codespan/highlighting.text +1 -0
  337. data/test/testcases/span/03_codespan/normal.html +16 -0
  338. data/test/testcases/span/03_codespan/normal.text +16 -0
  339. data/test/testcases/span/04_footnote/definitions.html +17 -0
  340. data/test/testcases/span/04_footnote/definitions.latex +17 -0
  341. data/test/testcases/span/04_footnote/definitions.text +24 -0
  342. data/test/testcases/span/04_footnote/footnote_nr.html +12 -0
  343. data/test/testcases/span/04_footnote/footnote_nr.latex +2 -0
  344. data/test/testcases/span/04_footnote/footnote_nr.options +1 -0
  345. data/test/testcases/span/04_footnote/footnote_nr.text +4 -0
  346. data/test/testcases/span/04_footnote/markers.html +46 -0
  347. data/test/testcases/span/04_footnote/markers.latex +23 -0
  348. data/test/testcases/span/04_footnote/markers.text +26 -0
  349. data/test/testcases/span/05_html/across_lines.html +1 -0
  350. data/test/testcases/span/05_html/across_lines.text +2 -0
  351. data/test/testcases/span/05_html/invalid.html +1 -0
  352. data/test/testcases/span/05_html/invalid.text +1 -0
  353. data/test/testcases/span/05_html/link_with_mailto.html +1 -0
  354. data/test/testcases/span/05_html/link_with_mailto.text +1 -0
  355. data/test/testcases/span/05_html/markdown_attr.html +6 -0
  356. data/test/testcases/span/05_html/markdown_attr.text +6 -0
  357. data/test/testcases/span/05_html/normal.html +30 -0
  358. data/test/testcases/span/05_html/normal.text +30 -0
  359. data/test/testcases/span/abbreviations/abbrev.html +8 -0
  360. data/test/testcases/span/abbreviations/abbrev.text +15 -0
  361. data/test/testcases/span/abbreviations/abbrev_defs.html +2 -0
  362. data/test/testcases/span/abbreviations/abbrev_defs.text +5 -0
  363. data/test/testcases/span/autolinks/url_links.html +12 -0
  364. data/test/testcases/span/autolinks/url_links.text +12 -0
  365. data/test/testcases/span/escaped_chars/normal.html +43 -0
  366. data/test/testcases/span/escaped_chars/normal.text +43 -0
  367. data/test/testcases/span/extension/comment.html +6 -0
  368. data/test/testcases/span/extension/comment.text +6 -0
  369. data/test/testcases/span/extension/ignored.html +1 -0
  370. data/test/testcases/span/extension/ignored.text +1 -0
  371. data/test/testcases/span/extension/nomarkdown.html +1 -0
  372. data/test/testcases/span/extension/nomarkdown.text +1 -0
  373. data/test/testcases/span/extension/options.html +1 -0
  374. data/test/testcases/span/extension/options.text +1 -0
  375. data/test/testcases/span/ial/simple.html +6 -0
  376. data/test/testcases/span/ial/simple.text +6 -0
  377. data/test/testcases/span/line_breaks/normal.html +11 -0
  378. data/test/testcases/span/line_breaks/normal.latex +12 -0
  379. data/test/testcases/span/line_breaks/normal.text +11 -0
  380. data/test/testcases/span/math/normal.html +5 -0
  381. data/test/testcases/span/math/normal.text +5 -0
  382. data/test/testcases/span/text_substitutions/entities.html +4 -0
  383. data/test/testcases/span/text_substitutions/entities.options +1 -0
  384. data/test/testcases/span/text_substitutions/entities.text +4 -0
  385. data/test/testcases/span/text_substitutions/entities_as_char.html +1 -0
  386. data/test/testcases/span/text_substitutions/entities_as_char.html.19 +1 -0
  387. data/test/testcases/span/text_substitutions/entities_as_char.options +1 -0
  388. data/test/testcases/span/text_substitutions/entities_as_char.text +1 -0
  389. data/test/testcases/span/text_substitutions/entities_as_input.html +1 -0
  390. data/test/testcases/span/text_substitutions/entities_as_input.options +1 -0
  391. data/test/testcases/span/text_substitutions/entities_as_input.text +1 -0
  392. data/test/testcases/span/text_substitutions/entities_numeric.html +1 -0
  393. data/test/testcases/span/text_substitutions/entities_numeric.options +1 -0
  394. data/test/testcases/span/text_substitutions/entities_numeric.text +1 -0
  395. data/test/testcases/span/text_substitutions/entities_symbolic.html +1 -0
  396. data/test/testcases/span/text_substitutions/entities_symbolic.options +1 -0
  397. data/test/testcases/span/text_substitutions/entities_symbolic.text +1 -0
  398. data/test/testcases/span/text_substitutions/greaterthan.html +1 -0
  399. data/test/testcases/span/text_substitutions/greaterthan.text +1 -0
  400. data/test/testcases/span/text_substitutions/lowerthan.html +1 -0
  401. data/test/testcases/span/text_substitutions/lowerthan.text +1 -0
  402. data/test/testcases/span/text_substitutions/typography.html +18 -0
  403. data/test/testcases/span/text_substitutions/typography.html.19 +18 -0
  404. data/test/testcases/span/text_substitutions/typography.text +18 -0
  405. metadata +476 -0
@@ -0,0 +1,51 @@
1
+ ---
2
+ title: Tests and Benchmark
3
+ ---
4
+
5
+ # Tests
6
+
7
+ There exist several test suites for testing the correctness of a Markdown implementation. The
8
+ original [Markdown Test Suite] is the standard which one needs to test against. The [PHP Markdown
9
+ suite][MDTest] contains the original test suite and several more tests (some specifically geared
10
+ towards the extension of the PHP Markdown Extra package). I have used the latter test tool to
11
+ roughly verify that newstile is able to parse standard Markdown. However, since the syntax used by
12
+ newstile varies slightly from standard Markdown most of the tests fail - which is fine. When looking
13
+ at the differences one can see that the failures result from these differences.
14
+
15
+ Besides using the above mentioned test suite newstile comes with its own set of tests which is used
16
+ to verify that the implementation matches the newstile specification.
17
+
18
+ If you believe you have found a bug in the implementation, please follow these steps:
19
+
20
+ * Check the syntax page and see if the behaviour is not intended.
21
+
22
+ * If the behaviour is not intended and it seems that newstile should parse some text in another
23
+ fashion, please open a bug report and attach two files: one with the text and one with the HTML
24
+ conversion you think is correct.
25
+
26
+
27
+ # Benchmark
28
+
29
+ newstile comes with a small benchmark to test how fast it is in regard to four other Ruby Markdown
30
+ implementations: Maruku, BlueFeather, BlueCloth and RDiscount. The first two are written using only
31
+ Ruby, the latter two use the C discount library for the actual hard work (which makes them really
32
+ fast but they do not provide additional syntax elements). As one can see below, newstile is
33
+ currently (June 2010) ~4x faster than Maruku, ~9x faster than BlueFeather but ~30x slower than
34
+ BlueCloth and rdiscount:
35
+
36
+ <pre><code>
37
+ {execute_cmd: {command: "ruby -Ilib -rubygems benchmark/benchmark.rb", process_output: false, escape_html: true}}
38
+ </code>
39
+ </pre>
40
+
41
+ And here are some graphs which show the execution times of the various newstile releases on
42
+ different Ruby interpreters:
43
+
44
+ ![ruby 1.8.6]({relocatable: img/graph-ruby-1.8.6.png})
45
+ ![ruby 1.8.7]({relocatable: img/graph-ruby-1.8.7.png})
46
+ ![ruby 1.9.1p243]({relocatable: img/graph-ruby-1.9.1p243.png})
47
+ ![ruby 1.9.2dev]({relocatable: img/graph-ruby-1.9.2dev.png})
48
+ ![jruby 1.4.0]({relocatable: img/graph-jruby-1.4.0.png})
49
+
50
+ [Markdown Test Suite]: http://daringfireball.net/projects/downloads/MarkdownTest_1.0.zip
51
+ [MDTest]: http://www.michelf.com/docs/projets/mdtest-1.0.zip
@@ -0,0 +1,2 @@
1
+ rdoc/index.html:
2
+ title: API Documentation
@@ -0,0 +1,23 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ #--
4
+ # Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
5
+ #
6
+ # This file is part of newstile.
7
+ #
8
+ # newstile is free software: you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation, either version 3 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
20
+ #++
21
+ #
22
+
23
+ require 'newstile/document'
@@ -0,0 +1,34 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ #--
4
+ # Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
5
+ #
6
+ # This file is part of newstile.
7
+ #
8
+ # newstile is free software: you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation, either version 3 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
20
+ #++
21
+ #
22
+
23
+ # All the code in this file is backported from Ruby 1.8.7 sothat newstile works under 1.8.5
24
+
25
+ if RUBY_VERSION == '1.8.5'
26
+ require 'rexml/parsers/baseparser'
27
+ module REXML
28
+ module Parsers
29
+ class BaseParser
30
+ UNAME_STR= "(?:#{NCNAME_STR}:)?#{NCNAME_STR}"
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,43 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ #--
4
+ # Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
5
+ #
6
+ # This file is part of newstile.
7
+ #
8
+ # newstile is free software: you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation, either version 3 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
20
+ #++
21
+ #
22
+
23
+ module Newstile
24
+
25
+ # == Converter Module
26
+ #
27
+ # This module contains all available converters, i.e. classes that take a document and convert the
28
+ # document tree to a specific output format, normally a string. For example, the Html module
29
+ # converts the document tree into HTML.
30
+ #
31
+ # Converters use the Base class for common functionality (like applying a template to the output)-
32
+ # see its API documentation for how to create a converter class.
33
+ module Converter
34
+
35
+ autoload :Base, 'newstile/converter/base'
36
+ autoload :Html, 'newstile/converter/html'
37
+ autoload :Latex, 'newstile/converter/latex'
38
+ autoload :Newstile, 'newstile/converter/newstile'
39
+ autoload :Markdown, 'newstile/converter/markdown'
40
+
41
+ end
42
+
43
+ end
@@ -0,0 +1,111 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ #--
4
+ # Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
5
+ #
6
+ # This file is part of newstile.
7
+ #
8
+ # newstile is free software: you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation, either version 3 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
20
+ #++
21
+ #
22
+
23
+ require 'erb'
24
+
25
+ module Newstile
26
+
27
+ module Converter
28
+
29
+ # == Base class for converters
30
+ #
31
+ # This class serves as base class for all converters. It provides methods that can/should be
32
+ # used by all converters (like #generate_id) as well as common functionality that is
33
+ # automatically applied to the result (for example, embedding the output into a template).
34
+ #
35
+ # == Implementing a converter
36
+ #
37
+ # Implementing a new converter is rather easy: just create a new sub class from this class and
38
+ # put it in the Newstile::Converter module (the latter is only needed if auto-detection should
39
+ # work properly). Then you need to implement the #convert(tree) method which takes a document
40
+ # tree and should return the converted output.
41
+ #
42
+ # The document instance is automatically set as @doc in Base#initialize. Furthermore, the
43
+ # document instance provides a hash called `conversion_infos` that is also automatically cleared
44
+ # and can be used to store information about the conversion process.
45
+ #
46
+ # The actual transformation of the document tree can be done in any way. However, writing one
47
+ # method per tree element type is a straight forward way to do it - this is how the Html and
48
+ # Latex converters do the transformation.
49
+ class Base
50
+
51
+ # Initialize the converter with the given Newstile document +doc+.
52
+ def initialize(doc)
53
+ @doc = doc
54
+ @doc.conversion_infos.clear
55
+ end
56
+ private_class_method(:new, :allocate)
57
+
58
+ # Convert the Newstile document +doc+ to the output format implemented by a subclass.
59
+ #
60
+ # Initializes a new instance of the calling class and then calls the #convert method that must
61
+ # be implemented by each subclass. If the +template+ option is specified and non-empty, the
62
+ # result is rendered into the specified template.
63
+ def self.convert(doc)
64
+ result = new(doc).convert(doc.tree)
65
+ result = apply_template(doc, result) if !doc.options[:template].empty?
66
+ result
67
+ end
68
+
69
+ # Apply the template specified in the +doc+ options, using +body+ as the body string.
70
+ def self.apply_template(doc, body)
71
+ erb = ERB.new(get_template(doc.options[:template]))
72
+ obj = Object.new
73
+ obj.instance_variable_set(:@doc, doc)
74
+ obj.instance_variable_set(:@body, body)
75
+ erb.result(obj.instance_eval{binding})
76
+ end
77
+
78
+ # Return the template specified by +template+.
79
+ def self.get_template(template)
80
+ format_ext = '.' + self.name.split(/::/).last.downcase
81
+ shipped = File.join(::Newstile.data_dir, template + format_ext)
82
+ if File.exist?(template)
83
+ File.read(template)
84
+ elsif File.exist?(template + format_ext)
85
+ File.read(template + format_ext)
86
+ elsif File.exist?(shipped)
87
+ File.read(shipped)
88
+ else
89
+ raise "The specified template file #{template} does not exist"
90
+ end
91
+ end
92
+
93
+
94
+ # Generate an unique alpha-numeric ID from the the string +str+ for use as header ID.
95
+ def generate_id(str)
96
+ gen_id = str.gsub(/[^a-zA-Z0-9 -]/, '').gsub(/^[^a-zA-Z]*/, '').gsub(' ', '-').downcase
97
+ gen_id = 'section' if gen_id.length == 0
98
+ @used_ids ||= {}
99
+ if @used_ids.has_key?(gen_id)
100
+ gen_id += '-' + (@used_ids[gen_id] += 1).to_s
101
+ else
102
+ @used_ids[gen_id] = 0
103
+ end
104
+ @doc.options[:auto_id_prefix] + gen_id
105
+ end
106
+
107
+ end
108
+
109
+ end
110
+
111
+ end
@@ -0,0 +1,405 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ #--
4
+ # Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
5
+ #
6
+ # This file is part of newstile.
7
+ #
8
+ # newstile is free software: you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation, either version 3 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
20
+ #++
21
+ #
22
+
23
+ require 'rexml/parsers/baseparser'
24
+
25
+ module Newstile
26
+
27
+ module Converter
28
+
29
+ # Converts a Newstile::Document to HTML.
30
+ class Html < Base
31
+
32
+ include ::Newstile::Utils::HTML
33
+
34
+ # :stopdoc:
35
+
36
+ # Defines the amount of indentation used when nesting HTML tags.
37
+ INDENTATION = 2
38
+
39
+ begin
40
+ require 'coderay'
41
+
42
+ # Highlighting via coderay is available if this constant is +true+.
43
+ HIGHLIGHTING_AVAILABLE = true
44
+ rescue LoadError => e
45
+ HIGHLIGHTING_AVAILABLE = false
46
+ end
47
+
48
+ # Initialize the HTML converter with the given Newstile document +doc+.
49
+ def initialize(doc)
50
+ super
51
+ @footnote_counter = @footnote_start = @doc.options[:footnote_nr]
52
+ @footnotes = []
53
+ @toc = []
54
+ @toc_code = nil
55
+ end
56
+
57
+ def convert(el, indent = -INDENTATION, opts = {})
58
+ send("convert_#{el.type}", el, indent, opts)
59
+ end
60
+
61
+ def inner(el, indent, opts)
62
+ result = ''
63
+ indent += INDENTATION
64
+ el.children.each do |inner_el|
65
+ opts[:parent] = el
66
+ result << send("convert_#{inner_el.type}", inner_el, indent, opts)
67
+ end
68
+ result
69
+ end
70
+
71
+ def convert_blank(el, indent, opts)
72
+ "\n"
73
+ end
74
+
75
+ def convert_text(el, indent, opts)
76
+ escape_html(el.value, :text)
77
+ end
78
+
79
+ def convert_p(el, indent, opts)
80
+ if el.options[:transparent]
81
+ "#{inner(el, indent, opts)}"
82
+ else
83
+ "#{' '*indent}<p#{html_attributes(el)}>#{inner(el, indent, opts)}</p>\n"
84
+ end
85
+ end
86
+
87
+ def convert_codeblock(el, indent, opts)
88
+ el = Marshal.load(Marshal.dump(el)) # so that the original is not changed
89
+ lang = el.attr.delete('lang')
90
+ if lang && HIGHLIGHTING_AVAILABLE
91
+ opts = {:wrap => @doc.options[:coderay_wrap], :line_numbers => @doc.options[:coderay_line_numbers],
92
+ :line_number_start => @doc.options[:coderay_line_number_start], :tab_width => @doc.options[:coderay_tab_width],
93
+ :bold_every => @doc.options[:coderay_bold_every], :css => @doc.options[:coderay_css]}
94
+ result = CodeRay.scan(el.value, lang.to_sym).html(opts).chomp + "\n"
95
+ "#{' '*indent}<div#{html_attributes(el)}>#{result}#{' '*indent}</div>\n"
96
+ else
97
+ result = escape_html(el.value)
98
+ if el.attr['class'].to_s =~ /\bshow-whitespaces\b/
99
+ result.gsub!(/(?:(^[ \t]+)|([ \t]+$)|([ \t]+))/) do |m|
100
+ suffix = ($1 ? '-l' : ($2 ? '-r' : ''))
101
+ m.scan(/./).map do |c|
102
+ case c
103
+ when "\t" then "<span class=\"ws-tab#{suffix}\">\t</span>"
104
+ when " " then "<span class=\"ws-space#{suffix}\">&#8901;</span>"
105
+ end
106
+ end.join('')
107
+ end
108
+ end
109
+ "#{' '*indent}<pre#{html_attributes(el)}><code>#{result}#{result =~ /\n\Z/ ? '' : "\n"}</code></pre>\n"
110
+ end
111
+ end
112
+
113
+ def convert_blockquote(el, indent, opts)
114
+ "#{' '*indent}<blockquote#{html_attributes(el)}>\n#{inner(el, indent, opts)}#{' '*indent}</blockquote>\n"
115
+ end
116
+
117
+ def convert_summary(el, indent, opts)
118
+ "#{' '*indent}<p#{html_attributes(el)}><b>#{inner(el, indent, opts)}#{' '*indent}</b></p>\n"
119
+ end
120
+
121
+ def convert_header(el, indent, opts)
122
+ el = Marshal.load(Marshal.dump(el)) # so that the original is not changed
123
+ if @doc.options[:auto_ids] && !el.attr['id']
124
+ el.attr['id'] = generate_id(el.options[:raw_text])
125
+ end
126
+ @toc << [el.options[:level], el.attr['id'], el.children] if el.attr['id'] && within_toc_depth?(el)
127
+ "#{' '*indent}<h#{el.options[:level]}#{html_attributes(el)}>#{inner(el, indent, opts)}</h#{el.options[:level]}>\n"
128
+ end
129
+
130
+ def within_toc_depth?(el)
131
+ @doc.options[:toc_depth] <= 0 || el.options[:level] <= @doc.options[:toc_depth]
132
+ end
133
+
134
+ def convert_hr(el, indent, opts)
135
+ "#{' '*indent}<hr />\n"
136
+ end
137
+
138
+ def convert_ul(el, indent, opts)
139
+ if !@toc_code && (el.options[:ial][:refs].include?('toc') rescue nil) && (el.type == :ul || el.type == :ol)
140
+ @toc_code = [el.type, el.attr, (0..128).to_a.map{|a| rand(36).to_s(36)}.join]
141
+ @toc_code.last
142
+ else
143
+ "#{' '*indent}<#{el.type}#{html_attributes(el)}>\n#{inner(el, indent, opts)}#{' '*indent}</#{el.type}>\n"
144
+ end
145
+ end
146
+ alias :convert_ol :convert_ul
147
+ alias :convert_dl :convert_ul
148
+
149
+ def convert_li(el, indent, opts)
150
+ output = ' '*indent << "<#{el.type}" << html_attributes(el) << ">"
151
+ res = inner(el, indent, opts)
152
+ if el.children.empty? || (el.children.first.type == :p && el.children.first.options[:transparent])
153
+ output << res << (res =~ /\n\Z/ ? ' '*indent : '')
154
+ else
155
+ output << "\n" << res << ' '*indent
156
+ end
157
+ output << "</#{el.type}>\n"
158
+ end
159
+ alias :convert_dd :convert_li
160
+
161
+ def convert_dt(el, indent, opts)
162
+ "#{' '*indent}<dt#{html_attributes(el)}>#{inner(el, indent, opts)}</dt>\n"
163
+ end
164
+
165
+ HTML_TAGS_WITH_BODY=['div', 'script', 'iframe', 'textarea']
166
+
167
+ def convert_html_element(el, indent, opts)
168
+ parent = opts[:parent]
169
+ res = inner(el, indent, opts)
170
+ if el.options[:category] == :span
171
+ "<#{el.value}#{html_attributes(el)}" << (!res.empty? || HTML_TAGS_WITH_BODY.include?(el.value) ? ">#{res}</#{el.value}>" : " />")
172
+ else
173
+ output = ''
174
+ output << ' '*indent if parent.type != :html_element || parent.options[:parse_type] != :raw
175
+ output << "<#{el.value}#{html_attributes(el)}"
176
+ if !res.empty? && el.options[:parse_type] != :block
177
+ output << ">#{res}</#{el.value}>"
178
+ elsif !res.empty?
179
+ output << ">\n#{res.chomp}\n" << ' '*indent << "</#{el.value}>"
180
+ elsif HTML_TAGS_WITH_BODY.include?(el.value)
181
+ output << "></#{el.value}>"
182
+ else
183
+ output << " />"
184
+ end
185
+ output << "\n" if parent.type != :html_element || parent.options[:parse_type] != :raw
186
+ output
187
+ end
188
+ end
189
+
190
+ def convert_xml_comment(el, indent, opts)
191
+ if el.options[:category] == :block && (opts[:parent].type != :html_element || opts[:parent].options[:parse_type] != :raw)
192
+ ' '*indent + el.value + "\n"
193
+ else
194
+ el.value
195
+ end
196
+ end
197
+ alias :convert_xml_pi :convert_xml_comment
198
+ alias :convert_html_doctype :convert_xml_comment
199
+
200
+ def convert_table(el, indent, opts)
201
+ if el.options[:alignment].all? {|a| a == :default}
202
+ alignment = ''
203
+ else
204
+ alignment = el.options[:alignment].map do |a|
205
+ "#{' '*(indent + INDENTATION)}" + (a == :default ? "<col />" : "<col align=\"#{a}\" />") + "\n"
206
+ end.join('')
207
+ end
208
+ "#{' '*indent}<table#{html_attributes(el)}>\n#{alignment}#{inner(el, indent, opts)}#{' '*indent}</table>\n"
209
+ end
210
+
211
+ def convert_thead(el, indent, opts)
212
+ "#{' '*indent}<#{el.type}#{html_attributes(el)}>\n#{inner(el, indent, opts)}#{' '*indent}</#{el.type}>\n"
213
+ end
214
+ alias :convert_tbody :convert_thead
215
+ alias :convert_tfoot :convert_thead
216
+ alias :convert_tr :convert_thead
217
+
218
+ def convert_td(el, indent, opts)
219
+ res = inner(el, indent, opts)
220
+ "#{' '*indent}<#{el.type}#{html_attributes(el)}>#{res.empty? ? "&nbsp;" : res}</#{el.type}>\n"
221
+ end
222
+ alias :convert_th :convert_td
223
+
224
+ def convert_comment(el, indent, opts)
225
+ if el.options[:category] == :block
226
+ "#{' '*indent}<!-- #{el.value} -->\n"
227
+ else
228
+ "<!-- #{el.value} -->"
229
+ end
230
+ end
231
+
232
+ def convert_br(el, indent, opts)
233
+ "<br />"
234
+ end
235
+
236
+ def convert_a(el, indent, opts)
237
+ do_obfuscation = el.attr['href'] =~ /^mailto:/
238
+ if do_obfuscation
239
+ el = Marshal.load(Marshal.dump(el)) # so that the original is not changed
240
+ href = obfuscate(el.attr['href'].sub(/^mailto:/, ''))
241
+ mailto = obfuscate('mailto')
242
+ el.attr['href'] = "#{mailto}:#{href}"
243
+ end
244
+ res = inner(el, indent, opts)
245
+ res = obfuscate(res) if do_obfuscation
246
+ "<a#{html_attributes(el)}>#{res}</a>"
247
+ end
248
+
249
+ def convert_img(el, indent, opts)
250
+ "<img#{html_attributes(el)} />"
251
+ end
252
+
253
+ def convert_codespan(el, indent, opts)
254
+ el = Marshal.load(Marshal.dump(el)) # so that the original is not changed
255
+ lang = el.attr.delete('lang')
256
+ if lang && HIGHLIGHTING_AVAILABLE
257
+ result = CodeRay.scan(el.value, lang.to_sym).html(:wrap => :span, :css => @doc.options[:coderay_css]).chomp
258
+ "<code#{html_attributes(el)}>#{result}</code>"
259
+ else
260
+ "<code#{html_attributes(el)}>#{escape_html(el.value)}</code>"
261
+ end
262
+ end
263
+
264
+ def convert_footnote(el, indent, opts)
265
+ number = @footnote_counter
266
+ @footnote_counter += 1
267
+ @footnotes << [el.options[:name], @doc.parse_infos[:footnotes][el.options[:name]]]
268
+ "<sup id=\"fnref:#{el.options[:name]}\"><a href=\"#fn:#{el.options[:name]}\" rel=\"footnote\">#{number}</a></sup>"
269
+ end
270
+
271
+ def convert_raw(el, indent, opts)
272
+ if !el.options[:type] || el.options[:type].empty? || el.options[:type].include?('html')
273
+ el.value + (el.options[:category] == :block ? "\n" : '')
274
+ else
275
+ ''
276
+ end
277
+ end
278
+
279
+ def convert_em(el, indent, opts)
280
+ "<#{el.type}#{html_attributes(el)}>#{inner(el, indent, opts)}</#{el.type}>"
281
+ end
282
+ alias :convert_strong :convert_em
283
+
284
+ def convert_entity(el, indent, opts)
285
+ entity_to_str(el.value, el.options[:original])
286
+ end
287
+
288
+ TYPOGRAPHIC_SYMS = {
289
+ :mdash => [::Newstile::Utils::Entities.entity('mdash')],
290
+ :ndash => [::Newstile::Utils::Entities.entity('ndash')],
291
+ :hellip => [::Newstile::Utils::Entities.entity('hellip')],
292
+ :laquo_space => [::Newstile::Utils::Entities.entity('laquo'), ::Newstile::Utils::Entities.entity('nbsp')],
293
+ :raquo_space => [::Newstile::Utils::Entities.entity('nbsp'), ::Newstile::Utils::Entities.entity('raquo')],
294
+ :laquo => [::Newstile::Utils::Entities.entity('laquo')],
295
+ :raquo => [::Newstile::Utils::Entities.entity('raquo')],
296
+ :qdash => [::Newstile::Utils::Entities.entity('8213')],
297
+ :qdash_space => [::Newstile::Utils::Entities.entity('8213'), ::Newstile::Utils::Entities.entity('nbsp')]
298
+ }
299
+ def convert_typographic_sym(el, indent, opts)
300
+ TYPOGRAPHIC_SYMS[el.value].map {|e| entity_to_str(e)}.join('')
301
+ end
302
+
303
+ def convert_smart_quote(el, indent, opts)
304
+ entity_to_str(::Newstile::Utils::Entities.entity(el.value.to_s))
305
+ end
306
+
307
+ def convert_math(el, indent, opts)
308
+ el = Marshal.load(Marshal.dump(el)) # so that the original is not changed
309
+ el.attr['class'] ||= ''
310
+ el.attr['class'] += (el.attr['class'].empty? ? '' : ' ') + 'math'
311
+ type = 'span'
312
+ type = 'div' if el.options[:category] == :block
313
+ "<#{type}#{html_attributes(el)}>#{escape_html(el.value)}</#{type}>#{type == 'div' ? "\n" : ''}"
314
+ end
315
+
316
+ def convert_abbreviation(el, indent, opts)
317
+ title = @doc.parse_infos[:abbrev_defs][el.value]
318
+ title = nil if title.empty?
319
+ "<abbr#{title ? " title=\"#{title}\"" : ''}>#{el.value}</abbr>"
320
+ end
321
+
322
+ def convert_root(el, indent, opts)
323
+ result = inner(el, indent, opts)
324
+ result << footnote_content
325
+ if @toc_code
326
+ toc_tree = generate_toc_tree(@toc, @toc_code[0], @toc_code[1] || {})
327
+ text = if toc_tree.children.size > 0
328
+ convert(toc_tree, 0)
329
+ else
330
+ ''
331
+ end
332
+ result.sub!(/#{@toc_code.last}/, text)
333
+ end
334
+ result
335
+ end
336
+
337
+ def generate_toc_tree(toc, type, attr)
338
+ sections = Element.new(type, nil, attr)
339
+ sections.attr['id'] ||= 'markdown-toc'
340
+ stack = []
341
+ toc.each do |level, id, children|
342
+ li = Element.new(:li, nil, nil, {:level => level})
343
+ li.children << Element.new(:p, nil, nil, {:transparent => true})
344
+ a = Element.new(:a, nil, {'href' => "##{id}"})
345
+ a.children += children
346
+ li.children.last.children << a
347
+ li.children << Element.new(type)
348
+
349
+ success = false
350
+ while !success
351
+ if stack.empty?
352
+ sections.children << li
353
+ stack << li
354
+ success = true
355
+ elsif stack.last.options[:level] < li.options[:level]
356
+ stack.last.children.last.children << li
357
+ stack << li
358
+ success = true
359
+ else
360
+ item = stack.pop
361
+ item.children.pop unless item.children.last.children.size > 0
362
+ end
363
+ end
364
+ end
365
+ while !stack.empty?
366
+ item = stack.pop
367
+ item.children.pop unless item.children.last.children.size > 0
368
+ end
369
+ sections
370
+ end
371
+
372
+ # Helper method for obfuscating the +text+ by using HTML entities.
373
+ def obfuscate(text)
374
+ result = ""
375
+ text.each_byte do |b|
376
+ result += (b > 128 ? b.chr : "&#%03d;" % b)
377
+ end
378
+ result.force_encoding(text.encoding) if RUBY_VERSION >= '1.9'
379
+ result
380
+ end
381
+
382
+ # Return a HTML list with the footnote content for the used footnotes.
383
+ def footnote_content
384
+ ol = Element.new(:ol)
385
+ ol.attr['start'] = @footnote_start if @footnote_start != 1
386
+ @footnotes.each do |name, data|
387
+ li = Element.new(:li, nil, {'id' => "fn:#{name}"}, {:first_is_block => true})
388
+ li.children = Marshal.load(Marshal.dump(data[:content].children))
389
+ ol.children << li
390
+
391
+ ref = Element.new(:raw, "<a href=\"#fnref:#{name}\" rev=\"footnote\">&#8617;</a>")
392
+ if li.children.last.type == :p
393
+ para = li.children.last
394
+ else
395
+ li.children << (para = Element.new(:p))
396
+ end
397
+ para.children << ref
398
+ end
399
+ (ol.children.empty? ? '' : "<div class=\"footnotes\">\n#{convert(ol, 2)}</div>\n")
400
+ end
401
+
402
+ end
403
+
404
+ end
405
+ end