commonmarker 0.0.1

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

Potentially problematic release.


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

Files changed (291) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +8 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.md +119 -0
  5. data/Rakefile +39 -0
  6. data/bin/commonmarker +41 -0
  7. data/commonmarker.gemspec +30 -0
  8. data/ext/commonmarker/cmark/CMakeLists.txt +25 -0
  9. data/ext/commonmarker/cmark/COPYING +192 -0
  10. data/ext/commonmarker/cmark/FindAsan.cmake +74 -0
  11. data/ext/commonmarker/cmark/Makefile +170 -0
  12. data/ext/commonmarker/cmark/Makefile.nmake +36 -0
  13. data/ext/commonmarker/cmark/README.md +169 -0
  14. data/ext/commonmarker/cmark/api_test/CMakeLists.txt +25 -0
  15. data/ext/commonmarker/cmark/api_test/cplusplus.cpp +15 -0
  16. data/ext/commonmarker/cmark/api_test/cplusplus.h +17 -0
  17. data/ext/commonmarker/cmark/api_test/harness.c +102 -0
  18. data/ext/commonmarker/cmark/api_test/harness.h +42 -0
  19. data/ext/commonmarker/cmark/api_test/main.c +700 -0
  20. data/ext/commonmarker/cmark/appveyor.yml +15 -0
  21. data/ext/commonmarker/cmark/bench/statistics.py +595 -0
  22. data/ext/commonmarker/cmark/bench/stats.py +19 -0
  23. data/ext/commonmarker/cmark/benchmarks.md +33 -0
  24. data/ext/commonmarker/cmark/build/CMakeCache.txt +362 -0
  25. data/ext/commonmarker/cmark/build/CMakeFiles/3.2.2/CMakeCCompiler.cmake +63 -0
  26. data/ext/commonmarker/cmark/build/CMakeFiles/3.2.2/CMakeCXXCompiler.cmake +64 -0
  27. data/ext/commonmarker/cmark/build/CMakeFiles/3.2.2/CMakeDetermineCompilerABI_C.bin +0 -0
  28. data/ext/commonmarker/cmark/build/CMakeFiles/3.2.2/CMakeDetermineCompilerABI_CXX.bin +0 -0
  29. data/ext/commonmarker/cmark/build/CMakeFiles/3.2.2/CMakeSystem.cmake +15 -0
  30. data/ext/commonmarker/cmark/build/CMakeFiles/3.2.2/CompilerIdC/CMakeCCompilerId.c +499 -0
  31. data/ext/commonmarker/cmark/build/CMakeFiles/3.2.2/CompilerIdC/a.out +0 -0
  32. data/ext/commonmarker/cmark/build/CMakeFiles/3.2.2/CompilerIdCXX/CMakeCXXCompilerId.cpp +489 -0
  33. data/ext/commonmarker/cmark/build/CMakeFiles/3.2.2/CompilerIdCXX/a.out +0 -0
  34. data/ext/commonmarker/cmark/build/CMakeFiles/CMakeDirectoryInformation.cmake +16 -0
  35. data/ext/commonmarker/cmark/build/CMakeFiles/CMakeError.log +30 -0
  36. data/ext/commonmarker/cmark/build/CMakeFiles/CMakeOutput.log +598 -0
  37. data/ext/commonmarker/cmark/build/CMakeFiles/Makefile.cmake +77 -0
  38. data/ext/commonmarker/cmark/build/CMakeFiles/Makefile2 +268 -0
  39. data/ext/commonmarker/cmark/build/CMakeFiles/TargetDirectories.txt +4 -0
  40. data/ext/commonmarker/cmark/build/CMakeFiles/cmake.check_cache +1 -0
  41. data/ext/commonmarker/cmark/build/CMakeFiles/feature_tests.bin +0 -0
  42. data/ext/commonmarker/cmark/build/CMakeFiles/feature_tests.c +34 -0
  43. data/ext/commonmarker/cmark/build/CMakeFiles/feature_tests.cxx +405 -0
  44. data/ext/commonmarker/cmark/build/CMakeFiles/progress.marks +1 -0
  45. data/ext/commonmarker/cmark/build/CTestTestfile.cmake +10 -0
  46. data/ext/commonmarker/cmark/build/Makefile +237 -0
  47. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/CMakeDirectoryInformation.cmake +16 -0
  48. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/C.includecache +92 -0
  49. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/CXX.includecache +36 -0
  50. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/DependInfo.cmake +29 -0
  51. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/build.make +155 -0
  52. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/cmake_clean.cmake +12 -0
  53. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/cplusplus.cpp.o +0 -0
  54. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/depend.internal +25 -0
  55. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/depend.make +25 -0
  56. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/flags.make +13 -0
  57. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/harness.c.o +0 -0
  58. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/link.txt +1 -0
  59. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/main.c.o +0 -0
  60. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/progress.make +4 -0
  61. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/progress.marks +1 -0
  62. data/ext/commonmarker/cmark/build/api_test/Makefile +277 -0
  63. data/ext/commonmarker/cmark/build/api_test/api_test +0 -0
  64. data/ext/commonmarker/cmark/build/api_test/cmake_install.cmake +29 -0
  65. data/ext/commonmarker/cmark/build/cmake_install.cmake +48 -0
  66. data/ext/commonmarker/cmark/build/man/CMakeFiles/CMakeDirectoryInformation.cmake +16 -0
  67. data/ext/commonmarker/cmark/build/man/CMakeFiles/progress.marks +1 -0
  68. data/ext/commonmarker/cmark/build/man/Makefile +181 -0
  69. data/ext/commonmarker/cmark/build/man/cmake_install.cmake +37 -0
  70. data/ext/commonmarker/cmark/build/src/CMakeFiles/CMakeDirectoryInformation.cmake +16 -0
  71. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/C.includecache +422 -0
  72. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/DependInfo.cmake +39 -0
  73. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/blocks.c.o +0 -0
  74. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/buffer.c.o +0 -0
  75. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/build.make +544 -0
  76. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/cmake_clean.cmake +27 -0
  77. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/cmark.c.o +0 -0
  78. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/cmark_ctype.c.o +0 -0
  79. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/commonmark.c.o +0 -0
  80. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/depend.internal +177 -0
  81. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/depend.make +177 -0
  82. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/flags.make +8 -0
  83. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/houdini_href_e.c.o +0 -0
  84. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/houdini_html_e.c.o +0 -0
  85. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/houdini_html_u.c.o +0 -0
  86. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/html.c.o +0 -0
  87. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/inlines.c.o +0 -0
  88. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/iterator.c.o +0 -0
  89. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/link.txt +1 -0
  90. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/main.c.o +0 -0
  91. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/man.c.o +0 -0
  92. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/node.c.o +0 -0
  93. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/progress.make +19 -0
  94. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/references.c.o +0 -0
  95. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/scanners.c.o +0 -0
  96. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/utf8.c.o +0 -0
  97. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/xml.c.o +0 -0
  98. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/C.includecache +394 -0
  99. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/DependInfo.cmake +44 -0
  100. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/blocks.c.o +0 -0
  101. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/buffer.c.o +0 -0
  102. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/build.make +522 -0
  103. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/cmake_clean.cmake +27 -0
  104. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/cmark.c.o +0 -0
  105. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/cmark_ctype.c.o +0 -0
  106. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/commonmark.c.o +0 -0
  107. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/depend.internal +169 -0
  108. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/depend.make +169 -0
  109. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/flags.make +8 -0
  110. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/houdini_href_e.c.o +0 -0
  111. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/houdini_html_e.c.o +0 -0
  112. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/houdini_html_u.c.o +0 -0
  113. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/html.c.o +0 -0
  114. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/inlines.c.o +0 -0
  115. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/iterator.c.o +0 -0
  116. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/link.txt +1 -0
  117. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/man.c.o +0 -0
  118. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/node.c.o +0 -0
  119. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/progress.make +18 -0
  120. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/references.c.o +0 -0
  121. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/scanners.c.o +0 -0
  122. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/utf8.c.o +0 -0
  123. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/xml.c.o +0 -0
  124. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/C.includecache +394 -0
  125. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/DependInfo.cmake +38 -0
  126. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/blocks.c.o +0 -0
  127. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/buffer.c.o +0 -0
  128. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/build.make +519 -0
  129. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/cmake_clean.cmake +26 -0
  130. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/cmake_clean_target.cmake +3 -0
  131. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/cmark.c.o +0 -0
  132. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/cmark_ctype.c.o +0 -0
  133. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/commonmark.c.o +0 -0
  134. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/depend.internal +169 -0
  135. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/depend.make +169 -0
  136. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/flags.make +8 -0
  137. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/houdini_href_e.c.o +0 -0
  138. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/houdini_html_e.c.o +0 -0
  139. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/houdini_html_u.c.o +0 -0
  140. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/html.c.o +0 -0
  141. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/inlines.c.o +0 -0
  142. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/iterator.c.o +0 -0
  143. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/link.txt +2 -0
  144. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/man.c.o +0 -0
  145. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/node.c.o +0 -0
  146. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/progress.make +18 -0
  147. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/references.c.o +0 -0
  148. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/scanners.c.o +0 -0
  149. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/utf8.c.o +0 -0
  150. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/xml.c.o +0 -0
  151. data/ext/commonmarker/cmark/build/src/CMakeFiles/progress.marks +1 -0
  152. data/ext/commonmarker/cmark/build/src/Makefile +814 -0
  153. data/ext/commonmarker/cmark/build/src/cmake_install.cmake +69 -0
  154. data/ext/commonmarker/cmark/build/src/cmark +0 -0
  155. data/ext/commonmarker/cmark/build/src/cmark_export.h +41 -0
  156. data/ext/commonmarker/cmark/build/src/cmark_version.h +7 -0
  157. data/ext/commonmarker/cmark/build/src/config.h +23 -0
  158. data/ext/commonmarker/cmark/build/src/libcmark.0.19.0.dylib +0 -0
  159. data/ext/commonmarker/cmark/build/src/libcmark.a +0 -0
  160. data/ext/commonmarker/cmark/build/src/libcmark.dylib +0 -0
  161. data/ext/commonmarker/cmark/build/src/libcmark.pc +10 -0
  162. data/ext/commonmarker/cmark/build/testdir/CMakeFiles/CMakeDirectoryInformation.cmake +16 -0
  163. data/ext/commonmarker/cmark/build/testdir/CMakeFiles/progress.marks +1 -0
  164. data/ext/commonmarker/cmark/build/testdir/CTestTestfile.cmake +12 -0
  165. data/ext/commonmarker/cmark/build/testdir/Makefile +181 -0
  166. data/ext/commonmarker/cmark/build/testdir/cmake_install.cmake +29 -0
  167. data/ext/commonmarker/cmark/changelog.txt +153 -0
  168. data/ext/commonmarker/cmark/data/CaseFolding-3.2.0.txt +912 -0
  169. data/ext/commonmarker/cmark/man/CMakeLists.txt +8 -0
  170. data/ext/commonmarker/cmark/man/make_man_page.py +131 -0
  171. data/ext/commonmarker/cmark/man/man1/cmark.1 +54 -0
  172. data/ext/commonmarker/cmark/man/man3/cmark.3 +583 -0
  173. data/ext/commonmarker/cmark/nmake.bat +1 -0
  174. data/ext/commonmarker/cmark/src/CMakeLists.txt +166 -0
  175. data/ext/commonmarker/cmark/src/bench.h +27 -0
  176. data/ext/commonmarker/cmark/src/blocks.c +887 -0
  177. data/ext/commonmarker/cmark/src/buffer.c +381 -0
  178. data/ext/commonmarker/cmark/src/buffer.h +113 -0
  179. data/ext/commonmarker/cmark/src/case_fold_switch.inc +2637 -0
  180. data/ext/commonmarker/cmark/src/chunk.h +110 -0
  181. data/ext/commonmarker/cmark/src/cmark.c +24 -0
  182. data/ext/commonmarker/cmark/src/cmark.h +565 -0
  183. data/ext/commonmarker/cmark/src/cmark_ctype.c +53 -0
  184. data/ext/commonmarker/cmark/src/cmark_ctype.h +24 -0
  185. data/ext/commonmarker/cmark/src/cmark_version.h.in +7 -0
  186. data/ext/commonmarker/cmark/src/commonmark.c +607 -0
  187. data/ext/commonmarker/cmark/src/config.h.in +23 -0
  188. data/ext/commonmarker/cmark/src/debug.h +36 -0
  189. data/ext/commonmarker/cmark/src/houdini.h +52 -0
  190. data/ext/commonmarker/cmark/src/houdini_href_e.c +107 -0
  191. data/ext/commonmarker/cmark/src/houdini_html_e.c +81 -0
  192. data/ext/commonmarker/cmark/src/houdini_html_u.c +116 -0
  193. data/ext/commonmarker/cmark/src/html.c +322 -0
  194. data/ext/commonmarker/cmark/src/html_unescape.gperf +2130 -0
  195. data/ext/commonmarker/cmark/src/html_unescape.h +13375 -0
  196. data/ext/commonmarker/cmark/src/inlines.c +1147 -0
  197. data/ext/commonmarker/cmark/src/inlines.h +19 -0
  198. data/ext/commonmarker/cmark/src/iterator.c +148 -0
  199. data/ext/commonmarker/cmark/src/iterator.h +25 -0
  200. data/ext/commonmarker/cmark/src/libcmark.pc.in +10 -0
  201. data/ext/commonmarker/cmark/src/main.c +191 -0
  202. data/ext/commonmarker/cmark/src/man.c +287 -0
  203. data/ext/commonmarker/cmark/src/node.c +873 -0
  204. data/ext/commonmarker/cmark/src/node.h +82 -0
  205. data/ext/commonmarker/cmark/src/parser.h +29 -0
  206. data/ext/commonmarker/cmark/src/references.c +154 -0
  207. data/ext/commonmarker/cmark/src/references.h +37 -0
  208. data/ext/commonmarker/cmark/src/scanners.c +15291 -0
  209. data/ext/commonmarker/cmark/src/scanners.h +41 -0
  210. data/ext/commonmarker/cmark/src/scanners.re +247 -0
  211. data/ext/commonmarker/cmark/src/utf8.c +452 -0
  212. data/ext/commonmarker/cmark/src/utf8.h +22 -0
  213. data/ext/commonmarker/cmark/src/xml.c +170 -0
  214. data/ext/commonmarker/cmark/test/CMakeLists.txt +53 -0
  215. data/ext/commonmarker/cmark/test/afl_dictionary/asterisk +1 -0
  216. data/ext/commonmarker/cmark/test/afl_dictionary/attr_generic +1 -0
  217. data/ext/commonmarker/cmark/test/afl_dictionary/attr_href +1 -0
  218. data/ext/commonmarker/cmark/test/afl_dictionary/attr_xml_lang +1 -0
  219. data/ext/commonmarker/cmark/test/afl_dictionary/attr_xmlns +1 -0
  220. data/ext/commonmarker/cmark/test/afl_dictionary/backslash +1 -0
  221. data/ext/commonmarker/cmark/test/afl_dictionary/backtick +1 -0
  222. data/ext/commonmarker/cmark/test/afl_dictionary/colon +1 -0
  223. data/ext/commonmarker/cmark/test/afl_dictionary/dashes +1 -0
  224. data/ext/commonmarker/cmark/test/afl_dictionary/double_quote +1 -0
  225. data/ext/commonmarker/cmark/test/afl_dictionary/entity_builtin +1 -0
  226. data/ext/commonmarker/cmark/test/afl_dictionary/entity_decimal +1 -0
  227. data/ext/commonmarker/cmark/test/afl_dictionary/entity_external +1 -0
  228. data/ext/commonmarker/cmark/test/afl_dictionary/entity_hex +1 -0
  229. data/ext/commonmarker/cmark/test/afl_dictionary/equals +1 -0
  230. data/ext/commonmarker/cmark/test/afl_dictionary/exclamation +1 -0
  231. data/ext/commonmarker/cmark/test/afl_dictionary/greater_than +1 -0
  232. data/ext/commonmarker/cmark/test/afl_dictionary/hash +1 -0
  233. data/ext/commonmarker/cmark/test/afl_dictionary/hyphen +0 -0
  234. data/ext/commonmarker/cmark/test/afl_dictionary/indent +1 -0
  235. data/ext/commonmarker/cmark/test/afl_dictionary/left_bracket +1 -0
  236. data/ext/commonmarker/cmark/test/afl_dictionary/left_paren +1 -0
  237. data/ext/commonmarker/cmark/test/afl_dictionary/less_than +1 -0
  238. data/ext/commonmarker/cmark/test/afl_dictionary/plus +1 -0
  239. data/ext/commonmarker/cmark/test/afl_dictionary/right_bracket +1 -0
  240. data/ext/commonmarker/cmark/test/afl_dictionary/right_paren +1 -0
  241. data/ext/commonmarker/cmark/test/afl_dictionary/single_quote +1 -0
  242. data/ext/commonmarker/cmark/test/afl_dictionary/string_any +1 -0
  243. data/ext/commonmarker/cmark/test/afl_dictionary/string_brackets +1 -0
  244. data/ext/commonmarker/cmark/test/afl_dictionary/string_cdata +1 -0
  245. data/ext/commonmarker/cmark/test/afl_dictionary/string_dashes +1 -0
  246. data/ext/commonmarker/cmark/test/afl_dictionary/string_empty_dblquotes +1 -0
  247. data/ext/commonmarker/cmark/test/afl_dictionary/string_empty_quotes +1 -0
  248. data/ext/commonmarker/cmark/test/afl_dictionary/string_idrefs +1 -0
  249. data/ext/commonmarker/cmark/test/afl_dictionary/string_parentheses +1 -0
  250. data/ext/commonmarker/cmark/test/afl_dictionary/string_pcdata +1 -0
  251. data/ext/commonmarker/cmark/test/afl_dictionary/tag_cdata +1 -0
  252. data/ext/commonmarker/cmark/test/afl_dictionary/tag_close +1 -0
  253. data/ext/commonmarker/cmark/test/afl_dictionary/tag_doctype +1 -0
  254. data/ext/commonmarker/cmark/test/afl_dictionary/tag_element +1 -0
  255. data/ext/commonmarker/cmark/test/afl_dictionary/tag_entity +1 -0
  256. data/ext/commonmarker/cmark/test/afl_dictionary/tag_notation +1 -0
  257. data/ext/commonmarker/cmark/test/afl_dictionary/tag_open +1 -0
  258. data/ext/commonmarker/cmark/test/afl_dictionary/tag_open_close +1 -0
  259. data/ext/commonmarker/cmark/test/afl_dictionary/tag_open_exclamation +1 -0
  260. data/ext/commonmarker/cmark/test/afl_dictionary/tag_open_q +1 -0
  261. data/ext/commonmarker/cmark/test/afl_dictionary/tag_sq2_close +1 -0
  262. data/ext/commonmarker/cmark/test/afl_dictionary/tag_xml_q +1 -0
  263. data/ext/commonmarker/cmark/test/afl_dictionary/underscore +1 -0
  264. data/ext/commonmarker/cmark/test/afl_test_cases/test.md +36 -0
  265. data/ext/commonmarker/cmark/test/cmark.py +40 -0
  266. data/ext/commonmarker/cmark/test/normalize.py +179 -0
  267. data/ext/commonmarker/cmark/test/pathological_tests.py +63 -0
  268. data/ext/commonmarker/cmark/test/roundtrip.sh +2 -0
  269. data/ext/commonmarker/cmark/test/smart_punct.txt +96 -0
  270. data/ext/commonmarker/cmark/test/spec.txt +7505 -0
  271. data/ext/commonmarker/cmark/test/spec_tests.py +139 -0
  272. data/ext/commonmarker/cmark/toolchain-mingw32.cmake +17 -0
  273. data/ext/commonmarker/cmark/tools/mkcasefold.pl +22 -0
  274. data/ext/commonmarker/cmark/wrappers/wrapper.lua +239 -0
  275. data/ext/commonmarker/cmark/wrappers/wrapper.py +37 -0
  276. data/ext/commonmarker/cmark/wrappers/wrapper.rb +15 -0
  277. data/ext/commonmarker/cmark/wrappers/wrapper.rkt +190 -0
  278. data/ext/commonmarker/commonmarker.c +165 -0
  279. data/ext/commonmarker/commonmarker.h +11 -0
  280. data/ext/commonmarker/extconf.rb +18 -0
  281. data/lib/commonmarker/config.rb +20 -0
  282. data/lib/commonmarker/version.rb +3 -0
  283. data/lib/commonmarker.rb +588 -0
  284. data/test/benchmark.rb +30 -0
  285. data/test/spec_tests.json +4074 -0
  286. data/test/test_basics.rb +44 -0
  287. data/test/test_helper.rb +5 -0
  288. data/test/test_maliciousness.rb +9 -0
  289. data/test/test_pathological_inputs.rb +52 -0
  290. data/test/test_spec.rb +20 -0
  291. metadata +399 -0
