kramdown 0.14.2 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of kramdown might be problematic. Click here for more details.

Files changed (323) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTERS +63 -1
  3. data/COPYING +17 -11
  4. data/README.md +35 -14
  5. data/VERSION +1 -1
  6. data/bin/kramdown +92 -40
  7. data/data/kramdown/document.html +4 -0
  8. data/data/kramdown/document.latex +7 -0
  9. data/lib/kramdown.rb +3 -16
  10. data/lib/kramdown/converter.rb +42 -16
  11. data/lib/kramdown/converter/base.rb +102 -38
  12. data/lib/kramdown/converter/hash_ast.rb +38 -0
  13. data/lib/kramdown/converter/html.rb +232 -141
  14. data/lib/kramdown/converter/kramdown.rb +122 -104
  15. data/lib/kramdown/converter/latex.rb +95 -78
  16. data/lib/kramdown/converter/man.rb +300 -0
  17. data/lib/kramdown/converter/math_engine/mathjax.rb +32 -0
  18. data/lib/kramdown/converter/remove_html_tags.rb +8 -17
  19. data/lib/kramdown/converter/syntax_highlighter.rb +56 -0
  20. data/lib/kramdown/converter/syntax_highlighter/minted.rb +35 -0
  21. data/lib/kramdown/converter/syntax_highlighter/rouge.rb +85 -0
  22. data/lib/kramdown/converter/toc.rb +7 -20
  23. data/lib/kramdown/document.rb +30 -37
  24. data/lib/kramdown/element.rb +54 -27
  25. data/lib/kramdown/error.rb +3 -16
  26. data/lib/kramdown/options.rb +392 -247
  27. data/lib/kramdown/parser.rb +3 -16
  28. data/lib/kramdown/parser/base.rb +28 -33
  29. data/lib/kramdown/parser/html.rb +151 -119
  30. data/lib/kramdown/parser/kramdown.rb +87 -50
  31. data/lib/kramdown/parser/kramdown/abbreviation.rb +33 -27
  32. data/lib/kramdown/parser/kramdown/autolink.rb +7 -25
  33. data/lib/kramdown/parser/kramdown/blank_line.rb +6 -19
  34. data/lib/kramdown/parser/kramdown/block_boundary.rb +6 -18
  35. data/lib/kramdown/parser/kramdown/blockquote.rb +6 -19
  36. data/lib/kramdown/parser/kramdown/codeblock.rb +15 -24
  37. data/lib/kramdown/parser/kramdown/codespan.rb +20 -22
  38. data/lib/kramdown/parser/kramdown/emphasis.rb +15 -24
  39. data/lib/kramdown/parser/kramdown/eob.rb +3 -16
  40. data/lib/kramdown/parser/kramdown/escaped_chars.rb +3 -16
  41. data/lib/kramdown/parser/kramdown/extensions.rb +66 -56
  42. data/lib/kramdown/parser/kramdown/footnote.rb +21 -31
  43. data/lib/kramdown/parser/kramdown/header.rb +37 -37
  44. data/lib/kramdown/parser/kramdown/horizontal_rule.rb +5 -17
  45. data/lib/kramdown/parser/kramdown/html.rb +47 -56
  46. data/lib/kramdown/parser/kramdown/html_entity.rb +9 -19
  47. data/lib/kramdown/parser/kramdown/line_break.rb +4 -17
  48. data/lib/kramdown/parser/kramdown/link.rb +39 -38
  49. data/lib/kramdown/parser/kramdown/list.rb +124 -82
  50. data/lib/kramdown/parser/kramdown/math.rb +12 -24
  51. data/lib/kramdown/parser/kramdown/paragraph.rb +23 -24
  52. data/lib/kramdown/parser/kramdown/smart_quotes.rb +26 -66
  53. data/lib/kramdown/parser/kramdown/table.rb +41 -48
  54. data/lib/kramdown/parser/kramdown/typographic_symbol.rb +14 -22
  55. data/lib/kramdown/parser/markdown.rb +11 -23
  56. data/lib/kramdown/utils.rb +21 -18
  57. data/lib/kramdown/utils/configurable.rb +45 -0
  58. data/lib/kramdown/utils/entities.rb +287 -292
  59. data/lib/kramdown/utils/html.rb +27 -30
  60. data/lib/kramdown/utils/lru_cache.rb +41 -0
  61. data/lib/kramdown/utils/string_scanner.rb +81 -0
  62. data/lib/kramdown/utils/unidecoder.rb +50 -0
  63. data/lib/kramdown/version.rb +4 -17
  64. data/man/man1/kramdown.1 +340 -347
  65. data/test/run_tests.rb +7 -20
  66. data/test/test_files.rb +188 -100
  67. data/test/test_location.rb +216 -0
  68. data/test/test_string_scanner_kramdown.rb +27 -0
  69. data/test/testcases/block/03_paragraph/indented.html.gfm +18 -0
  70. data/test/testcases/block/03_paragraph/line_break_last_line.html +9 -0
  71. data/test/testcases/block/03_paragraph/line_break_last_line.text +9 -0
  72. data/test/testcases/block/03_paragraph/standalone_image.html +8 -0
  73. data/test/testcases/block/03_paragraph/standalone_image.text +6 -0
  74. data/test/testcases/block/03_paragraph/with_html_to_native.html +1 -0
  75. data/test/testcases/block/03_paragraph/with_html_to_native.options +1 -0
  76. data/test/testcases/block/03_paragraph/with_html_to_native.text +1 -0
  77. data/test/testcases/block/04_header/atx_header.html +15 -1
  78. data/test/testcases/block/04_header/atx_header.text +14 -1
  79. data/test/testcases/block/04_header/setext_header.html +3 -1
  80. data/test/testcases/block/04_header/setext_header.text +4 -1
  81. data/test/testcases/block/04_header/with_auto_id_stripping.html +1 -0
  82. data/test/testcases/block/04_header/with_auto_id_stripping.options +1 -0
  83. data/test/testcases/block/04_header/with_auto_id_stripping.text +1 -0
  84. data/test/testcases/block/04_header/with_auto_ids.html +2 -0
  85. data/test/testcases/block/04_header/with_auto_ids.options +1 -0
  86. data/test/testcases/block/04_header/with_auto_ids.text +2 -0
  87. data/test/testcases/block/06_codeblock/guess_lang_css_class.html +15 -0
  88. data/test/testcases/block/06_codeblock/guess_lang_css_class.options +2 -0
  89. data/test/testcases/block/06_codeblock/guess_lang_css_class.text +13 -0
  90. data/test/testcases/block/06_codeblock/highlighting-minted-with-opts.latex +9 -0
  91. data/test/testcases/block/06_codeblock/highlighting-minted-with-opts.options +4 -0
  92. data/test/testcases/block/06_codeblock/highlighting-minted-with-opts.text +5 -0
  93. data/test/testcases/block/06_codeblock/highlighting-minted.latex +8 -0
  94. data/test/testcases/block/06_codeblock/highlighting-minted.options +3 -0
  95. data/test/testcases/block/06_codeblock/highlighting-minted.text +4 -0
  96. data/test/testcases/block/06_codeblock/highlighting-opts.html +6 -0
  97. data/test/testcases/block/06_codeblock/highlighting-opts.options +7 -0
  98. data/test/testcases/block/06_codeblock/highlighting-opts.text +4 -0
  99. data/test/testcases/block/06_codeblock/highlighting.html +5 -6
  100. data/test/testcases/block/06_codeblock/issue_gh45.html +164 -0
  101. data/test/testcases/block/06_codeblock/issue_gh45.test +188 -0
  102. data/test/testcases/block/06_codeblock/rouge/disabled.html +2 -0
  103. data/test/testcases/block/06_codeblock/rouge/disabled.options +4 -0
  104. data/test/testcases/block/06_codeblock/rouge/disabled.text +1 -0
  105. data/test/testcases/block/06_codeblock/rouge/multiple.html +11 -0
  106. data/test/testcases/block/06_codeblock/rouge/multiple.options +4 -0
  107. data/test/testcases/block/06_codeblock/rouge/multiple.text +11 -0
  108. data/test/testcases/block/06_codeblock/rouge/simple.html +10 -0
  109. data/test/testcases/block/06_codeblock/rouge/simple.options +3 -0
  110. data/test/testcases/block/06_codeblock/rouge/simple.text +9 -0
  111. data/test/testcases/block/06_codeblock/with_lang_in_fenced_block.options +1 -1
  112. data/test/testcases/block/06_codeblock/with_lang_in_fenced_block_any_char.html +8 -0
  113. data/test/testcases/block/06_codeblock/with_lang_in_fenced_block_any_char.options +2 -0
  114. data/test/testcases/block/06_codeblock/with_lang_in_fenced_block_any_char.text +11 -0
  115. data/test/testcases/block/06_codeblock/with_lang_in_fenced_block_name_with_dash.html +3 -0
  116. data/test/testcases/block/06_codeblock/with_lang_in_fenced_block_name_with_dash.options +2 -0
  117. data/test/testcases/block/06_codeblock/with_lang_in_fenced_block_name_with_dash.text +4 -0
  118. data/test/testcases/block/07_horizontal_rule/error.html +2 -2
  119. data/test/testcases/block/07_horizontal_rule/normal.html +2 -0
  120. data/test/testcases/block/07_horizontal_rule/normal.text +3 -0
  121. data/test/testcases/block/08_list/brackets_in_item.latex +3 -0
  122. data/test/testcases/block/08_list/brackets_in_item.text +1 -0
  123. data/test/testcases/block/08_list/lazy_and_nested.html +9 -0
  124. data/test/testcases/block/08_list/lazy_and_nested.text +4 -0
  125. data/test/testcases/block/09_html/html5_attributes.html +2 -0
  126. data/test/testcases/block/09_html/html5_attributes.text +2 -0
  127. data/test/testcases/block/09_html/html_after_block.html +7 -0
  128. data/test/testcases/block/09_html/html_after_block.text +5 -0
  129. data/test/testcases/block/09_html/html_to_native/table_simple.html +13 -0
  130. data/test/testcases/block/09_html/html_to_native/table_simple.text +15 -0
  131. data/test/testcases/block/09_html/html_to_native/typography.html +1 -1
  132. data/test/testcases/block/09_html/not_parsed.html +1 -1
  133. data/test/testcases/block/09_html/processing_instruction.html +5 -6
  134. data/test/testcases/block/09_html/simple.html +1 -5
  135. data/test/testcases/block/09_html/simple.text +1 -5
  136. data/test/testcases/block/09_html/standalone_image_in_div.htmlinput +7 -0
  137. data/test/testcases/block/09_html/standalone_image_in_div.text +8 -0
  138. data/test/testcases/block/09_html/textarea.html +8 -0
  139. data/test/testcases/block/09_html/textarea.text +8 -0
  140. data/test/testcases/block/09_html/xml.html +8 -0
  141. data/test/testcases/block/09_html/xml.text +7 -0
  142. data/test/testcases/block/11_ial/simple.html +5 -1
  143. data/test/testcases/block/11_ial/simple.text +8 -1
  144. data/test/testcases/block/12_extension/options.html +4 -4
  145. data/test/testcases/block/12_extension/options.text +2 -0
  146. data/test/testcases/block/12_extension/options2.html +4 -4
  147. data/test/testcases/block/12_extension/options3.html +7 -6
  148. data/test/testcases/block/12_extension/options3.text +2 -2
  149. data/test/testcases/block/13_definition_list/auto_ids.html +15 -0
  150. data/test/testcases/block/13_definition_list/auto_ids.text +18 -0
  151. data/test/testcases/block/13_definition_list/item_ial.html +5 -0
  152. data/test/testcases/block/13_definition_list/item_ial.text +8 -0
  153. data/test/testcases/block/14_table/empty_tag_in_cell.html +8 -0
  154. data/test/testcases/block/14_table/empty_tag_in_cell.options +1 -0
  155. data/test/testcases/block/14_table/empty_tag_in_cell.text +1 -0
  156. data/test/testcases/block/14_table/errors.html +4 -0
  157. data/test/testcases/block/14_table/errors.text +4 -0
  158. data/test/testcases/block/14_table/header.html +21 -0
  159. data/test/testcases/block/14_table/header.text +7 -0
  160. data/test/testcases/block/14_table/simple.html +22 -7
  161. data/test/testcases/block/14_table/simple.text +4 -0
  162. data/test/testcases/block/14_table/table_with_footnote.html +4 -4
  163. data/test/testcases/block/15_math/gh_128.html +1 -0
  164. data/test/testcases/block/15_math/gh_128.text +1 -0
  165. data/test/testcases/block/15_math/no_engine.html +3 -0
  166. data/test/testcases/block/15_math/no_engine.options +1 -0
  167. data/test/testcases/block/15_math/no_engine.text +2 -0
  168. data/test/testcases/block/15_math/normal.html +17 -14
  169. data/test/testcases/block/15_math/normal.text +2 -0
  170. data/test/testcases/block/16_toc/toc_exclude.html +7 -7
  171. data/test/testcases/block/16_toc/toc_levels.html +5 -5
  172. data/test/testcases/block/16_toc/toc_levels.text +1 -1
  173. data/test/testcases/block/16_toc/toc_with_footnotes.html +5 -5
  174. data/test/testcases/block/16_toc/toc_with_links.html +8 -0
  175. data/test/testcases/block/16_toc/toc_with_links.options +2 -0
  176. data/test/testcases/block/16_toc/toc_with_links.text +8 -0
  177. data/test/testcases/cjk-line-break.html +4 -0
  178. data/test/testcases/cjk-line-break.options +1 -0
  179. data/test/testcases/cjk-line-break.text +12 -0
  180. data/test/testcases/man/example.man +123 -0
  181. data/test/testcases/man/example.text +85 -0
  182. data/test/testcases/man/heading-name-dash-description.man +4 -0
  183. data/test/testcases/man/heading-name-dash-description.text +1 -0
  184. data/test/testcases/man/heading-name-description.man +4 -0
  185. data/test/testcases/man/heading-name-description.text +2 -0
  186. data/test/testcases/man/heading-name-section-description.man +4 -0
  187. data/test/testcases/man/heading-name-section-description.text +1 -0
  188. data/test/testcases/man/heading-name-section.man +2 -0
  189. data/test/testcases/man/heading-name-section.text +1 -0
  190. data/test/testcases/man/heading-name.man +2 -0
  191. data/test/testcases/man/heading-name.text +1 -0
  192. data/test/testcases/man/sections.man +4 -0
  193. data/test/testcases/man/sections.text +11 -0
  194. data/test/testcases/man/text-escaping.man +8 -0
  195. data/test/testcases/man/text-escaping.text +7 -0
  196. data/test/testcases/span/01_link/empty.html +1 -1
  197. data/test/testcases/span/01_link/empty_title.htmlinput +3 -0
  198. data/test/testcases/span/01_link/empty_title.text +7 -0
  199. data/test/testcases/span/01_link/imagelinks.html +1 -0
  200. data/test/testcases/span/01_link/imagelinks.text +2 -0
  201. data/test/testcases/span/01_link/inline.html +1 -1
  202. data/test/testcases/span/01_link/latex_escaping.latex +6 -0
  203. data/test/testcases/span/01_link/latex_escaping.text +5 -0
  204. data/test/testcases/span/01_link/link_defs.html +1 -1
  205. data/test/testcases/span/01_link/link_defs.text +2 -1
  206. data/test/testcases/span/01_link/link_defs_with_ial.html +4 -0
  207. data/test/testcases/span/01_link/link_defs_with_ial.text +16 -0
  208. data/test/testcases/span/01_link/reference.html +3 -3
  209. data/test/testcases/span/02_emphasis/nesting.html +3 -0
  210. data/test/testcases/span/02_emphasis/nesting.text +4 -1
  211. data/test/testcases/span/02_emphasis/normal.html +19 -0
  212. data/test/testcases/span/02_emphasis/normal.options +1 -0
  213. data/test/testcases/span/02_emphasis/normal.text +17 -0
  214. data/test/testcases/span/03_codespan/highlighting-minted.latex +2 -0
  215. data/test/testcases/span/03_codespan/highlighting-minted.options +1 -0
  216. data/test/testcases/span/03_codespan/highlighting-minted.text +1 -0
  217. data/test/testcases/span/03_codespan/highlighting.html +1 -1
  218. data/test/testcases/span/03_codespan/normal-css-class.html +1 -0
  219. data/test/testcases/span/03_codespan/normal-css-class.options +2 -0
  220. data/test/testcases/span/03_codespan/normal-css-class.text +1 -0
  221. data/test/testcases/span/03_codespan/rouge/disabled.html +1 -0
  222. data/test/testcases/span/03_codespan/rouge/disabled.options +4 -0
  223. data/test/testcases/span/03_codespan/rouge/disabled.text +1 -0
  224. data/test/testcases/span/03_codespan/rouge/simple.html +1 -0
  225. data/test/testcases/span/03_codespan/rouge/simple.options +1 -0
  226. data/test/testcases/span/03_codespan/rouge/simple.text +1 -0
  227. data/test/testcases/span/04_footnote/backlink_inline.html +79 -0
  228. data/test/testcases/span/04_footnote/backlink_inline.options +1 -0
  229. data/test/testcases/span/04_footnote/backlink_inline.text +38 -0
  230. data/test/testcases/span/04_footnote/backlink_text.html +9 -0
  231. data/test/testcases/span/04_footnote/backlink_text.options +1 -0
  232. data/test/testcases/span/04_footnote/backlink_text.text +3 -0
  233. data/test/testcases/span/04_footnote/definitions.latex +2 -2
  234. data/test/testcases/span/04_footnote/footnote_nr.html +6 -6
  235. data/test/testcases/span/04_footnote/footnote_prefix.html +12 -0
  236. data/test/testcases/span/04_footnote/footnote_prefix.options +1 -0
  237. data/test/testcases/span/04_footnote/footnote_prefix.text +4 -0
  238. data/test/testcases/span/04_footnote/inside_footnote.html +17 -0
  239. data/test/testcases/span/04_footnote/inside_footnote.text +9 -0
  240. data/test/testcases/span/04_footnote/markers.html +16 -16
  241. data/test/testcases/span/04_footnote/markers.latex +3 -3
  242. data/test/testcases/span/04_footnote/markers.options +2 -0
  243. data/test/testcases/span/04_footnote/markers.text +2 -1
  244. data/test/testcases/span/04_footnote/placement.html +11 -0
  245. data/test/testcases/span/04_footnote/placement.options +1 -0
  246. data/test/testcases/span/04_footnote/placement.text +8 -0
  247. data/test/testcases/span/04_footnote/regexp_problem.html +14 -0
  248. data/test/testcases/span/04_footnote/regexp_problem.options +2 -0
  249. data/test/testcases/span/04_footnote/regexp_problem.text +52 -0
  250. data/test/testcases/span/04_footnote/without_backlink.html +9 -0
  251. data/test/testcases/span/04_footnote/without_backlink.options +1 -0
  252. data/test/testcases/span/04_footnote/without_backlink.text +3 -0
  253. data/test/testcases/span/05_html/button.html +7 -0
  254. data/test/testcases/span/05_html/button.text +7 -0
  255. data/test/testcases/span/05_html/mark_element.html +3 -0
  256. data/test/testcases/span/05_html/mark_element.text +3 -0
  257. data/test/testcases/span/05_html/normal.html +10 -1
  258. data/test/testcases/span/05_html/normal.text +9 -0
  259. data/test/testcases/span/05_html/raw_span_elements.html +2 -0
  260. data/test/testcases/span/05_html/raw_span_elements.text +2 -0
  261. data/test/testcases/span/05_html/xml.html +5 -0
  262. data/test/testcases/span/05_html/xml.text +5 -0
  263. data/test/testcases/span/abbreviations/abbrev.html +14 -1
  264. data/test/testcases/span/abbreviations/abbrev.text +18 -2
  265. data/test/testcases/span/abbreviations/in_footnote.html +9 -0
  266. data/test/testcases/span/abbreviations/in_footnote.text +5 -0
  267. data/test/testcases/span/autolinks/url_links.html +5 -4
  268. data/test/testcases/span/autolinks/url_links.text +1 -0
  269. data/test/testcases/span/line_breaks/normal.html +2 -2
  270. data/test/testcases/span/line_breaks/normal.latex +2 -2
  271. data/test/testcases/span/math/no_engine.html +1 -0
  272. data/test/testcases/span/math/no_engine.options +1 -0
  273. data/test/testcases/span/math/no_engine.text +1 -0
  274. data/test/testcases/span/math/normal.html +4 -3
  275. data/test/testcases/span/math/normal.text +2 -1
  276. data/test/testcases/span/text_substitutions/entities_as_char.html +1 -1
  277. data/test/testcases/span/text_substitutions/entities_as_char.options +1 -0
  278. data/test/testcases/span/text_substitutions/entities_as_char.text +1 -1
  279. data/test/testcases/span/text_substitutions/typography.html +22 -0
  280. data/test/testcases/span/text_substitutions/typography.text +22 -0
  281. data/test/testcases/span/text_substitutions/typography_subst.html +3 -0
  282. data/test/testcases/span/text_substitutions/typography_subst.latex +4 -0
  283. data/test/testcases/span/text_substitutions/typography_subst.options +8 -0
  284. data/test/testcases/span/text_substitutions/typography_subst.text +3 -0
  285. metadata +218 -67
  286. data/ChangeLog +0 -7436
  287. data/GPL +0 -674
  288. data/Rakefile +0 -306
  289. data/benchmark/benchmark.rb +0 -36
  290. data/benchmark/benchmark.sh +0 -74
  291. data/benchmark/generate_data.rb +0 -119
  292. data/benchmark/mdbasics.text +0 -306
  293. data/benchmark/mdsyntax.text +0 -888
  294. data/benchmark/testing.sh +0 -9
  295. data/benchmark/timing.sh +0 -10
  296. data/doc/bg.png +0 -0
  297. data/doc/default.scss.css +0 -181
  298. data/doc/default.template +0 -68
  299. data/doc/design.scss.css +0 -441
  300. data/doc/documentation.page +0 -84
  301. data/doc/documentation.template +0 -20
  302. data/doc/index.page +0 -94
  303. data/doc/installation.page +0 -88
  304. data/doc/links.markdown +0 -6
  305. data/doc/metainfo +0 -3
  306. data/doc/news.feed +0 -10
  307. data/doc/news.page +0 -29
  308. data/doc/options.page +0 -10
  309. data/doc/quickref.page +0 -598
  310. data/doc/sidebar.template +0 -21
  311. data/doc/syntax.page +0 -1700
  312. data/doc/tests.page +0 -91
  313. data/doc/virtual +0 -2
  314. data/lib/kramdown/compatibility.rb +0 -49
  315. data/lib/kramdown/utils/ordered_hash.rb +0 -100
  316. data/setup.rb +0 -1585
  317. data/test/testcases/block/07_horizontal_rule/error.html.19 +0 -7
  318. data/test/testcases/block/09_html/html_to_native/typography.html.19 +0 -1
  319. data/test/testcases/block/09_html/simple.html.19 +0 -64
  320. data/test/testcases/block/14_table/simple.html.19 +0 -177
  321. data/test/testcases/span/01_link/inline.html.19 +0 -46
  322. data/test/testcases/span/01_link/reference.html.19 +0 -37
  323. data/test/testcases/span/text_substitutions/entities_as_char.html.19 +0 -1
