daqing_kramdown 2.3.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 (557) hide show
  1. checksums.yaml +7 -0
  2. data/AUTHORS +1 -0
  3. data/CONTRIBUTERS +78 -0
  4. data/COPYING +30 -0
  5. data/README.md +71 -0
  6. data/VERSION +1 -0
  7. data/bin/daqing_kramdown +132 -0
  8. data/data/kramdown/document.html +22 -0
  9. data/data/kramdown/document.latex +50 -0
  10. data/lib/kramdown.rb +10 -0
  11. data/lib/kramdown/converter.rb +68 -0
  12. data/lib/kramdown/converter/base.rb +261 -0
  13. data/lib/kramdown/converter/hash_ast.rb +38 -0
  14. data/lib/kramdown/converter/html.rb +535 -0
  15. data/lib/kramdown/converter/kramdown.rb +448 -0
  16. data/lib/kramdown/converter/latex.rb +625 -0
  17. data/lib/kramdown/converter/man.rb +300 -0
  18. data/lib/kramdown/converter/math_engine/mathjax.rb +32 -0
  19. data/lib/kramdown/converter/remove_html_tags.rb +57 -0
  20. data/lib/kramdown/converter/syntax_highlighter.rb +56 -0
  21. data/lib/kramdown/converter/syntax_highlighter/minted.rb +35 -0
  22. data/lib/kramdown/converter/syntax_highlighter/rouge.rb +85 -0
  23. data/lib/kramdown/converter/toc.rb +69 -0
  24. data/lib/kramdown/document.rb +139 -0
  25. data/lib/kramdown/element.rb +551 -0
  26. data/lib/kramdown/error.rb +17 -0
  27. data/lib/kramdown/options.rb +604 -0
  28. data/lib/kramdown/parser.rb +26 -0
  29. data/lib/kramdown/parser/base.rb +131 -0
  30. data/lib/kramdown/parser/html.rb +608 -0
  31. data/lib/kramdown/parser/kramdown.rb +376 -0
  32. data/lib/kramdown/parser/kramdown/abbreviation.rb +78 -0
  33. data/lib/kramdown/parser/kramdown/autolink.rb +31 -0
  34. data/lib/kramdown/parser/kramdown/blank_line.rb +30 -0
  35. data/lib/kramdown/parser/kramdown/block_boundary.rb +34 -0
  36. data/lib/kramdown/parser/kramdown/blockquote.rb +38 -0
  37. data/lib/kramdown/parser/kramdown/codeblock.rb +57 -0
  38. data/lib/kramdown/parser/kramdown/codespan.rb +54 -0
  39. data/lib/kramdown/parser/kramdown/emphasis.rb +61 -0
  40. data/lib/kramdown/parser/kramdown/eob.rb +26 -0
  41. data/lib/kramdown/parser/kramdown/escaped_chars.rb +25 -0
  42. data/lib/kramdown/parser/kramdown/extensions.rb +214 -0
  43. data/lib/kramdown/parser/kramdown/footnote.rb +64 -0
  44. data/lib/kramdown/parser/kramdown/header.rb +70 -0
  45. data/lib/kramdown/parser/kramdown/horizontal_rule.rb +27 -0
  46. data/lib/kramdown/parser/kramdown/html.rb +162 -0
  47. data/lib/kramdown/parser/kramdown/html_entity.rb +34 -0
  48. data/lib/kramdown/parser/kramdown/line_break.rb +25 -0
  49. data/lib/kramdown/parser/kramdown/link.rb +149 -0
  50. data/lib/kramdown/parser/kramdown/list.rb +284 -0
  51. data/lib/kramdown/parser/kramdown/math.rb +53 -0
  52. data/lib/kramdown/parser/kramdown/paragraph.rb +62 -0
  53. data/lib/kramdown/parser/kramdown/smart_quotes.rb +174 -0
  54. data/lib/kramdown/parser/kramdown/table.rb +171 -0
  55. data/lib/kramdown/parser/kramdown/typographic_symbol.rb +44 -0
  56. data/lib/kramdown/parser/markdown.rb +57 -0
  57. data/lib/kramdown/utils.rb +45 -0
  58. data/lib/kramdown/utils/configurable.rb +45 -0
  59. data/lib/kramdown/utils/entities.rb +344 -0
  60. data/lib/kramdown/utils/html.rb +84 -0
  61. data/lib/kramdown/utils/lru_cache.rb +41 -0
  62. data/lib/kramdown/utils/string_scanner.rb +81 -0
  63. data/lib/kramdown/utils/unidecoder.rb +50 -0
  64. data/lib/kramdown/version.rb +15 -0
  65. data/man/man1/kramdown.1 +0 -0
  66. data/test/run_tests.rb +46 -0
  67. data/test/test_files.rb +298 -0
  68. data/test/test_location.rb +216 -0
  69. data/test/test_string_scanner_kramdown.rb +27 -0
  70. data/test/testcases/block/01_blank_line/spaces.html +1 -0
  71. data/test/testcases/block/01_blank_line/spaces.text +3 -0
  72. data/test/testcases/block/01_blank_line/tabs.html +1 -0
  73. data/test/testcases/block/01_blank_line/tabs.text +6 -0
  74. data/test/testcases/block/02_eob/beginning.html +1 -0
  75. data/test/testcases/block/02_eob/beginning.text +3 -0
  76. data/test/testcases/block/02_eob/end.html +1 -0
  77. data/test/testcases/block/02_eob/end.text +3 -0
  78. data/test/testcases/block/02_eob/middle.html +1 -0
  79. data/test/testcases/block/02_eob/middle.text +5 -0
  80. data/test/testcases/block/03_paragraph/indented.html +18 -0
  81. data/test/testcases/block/03_paragraph/indented.html.gfm +18 -0
  82. data/test/testcases/block/03_paragraph/indented.text +19 -0
  83. data/test/testcases/block/03_paragraph/line_break_last_line.html +9 -0
  84. data/test/testcases/block/03_paragraph/line_break_last_line.text +9 -0
  85. data/test/testcases/block/03_paragraph/no_newline_at_end.html +5 -0
  86. data/test/testcases/block/03_paragraph/no_newline_at_end.text +5 -0
  87. data/test/testcases/block/03_paragraph/one_para.html +1 -0
  88. data/test/testcases/block/03_paragraph/one_para.text +1 -0
  89. data/test/testcases/block/03_paragraph/standalone_image.html +8 -0
  90. data/test/testcases/block/03_paragraph/standalone_image.text +6 -0
  91. data/test/testcases/block/03_paragraph/two_para.html +4 -0
  92. data/test/testcases/block/03_paragraph/two_para.text +4 -0
  93. data/test/testcases/block/03_paragraph/with_html_to_native.html +1 -0
  94. data/test/testcases/block/03_paragraph/with_html_to_native.options +1 -0
  95. data/test/testcases/block/03_paragraph/with_html_to_native.text +1 -0
  96. data/test/testcases/block/04_header/atx_header.html +57 -0
  97. data/test/testcases/block/04_header/atx_header.text +54 -0
  98. data/test/testcases/block/04_header/atx_header_no_newline_at_end.html +1 -0
  99. data/test/testcases/block/04_header/atx_header_no_newline_at_end.text +1 -0
  100. data/test/testcases/block/04_header/header_type_offset.html +11 -0
  101. data/test/testcases/block/04_header/header_type_offset.kramdown +12 -0
  102. data/test/testcases/block/04_header/header_type_offset.latex +12 -0
  103. data/test/testcases/block/04_header/header_type_offset.options +2 -0
  104. data/test/testcases/block/04_header/header_type_offset.text +13 -0
  105. data/test/testcases/block/04_header/setext_header.html +32 -0
  106. data/test/testcases/block/04_header/setext_header.text +39 -0
  107. data/test/testcases/block/04_header/setext_header_no_newline_at_end.html +1 -0
  108. data/test/testcases/block/04_header/setext_header_no_newline_at_end.text +2 -0
  109. data/test/testcases/block/04_header/with_auto_id_prefix.html +3 -0
  110. data/test/testcases/block/04_header/with_auto_id_prefix.options +2 -0
  111. data/test/testcases/block/04_header/with_auto_id_prefix.text +3 -0
  112. data/test/testcases/block/04_header/with_auto_id_stripping.html +1 -0
  113. data/test/testcases/block/04_header/with_auto_id_stripping.options +1 -0
  114. data/test/testcases/block/04_header/with_auto_id_stripping.text +1 -0
  115. data/test/testcases/block/04_header/with_auto_ids.html +21 -0
  116. data/test/testcases/block/04_header/with_auto_ids.options +2 -0
  117. data/test/testcases/block/04_header/with_auto_ids.text +24 -0
  118. data/test/testcases/block/05_blockquote/indented.html +25 -0
  119. data/test/testcases/block/05_blockquote/indented.text +14 -0
  120. data/test/testcases/block/05_blockquote/lazy.html +34 -0
  121. data/test/testcases/block/05_blockquote/lazy.text +20 -0
  122. data/test/testcases/block/05_blockquote/nested.html +10 -0
  123. data/test/testcases/block/05_blockquote/nested.text +6 -0
  124. data/test/testcases/block/05_blockquote/no_newline_at_end.html +4 -0
  125. data/test/testcases/block/05_blockquote/no_newline_at_end.text +2 -0
  126. data/test/testcases/block/05_blockquote/very_long_line.html +3 -0
  127. data/test/testcases/block/05_blockquote/very_long_line.text +1 -0
  128. data/test/testcases/block/05_blockquote/with_code_blocks.html +15 -0
  129. data/test/testcases/block/05_blockquote/with_code_blocks.text +11 -0
  130. data/test/testcases/block/06_codeblock/disable-highlighting.html +4 -0
  131. data/test/testcases/block/06_codeblock/disable-highlighting.options +1 -0
  132. data/test/testcases/block/06_codeblock/disable-highlighting.text +4 -0
  133. data/test/testcases/block/06_codeblock/error.html +4 -0
  134. data/test/testcases/block/06_codeblock/error.text +4 -0
  135. data/test/testcases/block/06_codeblock/guess_lang_css_class.html +15 -0
  136. data/test/testcases/block/06_codeblock/guess_lang_css_class.options +2 -0
  137. data/test/testcases/block/06_codeblock/guess_lang_css_class.text +13 -0
  138. data/test/testcases/block/06_codeblock/highlighting-minted-with-opts.latex +9 -0
  139. data/test/testcases/block/06_codeblock/highlighting-minted-with-opts.options +4 -0
  140. data/test/testcases/block/06_codeblock/highlighting-minted-with-opts.text +5 -0
  141. data/test/testcases/block/06_codeblock/highlighting-minted.latex +8 -0
  142. data/test/testcases/block/06_codeblock/highlighting-minted.options +3 -0
  143. data/test/testcases/block/06_codeblock/highlighting-minted.text +4 -0
  144. data/test/testcases/block/06_codeblock/highlighting-opts.html +6 -0
  145. data/test/testcases/block/06_codeblock/highlighting-opts.options +7 -0
  146. data/test/testcases/block/06_codeblock/highlighting-opts.text +4 -0
  147. data/test/testcases/block/06_codeblock/highlighting.html +5 -0
  148. data/test/testcases/block/06_codeblock/highlighting.options +5 -0
  149. data/test/testcases/block/06_codeblock/highlighting.text +4 -0
  150. data/test/testcases/block/06_codeblock/issue_gh45.html +164 -0
  151. data/test/testcases/block/06_codeblock/issue_gh45.test +188 -0
  152. data/test/testcases/block/06_codeblock/lazy.html +4 -0
  153. data/test/testcases/block/06_codeblock/lazy.text +5 -0
  154. data/test/testcases/block/06_codeblock/no_newline_at_end.html +2 -0
  155. data/test/testcases/block/06_codeblock/no_newline_at_end.text +1 -0
  156. data/test/testcases/block/06_codeblock/no_newline_at_end_1.html +2 -0
  157. data/test/testcases/block/06_codeblock/no_newline_at_end_1.text +2 -0
  158. data/test/testcases/block/06_codeblock/normal.html +13 -0
  159. data/test/testcases/block/06_codeblock/normal.text +10 -0
  160. data/test/testcases/block/06_codeblock/rouge/disabled.html +2 -0
  161. data/test/testcases/block/06_codeblock/rouge/disabled.options +4 -0
  162. data/test/testcases/block/06_codeblock/rouge/disabled.text +1 -0
  163. data/test/testcases/block/06_codeblock/rouge/multiple.html +11 -0
  164. data/test/testcases/block/06_codeblock/rouge/multiple.options +4 -0
  165. data/test/testcases/block/06_codeblock/rouge/multiple.text +11 -0
  166. data/test/testcases/block/06_codeblock/rouge/simple.html +10 -0
  167. data/test/testcases/block/06_codeblock/rouge/simple.options +3 -0
  168. data/test/testcases/block/06_codeblock/rouge/simple.text +9 -0
  169. data/test/testcases/block/06_codeblock/tilde_syntax.html +7 -0
  170. data/test/testcases/block/06_codeblock/tilde_syntax.text +9 -0
  171. data/test/testcases/block/06_codeblock/whitespace.html +3 -0
  172. data/test/testcases/block/06_codeblock/whitespace.text +3 -0
  173. data/test/testcases/block/06_codeblock/with_blank_line.html +13 -0
  174. data/test/testcases/block/06_codeblock/with_blank_line.text +12 -0
  175. data/test/testcases/block/06_codeblock/with_eob_marker.html +6 -0
  176. data/test/testcases/block/06_codeblock/with_eob_marker.text +5 -0
  177. data/test/testcases/block/06_codeblock/with_ial.html +6 -0
  178. data/test/testcases/block/06_codeblock/with_ial.text +5 -0
  179. data/test/testcases/block/06_codeblock/with_lang_in_fenced_block.html +24 -0
  180. data/test/testcases/block/06_codeblock/with_lang_in_fenced_block.options +2 -0
  181. data/test/testcases/block/06_codeblock/with_lang_in_fenced_block.text +33 -0
  182. data/test/testcases/block/06_codeblock/with_lang_in_fenced_block_any_char.html +8 -0
  183. data/test/testcases/block/06_codeblock/with_lang_in_fenced_block_any_char.options +2 -0
  184. data/test/testcases/block/06_codeblock/with_lang_in_fenced_block_any_char.text +11 -0
  185. data/test/testcases/block/06_codeblock/with_lang_in_fenced_block_name_with_dash.html +3 -0
  186. data/test/testcases/block/06_codeblock/with_lang_in_fenced_block_name_with_dash.options +2 -0
  187. data/test/testcases/block/06_codeblock/with_lang_in_fenced_block_name_with_dash.text +4 -0
  188. data/test/testcases/block/07_horizontal_rule/error.html +7 -0
  189. data/test/testcases/block/07_horizontal_rule/error.text +7 -0
  190. data/test/testcases/block/07_horizontal_rule/normal.html +19 -0
  191. data/test/testcases/block/07_horizontal_rule/normal.text +20 -0
  192. data/test/testcases/block/07_horizontal_rule/sepspaces.html +3 -0
  193. data/test/testcases/block/07_horizontal_rule/sepspaces.text +3 -0
  194. data/test/testcases/block/07_horizontal_rule/septabs.html +3 -0
  195. data/test/testcases/block/07_horizontal_rule/septabs.text +3 -0
  196. data/test/testcases/block/08_list/brackets_in_item.latex +3 -0
  197. data/test/testcases/block/08_list/brackets_in_item.text +1 -0
  198. data/test/testcases/block/08_list/escaping.html +17 -0
  199. data/test/testcases/block/08_list/escaping.text +17 -0
  200. data/test/testcases/block/08_list/item_ial.html +10 -0
  201. data/test/testcases/block/08_list/item_ial.text +8 -0
  202. data/test/testcases/block/08_list/lazy.html +39 -0
  203. data/test/testcases/block/08_list/lazy.text +29 -0
  204. data/test/testcases/block/08_list/lazy_and_nested.html +9 -0
  205. data/test/testcases/block/08_list/lazy_and_nested.text +4 -0
  206. data/test/testcases/block/08_list/list_and_hr.html +9 -0
  207. data/test/testcases/block/08_list/list_and_hr.text +5 -0
  208. data/test/testcases/block/08_list/list_and_others.html +40 -0
  209. data/test/testcases/block/08_list/list_and_others.text +26 -0
  210. data/test/testcases/block/08_list/mixed.html +117 -0
  211. data/test/testcases/block/08_list/mixed.text +66 -0
  212. data/test/testcases/block/08_list/nested.html +17 -0
  213. data/test/testcases/block/08_list/nested.text +7 -0
  214. data/test/testcases/block/08_list/other_first_element.html +39 -0
  215. data/test/testcases/block/08_list/other_first_element.text +18 -0
  216. data/test/testcases/block/08_list/simple_ol.html +19 -0
  217. data/test/testcases/block/08_list/simple_ol.text +13 -0
  218. data/test/testcases/block/08_list/simple_ul.html +48 -0
  219. data/test/testcases/block/08_list/simple_ul.text +36 -0
  220. data/test/testcases/block/08_list/single_item.html +3 -0
  221. data/test/testcases/block/08_list/single_item.text +1 -0
  222. data/test/testcases/block/08_list/special_cases.html +62 -0
  223. data/test/testcases/block/08_list/special_cases.text +40 -0
  224. data/test/testcases/block/09_html/comment.html +18 -0
  225. data/test/testcases/block/09_html/comment.text +15 -0
  226. data/test/testcases/block/09_html/content_model/deflists.html +6 -0
  227. data/test/testcases/block/09_html/content_model/deflists.options +1 -0
  228. data/test/testcases/block/09_html/content_model/deflists.text +6 -0
  229. data/test/testcases/block/09_html/content_model/tables.html +14 -0
  230. data/test/testcases/block/09_html/content_model/tables.options +1 -0
  231. data/test/testcases/block/09_html/content_model/tables.text +14 -0
  232. data/test/testcases/block/09_html/html5_attributes.html +15 -0
  233. data/test/testcases/block/09_html/html5_attributes.text +15 -0
  234. data/test/testcases/block/09_html/html_after_block.html +7 -0
  235. data/test/testcases/block/09_html/html_after_block.text +5 -0
  236. data/test/testcases/block/09_html/html_and_codeblocks.html +15 -0
  237. data/test/testcases/block/09_html/html_and_codeblocks.options +1 -0
  238. data/test/testcases/block/09_html/html_and_codeblocks.text +13 -0
  239. data/test/testcases/block/09_html/html_and_headers.html +5 -0
  240. data/test/testcases/block/09_html/html_and_headers.text +6 -0
  241. data/test/testcases/block/09_html/html_to_native/code.html +10 -0
  242. data/test/testcases/block/09_html/html_to_native/code.text +9 -0
  243. data/test/testcases/block/09_html/html_to_native/comment.html +7 -0
  244. data/test/testcases/block/09_html/html_to_native/comment.text +8 -0
  245. data/test/testcases/block/09_html/html_to_native/emphasis.html +6 -0
  246. data/test/testcases/block/09_html/html_to_native/emphasis.text +6 -0
  247. data/test/testcases/block/09_html/html_to_native/entity.html +1 -0
  248. data/test/testcases/block/09_html/html_to_native/entity.text +1 -0
  249. data/test/testcases/block/09_html/html_to_native/header.html +6 -0
  250. data/test/testcases/block/09_html/html_to_native/header.options +2 -0
  251. data/test/testcases/block/09_html/html_to_native/header.text +6 -0
  252. data/test/testcases/block/09_html/html_to_native/list_dl.html +8 -0
  253. data/test/testcases/block/09_html/html_to_native/list_dl.text +8 -0
  254. data/test/testcases/block/09_html/html_to_native/list_ol.html +15 -0
  255. data/test/testcases/block/09_html/html_to_native/list_ol.text +17 -0
  256. data/test/testcases/block/09_html/html_to_native/list_ul.html +19 -0
  257. data/test/testcases/block/09_html/html_to_native/list_ul.text +22 -0
  258. data/test/testcases/block/09_html/html_to_native/options +1 -0
  259. data/test/testcases/block/09_html/html_to_native/paragraph.html +3 -0
  260. data/test/testcases/block/09_html/html_to_native/paragraph.text +4 -0
  261. data/test/testcases/block/09_html/html_to_native/table_normal.html +12 -0
  262. data/test/testcases/block/09_html/html_to_native/table_normal.text +12 -0
  263. data/test/testcases/block/09_html/html_to_native/table_simple.html +61 -0
  264. data/test/testcases/block/09_html/html_to_native/table_simple.text +71 -0
  265. data/test/testcases/block/09_html/html_to_native/typography.html +1 -0
  266. data/test/testcases/block/09_html/html_to_native/typography.text +1 -0
  267. data/test/testcases/block/09_html/invalid_html_1.html +5 -0
  268. data/test/testcases/block/09_html/invalid_html_1.text +5 -0
  269. data/test/testcases/block/09_html/invalid_html_2.html +5 -0
  270. data/test/testcases/block/09_html/invalid_html_2.text +5 -0
  271. data/test/testcases/block/09_html/markdown_attr.html +38 -0
  272. data/test/testcases/block/09_html/markdown_attr.text +38 -0
  273. data/test/testcases/block/09_html/not_parsed.html +24 -0
  274. data/test/testcases/block/09_html/not_parsed.text +24 -0
  275. data/test/testcases/block/09_html/parse_as_raw.html +35 -0
  276. data/test/testcases/block/09_html/parse_as_raw.htmlinput +34 -0
  277. data/test/testcases/block/09_html/parse_as_raw.options +1 -0
  278. data/test/testcases/block/09_html/parse_as_raw.text +33 -0
  279. data/test/testcases/block/09_html/parse_as_span.html +12 -0
  280. data/test/testcases/block/09_html/parse_as_span.htmlinput +12 -0
  281. data/test/testcases/block/09_html/parse_as_span.options +1 -0
  282. data/test/testcases/block/09_html/parse_as_span.text +9 -0
  283. data/test/testcases/block/09_html/parse_block_html.html +21 -0
  284. data/test/testcases/block/09_html/parse_block_html.options +1 -0
  285. data/test/testcases/block/09_html/parse_block_html.text +17 -0
  286. data/test/testcases/block/09_html/processing_instruction.html +12 -0
  287. data/test/testcases/block/09_html/processing_instruction.text +12 -0
  288. data/test/testcases/block/09_html/simple.html +60 -0
  289. data/test/testcases/block/09_html/simple.options +1 -0
  290. data/test/testcases/block/09_html/simple.text +55 -0
  291. data/test/testcases/block/09_html/standalone_image_in_div.htmlinput +7 -0
  292. data/test/testcases/block/09_html/standalone_image_in_div.text +8 -0
  293. data/test/testcases/block/09_html/textarea.html +8 -0
  294. data/test/testcases/block/09_html/textarea.text +8 -0
  295. data/test/testcases/block/09_html/xml.html +8 -0
  296. data/test/testcases/block/09_html/xml.text +7 -0
  297. data/test/testcases/block/10_ald/simple.html +2 -0
  298. data/test/testcases/block/10_ald/simple.text +8 -0
  299. data/test/testcases/block/11_ial/auto_id_and_ial.html +1 -0
  300. data/test/testcases/block/11_ial/auto_id_and_ial.options +1 -0
  301. data/test/testcases/block/11_ial/auto_id_and_ial.text +2 -0
  302. data/test/testcases/block/11_ial/nested.html +11 -0
  303. data/test/testcases/block/11_ial/nested.text +15 -0
  304. data/test/testcases/block/11_ial/simple.html +29 -0
  305. data/test/testcases/block/11_ial/simple.text +41 -0
  306. data/test/testcases/block/12_extension/comment.html +8 -0
  307. data/test/testcases/block/12_extension/comment.text +12 -0
  308. data/test/testcases/block/12_extension/ignored.html +8 -0
  309. data/test/testcases/block/12_extension/ignored.text +8 -0
  310. data/test/testcases/block/12_extension/nomarkdown.html +10 -0
  311. data/test/testcases/block/12_extension/nomarkdown.kramdown +20 -0
  312. data/test/testcases/block/12_extension/nomarkdown.latex +13 -0
  313. data/test/testcases/block/12_extension/nomarkdown.text +21 -0
  314. data/test/testcases/block/12_extension/options.html +21 -0
  315. data/test/testcases/block/12_extension/options.text +23 -0
  316. data/test/testcases/block/12_extension/options2.html +10 -0
  317. data/test/testcases/block/12_extension/options2.text +5 -0
  318. data/test/testcases/block/12_extension/options3.html +8 -0
  319. data/test/testcases/block/12_extension/options3.text +7 -0
  320. data/test/testcases/block/13_definition_list/auto_ids.html +15 -0
  321. data/test/testcases/block/13_definition_list/auto_ids.text +18 -0
  322. data/test/testcases/block/13_definition_list/definition_at_beginning.html +1 -0
  323. data/test/testcases/block/13_definition_list/definition_at_beginning.text +1 -0
  324. data/test/testcases/block/13_definition_list/deflist_ial.html +4 -0
  325. data/test/testcases/block/13_definition_list/deflist_ial.text +4 -0
  326. data/test/testcases/block/13_definition_list/item_ial.html +17 -0
  327. data/test/testcases/block/13_definition_list/item_ial.text +16 -0
  328. data/test/testcases/block/13_definition_list/multiple_terms.html +13 -0
  329. data/test/testcases/block/13_definition_list/multiple_terms.text +10 -0
  330. data/test/testcases/block/13_definition_list/no_def_list.html +2 -0
  331. data/test/testcases/block/13_definition_list/no_def_list.text +2 -0
  332. data/test/testcases/block/13_definition_list/para_wrapping.html +10 -0
  333. data/test/testcases/block/13_definition_list/para_wrapping.text +6 -0
  334. data/test/testcases/block/13_definition_list/separated_by_eob.html +8 -0
  335. data/test/testcases/block/13_definition_list/separated_by_eob.text +5 -0
  336. data/test/testcases/block/13_definition_list/simple.html +10 -0
  337. data/test/testcases/block/13_definition_list/simple.text +10 -0
  338. data/test/testcases/block/13_definition_list/styled_terms.html +4 -0
  339. data/test/testcases/block/13_definition_list/styled_terms.text +2 -0
  340. data/test/testcases/block/13_definition_list/too_much_space.html +3 -0
  341. data/test/testcases/block/13_definition_list/too_much_space.text +4 -0
  342. data/test/testcases/block/13_definition_list/with_blocks.html +38 -0
  343. data/test/testcases/block/13_definition_list/with_blocks.text +24 -0
  344. data/test/testcases/block/14_table/empty_tag_in_cell.html +8 -0
  345. data/test/testcases/block/14_table/empty_tag_in_cell.options +1 -0
  346. data/test/testcases/block/14_table/empty_tag_in_cell.text +1 -0
  347. data/test/testcases/block/14_table/errors.html +12 -0
  348. data/test/testcases/block/14_table/errors.text +13 -0
  349. data/test/testcases/block/14_table/escaping.html +52 -0
  350. data/test/testcases/block/14_table/escaping.text +19 -0
  351. data/test/testcases/block/14_table/footer.html +65 -0
  352. data/test/testcases/block/14_table/footer.text +25 -0
  353. data/test/testcases/block/14_table/header.html +117 -0
  354. data/test/testcases/block/14_table/header.text +39 -0
  355. data/test/testcases/block/14_table/no_table.html +3 -0
  356. data/test/testcases/block/14_table/no_table.text +3 -0
  357. data/test/testcases/block/14_table/simple.html +192 -0
  358. data/test/testcases/block/14_table/simple.text +53 -0
  359. data/test/testcases/block/14_table/table_with_footnote.html +25 -0
  360. data/test/testcases/block/14_table/table_with_footnote.latex +11 -0
  361. data/test/testcases/block/14_table/table_with_footnote.text +6 -0
  362. data/test/testcases/block/15_math/gh_128.html +1 -0
  363. data/test/testcases/block/15_math/gh_128.text +1 -0
  364. data/test/testcases/block/15_math/no_engine.html +3 -0
  365. data/test/testcases/block/15_math/no_engine.options +1 -0
  366. data/test/testcases/block/15_math/no_engine.text +2 -0
  367. data/test/testcases/block/15_math/normal.html +30 -0
  368. data/test/testcases/block/15_math/normal.text +30 -0
  369. data/test/testcases/block/16_toc/no_toc.html +14 -0
  370. data/test/testcases/block/16_toc/no_toc.text +16 -0
  371. data/test/testcases/block/16_toc/toc_exclude.html +35 -0
  372. data/test/testcases/block/16_toc/toc_exclude.options +1 -0
  373. data/test/testcases/block/16_toc/toc_exclude.text +19 -0
  374. data/test/testcases/block/16_toc/toc_levels.html +24 -0
  375. data/test/testcases/block/16_toc/toc_levels.options +2 -0
  376. data/test/testcases/block/16_toc/toc_levels.text +16 -0
  377. data/test/testcases/block/16_toc/toc_with_footnotes.html +13 -0
  378. data/test/testcases/block/16_toc/toc_with_footnotes.options +1 -0
  379. data/test/testcases/block/16_toc/toc_with_footnotes.text +6 -0
  380. data/test/testcases/block/16_toc/toc_with_links.html +8 -0
  381. data/test/testcases/block/16_toc/toc_with_links.options +2 -0
  382. data/test/testcases/block/16_toc/toc_with_links.text +8 -0
  383. data/test/testcases/cjk-line-break.html +4 -0
  384. data/test/testcases/cjk-line-break.options +1 -0
  385. data/test/testcases/cjk-line-break.text +12 -0
  386. data/test/testcases/encoding.html +46 -0
  387. data/test/testcases/encoding.text +28 -0
  388. data/test/testcases/man/example.man +123 -0
  389. data/test/testcases/man/example.text +85 -0
  390. data/test/testcases/man/heading-name-dash-description.man +4 -0
  391. data/test/testcases/man/heading-name-dash-description.text +1 -0
  392. data/test/testcases/man/heading-name-description.man +4 -0
  393. data/test/testcases/man/heading-name-description.text +2 -0
  394. data/test/testcases/man/heading-name-section-description.man +4 -0
  395. data/test/testcases/man/heading-name-section-description.text +1 -0
  396. data/test/testcases/man/heading-name-section.man +2 -0
  397. data/test/testcases/man/heading-name-section.text +1 -0
  398. data/test/testcases/man/heading-name.man +2 -0
  399. data/test/testcases/man/heading-name.text +1 -0
  400. data/test/testcases/man/sections.man +4 -0
  401. data/test/testcases/man/sections.text +11 -0
  402. data/test/testcases/man/text-escaping.man +8 -0
  403. data/test/testcases/man/text-escaping.text +7 -0
  404. data/test/testcases/span/01_link/empty.html +5 -0
  405. data/test/testcases/span/01_link/empty.text +5 -0
  406. data/test/testcases/span/01_link/empty_title.htmlinput +3 -0
  407. data/test/testcases/span/01_link/empty_title.text +7 -0
  408. data/test/testcases/span/01_link/image_in_a.html +5 -0
  409. data/test/testcases/span/01_link/image_in_a.text +5 -0
  410. data/test/testcases/span/01_link/imagelinks.html +15 -0
  411. data/test/testcases/span/01_link/imagelinks.text +18 -0
  412. data/test/testcases/span/01_link/inline.html +46 -0
  413. data/test/testcases/span/01_link/inline.text +48 -0
  414. data/test/testcases/span/01_link/latex_escaping.latex +6 -0
  415. data/test/testcases/span/01_link/latex_escaping.text +5 -0
  416. data/test/testcases/span/01_link/link_defs.html +9 -0
  417. data/test/testcases/span/01_link/link_defs.text +27 -0
  418. data/test/testcases/span/01_link/link_defs_with_ial.html +4 -0
  419. data/test/testcases/span/01_link/link_defs_with_ial.text +16 -0
  420. data/test/testcases/span/01_link/links_with_angle_brackets.html +3 -0
  421. data/test/testcases/span/01_link/links_with_angle_brackets.text +3 -0
  422. data/test/testcases/span/01_link/reference.html +37 -0
  423. data/test/testcases/span/01_link/reference.options +3 -0
  424. data/test/testcases/span/01_link/reference.text +53 -0
  425. data/test/testcases/span/02_emphasis/empty.html +3 -0
  426. data/test/testcases/span/02_emphasis/empty.text +3 -0
  427. data/test/testcases/span/02_emphasis/errors.html +9 -0
  428. data/test/testcases/span/02_emphasis/errors.text +9 -0
  429. data/test/testcases/span/02_emphasis/nesting.html +41 -0
  430. data/test/testcases/span/02_emphasis/nesting.text +36 -0
  431. data/test/testcases/span/02_emphasis/normal.html +65 -0
  432. data/test/testcases/span/02_emphasis/normal.options +1 -0
  433. data/test/testcases/span/02_emphasis/normal.text +63 -0
  434. data/test/testcases/span/03_codespan/empty.html +5 -0
  435. data/test/testcases/span/03_codespan/empty.text +5 -0
  436. data/test/testcases/span/03_codespan/errors.html +1 -0
  437. data/test/testcases/span/03_codespan/errors.text +1 -0
  438. data/test/testcases/span/03_codespan/highlighting-minted.latex +2 -0
  439. data/test/testcases/span/03_codespan/highlighting-minted.options +1 -0
  440. data/test/testcases/span/03_codespan/highlighting-minted.text +1 -0
  441. data/test/testcases/span/03_codespan/highlighting.html +1 -0
  442. data/test/testcases/span/03_codespan/highlighting.text +1 -0
  443. data/test/testcases/span/03_codespan/normal-css-class.html +1 -0
  444. data/test/testcases/span/03_codespan/normal-css-class.options +2 -0
  445. data/test/testcases/span/03_codespan/normal-css-class.text +1 -0
  446. data/test/testcases/span/03_codespan/normal.html +16 -0
  447. data/test/testcases/span/03_codespan/normal.text +16 -0
  448. data/test/testcases/span/03_codespan/rouge/disabled.html +1 -0
  449. data/test/testcases/span/03_codespan/rouge/disabled.options +4 -0
  450. data/test/testcases/span/03_codespan/rouge/disabled.text +1 -0
  451. data/test/testcases/span/03_codespan/rouge/simple.html +1 -0
  452. data/test/testcases/span/03_codespan/rouge/simple.options +1 -0
  453. data/test/testcases/span/03_codespan/rouge/simple.text +1 -0
  454. data/test/testcases/span/04_footnote/backlink_inline.html +79 -0
  455. data/test/testcases/span/04_footnote/backlink_inline.options +1 -0
  456. data/test/testcases/span/04_footnote/backlink_inline.text +38 -0
  457. data/test/testcases/span/04_footnote/backlink_text.html +9 -0
  458. data/test/testcases/span/04_footnote/backlink_text.options +1 -0
  459. data/test/testcases/span/04_footnote/backlink_text.text +3 -0
  460. data/test/testcases/span/04_footnote/definitions.html +17 -0
  461. data/test/testcases/span/04_footnote/definitions.latex +17 -0
  462. data/test/testcases/span/04_footnote/definitions.text +24 -0
  463. data/test/testcases/span/04_footnote/footnote_nr.html +12 -0
  464. data/test/testcases/span/04_footnote/footnote_nr.latex +2 -0
  465. data/test/testcases/span/04_footnote/footnote_nr.options +1 -0
  466. data/test/testcases/span/04_footnote/footnote_nr.text +4 -0
  467. data/test/testcases/span/04_footnote/footnote_prefix.html +12 -0
  468. data/test/testcases/span/04_footnote/footnote_prefix.options +1 -0
  469. data/test/testcases/span/04_footnote/footnote_prefix.text +4 -0
  470. data/test/testcases/span/04_footnote/inside_footnote.html +17 -0
  471. data/test/testcases/span/04_footnote/inside_footnote.text +9 -0
  472. data/test/testcases/span/04_footnote/markers.html +46 -0
  473. data/test/testcases/span/04_footnote/markers.latex +23 -0
  474. data/test/testcases/span/04_footnote/markers.options +2 -0
  475. data/test/testcases/span/04_footnote/markers.text +27 -0
  476. data/test/testcases/span/04_footnote/placement.html +11 -0
  477. data/test/testcases/span/04_footnote/placement.options +1 -0
  478. data/test/testcases/span/04_footnote/placement.text +8 -0
  479. data/test/testcases/span/04_footnote/regexp_problem.html +14 -0
  480. data/test/testcases/span/04_footnote/regexp_problem.options +2 -0
  481. data/test/testcases/span/04_footnote/regexp_problem.text +52 -0
  482. data/test/testcases/span/04_footnote/without_backlink.html +9 -0
  483. data/test/testcases/span/04_footnote/without_backlink.options +1 -0
  484. data/test/testcases/span/04_footnote/without_backlink.text +3 -0
  485. data/test/testcases/span/05_html/across_lines.html +1 -0
  486. data/test/testcases/span/05_html/across_lines.text +2 -0
  487. data/test/testcases/span/05_html/button.html +7 -0
  488. data/test/testcases/span/05_html/button.text +7 -0
  489. data/test/testcases/span/05_html/invalid.html +1 -0
  490. data/test/testcases/span/05_html/invalid.text +1 -0
  491. data/test/testcases/span/05_html/link_with_mailto.html +1 -0
  492. data/test/testcases/span/05_html/link_with_mailto.text +1 -0
  493. data/test/testcases/span/05_html/mark_element.html +3 -0
  494. data/test/testcases/span/05_html/mark_element.text +3 -0
  495. data/test/testcases/span/05_html/markdown_attr.html +6 -0
  496. data/test/testcases/span/05_html/markdown_attr.text +6 -0
  497. data/test/testcases/span/05_html/normal.html +43 -0
  498. data/test/testcases/span/05_html/normal.text +43 -0
  499. data/test/testcases/span/05_html/raw_span_elements.html +2 -0
  500. data/test/testcases/span/05_html/raw_span_elements.text +2 -0
  501. data/test/testcases/span/05_html/xml.html +5 -0
  502. data/test/testcases/span/05_html/xml.text +5 -0
  503. data/test/testcases/span/abbreviations/abbrev.html +21 -0
  504. data/test/testcases/span/abbreviations/abbrev.text +34 -0
  505. data/test/testcases/span/abbreviations/abbrev_defs.html +2 -0
  506. data/test/testcases/span/abbreviations/abbrev_defs.text +5 -0
  507. data/test/testcases/span/abbreviations/in_footnote.html +9 -0
  508. data/test/testcases/span/abbreviations/in_footnote.text +5 -0
  509. data/test/testcases/span/autolinks/url_links.html +15 -0
  510. data/test/testcases/span/autolinks/url_links.text +16 -0
  511. data/test/testcases/span/escaped_chars/normal.html +47 -0
  512. data/test/testcases/span/escaped_chars/normal.text +47 -0
  513. data/test/testcases/span/extension/comment.html +6 -0
  514. data/test/testcases/span/extension/comment.text +6 -0
  515. data/test/testcases/span/extension/ignored.html +1 -0
  516. data/test/testcases/span/extension/ignored.text +1 -0
  517. data/test/testcases/span/extension/nomarkdown.html +1 -0
  518. data/test/testcases/span/extension/nomarkdown.text +1 -0
  519. data/test/testcases/span/extension/options.html +1 -0
  520. data/test/testcases/span/extension/options.text +1 -0
  521. data/test/testcases/span/ial/simple.html +6 -0
  522. data/test/testcases/span/ial/simple.text +6 -0
  523. data/test/testcases/span/line_breaks/normal.html +11 -0
  524. data/test/testcases/span/line_breaks/normal.latex +12 -0
  525. data/test/testcases/span/line_breaks/normal.text +11 -0
  526. data/test/testcases/span/math/no_engine.html +1 -0
  527. data/test/testcases/span/math/no_engine.options +1 -0
  528. data/test/testcases/span/math/no_engine.text +1 -0
  529. data/test/testcases/span/math/normal.html +10 -0
  530. data/test/testcases/span/math/normal.text +10 -0
  531. data/test/testcases/span/text_substitutions/entities.html +6 -0
  532. data/test/testcases/span/text_substitutions/entities.options +1 -0
  533. data/test/testcases/span/text_substitutions/entities.text +6 -0
  534. data/test/testcases/span/text_substitutions/entities_as_char.html +1 -0
  535. data/test/testcases/span/text_substitutions/entities_as_char.options +2 -0
  536. data/test/testcases/span/text_substitutions/entities_as_char.text +1 -0
  537. data/test/testcases/span/text_substitutions/entities_as_input.html +1 -0
  538. data/test/testcases/span/text_substitutions/entities_as_input.options +1 -0
  539. data/test/testcases/span/text_substitutions/entities_as_input.text +1 -0
  540. data/test/testcases/span/text_substitutions/entities_numeric.html +1 -0
  541. data/test/testcases/span/text_substitutions/entities_numeric.options +1 -0
  542. data/test/testcases/span/text_substitutions/entities_numeric.text +1 -0
  543. data/test/testcases/span/text_substitutions/entities_symbolic.html +1 -0
  544. data/test/testcases/span/text_substitutions/entities_symbolic.options +1 -0
  545. data/test/testcases/span/text_substitutions/entities_symbolic.text +1 -0
  546. data/test/testcases/span/text_substitutions/greaterthan.html +1 -0
  547. data/test/testcases/span/text_substitutions/greaterthan.text +1 -0
  548. data/test/testcases/span/text_substitutions/lowerthan.html +1 -0
  549. data/test/testcases/span/text_substitutions/lowerthan.text +1 -0
  550. data/test/testcases/span/text_substitutions/typography.html +40 -0
  551. data/test/testcases/span/text_substitutions/typography.options +1 -0
  552. data/test/testcases/span/text_substitutions/typography.text +40 -0
  553. data/test/testcases/span/text_substitutions/typography_subst.html +3 -0
  554. data/test/testcases/span/text_substitutions/typography_subst.latex +4 -0
  555. data/test/testcases/span/text_substitutions/typography_subst.options +8 -0
  556. data/test/testcases/span/text_substitutions/typography_subst.text +3 -0
  557. metadata +659 -0
