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.
- checksums.yaml +7 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +119 -0
- data/Rakefile +39 -0
- data/bin/commonmarker +41 -0
- data/commonmarker.gemspec +30 -0
- data/ext/commonmarker/cmark/CMakeLists.txt +25 -0
- data/ext/commonmarker/cmark/COPYING +192 -0
- data/ext/commonmarker/cmark/FindAsan.cmake +74 -0
- data/ext/commonmarker/cmark/Makefile +170 -0
- data/ext/commonmarker/cmark/Makefile.nmake +36 -0
- data/ext/commonmarker/cmark/README.md +169 -0
- data/ext/commonmarker/cmark/api_test/CMakeLists.txt +25 -0
- data/ext/commonmarker/cmark/api_test/cplusplus.cpp +15 -0
- data/ext/commonmarker/cmark/api_test/cplusplus.h +17 -0
- data/ext/commonmarker/cmark/api_test/harness.c +102 -0
- data/ext/commonmarker/cmark/api_test/harness.h +42 -0
- data/ext/commonmarker/cmark/api_test/main.c +700 -0
- data/ext/commonmarker/cmark/appveyor.yml +15 -0
- data/ext/commonmarker/cmark/bench/statistics.py +595 -0
- data/ext/commonmarker/cmark/bench/stats.py +19 -0
- data/ext/commonmarker/cmark/benchmarks.md +33 -0
- data/ext/commonmarker/cmark/build/CMakeCache.txt +362 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/3.2.2/CMakeCCompiler.cmake +63 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/3.2.2/CMakeCXXCompiler.cmake +64 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/3.2.2/CMakeDetermineCompilerABI_C.bin +0 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/3.2.2/CMakeDetermineCompilerABI_CXX.bin +0 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/3.2.2/CMakeSystem.cmake +15 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/3.2.2/CompilerIdC/CMakeCCompilerId.c +499 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/3.2.2/CompilerIdC/a.out +0 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/3.2.2/CompilerIdCXX/CMakeCXXCompilerId.cpp +489 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/3.2.2/CompilerIdCXX/a.out +0 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/CMakeDirectoryInformation.cmake +16 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/CMakeError.log +30 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/CMakeOutput.log +598 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/Makefile.cmake +77 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/Makefile2 +268 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/TargetDirectories.txt +4 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/cmake.check_cache +1 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/feature_tests.bin +0 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/feature_tests.c +34 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/feature_tests.cxx +405 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/progress.marks +1 -0
- data/ext/commonmarker/cmark/build/CTestTestfile.cmake +10 -0
- data/ext/commonmarker/cmark/build/Makefile +237 -0
- data/ext/commonmarker/cmark/build/api_test/CMakeFiles/CMakeDirectoryInformation.cmake +16 -0
- data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/C.includecache +92 -0
- data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/CXX.includecache +36 -0
- data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/DependInfo.cmake +29 -0
- data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/build.make +155 -0
- data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/cmake_clean.cmake +12 -0
- data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/cplusplus.cpp.o +0 -0
- data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/depend.internal +25 -0
- data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/depend.make +25 -0
- data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/flags.make +13 -0
- data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/harness.c.o +0 -0
- data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/link.txt +1 -0
- data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/main.c.o +0 -0
- data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/progress.make +4 -0
- data/ext/commonmarker/cmark/build/api_test/CMakeFiles/progress.marks +1 -0
- data/ext/commonmarker/cmark/build/api_test/Makefile +277 -0
- data/ext/commonmarker/cmark/build/api_test/api_test +0 -0
- data/ext/commonmarker/cmark/build/api_test/cmake_install.cmake +29 -0
- data/ext/commonmarker/cmark/build/cmake_install.cmake +48 -0
- data/ext/commonmarker/cmark/build/man/CMakeFiles/CMakeDirectoryInformation.cmake +16 -0
- data/ext/commonmarker/cmark/build/man/CMakeFiles/progress.marks +1 -0
- data/ext/commonmarker/cmark/build/man/Makefile +181 -0
- data/ext/commonmarker/cmark/build/man/cmake_install.cmake +37 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/CMakeDirectoryInformation.cmake +16 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/C.includecache +422 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/DependInfo.cmake +39 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/blocks.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/buffer.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/build.make +544 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/cmake_clean.cmake +27 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/cmark.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/cmark_ctype.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/commonmark.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/depend.internal +177 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/depend.make +177 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/flags.make +8 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/houdini_href_e.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/houdini_html_e.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/houdini_html_u.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/html.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/inlines.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/iterator.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/link.txt +1 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/main.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/man.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/node.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/progress.make +19 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/references.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/scanners.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/utf8.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/xml.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/C.includecache +394 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/DependInfo.cmake +44 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/blocks.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/buffer.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/build.make +522 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/cmake_clean.cmake +27 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/cmark.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/cmark_ctype.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/commonmark.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/depend.internal +169 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/depend.make +169 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/flags.make +8 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/houdini_href_e.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/houdini_html_e.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/houdini_html_u.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/html.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/inlines.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/iterator.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/link.txt +1 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/man.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/node.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/progress.make +18 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/references.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/scanners.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/utf8.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/xml.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/C.includecache +394 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/DependInfo.cmake +38 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/blocks.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/buffer.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/build.make +519 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/cmake_clean.cmake +26 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/cmake_clean_target.cmake +3 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/cmark.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/cmark_ctype.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/commonmark.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/depend.internal +169 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/depend.make +169 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/flags.make +8 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/houdini_href_e.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/houdini_html_e.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/houdini_html_u.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/html.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/inlines.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/iterator.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/link.txt +2 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/man.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/node.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/progress.make +18 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/references.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/scanners.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/utf8.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/xml.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/progress.marks +1 -0
- data/ext/commonmarker/cmark/build/src/Makefile +814 -0
- data/ext/commonmarker/cmark/build/src/cmake_install.cmake +69 -0
- data/ext/commonmarker/cmark/build/src/cmark +0 -0
- data/ext/commonmarker/cmark/build/src/cmark_export.h +41 -0
- data/ext/commonmarker/cmark/build/src/cmark_version.h +7 -0
- data/ext/commonmarker/cmark/build/src/config.h +23 -0
- data/ext/commonmarker/cmark/build/src/libcmark.0.19.0.dylib +0 -0
- data/ext/commonmarker/cmark/build/src/libcmark.a +0 -0
- data/ext/commonmarker/cmark/build/src/libcmark.dylib +0 -0
- data/ext/commonmarker/cmark/build/src/libcmark.pc +10 -0
- data/ext/commonmarker/cmark/build/testdir/CMakeFiles/CMakeDirectoryInformation.cmake +16 -0
- data/ext/commonmarker/cmark/build/testdir/CMakeFiles/progress.marks +1 -0
- data/ext/commonmarker/cmark/build/testdir/CTestTestfile.cmake +12 -0
- data/ext/commonmarker/cmark/build/testdir/Makefile +181 -0
- data/ext/commonmarker/cmark/build/testdir/cmake_install.cmake +29 -0
- data/ext/commonmarker/cmark/changelog.txt +153 -0
- data/ext/commonmarker/cmark/data/CaseFolding-3.2.0.txt +912 -0
- data/ext/commonmarker/cmark/man/CMakeLists.txt +8 -0
- data/ext/commonmarker/cmark/man/make_man_page.py +131 -0
- data/ext/commonmarker/cmark/man/man1/cmark.1 +54 -0
- data/ext/commonmarker/cmark/man/man3/cmark.3 +583 -0
- data/ext/commonmarker/cmark/nmake.bat +1 -0
- data/ext/commonmarker/cmark/src/CMakeLists.txt +166 -0
- data/ext/commonmarker/cmark/src/bench.h +27 -0
- data/ext/commonmarker/cmark/src/blocks.c +887 -0
- data/ext/commonmarker/cmark/src/buffer.c +381 -0
- data/ext/commonmarker/cmark/src/buffer.h +113 -0
- data/ext/commonmarker/cmark/src/case_fold_switch.inc +2637 -0
- data/ext/commonmarker/cmark/src/chunk.h +110 -0
- data/ext/commonmarker/cmark/src/cmark.c +24 -0
- data/ext/commonmarker/cmark/src/cmark.h +565 -0
- data/ext/commonmarker/cmark/src/cmark_ctype.c +53 -0
- data/ext/commonmarker/cmark/src/cmark_ctype.h +24 -0
- data/ext/commonmarker/cmark/src/cmark_version.h.in +7 -0
- data/ext/commonmarker/cmark/src/commonmark.c +607 -0
- data/ext/commonmarker/cmark/src/config.h.in +23 -0
- data/ext/commonmarker/cmark/src/debug.h +36 -0
- data/ext/commonmarker/cmark/src/houdini.h +52 -0
- data/ext/commonmarker/cmark/src/houdini_href_e.c +107 -0
- data/ext/commonmarker/cmark/src/houdini_html_e.c +81 -0
- data/ext/commonmarker/cmark/src/houdini_html_u.c +116 -0
- data/ext/commonmarker/cmark/src/html.c +322 -0
- data/ext/commonmarker/cmark/src/html_unescape.gperf +2130 -0
- data/ext/commonmarker/cmark/src/html_unescape.h +13375 -0
- data/ext/commonmarker/cmark/src/inlines.c +1147 -0
- data/ext/commonmarker/cmark/src/inlines.h +19 -0
- data/ext/commonmarker/cmark/src/iterator.c +148 -0
- data/ext/commonmarker/cmark/src/iterator.h +25 -0
- data/ext/commonmarker/cmark/src/libcmark.pc.in +10 -0
- data/ext/commonmarker/cmark/src/main.c +191 -0
- data/ext/commonmarker/cmark/src/man.c +287 -0
- data/ext/commonmarker/cmark/src/node.c +873 -0
- data/ext/commonmarker/cmark/src/node.h +82 -0
- data/ext/commonmarker/cmark/src/parser.h +29 -0
- data/ext/commonmarker/cmark/src/references.c +154 -0
- data/ext/commonmarker/cmark/src/references.h +37 -0
- data/ext/commonmarker/cmark/src/scanners.c +15291 -0
- data/ext/commonmarker/cmark/src/scanners.h +41 -0
- data/ext/commonmarker/cmark/src/scanners.re +247 -0
- data/ext/commonmarker/cmark/src/utf8.c +452 -0
- data/ext/commonmarker/cmark/src/utf8.h +22 -0
- data/ext/commonmarker/cmark/src/xml.c +170 -0
- data/ext/commonmarker/cmark/test/CMakeLists.txt +53 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/asterisk +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/attr_generic +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/attr_href +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/attr_xml_lang +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/attr_xmlns +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/backslash +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/backtick +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/colon +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/dashes +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/double_quote +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/entity_builtin +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/entity_decimal +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/entity_external +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/entity_hex +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/equals +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/exclamation +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/greater_than +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/hash +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/hyphen +0 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/indent +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/left_bracket +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/left_paren +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/less_than +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/plus +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/right_bracket +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/right_paren +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/single_quote +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/string_any +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/string_brackets +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/string_cdata +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/string_dashes +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/string_empty_dblquotes +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/string_empty_quotes +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/string_idrefs +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/string_parentheses +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/string_pcdata +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/tag_cdata +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/tag_close +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/tag_doctype +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/tag_element +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/tag_entity +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/tag_notation +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/tag_open +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/tag_open_close +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/tag_open_exclamation +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/tag_open_q +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/tag_sq2_close +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/tag_xml_q +1 -0
- data/ext/commonmarker/cmark/test/afl_dictionary/underscore +1 -0
- data/ext/commonmarker/cmark/test/afl_test_cases/test.md +36 -0
- data/ext/commonmarker/cmark/test/cmark.py +40 -0
- data/ext/commonmarker/cmark/test/normalize.py +179 -0
- data/ext/commonmarker/cmark/test/pathological_tests.py +63 -0
- data/ext/commonmarker/cmark/test/roundtrip.sh +2 -0
- data/ext/commonmarker/cmark/test/smart_punct.txt +96 -0
- data/ext/commonmarker/cmark/test/spec.txt +7505 -0
- data/ext/commonmarker/cmark/test/spec_tests.py +139 -0
- data/ext/commonmarker/cmark/toolchain-mingw32.cmake +17 -0
- data/ext/commonmarker/cmark/tools/mkcasefold.pl +22 -0
- data/ext/commonmarker/cmark/wrappers/wrapper.lua +239 -0
- data/ext/commonmarker/cmark/wrappers/wrapper.py +37 -0
- data/ext/commonmarker/cmark/wrappers/wrapper.rb +15 -0
- data/ext/commonmarker/cmark/wrappers/wrapper.rkt +190 -0
- data/ext/commonmarker/commonmarker.c +165 -0
- data/ext/commonmarker/commonmarker.h +11 -0
- data/ext/commonmarker/extconf.rb +18 -0
- data/lib/commonmarker/config.rb +20 -0
- data/lib/commonmarker/version.rb +3 -0
- data/lib/commonmarker.rb +588 -0
- data/test/benchmark.rb +30 -0
- data/test/spec_tests.json +4074 -0
- data/test/test_basics.rb +44 -0
- data/test/test_helper.rb +5 -0
- data/test/test_maliciousness.rb +9 -0
- data/test/test_pathological_inputs.rb +52 -0
- data/test/test_spec.rb +20 -0
- 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
|
+
}
|