@@ -1,26 +1,14 @@
1
- # -*- coding: utf-8 -*-
1
+ # -*- coding: utf-8; frozen_string_literal: true -*-
2
2
  #
3
3
  #--
4
- # Copyright (C) 2009-2012 Thomas Leitner <t_leitner@gmx.at>
4
+ # Copyright (C) 2009-2019 Thomas Leitner <t_leitner@gmx.at>
5
5
  #
6
- # This file is part of kramdown.
7
- #
8
- # kramdown 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/>.
6
+ # This file is part of kramdown which is licensed under the MIT.
20
7
  #++
21
8
  #
22
9
 
23
- require 'rexml/parsers/baseparser'
10
+ require 'kramdown/converter'
11
+ require 'kramdown/utils'
24
12
 
25
13
  module Kramdown
26
14
 
@@ -41,16 +29,18 @@ module Kramdown
41
29
  @stack = []
42
30
  end
43
31
 
44
- def convert(el, opts = {:indent => 0})
32
+ def convert(el, opts = {indent: 0})
45
33
  res = send("convert_#{el.type}", el, opts)
46
- if ![:html_element, :li, :dd, :td].include?(el.type) && (ial = ial_for_element(el))
34
+ res = res.dup if res.frozen?
35
+ if ![:html_element, :li, :dt, :dd, :td].include?(el.type) && (ial = ial_for_element(el))
47
36
  res << ial