@@ -0,0 +1,261 @@
1
+ # -*- coding: utf-8; frozen_string_literal: true -*-
2
+ #
3
+ #--
4
+ # Copyright (C) 2009-2019 Thomas Leitner <t_leitner@gmx.at>
5
+ #
6
+ # This file is part of kramdown which is licensed under the MIT.
7
+ #++
8
+ #
9
+
10
+ require 'erb'
11
+ require 'kramdown/utils'
12
+ require 'kramdown/document'
13
+
14
+ module Kramdown
15
+
16
+ module Converter
17
+
18
+ # == \Base class for converters
19
+ #
20
+ # This class serves as base class for all converters. It provides methods that can/should be
21
+ # used by all converters (like #generate_id) as well as common functionality that is
22
+ # automatically applied to the result (for example, embedding the output into a template).
23
+ #
24
+ # A converter object is used as a throw-away object, i.e. it is only used for storing the needed
25
+ # state information during conversion. Therefore one can't instantiate a converter object
26
+ # directly but only use the Base::convert method.
27
+ #
28
+ # == Implementing a converter
29
+ #
30
+ # Implementing a new converter is rather easy: just derive a new class from this class and put
31
+ # it in the Kramdown::Converter module (the latter is only needed if auto-detection should work
32
+ # properly). Then you need to implement the #convert method which has to contain the conversion
33
+ # code for converting an element and has to return the conversion result.
34
+ #
35
+ # The actual transformation of the document tree can be done in any way. However, writing one
36
+ # method per element type is a straight forward way to do it - this is how the Html and Latex
37
+ # converters do the transformation.
38
+ #
39
+ # Have a look at the Base::convert method for additional information!
40
+ class Base
41
+
42
+ # Can be used by a converter for storing arbitrary information during the conversion process.
43
+ attr_reader :data
44
+
45
+ # The hash with the conversion options.
46
+ attr_reader :options
47
+
48
+ # The root element that is converted.
49
+ attr_reader :root
50
+
51
+ # The warnings array.
52
+ attr_reader :warnings
53
+
54
+ # Initialize the converter with the given +root+ element and +options+ hash.
55
+ def initialize(root, options)
56
+ @options = options
57
+ @root = root
58
+ @data = {}
59
+ @warnings = []
60
+ end
61
+ private_class_method(:new, :allocate)
62
+
63
+ # Returns whether the template should be applied before the conversion of the tree.
64
+ #
65
+ # Defaults to false.
66
+ def apply_template_before?
67
+ false
68
+ end
69
+
70
+ # Returns whether the template should be applied after the conversion of the tree.
71
+ #
72
+ # Defaults to true.
73
+ def apply_template_after?
74
+ true
75
+ end
76
+
77
+ # Convert the element tree +tree+ and return the resulting conversion object (normally a
78
+ # string) and an array with warning messages. The parameter +options+ specifies the conversion
79
+ # options that should be used.
80
+ #
81
+ # Initializes a new instance of the calling class and then calls the #convert method with
82
+ # +tree+ as parameter.
83
+ #
84
+ # If the +template+ option is specified and non-empty, the template is evaluate with ERB
85
+ # before and/or after the tree conversion depending on the result of #apply_template_before?
86
+ # and #apply_template_after?. If the template is evaluated before, an empty string is used for
87
+ # the body; if evaluated after, the result is used as body. See ::apply_template.
88
+ #
89
+ # The template resolution is done in the following way (for the converter ConverterName):
90
+ #
91
+ # 1. Look in the current working directory for the template.
92
+ #
93
+ # 2. Append +.converter_name+ (e.g. +.html+) to the template name and look for the resulting
94
+ # file in the current working directory (the form +.convertername+ is deprecated).
95
+ #
96
+ # 3. Append +.converter_name+ to the template name and look for it in the kramdown data
97
+ # directory (the form +.convertername+ is deprecated).
98
+ #
99
+ # 4. Check if the template name starts with 'string://' and if so, strip this prefix away and
100
+ # use the rest as template.
101
+ def self.convert(tree, options = {})
102
+ converter = new(tree, ::Kramdown::Options.merge(options.merge(tree.options[:options] || {})))
103
+
104
+ if !converter.options[:template].empty? && converter.apply_template_before?
105
+ apply_template(converter, '')
106
+ end
107
+ result = converter.convert(tree)
108
+ if result.respond_to?(:encode!) && result.encoding != Encoding::BINARY
109
+ result.encode!(tree.options[:encoding] ||
110
+ (raise ::Kramdown::Error, "Missing encoding option on root element"))
111
+ end
112
+ if !converter.options[:template].empty? && converter.apply_template_after?
113
+ result = apply_template(converter, result)
114
+ end
115
+
116
+ [result, converter.warnings]
117
+ end
118
+
119
+ # Convert the element +el+ and return the resulting object.
120
+ #
121
+ # This is the only method that has to be implemented by sub-classes!
122
+ def convert(_el)
123
+ raise NotImplementedError
124
+ end
125
+
126
+ def convert_auto_a(el, opts)
127
+ convert_a(el, opts)
128
+ end
129
+
130
+ # Apply the +template+ using +body+ as the body string.
131
+ #
132
+ # The template is evaluated using ERB and the body is available in the @body instance variable
133
+ # and the converter object in the @converter instance variable.
134
+ def self.apply_template(converter, body) # :nodoc:
135
+ erb = ERB.new(get_template(converter.options[:template]))
136
+ obj = Object.new
137
+ obj.instance_variable_set(:@converter, converter)
138
+ obj.instance_variable_set(:@body, body)
139
+ erb.result(obj.instance_eval { binding })
140
+ end
141
+
142
+ # Return the template specified by +template+.
143
+ def self.get_template(template) # :nodoc:
144
+ format_ext = '.' + ::Kramdown::Utils.snake_case(self.name.split(/::/).last)
145
+ shipped = File.join(::Kramdown.data_dir, template + format_ext)
146
+ if File.exist?(template)
147
+ File.read(template)
148
+ elsif File.exist?(template + format_ext)
149
+ File.read(template + format_ext)
150
+ elsif File.exist?(shipped)
151
+ File.read(shipped)
152
+ elsif template.start_with?('string://')
153
+ template.sub(/\Astring:\/\//, '')
154
+ else
155
+ raise "The specified template file #{template} does not exist"
156
+ end
157
+ end
158
+
159
+ # Add the given warning +text+ to the warning array.
160
+ def warning(text)
161
+ @warnings << text
162
+ end
163
+
164
+ # Return +true+ if the header element +el+ should be used for the table of contents (as
165
+ # specified by the +toc_levels+ option).
166
+ def in_toc?(el)
167
+ @options[:toc_levels].include?(el.options[:level]) && (el.attr['class'] || '') !~ /\bno_toc\b/
168
+ end
169
+
170
+ # Return the output header level given a level.
171
+ #
172
+ # Uses the +header_offset+ option for adjusting the header level.
173
+ def output_header_level(level)
174
+ [[level + @options[:header_offset], 6].min, 1].max
175
+ end
176
+
177
+ # Extract the code block/span language from the attributes.
178
+ def extract_code_language(attr)
179
+ if attr['class'] && attr['class'] =~ /\blanguage-\S+/
180
+ attr['class'].scan(/\blanguage-(\S+)/).first.first
181
+ end
182
+ end
183
+
184
+ # See #extract_code_language
185
+ #
186
+ # *Warning*: This version will modify the given attributes if a language is present.
187
+ def extract_code_language!(attr)
188
+ lang = extract_code_language(attr)
189
+ attr['class'] = attr['class'].sub(/\blanguage-\S+/, '').strip if lang
190
+ attr.delete('class') if lang && attr['class'].empty?
191
+ lang
192
+ end
193
+
194
+ # Highlight the given +text+ in the language +lang+ with the syntax highlighter configured
195
+ # through the option 'syntax_highlighter'.
196
+ def highlight_code(text, lang, type, opts = {})
197
+ return nil unless @options[:syntax_highlighter]
198
+
199
+ highlighter = ::Kramdown::Converter.syntax_highlighter(@options[:syntax_highlighter])
200
+ if highlighter
201
+ highlighter.call(self, text, lang, type, opts)
202
+ else
203
+ warning("The configured syntax highlighter #{@options[:syntax_highlighter]} is not available.")
204
+ nil
205
+ end
206
+ end
207
+
208
+ # Format the given math element with the math engine configured through the option
209
+ # 'math_engine'.
210
+ def format_math(el, opts = {})
211
+ return nil unless @options[:math_engine]
212
+
213
+ engine = ::Kramdown::Converter.math_engine(@options[:math_engine])
214
+ if engine
215
+ engine.call(self, el, opts)
216
+ else
217
+ warning("The configured math engine #{@options[:math_engine]} is not available.")
218
+ nil
219
+ end
220
+ end
221
+
222
+ # Generate an unique alpha-numeric ID from the the string +str+ for use as a header ID.
223
+ #
224
+ # Uses the option +auto_id_prefix+: the value of this option is prepended to every generated
225
+ # ID.
226
+ def generate_id(str)
227
+ str = ::Kramdown::Utils::Unidecoder.decode(str) if @options[:transliterated_header_ids]
228
+ gen_id = basic_generate_id(str)
229
+ gen_id = 'section' if gen_id.empty?
230
+ @used_ids ||= {}
231
+ if @used_ids.key?(gen_id)
232
+ gen_id += "-#{@used_ids[gen_id] += 1}"
233
+ else
234
+ @used_ids[gen_id] = 0
235
+ end
236
+ @options[:auto_id_prefix] + gen_id
237
+ end
238
+
239
+ # The basic version of the ID generator, without any special provisions for empty or unique
240
+ # IDs.
241
+ def basic_generate_id(str)
242
+ gen_id = str.gsub(/^[^a-zA-Z]+/, '')
243
+ gen_id.tr!('^a-zA-Z0-9 -', '')
244
+ gen_id.tr!(' ', '-')
245
+ gen_id.downcase!
246
+ gen_id
247
+ end
248
+
249
+ SMART_QUOTE_INDICES = {lsquo: 0, rsquo: 1, ldquo: 2, rdquo: 3} # :nodoc:
250
+
251
+ # Return the entity that represents the given smart_quote element.
252
+ def smart_quote_entity(el)
253
+ res = @options[:smart_quotes][SMART_QUOTE_INDICES[el.value]]
254
+ ::Kramdown::Utils::Entities.entity(res)
255
+ end
256
+
257
+ end
258
+
259
+ end
260
+
261
+ end
@@ -0,0 +1,38 @@
1
+ # -*- coding: utf-8; frozen_string_literal: true -*-
2
+ #
3
+ #--
4
+ # Copyright (C) 2009-2019 Thomas Leitner <t_leitner@gmx.at>
5
+ #
6
+ # This file is part of kramdown which is licensed under the MIT.
7
+ #++
8
+ #
9
+
10
+ require 'kramdown/parser'
11
+ require 'kramdown/converter'
12
+ require 'kramdown/utils'
13
+
14
+ module Kramdown
15
+
16
+ module Converter
17
+
18
+ # Converts a Kramdown::Document to a nested hash for further processing or debug output.
19
+ class HashAST < Base
20
+
21
+ def convert(el)
22
+ hash = {type: el.type}
23
+ hash[:attr] = el.attr unless el.attr.empty?
24
+ hash[:value] = el.value unless el.value.nil?
25
+ hash[:options] = el.options unless el.options.empty?
26
+ unless el.children.empty?
27
+ hash[:children] = []
28
+ el.children.each {|child| hash[:children] << convert(child) }
29
+ end
30
+ hash
31
+ end
32
+
33
+ end
34
+
35
+ HashAst = HashAST
36
+
37
+ end
38
+ end
@@ -0,0 +1,535 @@
1
+ # -*- coding: utf-8; frozen_string_literal: true -*-
2
+ #
3
+ #--
4
+ # Copyright (C) 2009-2019 Thomas Leitner <t_leitner@gmx.at>
5
+ #
6
+ # This file is part of kramdown which is licensed under the MIT.
7
+ #++
8
+ #
9
+
10
+ require 'kramdown/parser'
11
+ require 'kramdown/converter'
12
+ require 'kramdown/utils'
13
+
14
+ module Kramdown
15
+
16
+ module Converter
17
+
18
+ # Converts a Kramdown::Document to HTML.
19
+ #
20
+ # You can customize the HTML converter by sub-classing it and overriding the +convert_NAME+
21
+ # methods. Each such method takes the following parameters:
22
+ #
23
+ # [+el+] The element of type +NAME+ to be converted.
24
+ #
25
+ # [+indent+] A number representing the current amount of spaces for indent (only used for
26
+ # block-level elements).
27
+ #
28
+ # The return value of such a method has to be a string containing the element +el+ formatted as
29
+ # HTML element.
30
+ class Html < Base
31
+
32
+ include ::Kramdown::Utils::Html
33
+ include ::Kramdown::Parser::Html::Constants
34
+
35
+ # The amount of indentation used when nesting HTML tags.
36
+ attr_accessor :indent
37
+
38
+ # Initialize the HTML converter with the given Kramdown document +doc+.
39
+ def initialize(root, options)
40
+ super
41
+ @footnote_counter = @footnote_start = @options[:footnote_nr]
42
+ @footnotes = []
43
+ @footnotes_by_name = {}
44
+ @footnote_location = nil
45
+ @toc = []
46
+ @toc_code = nil
47
+ @indent = 2
48
+ @stack = []
49
+
50
+ # stash string representation of symbol to avoid allocations from multiple interpolations.
51
+ @highlighter_class = " highlighter-#{options[:syntax_highlighter]}"
52
+ @dispatcher = Hash.new {|h, k| h[k] = :"convert_#{k}" }
53
+ end
54
+
55
+ # Dispatch the conversion of the element +el+ to a +convert_TYPE+ method using the +type+ of
56
+ # the element.
57
+ def convert(el, indent = -@indent)
58
+ send(@dispatcher[el.type], el, indent)
59
+ end
60
+
61
+ # Return the converted content of the children of +el+ as a string. The parameter +indent+ has
62
+ # to be the amount of indentation used for the element +el+.
63
+ #
64
+ # Pushes +el+ onto the @stack before converting the child elements and pops it from the stack
65
+ # afterwards.
66
+ def inner(el, indent)
67
+ result = +''
68
+ indent += @indent
69
+ @stack.push(el)
70
+ el.children.each do |inner_el|
71
+ result << send(@dispatcher[inner_el.type], inner_el, indent)
72
+ end
73
+ @stack.pop
74
+ result
75
+ end
76
+
77
+ def convert_blank(_el, _indent)
78
+ "\n"
79
+ end
80
+
81
+ def convert_text(el, _indent)
82
+ escaped = escape_html(el.value, :text)
83
+ @options[:remove_line_breaks_for_cjk] ? fix_cjk_line_break(escaped) : escaped
84
+ end
85
+
86
+ def convert_p(el, indent)
87
+ if el.options[:transparent]
88
+ inner(el, indent)
89
+ elsif el.children.size == 1 && el.children.first.type == :img &&
90
+ el.children.first.options[:ial]&.[](:refs)&.include?('standalone')
91
+ convert_standalone_image(el.children.first, indent)
92
+ else
93
+ format_as_block_html("p", el.attr, inner(el, indent), indent)
94
+ end
95
+ end
96
+
97
+ # Helper method used by +convert_p+ to convert a paragraph that only contains a single :img
98
+ # element.
99
+ def convert_standalone_image(el, indent)
100
+ attr = el.attr.dup
101
+ figure_attr = {}
102
+ figure_attr['class'] = attr.delete('class') if attr.key?('class')
103
+ figure_attr['id'] = attr.delete('id') if attr.key?('id')
104
+ body = "#{' ' * (indent + @indent)}<img#{html_attributes(attr)} />\n" \
105
+ "#{' ' * (indent + @indent)}<figcaption>#{attr['alt']}</figcaption>\n"
106
+ format_as_indented_block_html("figure", figure_attr, body, indent)
107
+ end
108
+
109
+ def convert_codeblock(el, indent)
110
+ attr = el.attr.dup
111
+ lang = extract_code_language!(attr)
112
+ hl_opts = {}
113
+ highlighted_code = highlight_code(el.value, el.options[:lang] || lang, :block, hl_opts)
114
+
115
+ if highlighted_code
116
+ add_syntax_highlighter_to_class_attr(attr, lang || hl_opts[:default_lang])
117
+ "#{' ' * indent}<div#{html_attributes(attr)}>#{highlighted_code}#{' ' * indent}</div>\n"
118
+ else
119
+ result = escape_html(el.value)
120
+ result.chomp!
121
+ if el.attr['class'].to_s =~ /\bshow-whitespaces\b/
122
+ result.gsub!(/(?:(^[ \t]+)|([ \t]+$)|([ \t]+))/) do |m|
123
+ suffix = ($1 ? '-l' : ($2 ? '-r' : ''))
124
+ m.scan(/./).map do |c|
125
+ case c
126
+ when "\t" then "<span class=\"ws-tab#{suffix}\">\t</span>"
127
+ when " " then "<span class=\"ws-space#{suffix}\">&#8901;</span>"
128
+ end
129
+ end.join('')
130
+ end
131
+ end
132
+ code_attr = {}
133
+ code_attr['class'] = "language-#{lang}" if lang
134
+ "#{' ' * indent}<pre#{html_attributes(attr)}>" \
135
+ "<code#{html_attributes(code_attr)}>#{result}\n</code></pre>\n"
136
+ end
137
+ end
138
+
139
+ def convert_blockquote(el, indent)
140
+ format_as_indented_block_html("blockquote", el.attr, inner(el, indent), indent)
141
+ end
142
+
143
+ def convert_header(el, indent)
144
+ attr = el.attr.dup
145
+ if @options[:auto_ids] && !attr['id']
146
+ attr['id'] = generate_id(el.options[:raw_text])
147
+ end
148
+ @toc << [el.options[:level], attr['id'], el.children] if attr['id'] && in_toc?(el)
149
+ level = output_header_level(el.options[:level])
150
+ format_as_block_html("h#{level}", attr, inner(el, indent), indent)
151
+ end
152
+
153
+ def convert_hr(el, indent)
154
+ "#{' ' * indent}<hr#{html_attributes(el.attr)} />\n"
155
+ end
156
+
157
+ ZERO_TO_ONETWENTYEIGHT = (0..128).to_a.freeze
158
+ private_constant :ZERO_TO_ONETWENTYEIGHT
159
+
160
+ def convert_ul(el, indent)
161
+ if !@toc_code && el.options.dig(:ial, :refs)&.include?('toc')
162
+ @toc_code = [el.type, el.attr, ZERO_TO_ONETWENTYEIGHT.map { rand(36).to_s(36) }.join]
163
+ @toc_code.last
164
+ elsif !@footnote_location && el.options.dig(:ial, :refs)&.include?('footnotes')
165
+ @footnote_location = ZERO_TO_ONETWENTYEIGHT.map { rand(36).to_s(36) }.join
166
+ else
167
+ format_as_indented_block_html(el.type, el.attr, inner(el, indent), indent)
168
+ end
169
+ end
170
+ alias convert_ol convert_ul
171
+
172
+ def convert_dl(el, indent)
173
+ format_as_indented_block_html("dl", el.attr, inner(el, indent), indent)
174
+ end
175
+
176
+ def convert_li(el, indent)
177
+ output = ' ' * indent << "<#{el.type}" << html_attributes(el.attr) << ">"
178
+ res = inner(el, indent)
179
+ if el.children.empty? || (el.children.first.type == :p && el.children.first.options[:transparent])
180
+ output << res << (res =~ /\n\Z/ ? ' ' * indent : '')
181
+ else
182
+ output << "\n" << res << ' ' * indent
183
+ end
184
+ output << "</#{el.type}>\n"
185
+ end
186
+ alias convert_dd convert_li
187
+
188
+ def convert_dt(el, indent)
189
+ attr = el.attr.dup
190
+ @stack.last.options[:ial][:refs].each do |ref|
191
+ if ref =~ /\Aauto_ids(?:-([\w-]+))?/
192
+ attr['id'] = "#{$1}#{basic_generate_id(el.options[:raw_text])}".lstrip
193
+ break
194
+ end
195
+ end if !attr['id'] && @stack.last.options[:ial] && @stack.last.options[:ial][:refs]
196
+ format_as_block_html("dt", attr, inner(el, indent), indent)
197
+ end
198
+
199
+ def convert_html_element(el, indent)
200
+ res = inner(el, indent)
201
+ if el.options[:category] == :span
202
+ "<#{el.value}#{html_attributes(el.attr)}" + \
203
+ (res.empty? && HTML_ELEMENTS_WITHOUT_BODY.include?(el.value) ? " />" : ">#{res}</#{el.value}>")
204
+ else
205
+ output = +''
206
+ if @stack.last.type != :html_element || @stack.last.options[:content_model] != :raw
207
+ output << ' ' * indent
208
+ end
209
+ output << "<#{el.value}#{html_attributes(el.attr)}"
210
+ if el.options[:is_closed] && el.options[:content_model] == :raw
211
+ output << " />"
212
+ elsif !res.empty? && el.options[:content_model] != :block
213
+ output << ">#{res}</#{el.value}>"
214
+ elsif !res.empty?
215
+ output << ">\n#{res.chomp}\n" << ' ' * indent << "</#{el.value}>"
216
+ elsif HTML_ELEMENTS_WITHOUT_BODY.include?(el.value)
217
+ output << " />"
218
+ else
219
+ output << "></#{el.value}>"
220
+ end
221
+ output << "\n" if @stack.last.type != :html_element || @stack.last.options[:content_model] != :raw
222
+ output
223
+ end
224
+ end
225
+
226
+ def convert_xml_comment(el, indent)
227
+ if el.options[:category] == :block &&
228
+ (@stack.last.type != :html_element || @stack.last.options[:content_model] != :raw)
229
+ ' ' * indent << el.value << "\n"
230
+ else
231
+ el.value
232
+ end
233
+ end
234
+ alias convert_xml_pi convert_xml_comment
235
+
236
+ def convert_table(el, indent)
237
+ format_as_indented_block_html(el.type, el.attr, inner(el, indent), indent)
238
+ end
239
+ alias convert_thead convert_table
240
+ alias convert_tbody convert_table
241
+ alias convert_tfoot convert_table
242
+ alias convert_tr convert_table
243
+
244
+ ENTITY_NBSP = ::Kramdown::Utils::Entities.entity('nbsp') # :nodoc:
245
+
246
+ def convert_td(el, indent)
247
+ res = inner(el, indent)
248
+ type = (@stack[-2].type == :thead ? :th : :td)
249
+ attr = el.attr
250
+ alignment = @stack[-3].options[:alignment][@stack.last.children.index(el)]
251
+ if alignment != :default
252
+ attr = el.attr.dup
253
+ attr['style'] = (attr.key?('style') ? "#{attr['style']}; " : '') + "text-align: #{alignment}"
254
+ end
255
+ format_as_block_html(type, attr, res.empty? ? entity_to_str(ENTITY_NBSP) : res, indent)
256
+ end
257
+
258
+ def convert_comment(el, indent)
259
+ if el.options[:category] == :block
260
+ "#{' ' * indent}<!-- #{el.value} -->\n"
261
+ else
262
+ "<!-- #{el.value} -->"
263
+ end
264
+ end
265
+
266
+ def convert_br(_el, _indent)
267
+ "<br />"
268
+ end
269
+
270
+ def convert_a(el, indent)
271
+ format_as_span_html("a", el.attr, inner(el, indent))
272
+ end
273
+
274
+ def convert_img(el, _indent)
275
+ "<img#{html_attributes(el.attr)} />"
276
+ end
277
+
278
+ def convert_codespan(el, _indent)
279
+ attr = el.attr.dup
280
+ lang = extract_code_language(attr)
281
+ hl_opts = {}
282
+ result = highlight_code(el.value, lang, :span, hl_opts)
283
+ if result
284
+ add_syntax_highlighter_to_class_attr(attr, hl_opts[:default_lang])
285
+ else
286
+ result = escape_html(el.value)
287
+ end
288
+
289
+ format_as_span_html('code', attr, result)
290
+ end
291
+
292
+ def convert_footnote(el, _indent)
293
+ repeat = ''
294
+ name = @options[:footnote_prefix] + el.options[:name]
295
+ if (footnote = @footnotes_by_name[name])
296
+ number = footnote[2]
297
+ repeat = ":#{footnote[3] += 1}"
298
+ else
299
+ number = @footnote_counter
300
+ @footnote_counter += 1
301
+ @footnotes << [name, el.value, number, 0]
302
+ @footnotes_by_name[name] = @footnotes.last
303
+ end
304
+ "<sup id=\"fnref:#{name}#{repeat}\" role=\"doc-noteref\">" \
305
+ "<a href=\"#fn:#{name}\" class=\"footnote\">" \
306
+ "#{number}</a></sup>"
307
+ end
308
+
309
+ def convert_raw(el, _indent)
310
+ if !el.options[:type] || el.options[:type].empty? || el.options[:type].include?('html')
311
+ el.value + (el.options[:category] == :block ? "\n" : '')
312
+ else
313
+ ''
314
+ end
315
+ end
316
+
317
+ def convert_em(el, indent)
318
+ format_as_span_html(el.type, el.attr, inner(el, indent))
319
+ end
320
+ alias convert_strong convert_em
321
+
322
+ def convert_entity(el, _indent)
323
+ entity_to_str(el.value, el.options[:original])
324
+ end
325
+
326
+ TYPOGRAPHIC_SYMS = {
327
+ mdash: [::Kramdown::Utils::Entities.entity('mdash')],
328
+ ndash: [::Kramdown::Utils::Entities.entity('ndash')],
329
+ hellip: [::Kramdown::Utils::Entities.entity('hellip')],
330
+ laquo_space: [::Kramdown::Utils::Entities.entity('laquo'),
331
+ ::Kramdown::Utils::Entities.entity('nbsp')],
332
+ raquo_space: [::Kramdown::Utils::Entities.entity('nbsp'),
333
+ ::Kramdown::Utils::Entities.entity('raquo')],
334
+ laquo: [::Kramdown::Utils::Entities.entity('laquo')],
335
+ raquo: [::Kramdown::Utils::Entities.entity('raquo')],
336
+ } # :nodoc:
337
+ def convert_typographic_sym(el, _indent)
338
+ if (result = @options[:typographic_symbols][el.value])
339
+ escape_html(result, :text)
340
+ else
341
+ TYPOGRAPHIC_SYMS[el.value].map {|e| entity_to_str(e) }.join('')
342
+ end
343
+ end
344
+
345
+ def convert_smart_quote(el, _indent)
346
+ entity_to_str(smart_quote_entity(el))
347
+ end
348
+
349
+ def convert_math(el, indent)
350
+ if (result = format_math(el, indent: indent))
351
+ result
352
+ else
353
+ attr = el.attr.dup
354
+ attr['class'] = "#{attr['class']} kdmath".lstrip
355
+ if el.options[:category] == :block
356
+ format_as_block_html('div', attr, "$$\n#{el.value}\n$$", indent)
357
+ else
358
+ format_as_span_html('span', attr, "$#{el.value}$")
359
+ end
360
+ end
361
+ end
362
+
363
+ def convert_abbreviation(el, _indent)
364
+ title = @root.options[:abbrev_defs][el.value]
365
+ attr = @root.options[:abbrev_attr][el.value].dup
366
+ attr['title'] = title unless title.empty?
367
+ format_as_span_html("abbr", attr, el.value)
368
+ end
369
+
370
+ def convert_root(el, indent)
371
+ result = inner(el, indent)
372
+ if @footnote_location
373
+ result.sub!(/#{@footnote_location}/, footnote_content.gsub(/\\/, "\\\\\\\\"))
374
+ else
375
+ result << footnote_content
376
+ end
377
+ if @toc_code
378
+ toc_tree = generate_toc_tree(@toc, @toc_code[0], @toc_code[1] || {})
379
+ text = if !toc_tree.children.empty?
380
+ convert(toc_tree, 0)
381
+ else
382
+ ''
383
+ end
384
+ result.sub!(/#{@toc_code.last}/, text.gsub(/\\/, "\\\\\\\\"))
385
+ end
386
+ result
387
+ end
388
+
389
+ # Format the given element as span HTML.
390
+ def format_as_span_html(name, attr, body)
391
+ "<#{name}#{html_attributes(attr)}>#{body}</#{name}>"
392
+ end
393
+
394
+ # Format the given element as block HTML.
395
+ def format_as_block_html(name, attr, body, indent)
396
+ "#{' ' * indent}<#{name}#{html_attributes(attr)}>#{body}</#{name}>\n"
397
+ end
398
+
399
+ # Format the given element as block HTML with a newline after the start tag and indentation
400
+ # before the end tag.
401
+ def format_as_indented_block_html(name, attr, body, indent)
402
+ "#{' ' * indent}<#{name}#{html_attributes(attr)}>\n#{body}#{' ' * indent}</#{name}>\n"
403
+ end
404
+
405
+ # Add the syntax highlighter name to the 'class' attribute of the given attribute hash. And
406
+ # overwrites or add a "language-LANG" part using the +lang+ parameter if +lang+ is not nil.
407
+ def add_syntax_highlighter_to_class_attr(attr, lang = nil)
408
+ (attr['class'] = (attr['class'] || '') + @highlighter_class).lstrip!
409
+ attr['class'].sub!(/\blanguage-\S+|(^)/) { "language-#{lang}#{$1 ? ' ' : ''}" } if lang
410
+ end
411
+
412
+ # Generate and return an element tree for the table of contents.
413
+ def generate_toc_tree(toc, type, attr)
414
+ sections = Element.new(type, nil, attr.dup)
415
+ sections.attr['id'] ||= 'markdown-toc'
416
+ stack = []
417
+ toc.each do |level, id, children|
418
+ li = Element.new(:li, nil, nil, level: level)
419
+ li.children << Element.new(:p, nil, nil, transparent: true)
420
+ a = Element.new(:a, nil)
421
+ a.attr['href'] = "##{id}"
422
+ a.attr['id'] = "#{sections.attr['id']}-#{id}"
423
+ a.children.concat(fix_for_toc_entry(Marshal.load(Marshal.dump(children))))
424
+ li.children.last.children << a
425
+ li.children << Element.new(type)
426
+
427
+ success = false
428
+ until success
429
+ if stack.empty?
430
+ sections.children << li
431
+ stack << li
432
+ success = true
433
+ elsif stack.last.options[:level] < li.options[:level]
434
+ stack.last.children.last.children << li
435
+ stack << li
436
+ success = true
437
+ else
438
+ item = stack.pop
439
+ item.children.pop if item.children.last.children.empty?
440
+ end
441
+ end
442
+ end
443
+ until stack.empty?
444
+ item = stack.pop
445
+ item.children.pop if item.children.last.children.empty?
446
+ end
447
+ sections
448
+ end
449
+
450
+ # Fixes the elements for use in a TOC entry.
451
+ def fix_for_toc_entry(elements)
452
+ remove_footnotes(elements)
453
+ unwrap_links(elements)
454
+ elements
455
+ end
456
+
457
+ # Remove all link elements by unwrapping them.
458
+ def unwrap_links(elements)
459
+ elements.map! do |c|
460
+ unwrap_links(c.children)
461
+ c.type == :a ? c.children : c
462
+ end.flatten!
463
+ end
464
+
465
+ # Remove all footnotes from the given elements.
466
+ def remove_footnotes(elements)
467
+ elements.delete_if do |c|
468
+ remove_footnotes(c.children)
469
+ c.type == :footnote
470
+ end
471
+ end
472
+
473
+ # Obfuscate the +text+ by using HTML entities.
474
+ def obfuscate(text)
475
+ result = +''
476
+ text.each_byte do |b|
477
+ result << (b > 128 ? b.chr : sprintf("&#%03d;", b))
478
+ end
479
+ result.force_encoding(text.encoding)
480
+ result
481
+ end
482
+
483
+ FOOTNOTE_BACKLINK_FMT = "%s<a href=\"#fnref:%s\" class=\"reversefootnote\" role=\"doc-backlink\">%s</a>"
484
+
485
+ # Return an HTML ordered list with the footnote content for the used footnotes.
486
+ def footnote_content
487
+ ol = Element.new(:ol)
488
+ ol.attr['start'] = @footnote_start if @footnote_start != 1
489
+ i = 0
490
+ backlink_text = escape_html(@options[:footnote_backlink], :text)
491
+ while i < @footnotes.length
492
+ name, data, _, repeat = *@footnotes[i]
493
+ li = Element.new(:li, nil, 'id' => "fn:#{name}", 'role' => 'doc-endnote')
494
+ li.children = Marshal.load(Marshal.dump(data.children))
495
+
496
+ para = nil
497
+ if li.children.last.type == :p || @options[:footnote_backlink_inline]
498
+ parent = li
499
+ while !parent.children.empty? && ![:p, :header].include?(parent.children.last.type)
500
+ parent = parent.children.last
501
+ end
502
+ para = parent.children.last
503
+ insert_space = true
504
+ end
505
+
506
+ unless para
507
+ li.children << (para = Element.new(:p))
508
+ insert_space = false
509
+ end
510
+
511
+ unless @options[:footnote_backlink].empty?
512
+ nbsp = entity_to_str(ENTITY_NBSP)
513
+ value = sprintf(FOOTNOTE_BACKLINK_FMT, (insert_space ? nbsp : ''), name, backlink_text)
514
+ para.children << Element.new(:raw, value)
515
+ (1..repeat).each do |index|
516
+ value = sprintf(FOOTNOTE_BACKLINK_FMT, nbsp, "#{name}:#{index}",
517
+ "#{backlink_text}<sup>#{index + 1}</sup>")
518
+ para.children << Element.new(:raw, value)
519
+ end
520
+ end
521
+
522
+ ol.children << Element.new(:raw, convert(li, 4))
523
+ i += 1
524
+ end
525
+ if ol.children.empty?
526
+ ''
527
+ else
528
+ format_as_indented_block_html('div', {class: "footnotes", role: "doc-endnotes"}, convert(ol, 2), 0)
529
+ end
530
+ end
531
+
532
+ end
533
+
534
+ end
535
+ end