@@ -0,0 +1,1147 @@
1
+ #include <stdlib.h>
2
+ #include <string.h>
3
+ #include <stdio.h>
4
+
5
+ #include "cmark_ctype.h"
6
+ #include "config.h"
7
+ #include "node.h"
8
+ #include "parser.h"
9
+ #include "references.h"
10
+ #include "cmark.h"
11
+ #include "houdini.h"
12
+ #include "utf8.h"
13
+ #include "scanners.h"
14
+ #include "inlines.h"
15
+
16
+
17
+ static const char *EMDASH = "\xE2\x80\x94";
18
+ static const char *ENDASH = "\xE2\x80\x93";
19
+ static const char *ELLIPSES = "\xE2\x80\xA6";
20
+ static const char *LEFTDOUBLEQUOTE = "\xE2\x80\x9C";
21
+ static const char *RIGHTDOUBLEQUOTE = "\xE2\x80\x9D";
22
+ static const char *LEFTSINGLEQUOTE = "\xE2\x80\x98";
23
+ static const char *RIGHTSINGLEQUOTE = "\xE2\x80\x99";
24
+
25
+
26
+ // Macros for creating various kinds of simple.
27
+ #define make_str(s) make_literal(CMARK_NODE_TEXT, s)
28
+ #define make_code(s) make_literal(CMARK_NODE_CODE, s)
29
+ #define make_raw_html(s) make_literal(CMARK_NODE_INLINE_HTML, s)
30
+ #define make_linebreak() make_simple(CMARK_NODE_LINEBREAK)
31
+ #define make_softbreak() make_simple(CMARK_NODE_SOFTBREAK)
32
+ #define make_emph() make_simple(CMARK_NODE_EMPH)
33
+ #define make_strong() make_simple(CMARK_NODE_STRONG)
34
+
35
+ typedef struct delimiter {
36
+ struct delimiter *previous;
37
+ struct delimiter *next;
38
+ cmark_node *inl_text;
39
+ int position;
40
+ unsigned char delim_char;
41
+ bool can_open;
42
+ bool can_close;
43
+ bool active;
44
+ } delimiter;
45
+
46
+ typedef struct {
47
+ cmark_chunk input;
48
+ int pos;
49
+ cmark_reference_map *refmap;
50
+ delimiter *last_delim;
51
+ } subject;
52
+
53
+ static delimiter*
54
+ S_insert_emph(subject *subj, delimiter *opener, delimiter *closer);
55
+
56
+ static int parse_inline(subject* subj, cmark_node * parent, int options);
57
+
58
+ static void subject_from_buf(subject *e, cmark_strbuf *buffer,
59
+ cmark_reference_map *refmap);
60
+ static int subject_find_special_char(subject *subj, int options);
61
+
62
+ static unsigned char *cmark_clean_autolink(cmark_chunk *url, int is_email)
63
+ {
64
+ cmark_strbuf buf = GH_BUF_INIT;
65
+
66
+ cmark_chunk_trim(url);
67
+
68
+ if (url->len == 0)
69
+ return NULL;
70
+
71
+ if (is_email)
72
+ cmark_strbuf_puts(&buf, "mailto:");
73
+
74
+ houdini_unescape_html_f(&buf, url->data, url->len);
75
+ return cmark_strbuf_detach(&buf);
76
+ }
77
+
78
+ static inline cmark_node *make_link(cmark_node *label, unsigned char *url, unsigned char *title)
79
+ {
80
+ cmark_node* e = (cmark_node *)calloc(1, sizeof(*e));
81
+ if(e != NULL) {
82
+ e->type = CMARK_NODE_LINK;
83
+ e->first_child = label;
84
+ e->last_child = label;
85
+ e->as.link.url = url;
86
+ e->as.link.title = title;
87
+ e->next = NULL;
88
+ label->parent = e;
89
+ }
90
+ return e;
91
+ }
92
+
93
+ static inline cmark_node* make_autolink(cmark_node* label, cmark_chunk url, int is_email)
94
+ {
95
+ return make_link(label, cmark_clean_autolink(&url, is_email), NULL);
96
+ }
97
+
98
+ // Create an inline with a literal string value.
99
+ static inline cmark_node* make_literal(cmark_node_type t, cmark_chunk s)
100
+ {
101
+ cmark_node * e = (cmark_node *)calloc(1, sizeof(*e));
102
+ if(e != NULL) {
103
+ e->type = t;
104
+ e->as.literal = s;
105
+ e->next = NULL;
106
+ e->prev = NULL;
107
+ e->parent = NULL;
108
+ e->first_child = NULL;
109
+ e->last_child = NULL;
110
+ // These fields aren't used for inlines:
111
+ e->start_line = 0;
112
+ e->start_column = 0;
113
+ e->end_line = 0;
114
+ }
115
+ return e;
116
+ }
117
+
118
+ // Create an inline with no value.
119
+ static inline cmark_node* make_simple(cmark_node_type t)
120
+ {
121
+ cmark_node* e = (cmark_node *)calloc(1, sizeof(*e));
122
+ if(e != NULL) {
123
+ e->type = t;
124
+ e->next = NULL;
125
+ e->prev = NULL;
126
+ e->parent = NULL;
127
+ e->first_child = NULL;
128
+ e->last_child = NULL;
129
+ // These fields aren't used for inlines:
130
+ e->start_line = 0;
131
+ e->start_column = 0;
132
+ e->end_line = 0;
133
+ }
134
+ return e;
135
+ }
136
+
137
+ static unsigned char *bufdup(const unsigned char *buf)
138
+ {
139
+ unsigned char *new_buf = NULL;
140
+
141
+ if (buf) {
142
+ int len = strlen((char *)buf);
143
+ new_buf = (unsigned char *)calloc(len + 1, sizeof(*new_buf));
144
+ if(new_buf != NULL) {
145
+ memcpy(new_buf, buf, len + 1);
146
+ }
147
+ }
148
+
149
+ return new_buf;
150
+ }
151
+
152
+ static void subject_from_buf(subject *e, cmark_strbuf *buffer,
153
+ cmark_reference_map *refmap)
154
+ {
155
+ e->input.data = buffer->ptr;
156
+ e->input.len = buffer->size;
157
+ e->input.alloc = 0;
158
+ e->pos = 0;
159
+ e->refmap = refmap;
160
+ e->last_delim = NULL;
161
+
162
+ cmark_chunk_rtrim(&e->input);
163
+ }
164
+
165
+ static inline int isbacktick(int c)
166
+ {
167
+ return (c == '`');
168
+ }
169
+
170
+ static inline unsigned char peek_char(subject *subj)
171
+ {
172
+ return (subj->pos < subj->input.len) ? subj->input.data[subj->pos] : 0;
173
+ }
174
+
175
+ static inline unsigned char peek_at(subject *subj, int pos)
176
+ {
177
+ return subj->input.data[pos];
178
+ }
179
+
180
+ // Return true if there are more characters in the subject.
181
+ static inline int is_eof(subject* subj)
182
+ {
183
+ return (subj->pos >= subj->input.len);
184
+ }
185
+
186
+ // Advance the subject. Doesn't check for eof.
187
+ #define advance(subj) (subj)->pos += 1
188
+
189
+ // Take characters while a predicate holds, and return a string.
190
+ static inline cmark_chunk take_while(subject* subj, int (*f)(int))
191
+ {
192
+ unsigned char c;
193
+ int startpos = subj->pos;
194
+ int len = 0;
195
+
196
+ while ((c = peek_char(subj)) && (*f)(c)) {
197
+ advance(subj);
198
+ len++;
199
+ }
200
+
201
+ return cmark_chunk_dup(&subj->input, startpos, len);
202
+ }
203
+
204
+ // Try to process a backtick code span that began with a
205
+ // span of ticks of length openticklength length (already
206
+ // parsed). Return 0 if you don't find matching closing
207
+ // backticks, otherwise return the position in the subject
208
+ // after the closing backticks.
209
+ static int scan_to_closing_backticks(subject* subj, int openticklength)
210
+ {
211
+ // read non backticks
212
+ unsigned char c;
213
+ while ((c = peek_char(subj)) && c != '`') {
214
+ advance(subj);
215
+ }
216
+ if (is_eof(subj)) {
217
+ return 0; // did not find closing ticks, return 0
218
+ }
219
+ int numticks = 0;
220
+ while (peek_char(subj) == '`') {
221
+ advance(subj);
222
+ numticks++;
223
+ }
224
+ if (numticks != openticklength) {
225
+ return(scan_to_closing_backticks(subj, openticklength));
226
+ }
227
+ return (subj->pos);
228
+ }
229
+
230
+ // Parse backtick code section or raw backticks, return an inline.
231
+ // Assumes that the subject has a backtick at the current position.
232
+ static cmark_node* handle_backticks(subject *subj)
233
+ {
234
+ cmark_chunk openticks = take_while(subj, isbacktick);
235
+ int startpos = subj->pos;
236
+ int endpos = scan_to_closing_backticks(subj, openticks.len);
237
+
238
+ if (endpos == 0) { // not found
239
+ subj->pos = startpos; // rewind
240
+ return make_str(openticks);
241
+ } else {
242
+ cmark_strbuf buf = GH_BUF_INIT;
243
+
244
+ cmark_strbuf_set(&buf, subj->input.data + startpos, endpos - startpos - openticks.len);
245
+ cmark_strbuf_trim(&buf);
246
+ cmark_strbuf_normalize_whitespace(&buf);
247
+
248
+ return make_code(cmark_chunk_buf_detach(&buf));
249
+ }
250
+ }
251
+
252
+ // Scan ***, **, or * and return number scanned, or 0.
253
+ // Advances position.
254
+ static int
255
+ scan_delims(subject* subj, unsigned char c, bool * can_open, bool * can_close)
256
+ {
257
+ int numdelims = 0;
258
+ int before_char_pos;
259
+ int32_t after_char = 0;
260
+ int32_t before_char = 0;
261
+ int len;
262
+ bool left_flanking, right_flanking;
263
+
264
+ if (subj->pos == 0) {
265
+ before_char = 10;
266
+ } else {
267
+ before_char_pos = subj->pos - 1;
268
+ // walk back to the beginning of the UTF_8 sequence:
269
+ while (peek_at(subj, before_char_pos) >> 6 == 2 &&
270
+ before_char_pos > 0) {
271
+ before_char_pos -= 1;
272
+ }
273
+ len = utf8proc_iterate(subj->input.data + before_char_pos,
274
+ subj->pos - before_char_pos, &before_char);
275
+ if (len == -1) {
276
+ before_char = 10;
277
+ }
278
+ }
279
+
280
+ if (c == '\'' || c == '"') {
281
+ numdelims++;
282
+ advance(subj); // limit to 1 delim for quotes
283
+ } else {
284
+ while (peek_char(subj) == c) {
285
+ numdelims++;
286
+ advance(subj);
287
+ }
288
+ }
289
+
290
+ len = utf8proc_iterate(subj->input.data + subj->pos,
291
+ subj->input.len - subj->pos, &after_char);
292
+ if (len == -1) {
293
+ after_char = 10;
294
+ }
295
+ left_flanking = numdelims > 0 && !utf8proc_is_space(after_char) &&
296
+ !(utf8proc_is_punctuation(after_char) &&
297
+ !utf8proc_is_space(before_char) &&
298
+ !utf8proc_is_punctuation(before_char));
299
+ right_flanking = numdelims > 0 && !utf8proc_is_space(before_char) &&
300
+ !(utf8proc_is_punctuation(before_char) &&
301
+ !utf8proc_is_space(after_char) &&
302
+ !utf8proc_is_punctuation(after_char));
303
+ if (c == '_') {
304
+ *can_open = left_flanking &&
305
+ (!right_flanking || utf8proc_is_punctuation(before_char));
306
+ *can_close = right_flanking &&
307
+ (!left_flanking || utf8proc_is_punctuation(after_char));
308
+ } else if (c == '\'' || c == '"') {
309
+ *can_open = left_flanking && !right_flanking;
310
+ *can_close = right_flanking;
311
+ } else {
312
+ *can_open = left_flanking;
313
+ *can_close = right_flanking;
314
+ }
315
+ return numdelims;
316
+ }
317
+
318
+ /*
319
+ static void print_delimiters(subject *subj)
320
+ {
321
+ delimiter *delim;
322
+ delim = subj->last_delim;
323
+ while (delim != NULL) {
324
+ printf("Item at %p: %d %d %d next(%p) prev(%p)\n",
325
+ delim, delim->delim_char,
326
+ delim->can_open, delim->can_close,
327
+ delim->next, delim->previous);
328
+ delim = delim->previous;
329
+ }
330
+ }
331
+ */
332
+
333
+ static void remove_delimiter(subject *subj, delimiter *delim)
334
+ {
335
+ if (delim == NULL) return;
336
+ if (delim->next == NULL) {
337
+ // end of list:
338
+ assert(delim == subj->last_delim);
339
+ subj->last_delim = delim->previous;
340
+ } else {
341
+ delim->next->previous = delim->previous;
342
+ }
343
+ if (delim->previous != NULL) {
344
+ delim->previous->next = delim->next;
345
+ }
346
+ free(delim);
347
+ }
348
+
349
+ static void push_delimiter(subject *subj, unsigned char c, bool can_open,
350
+ bool can_close, cmark_node *inl_text)
351
+ {
352
+ delimiter *delim =
353
+ (delimiter*)malloc(sizeof(delimiter));
354
+ if (delim == NULL) {
355
+ return;
356
+ }
357
+ delim->delim_char = c;
358
+ delim->can_open = can_open;
359
+ delim->can_close = can_close;
360
+ delim->inl_text = inl_text;
361
+ delim->previous = subj->last_delim;
362
+ delim->next = NULL;
363
+ if (delim->previous != NULL) {
364
+ delim->previous->next = delim;
365
+ }
366
+ delim->position = subj->pos;
367
+ delim->active = true;
368
+ subj->last_delim = delim;
369
+ }
370
+
371
+ // Assumes the subject has a c at the current position.
372
+ static cmark_node* handle_delim(subject* subj, unsigned char c, bool smart)
373
+ {
374
+ int numdelims;
375
+ cmark_node * inl_text;
376
+ bool can_open, can_close;
377
+ cmark_chunk contents;
378
+
379
+ numdelims = scan_delims(subj, c, &can_open, &can_close);
380
+
381
+ if (c == '\'' && smart) {
382
+ contents = cmark_chunk_literal(RIGHTSINGLEQUOTE);
383
+ } else if (c == '"' && smart) {
384
+ contents = cmark_chunk_literal(can_close ? RIGHTDOUBLEQUOTE : LEFTDOUBLEQUOTE);
385
+ } else {
386
+ contents = cmark_chunk_dup(&subj->input, subj->pos - numdelims, numdelims);
387
+ }
388
+
389
+ inl_text = make_str(contents);
390
+
391
+ if ((can_open || can_close) &&
392
+ (!(c == '\'' || c == '"') || smart)) {
393
+ push_delimiter(subj, c, can_open, can_close, inl_text);
394
+ }
395
+
396
+ return inl_text;
397
+ }
398
+
399
+ // Assumes we have a hyphen at the current position.
400
+ static cmark_node* handle_hyphen(subject* subj, bool smart)
401
+ {
402
+ advance(subj);
403
+ if (smart && peek_char(subj) == '-') {
404
+ advance(subj);
405
+ if (peek_char(subj) == '-') {
406
+ advance(subj);
407
+ return make_str(cmark_chunk_literal(EMDASH));
408
+ } else {
409
+ return make_str(cmark_chunk_literal(ENDASH));
410
+ }
411
+ } else {
412
+ return make_str(cmark_chunk_literal("-"));
413
+ }
414
+ }
415
+
416
+ // Assumes we have a period at the current position.
417
+ static cmark_node* handle_period(subject* subj, bool smart)
418
+ {
419
+ advance(subj);
420
+ if (smart && peek_char(subj) == '.') {
421
+ advance(subj);
422
+ if (peek_char(subj) == '.') {
423
+ advance(subj);
424
+ return make_str(cmark_chunk_literal(ELLIPSES));
425
+ } else {
426
+ return make_str(cmark_chunk_literal(".."));
427
+ }
428
+ } else {
429
+ return make_str(cmark_chunk_literal("."));
430
+ }
431
+ }
432
+
433
+ static void process_emphasis(subject *subj, delimiter *start_delim)
434
+ {
435
+ delimiter *closer = subj->last_delim;
436
+ delimiter *opener;
437
+
438
+ // move back to first relevant delim.
439
+ while (closer != NULL && closer->previous != start_delim) {
440
+ closer = closer->previous;
441
+ }
442
+
443
+ // now move forward, looking for closers, and handling each
444
+ while (closer != NULL) {
445
+ if (closer->can_close &&
446
+ (closer->delim_char == '*' || closer->delim_char == '_' ||
447
+ closer->delim_char == '"' || closer->delim_char == '\'')) {
448
+ // Now look backwards for first matching opener:
449
+ opener = closer->previous;
450
+ while (opener != NULL && opener != start_delim) {
451
+ if (opener->delim_char == closer->delim_char &&
452
+ opener->can_open) {
453
+ break;
454
+ }
455
+ opener = opener->previous;
456
+ }
457
+ if (closer->delim_char == '*' || closer->delim_char == '_') {
458
+ if (opener != NULL && opener != start_delim) {
459
+ closer = S_insert_emph(subj, opener, closer);
460
+ } else {
461
+ closer = closer->next;
462
+ }
463
+ } else if (closer->delim_char == '\'') {
464
+ cmark_chunk_free(&closer->inl_text->as.literal);
465
+ closer->inl_text->as.literal =
466
+ cmark_chunk_literal(RIGHTSINGLEQUOTE);
467
+ if (opener != NULL && opener != start_delim) {
468
+ cmark_chunk_free(&opener->inl_text->as.literal);
469
+ opener->inl_text->as.literal =
470
+ cmark_chunk_literal(LEFTSINGLEQUOTE);
471
+ }
472
+ closer = closer->next;
473
+ } else if (closer->delim_char == '"') {
474
+ cmark_chunk_free(&closer->inl_text->as.literal);
475
+ closer->inl_text->as.literal =
476
+ cmark_chunk_literal(RIGHTDOUBLEQUOTE);
477
+ if (opener != NULL && opener != start_delim) {
478
+ cmark_chunk_free(&opener->inl_text->as.literal);
479
+ opener->inl_text->as.literal =
480
+ cmark_chunk_literal(LEFTDOUBLEQUOTE);
481
+ }
482
+ closer = closer->next;
483
+ }
484
+ } else {
485
+ closer = closer->next;
486
+ }
487
+ }
488
+ // free all delimiters in list until start_delim:
489
+ while (subj->last_delim != start_delim) {
490
+ remove_delimiter(subj, subj->last_delim);
491
+ }
492
+ }
493
+
494
+ static delimiter*
495
+ S_insert_emph(subject *subj, delimiter *opener, delimiter *closer)
496
+ {
497
+ delimiter *delim, *tmp_delim;
498
+ int use_delims;
499
+ cmark_node *opener_inl = opener->inl_text;
500
+ cmark_node *closer_inl = closer->inl_text;
501
+ int opener_num_chars = opener_inl->as.literal.len;
502
+ int closer_num_chars = closer_inl->as.literal.len;
503
+ cmark_node *tmp, *emph, *first_child, *last_child;
504
+
505
+ // calculate the actual number of characters used from this closer
506
+ if (closer_num_chars < 3 || opener_num_chars < 3) {
507
+ use_delims = closer_num_chars <= opener_num_chars ?
508
+ closer_num_chars : opener_num_chars;
509
+ } else { // closer and opener both have >= 3 characters
510
+ use_delims = closer_num_chars % 2 == 0 ? 2 : 1;
511
+ }
512
+
513
+ // remove used characters from associated inlines.
514
+ opener_num_chars -= use_delims;
515
+ closer_num_chars -= use_delims;
516
+ opener_inl->as.literal.len = opener_num_chars;
517
+ closer_inl->as.literal.len = closer_num_chars;
518
+
519
+ // free delimiters between opener and closer
520
+ delim = closer->previous;
521
+ while (delim != NULL && delim != opener) {
522
+ tmp_delim = delim->previous;
523
+ remove_delimiter(subj, delim);
524
+ delim = tmp_delim;
525
+ }
526
+
527
+ first_child = opener_inl->next;
528
+ last_child = closer_inl->prev;
529
+
530
+ // if opener has 0 characters, remove it and its associated inline
531
+ if (opener_num_chars == 0) {
532
+ // replace empty opener inline with emph
533
+ cmark_chunk_free(&(opener_inl->as.literal));
534
+ emph = opener_inl;
535
+ emph->type = use_delims == 1 ? NODE_EMPH : NODE_STRONG;
536
+ // remove opener from list
537
+ remove_delimiter(subj, opener);
538
+ } else {
539
+ // create new emph or strong, and splice it in to our inlines
540
+ // between the opener and closer
541
+ emph = use_delims == 1 ? make_emph() : make_strong();
542
+ emph->parent = opener_inl->parent;
543
+ emph->prev = opener_inl;
544
+ opener_inl->next = emph;
545
+ }
546
+
547
+ // push children below emph
548
+ emph->next = closer_inl;
549
+ closer_inl->prev = emph;
550
+ emph->first_child = first_child;
551
+ emph->last_child = last_child;
552
+
553
+ // fix children pointers
554
+ first_child->prev = NULL;
555
+ last_child->next = NULL;
556
+ for (tmp = first_child; tmp != NULL; tmp = tmp->next) {
557
+ tmp->parent = emph;
558
+ }
559
+
560
+ // if closer has 0 characters, remove it and its associated inline
561
+ if (closer_num_chars == 0) {
562
+ // remove empty closer inline
563
+ cmark_node_free(closer_inl);
564
+ // remove closer from list
565
+ tmp_delim = closer->next;
566
+ remove_delimiter(subj, closer);
567
+ closer = tmp_delim;
568
+ }
569
+
570
+ return closer;
571
+ }
572
+
573
+ // Parse backslash-escape or just a backslash, returning an inline.
574
+ static cmark_node* handle_backslash(subject *subj)
575
+ {
576
+ advance(subj);
577
+ unsigned char nextchar = peek_char(subj);
578
+ if (cmark_ispunct(nextchar)) { // only ascii symbols and newline can be escaped
579
+ advance(subj);
580
+ return make_str(cmark_chunk_dup(&subj->input, subj->pos - 1, 1));
581
+ } else if (nextchar == '\n') {
582
+ advance(subj);
583
+ return make_linebreak();
584
+ } else {
585
+ return make_str(cmark_chunk_literal("\\"));
586
+ }
587
+ }
588
+
589
+ // Parse an entity or a regular "&" string.
590
+ // Assumes the subject has an '&' character at the current position.
591
+ static cmark_node* handle_entity(subject* subj)
592
+ {
593
+ cmark_strbuf ent = GH_BUF_INIT;
594
+ size_t len;
595
+
596
+ advance(subj);
597
+
598
+ len = houdini_unescape_ent(&ent,
599
+ subj->input.data + subj->pos,
600
+ subj->input.len - subj->pos
601
+ );
602
+
603
+ if (len == 0)
604
+ return make_str(cmark_chunk_literal("&"));
605
+
606
+ subj->pos += len;
607
+ return make_str(cmark_chunk_buf_detach(&ent));
608
+ }
609
+
610
+ // Like make_str, but parses entities.
611
+ // Returns an inline sequence consisting of str and entity elements.
612
+ static cmark_node *make_str_with_entities(cmark_chunk *content)
613
+ {
614
+ cmark_strbuf unescaped = GH_BUF_INIT;
615
+
616
+ if (houdini_unescape_html(&unescaped, content->data, (size_t)content->len)) {
617
+ return make_str(cmark_chunk_buf_detach(&unescaped));
618
+ } else {
619
+ return make_str(*content);
620
+ }
621
+ }
622
+
623
+ // Clean a URL: remove surrounding whitespace and surrounding <>,
624
+ // and remove \ that escape punctuation.
625
+ unsigned char *cmark_clean_url(cmark_chunk *url)
626
+ {
627
+ cmark_strbuf buf = GH_BUF_INIT;
628
+
629
+ cmark_chunk_trim(url);
630
+
631
+ if (url->len == 0)
632
+ return NULL;
633
+
634
+ if (url->data[0] == '<' && url->data[url->len - 1] == '>') {
635
+ houdini_unescape_html_f(&buf, url->data + 1, url->len - 2);
636
+ } else {
637
+ houdini_unescape_html_f(&buf, url->data, url->len);
638
+ }
639
+
640
+ cmark_strbuf_unescape(&buf);
641
+ return buf.size == 0 ? NULL : cmark_strbuf_detach(&buf);
642
+ }
643
+
644
+ unsigned char *cmark_clean_title(cmark_chunk *title)
645
+ {
646
+ cmark_strbuf buf = GH_BUF_INIT;
647
+ unsigned char first, last;
648
+
649
+ if (title->len == 0)
650
+ return NULL;
651
+
652
+ first = title->data[0];
653
+ last = title->data[title->len - 1];
654
+
655
+ // remove surrounding quotes if any:
656
+ if ((first == '\'' && last == '\'') ||
657
+ (first == '(' && last == ')') ||
658
+ (first == '"' && last == '"')) {
659
+ houdini_unescape_html_f(&buf, title->data + 1, title->len - 2);
660
+ } else {
661
+ houdini_unescape_html_f(&buf, title->data, title->len);
662
+ }
663
+
664
+ cmark_strbuf_unescape(&buf);
665
+ return buf.size == 0 ? NULL : cmark_strbuf_detach(&buf);
666
+ }
667
+
668
+ // Parse an autolink or HTML tag.
669
+ // Assumes the subject has a '<' character at the current position.
670
+ static cmark_node* handle_pointy_brace(subject* subj)
671
+ {
672
+ int matchlen = 0;
673
+ cmark_chunk contents;
674
+
675
+ advance(subj); // advance past first <
676
+
677
+ // first try to match a URL autolink
678
+ matchlen = scan_autolink_uri(&subj->input, subj->pos);
679
+ if (matchlen > 0) {
680
+ contents = cmark_chunk_dup(&subj->input, subj->pos, matchlen - 1);
681
+ subj->pos += matchlen;
682
+
683
+ return make_autolink(
684
+ make_str_with_entities(&contents),
685
+ contents, 0
686
+ );
687
+ }
688
+
689
+ // next try to match an email autolink
690
+ matchlen = scan_autolink_email(&subj->input, subj->pos);
691
+ if (matchlen > 0) {
692
+ contents = cmark_chunk_dup(&subj->input, subj->pos, matchlen - 1);
693
+ subj->pos += matchlen;
694
+
695
+ return make_autolink(
696
+ make_str_with_entities(&contents),
697
+ contents, 1
698
+ );
699
+ }
700
+
701
+ // finally, try to match an html tag
702
+ matchlen = scan_html_tag(&subj->input, subj->pos);
703
+ if (matchlen > 0) {
704
+ contents = cmark_chunk_dup(&subj->input, subj->pos - 1, matchlen + 1);
705
+ subj->pos += matchlen;
706
+ return make_raw_html(contents);
707
+ }
708
+
709
+ // if nothing matches, just return the opening <:
710
+ return make_str(cmark_chunk_literal("<"));
711
+ }
712
+
713
+ // Parse a link label. Returns 1 if successful.
714
+ // Note: unescaped brackets are not allowed in labels.
715
+ // The label begins with `[` and ends with the first `]` character
716
+ // encountered. Backticks in labels do not start code spans.
717
+ static int link_label(subject* subj, cmark_chunk *raw_label)
718
+ {
719
+ int startpos = subj->pos;
720
+ int length = 0;
721
+ unsigned char c;
722
+
723
+ // advance past [
724
+ if (peek_char(subj) == '[') {
725
+ advance(subj);
726
+ } else {
727
+ return 0;
728
+ }
729
+
730
+ while ((c = peek_char(subj)) && c != '[' && c != ']') {
731
+ if (c == '\\') {
732
+ advance(subj);
733
+ length++;
734
+ if (cmark_ispunct(peek_char(subj))) {
735
+ advance(subj);
736
+ length++;
737
+ }
738
+ } else {
739
+ advance(subj);
740
+ length++;
741
+ }
742
+ if (length > MAX_LINK_LABEL_LENGTH) {
743
+ goto noMatch;
744
+ }
745
+ }
746
+
747
+ if (c == ']') { // match found
748
+ *raw_label = cmark_chunk_dup(&subj->input, startpos + 1, subj->pos - (startpos + 1));
749
+ advance(subj); // advance past ]
750
+ return 1;
751
+ }
752
+
753
+ noMatch:
754
+ subj->pos = startpos; // rewind
755
+ return 0;
756
+
757
+ }
758
+
759
+ // Return a link, an image, or a literal close bracket.
760
+ static cmark_node* handle_close_bracket(subject* subj, cmark_node *parent)
761
+ {
762
+ int initial_pos;
763
+ int starturl, endurl, starttitle, endtitle, endall;
764
+ int n;
765
+ int sps;
766
+ cmark_reference *ref;
767
+ bool is_image = false;
768
+ cmark_chunk url_chunk, title_chunk;
769
+ unsigned char *url, *title;
770
+ delimiter *opener;
771
+ cmark_node *link_text;
772
+ cmark_node *inl;
773
+ cmark_chunk raw_label;
774
+ int found_label;
775
+
776
+ advance(subj); // advance past ]
777
+ initial_pos = subj->pos;
778
+
779
+ // look through list of delimiters for a [ or !
780
+ opener = subj->last_delim;
781
+ while (opener) {
782
+ if (opener->delim_char == '[' || opener->delim_char == '!') {
783
+ break;
784
+ }
785
+ opener = opener->previous;
786
+ }
787
+
788
+ if (opener == NULL) {
789
+ return make_str(cmark_chunk_literal("]"));
790
+ }
791
+
792
+ if (!opener->active) {
793
+ // take delimiter off stack
794
+ remove_delimiter(subj, opener);
795
+ return make_str(cmark_chunk_literal("]"));
796
+ }
797
+
798
+ // If we got here, we matched a potential link/image text.
799
+ is_image = opener->delim_char == '!';
800
+ link_text = opener->inl_text->next;
801
+
802
+ // Now we check to see if it's a link/image.
803
+
804
+ // First, look for an inline link.
805
+ if (peek_char(subj) == '(' &&
806
+ ((sps = scan_spacechars(&subj->input, subj->pos + 1)) > -1) &&
807
+ ((n = scan_link_url(&subj->input, subj->pos + 1 + sps)) > -1)) {
808
+
809
+ // try to parse an explicit link:
810
+ starturl = subj->pos + 1 + sps; // after (
811
+ endurl = starturl + n;
812
+ starttitle = endurl + scan_spacechars(&subj->input, endurl);
813
+
814
+ // ensure there are spaces btw url and title
815
+ endtitle = (starttitle == endurl) ? starttitle :
816
+ starttitle + scan_link_title(&subj->input, starttitle);
817
+
818
+ endall = endtitle + scan_spacechars(&subj->input, endtitle);
819
+
820
+ if (peek_at(subj, endall) == ')') {
821
+ subj->pos = endall + 1;
822
+
823
+ url_chunk = cmark_chunk_dup(&subj->input, starturl, endurl - starturl);
824
+ title_chunk = cmark_chunk_dup(&subj->input, starttitle, endtitle - starttitle);
825
+ url = cmark_clean_url(&url_chunk);
826
+ title = cmark_clean_title(&title_chunk);
827
+ cmark_chunk_free(&url_chunk);
828
+ cmark_chunk_free(&title_chunk);
829
+ goto match;
830
+
831
+ } else {
832
+ goto noMatch;
833
+ }
834
+ }
835
+
836
+ // Next, look for a following [link label] that matches in refmap.
837
+ // skip spaces
838
+ subj->pos = subj->pos + scan_spacechars(&subj->input, subj->pos);
839
+ raw_label = cmark_chunk_literal("");
840
+ found_label = link_label(subj, &raw_label);
841
+ if (!found_label || raw_label.len == 0) {
842
+ cmark_chunk_free(&raw_label);
843
+ raw_label = cmark_chunk_dup(&subj->input, opener->position,
844
+ initial_pos - opener->position - 1);
845
+ }
846
+
847
+ if (!found_label) {
848
+ // If we have a shortcut reference link, back up
849
+ // to before the spacse we skipped.
850
+ subj->pos = initial_pos;
851
+ }
852
+
853
+ ref = cmark_reference_lookup(subj->refmap, &raw_label);
854
+ cmark_chunk_free(&raw_label);
855
+
856
+ if (ref != NULL) { // found
857
+ url = bufdup(ref->url);
858
+ title = bufdup(ref->title);
859
+ goto match;
860
+ } else {
861
+ goto noMatch;
862
+ }
863
+
864
+ noMatch:
865
+ // If we fall through to here, it means we didn't match a link:
866
+ remove_delimiter(subj, opener); // remove this opener from delimiter list
867
+ subj->pos = initial_pos;
868
+ return make_str(cmark_chunk_literal("]"));
869
+
870
+ match:
871
+ inl = opener->inl_text;
872
+ inl->type = is_image ? NODE_IMAGE : NODE_LINK;
873
+ cmark_chunk_free(&inl->as.literal);
874
+ inl->first_child = link_text;
875
+ process_emphasis(subj, opener->previous);
876
+ inl->as.link.url = url;
877
+ inl->as.link.title = title;
878
+ inl->next = NULL;
879
+ if (link_text) {
880
+ cmark_node *tmp;
881
+ link_text->prev = NULL;
882
+ for (tmp = link_text; tmp->next != NULL; tmp = tmp->next) {
883
+ tmp->parent = inl;
884
+ }
885
+ tmp->parent = inl;
886
+ inl->last_child = tmp;
887
+ }
888
+ parent->last_child = inl;
889
+
890
+ // process_emphasis will remove this delimiter and all later ones.
891
+ // Now, if we have a link, we also want to deactivate earlier link
892
+ // delimiters. (This code can be removed if we decide to allow links
893
+ // inside links.)
894
+ if (!is_image) {
895
+ opener = subj->last_delim;
896
+ while (opener != NULL) {
897
+ if (opener->delim_char == '[') {
898
+ if (!opener->active) {
899
+ break;
900
+ } else {
901
+ opener->active = false;
902
+ }
903
+ }
904
+ opener = opener->previous;
905
+ }
906
+ }
907
+
908
+ return NULL;
909
+ }
910
+
911
+ // Parse a hard or soft linebreak, returning an inline.
912
+ // Assumes the subject has a newline at the current position.
913
+ static cmark_node* handle_newline(subject *subj)
914
+ {
915
+ int nlpos = subj->pos;
916
+ // skip over newline
917
+ advance(subj);
918
+ // skip spaces at beginning of line
919
+ while (peek_char(subj) == ' ') {
920
+ advance(subj);
921
+ }
922
+ if (nlpos > 1 &&
923
+ peek_at(subj, nlpos - 1) == ' ' &&
924
+ peek_at(subj, nlpos - 2) == ' ') {
925
+ return make_linebreak();
926
+ } else {
927
+ return make_softbreak();
928
+ }
929
+ }
930
+
931
+ static int subject_find_special_char(subject *subj, int options)
932
+ {
933
+ // "\n\\`&_*[]<!"
934
+ static const int8_t SPECIAL_CHARS[256] = {
935
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
936
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
937
+ 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0,
938
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
939
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
940
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1,
941
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
942
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
943
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
944
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
945
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
946
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
947
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
948
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
949
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
950
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
951
+ };
952
+
953
+ // " ' . -
954
+ static const char SMART_PUNCT_CHARS[] = {
955
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
956
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
957
+ 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0,
958
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
959
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
960
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
961
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
962
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
963
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
964
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
965
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
966
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
967
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
968
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
969
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
970
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
971
+ };
972
+
973
+ int n = subj->pos + 1;
974
+
975
+ while (n < subj->input.len) {
976
+ if (SPECIAL_CHARS[subj->input.data[n]])
977
+ return n;
978
+ if (options & CMARK_OPT_SMART &&
979
+ SMART_PUNCT_CHARS[subj->input.data[n]])
980
+ return n;
981
+ n++;
982
+ }
983
+
984
+ return subj->input.len;
985
+ }
986
+
987
+ // Parse an inline, advancing subject, and add it as a child of parent.
988
+ // Return 0 if no inline can be parsed, 1 otherwise.
989
+ static int parse_inline(subject* subj, cmark_node * parent, int options)
990
+ {
991
+ cmark_node* new_inl = NULL;
992
+ cmark_chunk contents;
993
+ unsigned char c;
994
+ int endpos;
995
+ c = peek_char(subj);
996
+ if (c == 0) {
997
+ return 0;
998
+ }
999
+ switch(c) {
1000
+ case '\n':
1001
+ new_inl = handle_newline(subj);
1002
+ break;
1003
+ case '`':
1004
+ new_inl = handle_backticks(subj);
1005
+ break;
1006
+ case '\\':
1007
+ new_inl = handle_backslash(subj);
1008
+ break;
1009
+ case '&':
1010
+ new_inl = handle_entity(subj);
1011
+ break;
1012
+ case '<':
1013
+ new_inl = handle_pointy_brace(subj);
1014
+ break;
1015
+ case '*':
1016
+ case '_':
1017
+ case '\'':
1018
+ case '"':
1019
+ new_inl = handle_delim(subj, c, options & CMARK_OPT_SMART);
1020
+ break;
1021
+ case '-':
1022
+ new_inl = handle_hyphen(subj, options & CMARK_OPT_SMART);
1023
+ break;
1024
+ case '.':
1025
+ new_inl = handle_period(subj, options & CMARK_OPT_SMART);
1026
+ break;
1027
+ case '[':
1028
+ advance(subj);
1029
+ new_inl = make_str(cmark_chunk_literal("["));
1030
+ push_delimiter(subj, '[', true, false, new_inl);
1031
+ break;
1032
+ case ']':
1033
+ new_inl = handle_close_bracket(subj, parent);
1034
+ break;
1035
+ case '!':
1036
+ advance(subj);
1037
+ if (peek_char(subj) == '[') {
1038
+ advance(subj);
1039
+ new_inl = make_str(cmark_chunk_literal("!["));
1040
+ push_delimiter(subj, '!', false, true, new_inl);
1041
+ } else {
1042
+ new_inl = make_str(cmark_chunk_literal("!"));
1043
+ }
1044
+ break;
1045
+ default:
1046
+ endpos = subject_find_special_char(subj, options);
1047
+ contents = cmark_chunk_dup(&subj->input, subj->pos, endpos - subj->pos);
1048
+ subj->pos = endpos;
1049
+
1050
+ // if we're at a newline, strip trailing spaces.
1051
+ if (peek_char(subj) == '\n') {
1052
+ cmark_chunk_rtrim(&contents);
1053
+ }
1054
+
1055
+ new_inl = make_str(contents);
1056
+ }
1057
+ if (new_inl != NULL) {
1058
+ cmark_node_append_child(parent, new_inl);
1059
+ }
1060
+
1061
+ return 1;
1062
+ }
1063
+
1064
+ // Parse inlines from parent's string_content, adding as children of parent.
1065
+ extern void cmark_parse_inlines(cmark_node* parent, cmark_reference_map *refmap, int options)
1066
+ {
1067
+ subject subj;
1068
+ subject_from_buf(&subj, &parent->string_content, refmap);
1069
+
1070
+ while (!is_eof(&subj) && parse_inline(&subj, parent, options)) ;
1071
+
1072
+ process_emphasis(&subj, NULL);
1073
+ }
1074
+
1075
+ // Parse zero or more space characters, including at most one newline.
1076
+ static void spnl(subject* subj)
1077
+ {
1078
+ bool seen_newline = false;
1079
+ while (peek_char(subj) == ' ' ||
1080
+ (!seen_newline &&
1081
+ (seen_newline = peek_char(subj) == '\n'))) {
1082
+ advance(subj);
1083
+ }
1084
+ }
1085
+
1086
+ // Parse reference. Assumes string begins with '[' character.
1087
+ // Modify refmap if a reference is encountered.
1088
+ // Return 0 if no reference found, otherwise position of subject
1089
+ // after reference is parsed.
1090
+ int cmark_parse_reference_inline(cmark_strbuf *input, cmark_reference_map *refmap)
1091
+ {
1092
+ subject subj;
1093
+
1094
+ cmark_chunk lab;
1095
+ cmark_chunk url;
1096
+ cmark_chunk title;
1097
+
1098
+ int matchlen = 0;
1099
+ int beforetitle;
1100
+
1101
+ subject_from_buf(&subj, input, NULL);
1102
+
1103
+ // parse label:
1104
+ if (!link_label(&subj, &lab))
1105
+ return 0;
1106
+
1107
+ // colon:
1108
+ if (peek_char(&subj) == ':') {
1109
+ advance(&subj);
1110
+ } else {
1111
+ return 0;
1112
+ }
1113
+
1114
+ // parse link url:
1115
+ spnl(&subj);
1116
+ matchlen = scan_link_url(&subj.input, subj.pos);
1117
+ if (matchlen) {
1118
+ url = cmark_chunk_dup(&subj.input, subj.pos, matchlen);
1119
+ subj.pos += matchlen;
1120
+ } else {
1121
+ return 0;
1122
+ }
1123
+
1124
+ // parse optional link_title
1125
+ beforetitle = subj.pos;
1126
+ spnl(&subj);
1127
+ matchlen = scan_link_title(&subj.input, subj.pos);
1128
+ if (matchlen) {
1129
+ title = cmark_chunk_dup(&subj.input, subj.pos, matchlen);
1130
+ subj.pos += matchlen;
1131
+ } else {
1132
+ subj.pos = beforetitle;
1133
+ title = cmark_chunk_literal("");
1134
+ }
1135
+ // parse final spaces and newline:
1136
+ while (peek_char(&subj) == ' ') {
1137
+ advance(&subj);
1138
+ }
1139
+ if (peek_char(&subj) == '\n') {
1140
+ advance(&subj);
1141
+ } else if (peek_char(&subj) != 0) {
1142
+ return 0;
1143
+ }
1144
+ // insert reference into refmap
1145
+ cmark_reference_create(refmap, &lab, &url, &title);
1146
+ return subj.pos;
1147
+ }