48
- res << "\n\n" if Element.category(el) == :block
37
+ res << "\n\n" if el.block?
49
38
  elsif [:ul, :dl, :ol, :codeblock].include?(el.type) && opts[:next] &&
50
39
  ([el.type, :codeblock].include?(opts[:next].type) ||
51
- (opts[:next].type == :blank && opts[:nnext] && [el.type, :codeblock].include?(opts[:nnext].type)))
40
+ (opts[:next].type == :blank && opts[:nnext] &&
41
+ [el.type, :codeblock].include?(opts[:nnext].type)))
52
42
  res << "^\n\n"
53
- elsif Element.category(el) == :block &&
43
+ elsif el.block? &&
54
44
  ![:li, :dd, :dt, :td, :th, :tr, :thead, :tbody, :tfoot, :blank].include?(el.type) &&
55
45
  (el.type != :html_element || @stack.last.type != :html_element) &&
56
46
  (el.type != :p || !el.options[:transparent])
@@ -59,23 +49,23 @@ module Kramdown
59
49
  res
60
50
  end
61
51
 
62
- def inner(el, opts = {:indent => 0})
52
+ def inner(el, opts = {indent: 0})
63
53
  @stack.push(el)
64
- result = ''
54
+ result = +''
65
55
  el.children.each_with_index do |inner_el, index|
66
56
  options = opts.dup
67
57
  options[:index] = index
68
- options[:prev] = (index == 0 ? nil : el.children[index-1])
69
- options[:pprev] = (index <= 1 ? nil : el.children[index-2])
70
- options[:next] = (index == el.children.length - 1 ? nil : el.children[index+1])
71
- options[:nnext] = (index >= el.children.length - 2 ? nil : el.children[index+2])
58
+ options[:prev] = (index == 0 ? nil : el.children[index - 1])
59
+ options[:pprev] = (index <= 1 ? nil : el.children[index - 2])
60
+ options[:next] = (index == el.children.length - 1 ? nil : el.children[index + 1])
61
+ options[:nnext] = (index >= el.children.length - 2 ? nil : el.children[index + 2])
72
62
  result << convert(inner_el, options)
73
63
  end
74
64
  @stack.pop
75
65
  result
76
66
  end
77
67
 
78
- def convert_blank(el, opts)
68
+ def convert_blank(_el, _opts)
79
69
  ""
80
70
  end
81
71
 
@@ -94,8 +84,8 @@ module Kramdown
94
84
  def convert_p(el, opts)
95
85
  w = @options[:line_width] - opts[:indent].to_s.to_i
96
86
  first, second, *rest = inner(el, opts).strip.gsub(/(.{1,#{w}})( +|$\n?)/, "\\1\n").split(/\n/)
97
- first.gsub!(/^(?:(#|>)|(\d+)\.|([+-]\s))/) { $1 || $3 ? "\\#{$1 || $3}" : "#{$2}\\."} if first
98
- second.gsub!(/^([=-]+\s*?)$/, "\\\1") if second
87
+ first&.gsub!(/^(?:(#|>)|(\d+)\.|([+-]\s))/) { $1 || $3 ? "\\#{$1 || $3}" : "#{$2}\\." }
88
+ second&.gsub!(/^([=-]+\s*?)$/, "\\\1")
99
89
  res = [first, second, *rest].compact.join("\n") + "\n"
100
90
  if el.children.length == 1 && el.children.first.type == :math
101
91
  res = "\\#{res}"
@@ -105,40 +95,40 @@ module Kramdown
105
95
  res
106
96
  end
107
97
 
108
-
109
- def convert_codeblock(el, opts)
110
- el.value.split(/\n/).map {|l| l.empty? ? " " : " #{l}"}.join("\n") + "\n"
98
+ def convert_codeblock(el, _opts)
99
+ el.value.split(/\n/).map {|l| l.empty? ? " " : " #{l}" }.join("\n") + "\n"
111
100
  end
112
101
 
113
102
  def convert_blockquote(el, opts)
114
103
  opts[:indent] += 2
115
- inner(el, opts).chomp.split(/\n/).map {|l| "> #{l}"}.join("\n") << "\n"
104
+ inner(el, opts).chomp.split(/\n/).map {|l| "> #{l}" }.join("\n") << "\n"
116
105
  end
117
106
 
118
107
  def convert_header(el, opts)
119
- res = ''
108
+ res = +''
120
109
  res << "#{'#' * output_header_level(el.options[:level])} #{inner(el, opts)}"
110
+ res[-1, 1] = "\\#" if res[-1] == '#'
121
111
  res << " {##{el.attr['id']}}" if el.attr['id'] && !el.attr['id'].strip.empty?
122
112
  res << "\n"
123
113
  end
124
114
 
125
- def convert_hr(el, opts)
115
+ def convert_hr(_el, _opts)
126
116
  "* * *\n"
127
117
  end
128
118
 
129
119
  def convert_ul(el, opts)
130
120
  inner(el, opts).sub(/\n+\Z/, "\n")
131
121
  end
132
- alias :convert_ol :convert_ul
133
- alias :convert_dl :convert_ul
122
+ alias convert_ol convert_ul
123
+ alias convert_dl convert_ul
134
124
 
135
125
  def convert_li(el, opts)
136
126
  sym, width = if @stack.last.type == :ul
137
- ['* ', el.children.first && el.children.first.type == :codeblock ? 4 : 2]
127
+ [+'* ', el.children.first && el.children.first.type == :codeblock ? 4 : 2]
138
128
  else
139
129
  ["#{opts[:index] + 1}.".ljust(4), 4]
140
130
  end
141
- if ial = ial_for_element(el)
131
+ if (ial = ial_for_element(el))
142
132
  sym << ial << " "
143
133
  end
144
134
 
@@ -146,12 +136,12 @@ module Kramdown
146
136
  text = inner(el, opts)
147
137
  newlines = text.scan(/\n*\Z/).first
148
138
  first, *last = text.split(/\n/)
149
- last = last.map {|l| " "*width + l}.join("\n")
139
+ last = last.map {|l| " " * width + l }.join("\n")
150
140
  text = (first.nil? ? "\n" : first + (last.empty? ? "" : "\n") + last + newlines)
151
141
  if el.children.first && el.children.first.type == :p && !el.children.first.options[:transparent]
152
- res = "#{sym}#{text}"
142
+ res = +"#{sym}#{text}"
153
143
  res << "^\n" if el.children.size == 1 && @stack.last.children.last == el &&
154
- (@stack.last.children.any? {|c| c.children.first.type != :p} || @stack.last.children.size == 1)
144
+ (@stack.last.children.any? {|c| c.children.first.type != :p } || @stack.last.children.size == 1)
155
145
  res
156
146
  elsif el.children.first && el.children.first.type == :codeblock
157
147
  "#{sym}\n #{text}"
@@ -161,8 +151,8 @@ module Kramdown
161
151
  end
162
152
 
163
153
  def convert_dd(el, opts)
164
- sym, width = ": ", (el.children.first && el.children.first.type == :codeblock ? 4 : 2)
165
- if ial = ial_for_element(el)
154
+ sym, width = +": ", (el.children.first && el.children.first.type == :codeblock ? 4 : 2)
155
+ if (ial = ial_for_element(el))
166
156
  sym << ial << " "
167
157
  end
168
158
 
@@ -170,10 +160,10 @@ module Kramdown
170
160
  text = inner(el, opts)
171
161
  newlines = text.scan(/\n*\Z/).first
172
162
  first, *last = text.split(/\n/)
173
- last = last.map {|l| " "*width + l}.join("\n")
163
+ last = last.map {|l| " " * width + l }.join("\n")
174
164
  text = first.to_s + (last.empty? ? "" : "\n") + last + newlines
175
165
  text.chomp! if text =~ /\n\n\Z/ && opts[:next] && opts[:next].type == :dd
176
- text << "\n" if (text !~ /\n\n\Z/ && opts[:next] && opts[:next].type == :dt)
166
+ text << "\n" if text !~ /\n\n\Z/ && opts[:next] && opts[:next].type == :dt
177
167
  text << "\n" if el.children.empty?
178
168
  if el.children.first && el.children.first.type == :p && !el.children.first.options[:transparent]
179
169
  "\n#{sym}#{text}"
@@ -185,30 +175,42 @@ module Kramdown
185
175
  end
186
176
 
187
177
  def convert_dt(el, opts)
188
- inner(el, opts) << "\n"
178
+ result = +''
179
+ if (ial = ial_for_element(el))
180
+ result << ial << " "
181
+ end
182
+ result << inner(el, opts) << "\n"
189
183
  end
190
184
 
191
- HTML_TAGS_WITH_BODY=['div', 'script', 'iframe', 'textarea']
185
+ HTML_TAGS_WITH_BODY = ['div', 'script', 'iframe', 'textarea']
186
+
187
+ HTML_ELEMENT_TYPES = [:entity, :text, :html_element].freeze
188
+ private_constant :HTML_ELEMENT_TYPES
192
189
 
193
190
  def convert_html_element(el, opts)
194
191
  markdown_attr = el.options[:category] == :block && el.children.any? do |c|
195
- c.type != :html_element && (c.type != :p || !c.options[:transparent]) && Element.category(c) == :block
192
+ c.type != :html_element &&
193
+ (c.type != :p || !c.options[:transparent] ||
194
+ c.children.any? {|t| !HTML_ELEMENT_TYPES.member?(t.type) }) &&
195
+ c.block?
196
196
  end
197
- opts[:force_raw_text] = true if %w{script pre code}.include?(el.value)
198
- opts[:raw_text] = opts[:force_raw_text] || opts[:block_raw_text] || (el.options[:category] != :span && !markdown_attr)
197
+ opts[:force_raw_text] = true if %w[script pre code].include?(el.value)
198
+ opts[:raw_text] = opts[:force_raw_text] || opts[:block_raw_text] || \
199
+ (el.options[:category] != :span && !markdown_attr)
199
200
  opts[:block_raw_text] = true if el.options[:category] == :block && opts[:raw_text]
200
201
  res = inner(el, opts)
201
202
  if el.options[:category] == :span
202
- "<#{el.value}#{html_attributes(el.attr)}" << (!res.empty? || HTML_TAGS_WITH_BODY.include?(el.value) ? ">#{res}</#{el.value}>" : " />")
203
+ "<#{el.value}#{html_attributes(el.attr)}" + \
204
+ (!res.empty? || HTML_TAGS_WITH_BODY.include?(el.value) ? ">#{res}</#{el.value}>" : " />")
203
205
  else
204
- output = ''
206
+ output = +''
205
207
  attr = el.attr.dup
206
208
  attr['markdown'] = '1' if markdown_attr
207
209
  output << "<#{el.value}#{html_attributes(attr)}"
208
210
  if !res.empty? && el.options[:content_model] != :block
209
211
  output << ">#{res}</#{el.value}>"
210
212
  elsif !res.empty?
211
- output << ">\n#{res}" << "</#{el.value}>"
213
+ output << ">\n#{res}" << "</#{el.value}>"
212
214
  elsif HTML_TAGS_WITH_BODY.include?(el.value)
213
215
  output << "></#{el.value}>"
214
216
  else
@@ -219,14 +221,15 @@ module Kramdown
219
221
  end
220
222
  end
221
223
 
222
- def convert_xml_comment(el, opts)
223
- if el.options[:category] == :block && (@stack.last.type != :html_element || @stack.last.options[:content_model] != :raw)
224
+ def convert_xml_comment(el, _opts)
225
+ if el.options[:category] == :block &&
226
+ (@stack.last.type != :html_element || @stack.last.options[:content_model] != :raw)
224
227
  el.value + "\n"
225
228
  else
226
229
  el.value.dup
227
230
  end
228
231
  end
229
- alias :convert_xml_pi :convert_xml_comment
232
+ alias convert_xml_pi convert_xml_comment
230
233
 
231
234
  def convert_table(el, opts)
232
235
  opts[:alignment] = el.options[:alignment]
@@ -235,8 +238,8 @@ module Kramdown
235
238
 
236
239
  def convert_thead(el, opts)
237
240
  rows = inner(el, opts)
238
- if opts[:alignment].all? {|a| a == :default}
239
- "#{rows}|" + "-"*10 + "\n"
241
+ if opts[:alignment].all? {|a| a == :default }
242
+ "#{rows}|#{'-' * 10}\n"
240
243
  else
241
244
  "#{rows}| " + opts[:alignment].map do |a|
242
245
  case a
@@ -245,30 +248,30 @@ module Kramdown
245
248
  when :center then ":-:"
246
249
  when :default then "-"
247
250
  end
248
- end.join(' ') + "\n"
251
+ end.join(' ') << "\n"
249
252
  end
250
253
  end
251
254
 
252
255
  def convert_tbody(el, opts)
253
- res = ''
256
+ res = +''
254
257
  res << inner(el, opts)
255
- res << '|' << '-'*10 << "\n" if opts[:next] && opts[:next].type == :tbody
258
+ res << '|' << '-' * 10 << "\n" if opts[:next] && opts[:next].type == :tbody
256
259
  res
257
260
  end
258
261
 
259
262
  def convert_tfoot(el, opts)
260
- "|" + "="*10 + "\n#{inner(el, opts)}"
263
+ "|#{'=' * 10}\n#{inner(el, opts)}"
261
264
  end
262
265
 
263
266
  def convert_tr(el, opts)
264
- "| " + el.children.map {|c| convert(c, opts)}.join(" | ") + " |\n"
267
+ "| #{el.children.map {|c| convert(c, opts) }.join(' | ')} |\n"
265
268
  end
266
269
 
267
270
  def convert_td(el, opts)
268
271
  inner(el, opts)
269
272
  end
270
273
 
271
- def convert_comment(el, opts)
274
+ def convert_comment(el, _opts)
272
275
  if el.options[:category] == :block
273
276
  "{::comment}\n#{el.value}\n{:/}\n"
274
277
  else
@@ -276,7 +279,7 @@ module Kramdown
276
279
  end
277
280
  end
278
281
 
279
- def convert_br(el, opts)
282
+ def convert_br(_el, _opts)
280
283
  " \n"
281
284
  end
282
285
 
@@ -284,7 +287,7 @@ module Kramdown
284
287
  if el.attr['href'].empty?
285
288
  "[#{inner(el, opts)}]()"
286
289
  elsif el.attr['href'] =~ /^(?:http|ftp)/ || el.attr['href'].count("()") > 0
287
- index = if link_el = @linkrefs.find {|c| c.attr['href'] == el.attr['href']}
290
+ index = if (link_el = @linkrefs.find {|c| c.attr['href'] == el.attr['href'] })
288
291
  @linkrefs.index(link_el) + 1
289
292
  else
290
293
  @linkrefs << el
@@ -292,38 +295,40 @@ module Kramdown
292
295
  end
293
296
  "[#{inner(el, opts)}][#{index}]"
294
297
  else
295
- title = el.attr['title'].to_s.empty? ? '' : ' "' + el.attr['title'].gsub(/"/, "&quot;") + '"'
298
+ title = parse_title(el.attr['title'])
296
299
  "[#{inner(el, opts)}](#{el.attr['href']}#{title})"
297
300
  end
298
301
  end
299
302
 
300
- def convert_img(el, opts)
301
- if el.attr['src'].empty?
302
- "![#{el.attr['alt']}]()"
303
+ def convert_img(el, _opts)
304
+ alt_text = el.attr['alt'].to_s.gsub(ESCAPED_CHAR_RE) { $1 ? "\\#{$1}" : $2 }
305
+ src = el.attr['src'].to_s
306
+ if src.empty?
307
+ "![#{alt_text}]()"
303
308
  else
304
- title = (el.attr['title'] ? ' "' + el.attr['title'].gsub(/"/, "&quot;") + '"' : '')
305
- link = if el.attr['src'].count("()") > 0
306
- "<#{el.attr['src']}>"
309
+ title = parse_title(el.attr['title'])
310
+ link = if src.count("()") > 0
311
+ "<#{src}>"
307
312
  else
308
- el.attr['src']
313
+ src
309
314
  end
310
- "![#{el.attr['alt']}](#{link}#{title})"
315
+ "![#{alt_text}](#{link}#{title})"
311
316
  end
312
317
  end
313
318
 
314
- def convert_codespan(el, opts)
319
+ def convert_codespan(el, _opts)
315
320
  delim = (el.value.scan(/`+/).max || '') + '`'
316
321
  "#{delim}#{' ' if delim.size > 1}#{el.value}#{' ' if delim.size > 1}#{delim}"
317
322
  end
318
323
 
319
- def convert_footnote(el, opts)
324
+ def convert_footnote(el, _opts)
320
325
  @footnotes << [el.options[:name], el.value]
321
326
  "[^#{el.options[:name]}]"
322
327
  end
323
328
 
324
- def convert_raw(el, opts)
329
+ def convert_raw(el, _opts)
325
330
  attr = (el.options[:type] || []).join(' ')
326
- attr = " type=\"#{attr}\"" if attr.length > 0
331
+ attr = " type=\"#{attr}\"" unless attr.empty?
327
332
  if @stack.last.type == :html_element
328
333
  el.value
329
334
  elsif el.options[:category] == :block
@@ -334,35 +339,37 @@ module Kramdown
334
339
  end
335
340
 
336
341
  def convert_em(el, opts)
337
- "*#{inner(el, opts)}*"
342
+ "*#{inner(el, opts)}*" +
343
+ (opts[:next] && [:em, :strong].include?(opts[:next].type) && !ial_for_element(el) ? '{::}' : '')
338
344
  end
339
345
 
340
346
  def convert_strong(el, opts)
341
- "**#{inner(el, opts)}**"
347
+ "**#{inner(el, opts)}**" +
348
+ (opts[:next] && [:em, :strong].include?(opts[:next].type) && !ial_for_element(el) ? '{::}' : '')
342
349
  end
343
350
 
344
- def convert_entity(el, opts)
351
+ def convert_entity(el, _opts)
345
352
  entity_to_str(el.value, el.options[:original])
346
353
  end
347
354
 
348
355
  TYPOGRAPHIC_SYMS = {
349
- :mdash => '---', :ndash => '--', :hellip => '...',
350
- :laquo_space => '<< ', :raquo_space => ' >>',
351
- :laquo => '<<', :raquo => '>>'
356
+ mdash: '---', ndash: '--', hellip: '...',
357
+ laquo_space: '<< ', raquo_space: ' >>',
358
+ laquo: '<<', raquo: '>>'
352
359
  }
353
- def convert_typographic_sym(el, opts)
360
+ def convert_typographic_sym(el, _opts)
354
361
  TYPOGRAPHIC_SYMS[el.value]
355
362
  end
356
363
 
357
- def convert_smart_quote(el, opts)
364
+ def convert_smart_quote(el, _opts)
358
365
  el.value.to_s =~ /[rl]dquo/ ? "\"" : "'"
359
366
  end
360
367
 
361
- def convert_math(el, opts)
368
+ def convert_math(el, _opts)
362
369
  "$$#{el.value}$$" + (el.options[:category] == :block ? "\n" : '')
363
370
  end
364
371
 
365
- def convert_abbreviation(el, opts)
372
+ def convert_abbreviation(el, _opts)
366
373
  el.value
367
374
  end
368
375
 
@@ -375,53 +382,64 @@ module Kramdown
375
382
  end
376
383
 
377
384
  def create_link_defs
378
- res = ''
379
- res << "\n\n" if @linkrefs.size > 0
385
+ res = +''
386
+ res << "\n\n" unless @linkrefs.empty?
380
387
  @linkrefs.each_with_index do |el, i|
381
- title = el.attr['title']
382
- res << "[#{i+1}]: #{el.attr['href']} #{title ? '"' + title.gsub(/"/, "&quot;") + '"' : ''}\n"
388
+ title = parse_title(el.attr['title'])
389
+ res << "[#{i + 1}]: #{el.attr['href']}#{title}\n"
383
390
  end
384
391
  res
385
392
  end
386
393
 
387
394
  def create_footnote_defs
388
- res = ''
395
+ res = +''
389
396
  @footnotes.each do |name, data|
390
397
  res << "[^#{name}]:\n"
391
- res << inner(data).chomp.split(/\n/).map {|l| " #{l}"}.join("\n") + "\n\n"
398
+ res << inner(data).chomp.split(/\n/).map {|l| " #{l}" }.join("\n") + "\n\n"
392
399
  end
393
400
  res
394
401
  end
395
402
 
396
403
  def create_abbrev_defs
397
404
  return '' unless @root.options[:abbrev_defs]
398
- res = ''
405
+ res = +''
399
406
  @root.options[:abbrev_defs].each do |name, text|
400
407
  res << "*[#{name}]: #{text}\n"
408
+ res << ial_for_element(Element.new(:unused, nil, @root.options[:abbrev_attr][name])).to_s << "\n\n"
401
409
  end
402
410
  res
403
411
  end
404
412
 
405
413
  # Return the IAL containing the attributes of the element +el+.
406
414
  def ial_for_element(el)
407
- res = el.attr.map do |k,v|
415
+ res = el.attr.map do |k, v|
408
416
  next if [:img, :a].include?(el.type) && ['href', 'src', 'alt', 'title'].include?(k)
409
417
  next if el.type == :header && k == 'id' && !v.strip.empty?
410
418
  if v.nil?
411
419
  ''
412
- elsif k == 'class' && !v.empty?
413
- " " + v.split(/\s+/).map {|w| ".#{w}"}.join(" ")
420
+ elsif k == 'class' && !v.empty? && !v.index(/[\.#]/)
421
+ " " + v.split(/\s+/).map {|w| ".#{w}" }.join(" ")
414
422
  elsif k == 'id' && !v.strip.empty?
415
423
  " ##{v}"
416
424
  else
417
- " #{k}=\"#{v.to_s}\""
425
+ " #{k}=\"#{v}\""
418
426
  end
419
427
  end.compact.join('')
420
428
  res = "toc" + (res.strip.empty? ? '' : " #{res}") if (el.type == :ul || el.type == :ol) &&
421
- (el.options[:ial][:refs].include?('toc') rescue nil)
429
+ el.options.dig(:ial, :refs)&.include?('toc')
430
+ res = "footnotes" + (res.strip.empty? ? '' : " #{res}") if (el.type == :ul || el.type == :ol) &&
431
+ el.options.dig(:ial, :refs)&.include?('footnotes')
432
+ if el.type == :dl && el.options[:ial] && el.options[:ial][:refs]
433
+ auto_ids = el.options[:ial][:refs].select {|ref| ref.start_with?('auto_ids') }.join(" ")
434
+ res = auto_ids << (res.strip.empty? ? '' : " #{res}") unless auto_ids.empty?
435
+ end
422
436
  res.strip.empty? ? nil : "{:#{res}}"
423
437
  end
424
438
 
439
+ def parse_title(attr)
440
+ attr.to_s.empty? ? '' : ' "' + attr.gsub(/"/, '&quot;') + '"'
441
+ end
442
+
425
443
  # :startdoc:
426
444
 
427
445
  end