commonmarker 0.7.0 → 0.8.0

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 (102) hide show
  1. checksums.yaml +4 -4
  2. data/ext/commonmarker/cmark/CMakeLists.txt +3 -3
  3. data/ext/commonmarker/cmark/Makefile +2 -3
  4. data/ext/commonmarker/cmark/README.md +1 -1
  5. data/ext/commonmarker/cmark/api_test/main.c +15 -0
  6. data/ext/commonmarker/cmark/appveyor.yml +4 -2
  7. data/ext/commonmarker/cmark/build/CMakeCache.txt +86 -14
  8. data/ext/commonmarker/cmark/build/CMakeFiles/{3.3.2 → 3.5.1}/CMakeCCompiler.cmake +9 -5
  9. data/ext/commonmarker/cmark/build/CMakeFiles/{3.3.2 → 3.5.1}/CMakeCXXCompiler.cmake +9 -5
  10. data/ext/commonmarker/cmark/build/CMakeFiles/{3.3.2/CMakeDetermineCompilerABI_CXX.bin → 3.5.1/CMakeDetermineCompilerABI_C.bin} +0 -0
  11. data/ext/commonmarker/cmark/build/CMakeFiles/{3.3.2/CMakeDetermineCompilerABI_C.bin → 3.5.1/CMakeDetermineCompilerABI_CXX.bin} +0 -0
  12. data/ext/commonmarker/cmark/build/CMakeFiles/{3.3.2 → 3.5.1}/CMakeSystem.cmake +4 -4
  13. data/ext/commonmarker/cmark/build/CMakeFiles/{3.3.2 → 3.5.1}/CompilerIdC/CMakeCCompilerId.c +39 -3
  14. data/ext/commonmarker/cmark/build/CMakeFiles/{3.3.2 → 3.5.1}/CompilerIdC/a.out +0 -0
  15. data/ext/commonmarker/cmark/build/CMakeFiles/{3.3.2 → 3.5.1}/CompilerIdCXX/CMakeCXXCompilerId.cpp +38 -3
  16. data/ext/commonmarker/cmark/build/CMakeFiles/{3.3.2 → 3.5.1}/CompilerIdCXX/a.out +0 -0
  17. data/ext/commonmarker/cmark/build/CMakeFiles/CMakeDirectoryInformation.cmake +1 -1
  18. data/ext/commonmarker/cmark/build/CMakeFiles/CMakeError.log +6 -6
  19. data/ext/commonmarker/cmark/build/CMakeFiles/CMakeOutput.log +171 -167
  20. data/ext/commonmarker/cmark/build/CMakeFiles/Makefile.cmake +107 -104
  21. data/ext/commonmarker/cmark/build/CMakeFiles/Makefile2 +42 -42
  22. data/ext/commonmarker/cmark/build/CMakeFiles/TargetDirectories.txt +36 -1
  23. data/ext/commonmarker/cmark/build/CMakeFiles/feature_tests.bin +0 -0
  24. data/ext/commonmarker/cmark/build/CMakeFiles/feature_tests.c +1 -1
  25. data/ext/commonmarker/cmark/build/CMakeFiles/feature_tests.cxx +1 -1
  26. data/ext/commonmarker/cmark/build/Makefile +23 -23
  27. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/CMakeDirectoryInformation.cmake +1 -1
  28. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/DependInfo.cmake +3 -0
  29. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/build.make +13 -13
  30. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/flags.make +7 -3
  31. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/link.txt +1 -1
  32. data/ext/commonmarker/cmark/build/api_test/Makefile +10 -10
  33. data/ext/commonmarker/cmark/build/man/CMakeFiles/CMakeDirectoryInformation.cmake +1 -1
  34. data/ext/commonmarker/cmark/build/man/Makefile +10 -10
  35. data/ext/commonmarker/cmark/build/src/CMakeFiles/CMakeDirectoryInformation.cmake +1 -1
  36. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/DependInfo.cmake +3 -0
  37. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/build.make +63 -63
  38. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/flags.make +4 -2
  39. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/DependInfo.cmake +4 -1
  40. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/build.make +83 -83
  41. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/cmake_clean.cmake +1 -1
  42. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/flags.make +4 -2
  43. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/link.txt +1 -1
  44. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/DependInfo.cmake +3 -0
  45. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/blocks.c.o +0 -0
  46. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/buffer.c.o +0 -0
  47. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/build.make +60 -60
  48. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/cmark.c.o +0 -0
  49. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/cmark_ctype.c.o +0 -0
  50. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/commonmark.c.o +0 -0
  51. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/depend.internal +1 -1
  52. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/depend.make +1 -1
  53. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/flags.make +4 -2
  54. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/houdini_href_e.c.o +0 -0
  55. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/houdini_html_e.c.o +0 -0
  56. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/houdini_html_u.c.o +0 -0
  57. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/html.c.o +0 -0
  58. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/inlines.c.o +0 -0
  59. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/iterator.c.o +0 -0
  60. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/latex.c.o +0 -0
  61. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/link.txt +1 -1
  62. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/man.c.o +0 -0
  63. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/node.c.o +0 -0
  64. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/references.c.o +0 -0
  65. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/render.c.o +0 -0
  66. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/scanners.c.o +0 -0
  67. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/utf8.c.o +0 -0
  68. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/xml.c.o +0 -0
  69. data/ext/commonmarker/cmark/build/src/Makefile +82 -82
  70. data/ext/commonmarker/cmark/build/src/cmake_install.cmake +2 -2
  71. data/ext/commonmarker/cmark/build/src/cmark_version.h +2 -2
  72. data/ext/commonmarker/cmark/build/src/libcmark.a +0 -0
  73. data/ext/commonmarker/cmark/build/src/libcmark.pc +1 -1
  74. data/ext/commonmarker/cmark/build/testdir/CMakeFiles/CMakeDirectoryInformation.cmake +1 -1
  75. data/ext/commonmarker/cmark/build/testdir/CTestTestfile.cmake +1 -0
  76. data/ext/commonmarker/cmark/build/testdir/Makefile +10 -10
  77. data/ext/commonmarker/cmark/changelog.txt +72 -0
  78. data/ext/commonmarker/cmark/man/CMakeLists.txt +5 -3
  79. data/ext/commonmarker/cmark/man/man1/cmark.1 +2 -2
  80. data/ext/commonmarker/cmark/man/man3/cmark.3 +10 -10
  81. data/ext/commonmarker/cmark/src/CMakeLists.txt +2 -2
  82. data/ext/commonmarker/cmark/src/blocks.c +407 -245
  83. data/ext/commonmarker/cmark/src/buffer.c +3 -2
  84. data/ext/commonmarker/cmark/src/cmark.h +3 -3
  85. data/ext/commonmarker/cmark/src/commonmark.c +5 -5
  86. data/ext/commonmarker/cmark/src/html.c +3 -3
  87. data/ext/commonmarker/cmark/src/inlines.c +11 -11
  88. data/ext/commonmarker/cmark/src/latex.c +2 -2
  89. data/ext/commonmarker/cmark/src/main.c +2 -1
  90. data/ext/commonmarker/cmark/src/man.c +1 -1
  91. data/ext/commonmarker/cmark/src/node.c +2 -2
  92. data/ext/commonmarker/cmark/src/parser.h +2 -0
  93. data/ext/commonmarker/cmark/src/render.c +2 -2
  94. data/ext/commonmarker/cmark/src/scanners.c +2431 -2620
  95. data/ext/commonmarker/cmark/src/xml.c +3 -2
  96. data/ext/commonmarker/cmark/test/CMakeLists.txt +7 -0
  97. data/ext/commonmarker/cmark/test/regression.txt +34 -0
  98. data/ext/commonmarker/cmark/test/spec.txt +49 -6
  99. data/ext/commonmarker/cmark/test/spec_tests.py +1 -1
  100. data/ext/commonmarker/cmark/tools/appveyor-build.bat +13 -0
  101. data/lib/commonmarker/version.rb +1 -1
  102. metadata +13 -11
@@ -43,11 +43,11 @@ endif()
43
43
 
44
44
  if(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified")
45
45
  file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/lib" TYPE SHARED_LIBRARY FILES
46
- "/Users/gjtorikian/Development/commonmarker/ext/commonmarker/cmark/build/src/libcmark.0.24.1.dylib"
46
+ "/Users/gjtorikian/Development/commonmarker/ext/commonmarker/cmark/build/src/libcmark.0.25.2.dylib"
47
47
  "/Users/gjtorikian/Development/commonmarker/ext/commonmarker/cmark/build/src/libcmark.dylib"
48
48
  )
49
49
  foreach(file
50
- "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/lib/libcmark.0.24.1.dylib"
50
+ "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/lib/libcmark.0.25.2.dylib"
51
51
  "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/lib/libcmark.dylib"
52
52
  )
53
53
  if(EXISTS "${file}" AND
@@ -1,7 +1,7 @@
1
1
  #ifndef CMARK_VERSION_H
2
2
  #define CMARK_VERSION_H
3
3
 
4
- #define CMARK_VERSION ((0 << 16) | (24 << 8) | 1)
5
- #define CMARK_VERSION_STRING "0.24.1"
4
+ #define CMARK_VERSION ((0 << 16) | (25 << 8) | 2)
5
+ #define CMARK_VERSION_STRING "0.25.2"
6
6
 
7
7
  #endif
@@ -5,6 +5,6 @@ includedir=/usr/local/include
5
5
 
6
6
  Name: libcmark
7
7
  Description: CommonMark parsing, rendering, and manipulation
8
- Version: 0.24.1
8
+ Version: 0.25.2
9
9
  Libs: -L${libdir} -lcmark
10
10
  Cflags: -I${includedir}
@@ -1,5 +1,5 @@
1
1
  # CMAKE generated file: DO NOT EDIT!
2
- # Generated by "Unix Makefiles" Generator, CMake Version 3.3
2
+ # Generated by "Unix Makefiles" Generator, CMake Version 3.5
3
3
 
4
4
  # Relative path conversion top directories.
5
5
  set(CMAKE_RELATIVE_PATH_TOP_SOURCE "/Users/gjtorikian/Development/commonmarker/ext/commonmarker/cmark")
@@ -11,3 +11,4 @@ add_test(pathological_tests_library "/usr/local/bin/python3" "/Users/gjtorikian/
11
11
  add_test(spectest_executable "/usr/local/bin/python3" "/Users/gjtorikian/Development/commonmarker/ext/commonmarker/cmark/test/spec_tests.py" "--no-normalize" "--spec" "/Users/gjtorikian/Development/commonmarker/ext/commonmarker/cmark/test/spec.txt" "--program" "/Users/gjtorikian/Development/commonmarker/ext/commonmarker/cmark/build/testdir/../src/cmark")
12
12
  add_test(smartpuncttest_executable "/usr/local/bin/python3" "/Users/gjtorikian/Development/commonmarker/ext/commonmarker/cmark/test/spec_tests.py" "--no-normalize" "--spec" "/Users/gjtorikian/Development/commonmarker/ext/commonmarker/cmark/test/smart_punct.txt" "--program" "/Users/gjtorikian/Development/commonmarker/ext/commonmarker/cmark/build/testdir/../src/cmark --smart")
13
13
  add_test(roundtriptest_executable "/usr/local/bin/python3" "/Users/gjtorikian/Development/commonmarker/ext/commonmarker/cmark/test/spec_tests.py" "--no-normalize" "--spec" "/Users/gjtorikian/Development/commonmarker/ext/commonmarker/cmark/test/spec.txt" "--program" " /Users/gjtorikian/Development/commonmarker/ext/commonmarker/cmark/build/testdir/../src/cmark")
14
+ add_test(regressiontest_executable "/usr/local/bin/python3" "/Users/gjtorikian/Development/commonmarker/ext/commonmarker/cmark/test/spec_tests.py" "--no-normalize" "--spec" "/Users/gjtorikian/Development/commonmarker/ext/commonmarker/cmark/test/regression.txt" "--program" "/Users/gjtorikian/Development/commonmarker/ext/commonmarker/cmark/build/testdir/../src/cmark")
@@ -1,5 +1,5 @@
1
1
  # CMAKE generated file: DO NOT EDIT!
2
- # Generated by "Unix Makefiles" Generator, CMake Version 3.3
2
+ # Generated by "Unix Makefiles" Generator, CMake Version 3.5
3
3
 
4
4
  # Default target executed when no arguments are given to make.
5
5
  default_target: all
@@ -39,10 +39,10 @@ cmake_force:
39
39
  SHELL = /bin/sh
40
40
 
41
41
  # The CMake executable.
42
- CMAKE_COMMAND = /usr/local/Cellar/cmake/3.3.2/bin/cmake
42
+ CMAKE_COMMAND = /usr/local/Cellar/cmake/3.5.1/bin/cmake
43
43
 
44
44
  # The command to remove a file.
45
- RM = /usr/local/Cellar/cmake/3.3.2/bin/cmake -E remove -f
45
+ RM = /usr/local/Cellar/cmake/3.5.1/bin/cmake -E remove -f
46
46
 
47
47
  # Escaping for special characters.
48
48
  EQUALS = =
@@ -59,7 +59,7 @@ CMAKE_BINARY_DIR = /Users/gjtorikian/Development/commonmarker/ext/commonmarker/c
59
59
  # Special rule for the target test
60
60
  test:
61
61
  @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running tests..."
62
- /usr/local/Cellar/cmake/3.3.2/bin/ctest --force-new-ctest-process $(ARGS)
62
+ /usr/local/Cellar/cmake/3.5.1/bin/ctest --force-new-ctest-process $(ARGS)
63
63
  .PHONY : test
64
64
 
65
65
  # Special rule for the target test
@@ -70,7 +70,7 @@ test/fast: test
70
70
  # Special rule for the target install/local
71
71
  install/local: preinstall
72
72
  @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..."
73
- /usr/local/Cellar/cmake/3.3.2/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake
73
+ /usr/local/Cellar/cmake/3.5.1/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake
74
74
  .PHONY : install/local
75
75
 
76
76
  # Special rule for the target install/local
@@ -81,7 +81,7 @@ install/local/fast: install/local
81
81
  # Special rule for the target edit_cache
82
82
  edit_cache:
83
83
  @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..."
84
- /usr/local/Cellar/cmake/3.3.2/bin/ccmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
84
+ /usr/local/Cellar/cmake/3.5.1/bin/ccmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
85
85
  .PHONY : edit_cache
86
86
 
87
87
  # Special rule for the target edit_cache
@@ -92,7 +92,7 @@ edit_cache/fast: edit_cache
92
92
  # Special rule for the target rebuild_cache
93
93
  rebuild_cache:
94
94
  @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..."
95
- /usr/local/Cellar/cmake/3.3.2/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
95
+ /usr/local/Cellar/cmake/3.5.1/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
96
96
  .PHONY : rebuild_cache
97
97
 
98
98
  # Special rule for the target rebuild_cache
@@ -113,19 +113,19 @@ list_install_components/fast: list_install_components
113
113
  # Special rule for the target install
114
114
  install: preinstall
115
115
  @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..."
116
- /usr/local/Cellar/cmake/3.3.2/bin/cmake -P cmake_install.cmake
116
+ /usr/local/Cellar/cmake/3.5.1/bin/cmake -P cmake_install.cmake
117
117
  .PHONY : install
118
118
 
119
119
  # Special rule for the target install
120
120
  install/fast: preinstall/fast
121
121
  @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..."
122
- /usr/local/Cellar/cmake/3.3.2/bin/cmake -P cmake_install.cmake
122
+ /usr/local/Cellar/cmake/3.5.1/bin/cmake -P cmake_install.cmake
123
123
  .PHONY : install/fast
124
124
 
125
125
  # Special rule for the target install/strip
126
126
  install/strip: preinstall
127
127
  @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..."
128
- /usr/local/Cellar/cmake/3.3.2/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake
128
+ /usr/local/Cellar/cmake/3.5.1/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake
129
129
  .PHONY : install/strip
130
130
 
131
131
  # Special rule for the target install/strip
@@ -1,3 +1,75 @@
1
+ [0.25.2]
2
+
3
+ * Open files in binary mode (#113, Nick Wellnhofer). Now that cmark
4
+ supports different line endings, files must be openend in binary mode
5
+ on Windows.
6
+ * Reset `partially_consumed_tab` on every new line (#114, Nick Wellnhofer).
7
+ * Handle buffer split across a CRLF line ending (#117). Adds an internal
8
+ field to the parser struct to keep track of `last_buffer_ended_with_cr`.
9
+ Added test.
10
+
11
+ [0.25.1]
12
+
13
+ * Release with no code changes. cmark version was mistakenly set to
14
+ 0.25.1 in the 0.25.0 release (#112), so this release just
15
+ ensures that this will cause no confusion later.
16
+
17
+ [0.25.0]
18
+
19
+ * Fixed tabs in indentation (#101). This patch fixes S_advance_offset
20
+ so that it doesn't gobble a tab character when advancing less than the
21
+ width of a tab.
22
+ * Added partially_consumed_tab to parser. This keeps track of when we
23
+ have gotten partway through a tab when consuming initial indentation.
24
+ * Simplified add_line (only need parser parameter).
25
+ * Properly handle partially consumed tab. E.g. in
26
+
27
+ - foo
28
+
29
+ <TAB><TAB>bar
30
+
31
+ we should consume two spaces from the second tab, including two spaces
32
+ in the code block.
33
+ * Properly handle tabs with blockquotes and fenced blocks.
34
+ * Fixed handling of tabs in lists.
35
+ * Clarified logic in S_advance_offset.
36
+ * Use an assertion to check for in-range html_block_type.
37
+ It's a programming error if the type is out of range.
38
+ * Refactored S_processLines to make the logic easier to
39
+ understand, and added documentation (Mathieu Duponchelle).
40
+ * Removed unnecessary check for empty string_content.
41
+ * Factored out contains_inlines.
42
+ * Moved the cmake minimum version to top line of CMakeLists.txt
43
+ (tinysun212).
44
+ * Fix ctype(3) usage on NetBSD (Kamil Rytarowski). We need to cast value
45
+ passed to isspace(3) to unsigned char to explicitly prevent possibly
46
+ undefined behavior.
47
+ * Compile in plain C mode with MSVC 12.0 or newer (Nick Wellnhofer).
48
+ Under MSVC, we used to compile in C++ mode to get some C99 features
49
+ like mixing declarations and code. With newer MSVC versions, it's
50
+ possible to build in plain C mode.
51
+ * Switched from "inline" to "CMARK_INLINE" (Nick Wellnhofer).
52
+ Newer MSVC versions support enough of C99 to be able to compile cmark
53
+ in plain C mode. Only the "inline" keyword is still unsupported.
54
+ We have to use "__inline" instead.
55
+ * Added include guards to config.h
56
+ * config.h.in - added compatibility snprintf, vsnprintf for MSVC.
57
+ * Replaced sprintf with snprintf (Marco Benelli).
58
+ * config.h: include stdio.h for _vscprintf etc.
59
+ * Include starg.h when needed in config.h.
60
+ * Removed an unnecessary C99-ism in buffer.c. This helps compiling on
61
+ systems like luarocks that don't have all the cmake configuration
62
+ goodness (thanks to carlmartus).
63
+ * Don't use variable length arrays (Nick Wellnhofer).
64
+ They're not supported by MSVC.
65
+ * Test with multiple MSVC versions under Appveyor (Nick Wellnhofer).
66
+ * Fix installation dir of man-pages on NetBSD (Kamil Rytarowski).
67
+ * Fixed typo in cmark.h comments (Chris Eidhof).
68
+ * Clarify in man page that cmark_node_free frees a node's children too.
69
+ * Fixed documentation of --width in man page.
70
+ * Require re2c >= 1.14.2 (#102).
71
+ * Generated scanners.c with more recent re2c.
72
+
1
73
  [0.24.1]
2
74
 
3
75
  * Commonmark renderer:
@@ -1,8 +1,10 @@
1
1
  if (NOT MSVC)
2
+
3
+ include(GNUInstallDirs)
4
+
2
5
  install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/man1/cmark.1
3
- DESTINATION share/man/man1)
6
+ DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
4
7
 
5
8
  install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/man3/cmark.3
6
- DESTINATION share/man/man3)
9
+ DESTINATION ${CMAKE_INSTALL_MANDIR}/man3)
7
10
  endif(NOT MSVC)
8
-
@@ -1,4 +1,4 @@
1
- .TH "cmark" "1" "November 30, 2014" "LOCAL" "General Commands Manual"
1
+ .TH "cmark" "1" "March 24, 2016" "LOCAL" "General Commands Manual"
2
2
  .SH "NAME"
3
3
  \fBcmark\fR
4
4
  \- convert CommonMark formatted text to HTML
@@ -23,7 +23,7 @@ Specify output format (\f[C]html\f[], \f[C]man\f[], \f[C]xml\f[],
23
23
  .B \-\-width \f[I]WIDTH\f[]
24
24
  Specify a column width to which to wrap the output. For no wrapping, use
25
25
  the value 0 (the default). This option currently only affects the
26
- commonmark renderer.
26
+ commonmark, latex, and man renderers.
27
27
  .TP 12n
28
28
  .B \-\-sourcepos
29
29
  Include source position attribute.
@@ -1,4 +1,4 @@
1
- .TH cmark 3 "January 11, 2016" "LOCAL" "Library Functions Manual"
1
+ .TH cmark 3 "March 24, 2016" "LOCAL" "Library Functions Manual"
2
2
  .SH
3
3
  NAME
4
4
  .PP
@@ -14,7 +14,7 @@ Simple Interface
14
14
 
15
15
  .PP
16
16
  Convert \f[I]text\f[] (assumed to be a UTF\-8 encoded string with length
17
- \f[I]len\f[] from CommonMark Markdown to HTML, returning a
17
+ \f[I]len\f[]) from CommonMark Markdown to HTML, returning a
18
18
  null\-terminated, UTF\-8\-encoded string.
19
19
 
20
20
  .SS
@@ -109,7 +109,7 @@ to assign.
109
109
  \fIvoid\f[] \fBcmark_node_free\f[](\fIcmark_node *node\f[])
110
110
 
111
111
  .PP
112
- Frees the memory allocated for a node.
112
+ Frees the memory allocated for a node and any children.
113
113
 
114
114
  .SS
115
115
  Tree Traversal
@@ -363,8 +363,8 @@ otherwise 0.
363
363
  \fIint\f[] \fBcmark_node_set_list_start\f[](\fIcmark_node *node\f[], \fIint start\f[])
364
364
 
365
365
  .PP
366
- Sets starting number of \f[I]node\f[], if it is an ordered list. Returns
367
- 1 on success, 0 on failure.
366
+ Sets starting number of \f[I]node\f[], if it is an ordered list.
367
+ Returns 1 on success, 0 on failure.
368
368
 
369
369
  .PP
370
370
  \fIint\f[] \fBcmark_node_get_list_tight\f[](\fIcmark_node *node\f[])
@@ -389,8 +389,8 @@ Returns the info string from a fenced code block.
389
389
  \fIint\f[] \fBcmark_node_set_fence_info\f[](\fIcmark_node *node\f[], \fIconst char *info\f[])
390
390
 
391
391
  .PP
392
- Sets the info string in a fenced code block, returning 1 on success and
393
- 0 on failure.
392
+ Sets the info string in a fenced code block, returning 1 on success
393
+ and 0 on failure.
394
394
 
395
395
  .PP
396
396
  \fIconst char *\f[] \fBcmark_node_get_url\f[](\fIcmark_node *node\f[])
@@ -517,8 +517,8 @@ Returns 1 on success, 0 on failure.
517
517
  \fIint\f[] \fBcmark_node_append_child\f[](\fIcmark_node *node\f[], \fIcmark_node *child\f[])
518
518
 
519
519
  .PP
520
- Adds \f[I]child\f[] to the end of the children of \f[I]node\f[]. Returns
521
- 1 on success, 0 on failure.
520
+ Adds \f[I]child\f[] to the end of the children of \f[I]node\f[].
521
+ Returns 1 on success, 0 on failure.
522
522
 
523
523
  .PP
524
524
  \fIvoid\f[] \fBcmark_consolidate_text_nodes\f[](\fIcmark_node *root\f[])
@@ -543,7 +543,7 @@ Streaming interface:
543
543
  .nf
544
544
  \f[C]
545
545
  cmark_parser *parser = cmark_parser_new(CMARK_OPT_DEFAULT);
546
- FILE *fp = fopen("myfile.md", "r");
546
+ FILE *fp = fopen("myfile.md", "rb");
547
547
  while ((bytes = fread(buffer, 1, sizeof(buffer), fp)) > 0) {
548
548
  cmark_parser_feed(parser, buffer, bytes);
549
549
  if (bytes < sizeof(buffer)) {
@@ -169,8 +169,8 @@ elseif(CMAKE_COMPILER_IS_GNUCC OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
169
169
  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -std=c99 -pedantic")
170
170
  endif()
171
171
 
172
- # Compile as C++ under MSVC
173
- if(MSVC)
172
+ # Compile as C++ under MSVC older than 12.0
173
+ if(MSVC AND MSVC_VERSION LESS 1800)
174
174
  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /TP")
175
175
  endif()
176
176
 
@@ -1,3 +1,10 @@
1
+ /**
2
+ * Block parsing implementation.
3
+ *
4
+ * For a high-level overview of the block parsing process,
5
+ * see http://spec.commonmark.org/0.24/#phase-1-block-structure
6
+ */
7
+
1
8
  #include <stdlib.h>
2
9
  #include <assert.h>
3
10
  #include <stdio.h>
@@ -17,12 +24,20 @@
17
24
  #define CODE_INDENT 4
18
25
  #define TAB_STOP 4
19
26
 
27
+ #ifndef MIN
28
+ #define MIN(x, y) ((x < y) ? x : y)
29
+ #endif
30
+
20
31
  #define peek_at(i, n) (i)->data[n]
21
32
 
22
- static inline bool S_is_line_end_char(char c) {
33
+ static CMARK_INLINE bool S_is_line_end_char(char c) {
23
34
  return (c == '\n' || c == '\r');
24
35
  }
25
36
 
37
+ static CMARK_INLINE bool S_is_space_or_tab(char c) {
38
+ return (c == ' ' || c == '\t');
39
+ }
40
+
26
41
  static void S_parser_feed(cmark_parser *parser, const unsigned char *buffer,
27
42
  size_t len, bool eof);
28
43
 
@@ -70,10 +85,12 @@ cmark_parser *cmark_parser_new(int options) {
70
85
  parser->first_nonspace_column = 0;
71
86
  parser->indent = 0;
72
87
  parser->blank = false;
88
+ parser->partially_consumed_tab = false;
73
89
  parser->curline = line;
74
90
  parser->last_line_length = 0;
75
91
  parser->linebuf = buf;
76
92
  parser->options = options;
93
+ parser->last_buffer_ended_with_cr = false;
77
94
 
78
95
  return parser;
79
96
  }
@@ -110,7 +127,7 @@ static bool is_blank(cmark_strbuf *s, bufsize_t offset) {
110
127
  return true;
111
128
  }
112
129
 
113
- static inline bool can_contain(cmark_node_type parent_type,
130
+ static CMARK_INLINE bool can_contain(cmark_node_type parent_type,
114
131
  cmark_node_type child_type) {
115
132
  return (parent_type == CMARK_NODE_DOCUMENT ||
116
133
  parent_type == CMARK_NODE_BLOCK_QUOTE ||
@@ -118,15 +135,32 @@ static inline bool can_contain(cmark_node_type parent_type,
118
135
  (parent_type == CMARK_NODE_LIST && child_type == CMARK_NODE_ITEM));
119
136
  }
120
137
 
121
- static inline bool accepts_lines(cmark_node_type block_type) {
138
+ static CMARK_INLINE bool accepts_lines(cmark_node_type block_type) {
122
139
  return (block_type == CMARK_NODE_PARAGRAPH ||
123
140
  block_type == CMARK_NODE_HEADING ||
124
141
  block_type == CMARK_NODE_CODE_BLOCK);
125
142
  }
126
143
 
127
- static void add_line(cmark_node *node, cmark_chunk *ch, bufsize_t offset) {
144
+ static CMARK_INLINE bool contains_inlines(cmark_node_type block_type) {
145
+ return (block_type == CMARK_NODE_PARAGRAPH ||
146
+ block_type == CMARK_NODE_HEADING);
147
+ }
148
+
149
+ static void add_line(cmark_node *node, cmark_chunk *ch, cmark_parser *parser) {
150
+ int chars_to_tab;
151
+ int i;
128
152
  assert(node->open);
129
- cmark_strbuf_put(&node->string_content, ch->data + offset, ch->len - offset);
153
+ if (parser->partially_consumed_tab) {
154
+ parser->offset += 1; // skip over tab
155
+ // add space characters:
156
+ chars_to_tab = TAB_STOP - (parser->column % TAB_STOP);
157
+ for (i = 0; i < chars_to_tab; i++) {
158
+ cmark_strbuf_putc(&node->string_content, ' ');
159
+ }
160
+ }
161
+ cmark_strbuf_put(&node->string_content,
162
+ ch->data + parser->offset,
163
+ ch->len - parser->offset);
130
164
  }
131
165
 
132
166
  static void remove_trailing_blank_lines(cmark_strbuf *ln) {
@@ -336,8 +370,7 @@ static void process_inlines(cmark_node *root, cmark_reference_map *refmap,
336
370
  while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
337
371
  cur = cmark_iter_get_node(iter);
338
372
  if (ev_type == CMARK_EVENT_ENTER) {
339
- if (cur->type == CMARK_NODE_PARAGRAPH ||
340
- cur->type == CMARK_NODE_HEADING) {
373
+ if (contains_inlines(cur->type)) {
341
374
  cmark_parse_inlines(cur, refmap, options);
342
375
  }
343
376
  }
@@ -474,6 +507,11 @@ static void S_parser_feed(cmark_parser *parser, const unsigned char *buffer,
474
507
  const unsigned char *end = buffer + len;
475
508
  static const uint8_t repl[] = {239, 191, 189};
476
509
 
510
+ if (parser->last_buffer_ended_with_cr && *buffer == '\n') {
511
+ // skip NL if last buffer ended with CR ; see #117
512
+ buffer++;
513
+ }
514
+ parser->last_buffer_ended_with_cr = false;
477
515
  while (buffer < end) {
478
516
  const unsigned char *eol;
479
517
  bufsize_t chunk_len;
@@ -514,8 +552,11 @@ static void S_parser_feed(cmark_parser *parser, const unsigned char *buffer,
514
552
 
515
553
  buffer += chunk_len;
516
554
  // skip over line ending characters:
517
- if (buffer < end && *buffer == '\r')
555
+ if (buffer < end && *buffer == '\r') {
518
556
  buffer++;
557
+ if (buffer == end)
558
+ parser->last_buffer_ended_with_cr = true;
559
+ }
519
560
  if (buffer < end && *buffer == '\n')
520
561
  buffer++;
521
562
  }
@@ -532,13 +573,15 @@ static void chop_trailing_hashtags(cmark_chunk *ch) {
532
573
  n--;
533
574
 
534
575
  // Check for a space before the final #s:
535
- if (n != orig_n && n >= 0 &&
536
- (peek_at(ch, n) == ' ' || peek_at(ch, n) == '\t')) {
576
+ if (n != orig_n && n >= 0 && S_is_space_or_tab(peek_at(ch, n))) {
537
577
  ch->len = n;
538
578
  cmark_chunk_rtrim(ch);
539
579
  }
540
580
  }
541
581
 
582
+ // Find first nonspace character from current offset, setting
583
+ // parser->first_nonspace, parser->first_nonspace_column,
584
+ // parser->indent, and parser->blank. Does not advance parser->offset.
542
585
  static void S_find_first_nonspace(cmark_parser *parser, cmark_chunk *input) {
543
586
  char c;
544
587
  int chars_to_tab = TAB_STOP - (parser->column % TAB_STOP);
@@ -566,17 +609,37 @@ static void S_find_first_nonspace(cmark_parser *parser, cmark_chunk *input) {
566
609
  parser->blank = S_is_line_end_char(peek_at(input, parser->first_nonspace));
567
610
  }
568
611
 
612
+ // Advance parser->offset and parser->column. parser->offset is the
613
+ // byte position in input; parser->column is a virtual column number
614
+ // that takes into account tabs. (Multibyte characters are not taken
615
+ // into account, because the Markdown line prefixes we are interested in
616
+ // analyzing are entirely ASCII.) The count parameter indicates
617
+ // how far to advance the offset. If columns is true, then count
618
+ // indicates a number of columns; otherwise, a number of bytes.
619
+ // If advancing a certain number of columns partially consumes
620
+ // a tab character, parser->partially_consumed_tab is set to true.
569
621
  static void S_advance_offset(cmark_parser *parser, cmark_chunk *input,
570
622
  bufsize_t count, bool columns) {
571
623
  char c;
572
624
  int chars_to_tab;
625
+ int chars_to_advance;
573
626
  while (count > 0 && (c = peek_at(input, parser->offset))) {
574
627
  if (c == '\t') {
575
628
  chars_to_tab = TAB_STOP - (parser->column % TAB_STOP);
576
- parser->column += chars_to_tab;
577
- parser->offset += 1;
578
- count -= (columns ? chars_to_tab : 1);
629
+ if (columns) {
630
+ parser->partially_consumed_tab = chars_to_tab > count;
631
+ chars_to_advance = MIN(count, chars_to_tab);
632
+ parser->column += chars_to_advance;
633
+ parser->offset += (parser->partially_consumed_tab ? 0 : 1);
634
+ count -= chars_to_advance;
635
+ } else {
636
+ parser->partially_consumed_tab = false;
637
+ parser->column += chars_to_tab;
638
+ parser->offset += 1;
639
+ count -= 1;
640
+ }
579
641
  } else {
642
+ parser->partially_consumed_tab = false;
580
643
  parser->offset += 1;
581
644
  parser->column += 1; // assume ascii; block starts are ascii
582
645
  count -= 1;
@@ -584,263 +647,314 @@ static void S_advance_offset(cmark_parser *parser, cmark_chunk *input,
584
647
  }
585
648
  }
586
649
 
587
- static void S_process_line(cmark_parser *parser, const unsigned char *buffer,
588
- bufsize_t bytes) {
589
- cmark_node *last_matched_container;
650
+ static bool S_last_child_is_open(cmark_node *container) {
651
+ return container->last_child && container->last_child->open;
652
+ }
653
+
654
+ static bool parse_block_quote_prefix(cmark_parser *parser,
655
+ cmark_chunk *input)
656
+ {
657
+ bool res = false;
590
658
  bufsize_t matched = 0;
591
- int lev = 0;
592
- int i;
593
- cmark_list *data = NULL;
594
- bool all_matched = true;
595
- cmark_node *container;
596
- bool indented;
597
- cmark_chunk input;
598
- bool maybe_lazy;
599
659
 
600
- if (parser->options & CMARK_OPT_VALIDATE_UTF8) {
601
- cmark_utf8proc_check(parser->curline, buffer, bytes);
602
- } else {
603
- cmark_strbuf_put(parser->curline, buffer, bytes);
604
- }
605
- // ensure line ends with a newline:
606
- if (bytes == 0 || !S_is_line_end_char(parser->curline->ptr[bytes - 1])) {
607
- cmark_strbuf_putc(parser->curline, '\n');
608
- }
609
- parser->offset = 0;
610
- parser->column = 0;
611
- parser->blank = false;
660
+ matched =
661
+ parser->indent <= 3 && peek_at(input, parser->first_nonspace) == '>';
662
+ if (matched) {
612
663
 
613
- input.data = parser->curline->ptr;
614
- input.len = parser->curline->size;
664
+ S_advance_offset(parser, input, parser->indent + 1, true);
615
665
 
616
- // container starts at the document root.
617
- container = parser->root;
666
+ if (S_is_space_or_tab(peek_at(input, parser->offset))) {
667
+ S_advance_offset(parser, input, 1, true);
668
+ }
618
669
 
619
- parser->line_number++;
670
+ res = true;
671
+ }
672
+ return res;
673
+ }
620
674
 
621
- // for each containing node, try to parse the associated line start.
622
- // bail out on failure: container will point to the last matching node.
675
+ static bool parse_node_item_prefix(cmark_parser *parser,
676
+ cmark_chunk *input,
677
+ cmark_node *container)
678
+ {
679
+ bool res = false;
680
+
681
+ if (parser->indent >=
682
+ container->as.list.marker_offset + container->as.list.padding) {
683
+ S_advance_offset(parser, input, container->as.list.marker_offset +
684
+ container->as.list.padding,
685
+ true);
686
+ res = true;
687
+ } else if (parser->blank && container->first_child != NULL) {
688
+ // if container->first_child is NULL, then the opening line
689
+ // of the list item was blank after the list marker; in this
690
+ // case, we are done with the list item.
691
+ S_advance_offset(parser, input,
692
+ parser->first_nonspace - parser->offset, false);
693
+ res = true;
694
+ }
695
+ return res;
696
+ }
623
697
 
624
- while (container->last_child && container->last_child->open) {
625
- container = container->last_child;
698
+ static bool parse_code_block_prefix(cmark_parser *parser,
699
+ cmark_chunk *input,
700
+ cmark_node *container,
701
+ bool *should_continue)
702
+ {
703
+ bool res = false;
704
+
705
+ if (!container->as.code.fenced) { // indented
706
+ if (parser->indent >= CODE_INDENT) {
707
+ S_advance_offset(parser, input, CODE_INDENT, true);
708
+ res = true;
709
+ } else if (parser->blank) {
710
+ S_advance_offset(parser, input,
711
+ parser->first_nonspace - parser->offset, false);
712
+ res = true;
713
+ }
714
+ } else { // fenced
715
+ bufsize_t matched = 0;
626
716
 
627
- S_find_first_nonspace(parser, &input);
717
+ if (parser->indent <= 3 && (peek_at(input, parser->first_nonspace) ==
718
+ container->as.code.fence_char)) {
719
+ matched = scan_close_code_fence(input, parser->first_nonspace);
720
+ }
628
721
 
629
- if (container->type == CMARK_NODE_BLOCK_QUOTE) {
630
- matched =
631
- parser->indent <= 3 && peek_at(&input, parser->first_nonspace) == '>';
632
- if (matched) {
633
- S_advance_offset(parser, &input, parser->indent + 1, true);
634
- if (peek_at(&input, parser->offset) == ' ')
635
- parser->offset++;
636
- } else {
637
- all_matched = false;
638
- }
722
+ if (matched >= container->as.code.fence_length) {
723
+ // closing fence - and since we're at
724
+ // the end of a line, we can stop processing it:
725
+ *should_continue = false;
726
+ S_advance_offset(parser, input, matched, false);
727
+ parser->current = finalize(parser, container);
728
+ } else {
729
+ // skip opt. spaces of fence parser->offset
730
+ int i = container->as.code.fence_offset;
639
731
 
640
- } else if (container->type == CMARK_NODE_ITEM) {
641
- if (parser->indent >=
642
- container->as.list.marker_offset + container->as.list.padding) {
643
- S_advance_offset(parser, &input, container->as.list.marker_offset +
644
- container->as.list.padding,
645
- true);
646
- } else if (parser->blank && container->first_child != NULL) {
647
- // if container->first_child is NULL, then the opening line
648
- // of the list item was blank after the list marker; in this
649
- // case, we are done with the list item.
650
- S_advance_offset(parser, &input,
651
- parser->first_nonspace - parser->offset, false);
652
- } else {
653
- all_matched = false;
732
+ while (i > 0 && S_is_space_or_tab(peek_at(input, parser->offset))) {
733
+ S_advance_offset(parser, input, 1, true);
734
+ i--;
654
735
  }
736
+ res = true;
737
+ }
738
+ }
655
739
 
656
- } else if (container->type == CMARK_NODE_CODE_BLOCK) {
740
+ return res;
741
+ }
657
742
 
658
- if (!container->as.code.fenced) { // indented
659
- if (parser->indent >= CODE_INDENT) {
660
- S_advance_offset(parser, &input, CODE_INDENT, true);
661
- } else if (parser->blank) {
662
- S_advance_offset(parser, &input,
663
- parser->first_nonspace - parser->offset, false);
664
- } else {
665
- all_matched = false;
666
- }
667
- } else { // fenced
668
- matched = 0;
669
- if (parser->indent <= 3 && (peek_at(&input, parser->first_nonspace) ==
670
- container->as.code.fence_char)) {
671
- matched = scan_close_code_fence(&input, parser->first_nonspace);
672
- }
673
- if (matched >= container->as.code.fence_length) {
674
- // closing fence - and since we're at
675
- // the end of a line, we can return:
676
- all_matched = false;
677
- S_advance_offset(parser, &input, matched, false);
678
- parser->current = finalize(parser, container);
679
- goto finished;
680
- } else {
681
- // skip opt. spaces of fence parser->offset
682
- i = container->as.code.fence_offset;
683
- while (i > 0 && peek_at(&input, parser->offset) == ' ') {
684
- S_advance_offset(parser, &input, 1, false);
685
- i--;
686
- }
687
- }
688
- }
689
- } else if (container->type == CMARK_NODE_HEADING) {
743
+ static bool parse_html_block_prefix(cmark_parser *parser,
744
+ cmark_node *container)
745
+ {
746
+ bool res = false;
747
+ int html_block_type = container->as.html_block_type;
748
+
749
+ assert(html_block_type >= 1 && html_block_type <= 7);
750
+ switch (html_block_type) {
751
+ case 1:
752
+ case 2:
753
+ case 3:
754
+ case 4:
755
+ case 5:
756
+ // these types of blocks can accept blanks
757
+ res = true;
758
+ break;
759
+ case 6:
760
+ case 7:
761
+ res = !parser->blank;
762
+ break;
763
+ }
690
764
 
691
- // a heading can never contain more than one line
692
- all_matched = false;
765
+ return res;
766
+ }
693
767
 
694
- } else if (container->type == CMARK_NODE_HTML_BLOCK) {
768
+ /**
769
+ * For each containing node, try to parse the associated line start.
770
+ *
771
+ * Will not close unmatched blocks, as we may have a lazy continuation
772
+ * line -> http://spec.commonmark.org/0.24/#lazy-continuation-line
773
+ *
774
+ * Returns: The last matching node, or NULL
775
+ */
776
+ static cmark_node *check_open_blocks(cmark_parser *parser,
777
+ cmark_chunk *input,
778
+ bool *all_matched)
779
+ {
780
+ bool should_continue = true;
781
+ *all_matched = false;
782
+ cmark_node *container = parser->root;
783
+ cmark_node_type cont_type;
784
+
785
+ while (S_last_child_is_open(container)) {
786
+ container = container->last_child;
787
+ cont_type = container->type;
695
788
 
696
- switch (container->as.html_block_type) {
697
- case 1:
698
- case 2:
699
- case 3:
700
- case 4:
701
- case 5:
702
- // these types of blocks can accept blanks
789
+ S_find_first_nonspace(parser, input);
790
+
791
+ switch (cont_type) {
792
+ case CMARK_NODE_BLOCK_QUOTE:
793
+ if (!parse_block_quote_prefix(parser, input))
794
+ goto done;
703
795
  break;
704
- case 6:
705
- case 7:
706
- if (parser->blank) {
707
- all_matched = false;
708
- }
796
+ case CMARK_NODE_ITEM:
797
+ if (!parse_node_item_prefix(parser, input, container))
798
+ goto done;
799
+ break;
800
+ case CMARK_NODE_CODE_BLOCK:
801
+ if (!parse_code_block_prefix(parser, input, container, &should_continue))
802
+ goto done;
803
+ break;
804
+ case CMARK_NODE_HEADING:
805
+ // a heading can never contain more than one line
806
+ goto done;
807
+ case CMARK_NODE_HTML_BLOCK:
808
+ if (!parse_html_block_prefix(parser, container))
809
+ goto done;
810
+ break;
811
+ case CMARK_NODE_PARAGRAPH:
812
+ if (parser->blank)
813
+ goto done;
709
814
  break;
710
815
  default:
711
- fprintf(stderr, "Error (%s:%d): Unknown HTML block type %d\n", __FILE__,
712
- __LINE__, container->as.html_block_type);
713
- exit(1);
714
- }
816
+ break;
817
+ }
818
+ }
715
819
 
716
- } else if (container->type == CMARK_NODE_PARAGRAPH) {
820
+ *all_matched = true;
717
821
 
718
- if (parser->blank) {
719
- all_matched = false;
720
- }
721
- }
822
+ done:
823
+ if (!*all_matched) {
824
+ container = container->parent; // back up to last matching node
825
+ }
722
826
 
723
- if (!all_matched) {
724
- container = container->parent; // back up to last matching node
725
- break;
726
- }
827
+ if (!should_continue) {
828
+ container = NULL;
727
829
  }
728
830
 
729
- last_matched_container = container;
831
+ return container;
832
+ }
730
833
 
731
- // check to see if we've hit 2nd blank line, break out of list:
732
- if (parser->blank && container->last_line_blank) {
733
- break_out_of_lists(parser, &container);
734
- }
834
+ static void open_new_blocks(cmark_parser *parser,
835
+ cmark_node **container,
836
+ cmark_chunk *input,
837
+ bool all_matched)
838
+ {
839
+ bool indented;
840
+ cmark_list *data = NULL;
841
+ bool maybe_lazy = parser->current->type == CMARK_NODE_PARAGRAPH;
842
+ cmark_node_type cont_type = (*container)->type;
843
+ bufsize_t matched = 0;
844
+ int lev = 0;
845
+ bool save_partially_consumed_tab;
846
+ int save_offset;
847
+ int save_column;
735
848
 
736
- maybe_lazy = parser->current->type == CMARK_NODE_PARAGRAPH;
737
- // try new container starts:
738
- while (container->type != CMARK_NODE_CODE_BLOCK &&
739
- container->type != CMARK_NODE_HTML_BLOCK) {
849
+ while (cont_type != CMARK_NODE_CODE_BLOCK &&
850
+ cont_type != CMARK_NODE_HTML_BLOCK) {
740
851
 
741
- S_find_first_nonspace(parser, &input);
852
+ S_find_first_nonspace(parser, input);
742
853
  indented = parser->indent >= CODE_INDENT;
743
854
 
744
- if (!indented && peek_at(&input, parser->first_nonspace) == '>') {
855
+ if (!indented && peek_at(input, parser->first_nonspace) == '>') {
745
856
 
746
- S_advance_offset(parser, &input,
857
+ S_advance_offset(parser, input,
747
858
  parser->first_nonspace + 1 - parser->offset, false);
748
859
  // optional following character
749
- if (peek_at(&input, parser->offset) == ' ')
750
- S_advance_offset(parser, &input, 1, false);
751
- container = add_child(parser, container, CMARK_NODE_BLOCK_QUOTE,
860
+ if (S_is_space_or_tab(peek_at(input, parser->offset))) {
861
+ S_advance_offset(parser, input, 1, true);
862
+ }
863
+ *container = add_child(parser, *container, CMARK_NODE_BLOCK_QUOTE,
752
864
  parser->offset + 1);
753
865
 
754
866
  } else if (!indented && (matched = scan_atx_heading_start(
755
- &input, parser->first_nonspace))) {
867
+ input, parser->first_nonspace))) {
868
+ bufsize_t hashpos;
869
+ int level = 0;
756
870
 
757
- S_advance_offset(parser, &input,
871
+ S_advance_offset(parser, input,
758
872
  parser->first_nonspace + matched - parser->offset,
759
873
  false);
760
- container =
761
- add_child(parser, container, CMARK_NODE_HEADING, parser->offset + 1);
874
+ *container =
875
+ add_child(parser, *container, CMARK_NODE_HEADING, parser->offset + 1);
762
876
 
763
- bufsize_t hashpos =
764
- cmark_chunk_strchr(&input, '#', parser->first_nonspace);
765
- int level = 0;
877
+ hashpos = cmark_chunk_strchr(input, '#', parser->first_nonspace);
766
878
 
767
- while (peek_at(&input, hashpos) == '#') {
879
+ while (peek_at(input, hashpos) == '#') {
768
880
  level++;
769
881
  hashpos++;
770
882
  }
771
- container->as.heading.level = level;
772
- container->as.heading.setext = false;
773
883
 
774
- } else if (!indented && (matched = scan_open_code_fence(
775
- &input, parser->first_nonspace))) {
884
+ (*container)->as.heading.level = level;
885
+ (*container)->as.heading.setext = false;
776
886
 
777
- container = add_child(parser, container, CMARK_NODE_CODE_BLOCK,
887
+ } else if (!indented && (matched = scan_open_code_fence(
888
+ input, parser->first_nonspace))) {
889
+ *container = add_child(parser, *container, CMARK_NODE_CODE_BLOCK,
778
890
  parser->first_nonspace + 1);
779
- container->as.code.fenced = true;
780
- container->as.code.fence_char = peek_at(&input, parser->first_nonspace);
781
- container->as.code.fence_length = matched;
782
- container->as.code.fence_offset =
891
+ (*container)->as.code.fenced = true;
892
+ (*container)->as.code.fence_char = peek_at(input, parser->first_nonspace);
893
+ (*container)->as.code.fence_length = matched;
894
+ (*container)->as.code.fence_offset =
783
895
  (int8_t)(parser->first_nonspace - parser->offset);
784
- container->as.code.info = cmark_chunk_literal("");
785
- S_advance_offset(parser, &input,
896
+ (*container)->as.code.info = cmark_chunk_literal("");
897
+ S_advance_offset(parser, input,
786
898
  parser->first_nonspace + matched - parser->offset,
787
899
  false);
788
900
 
789
901
  } else if (!indented && ((matched = scan_html_block_start(
790
- &input, parser->first_nonspace)) ||
791
- (container->type != CMARK_NODE_PARAGRAPH &&
902
+ input, parser->first_nonspace)) ||
903
+ (cont_type != CMARK_NODE_PARAGRAPH &&
792
904
  (matched = scan_html_block_start_7(
793
- &input, parser->first_nonspace))))) {
794
-
795
- container = add_child(parser, container, CMARK_NODE_HTML_BLOCK,
905
+ input, parser->first_nonspace))))) {
906
+ *container = add_child(parser, *container, CMARK_NODE_HTML_BLOCK,
796
907
  parser->first_nonspace + 1);
797
- container->as.html_block_type = matched;
908
+ (*container)->as.html_block_type = matched;
798
909
  // note, we don't adjust parser->offset because the tag is part of the
799
910
  // text
800
-
801
- } else if (!indented && container->type == CMARK_NODE_PARAGRAPH &&
911
+ } else if (!indented && cont_type == CMARK_NODE_PARAGRAPH &&
802
912
  (lev =
803
- scan_setext_heading_line(&input, parser->first_nonspace))) {
804
-
805
- container->type = CMARK_NODE_HEADING;
806
- container->as.heading.level = lev;
807
- container->as.heading.setext = true;
808
- S_advance_offset(parser, &input, input.len - 1 - parser->offset, false);
809
-
913
+ scan_setext_heading_line(input, parser->first_nonspace))) {
914
+ (*container)->type = CMARK_NODE_HEADING;
915
+ (*container)->as.heading.level = lev;
916
+ (*container)->as.heading.setext = true;
917
+ S_advance_offset(parser, input, input->len - 1 - parser->offset, false);
810
918
  } else if (!indented &&
811
- !(container->type == CMARK_NODE_PARAGRAPH && !all_matched) &&
919
+ !(cont_type == CMARK_NODE_PARAGRAPH && !all_matched) &&
812
920
  (matched =
813
- scan_thematic_break(&input, parser->first_nonspace))) {
814
-
921
+ scan_thematic_break(input, parser->first_nonspace))) {
815
922
  // it's only now that we know the line is not part of a setext heading:
816
- container = add_child(parser, container, CMARK_NODE_THEMATIC_BREAK,
923
+ *container = add_child(parser, *container, CMARK_NODE_THEMATIC_BREAK,
817
924
  parser->first_nonspace + 1);
818
- S_advance_offset(parser, &input, input.len - 1 - parser->offset, false);
819
-
925
+ S_advance_offset(parser, input, input->len - 1 - parser->offset, false);
820
926
  } else if ((matched =
821
- parse_list_marker(&input, parser->first_nonspace, &data)) &&
822
- (!indented || container->type == CMARK_NODE_LIST)) {
927
+ parse_list_marker(input, parser->first_nonspace, &data)) &&
928
+ (!indented || cont_type == CMARK_NODE_LIST)) {
823
929
  // Note that we can have new list items starting with >= 4
824
930
  // spaces indent, as long as the list container is still open.
931
+ int i = 0;
825
932
 
826
933
  // compute padding:
827
- S_advance_offset(parser, &input,
934
+ S_advance_offset(parser, input,
828
935
  parser->first_nonspace + matched - parser->offset,
829
936
  false);
830
- i = 0;
831
- while (i <= 5 && peek_at(&input, parser->offset + i) == ' ') {
832
- i++;
937
+
938
+ save_partially_consumed_tab = parser->partially_consumed_tab;
939
+ save_offset = parser->offset;
940
+ save_column = parser->column;
941
+
942
+ while (parser->column - save_column <= 5 &&
943
+ S_is_space_or_tab(peek_at(input, parser->offset))) {
944
+ S_advance_offset(parser, input, 1, true);
833
945
  }
834
- // i = number of spaces after marker, up to 5
835
- if (i >= 5 || i < 1 ||
836
- S_is_line_end_char(peek_at(&input, parser->offset))) {
946
+
947
+ i = parser->column - save_column;
948
+ if (i >= 5 || i < 1) {
837
949
  data->padding = matched + 1;
950
+ parser->offset = save_offset;
951
+ parser->column = save_column;
952
+ parser->partially_consumed_tab = save_partially_consumed_tab;
838
953
  if (i > 0) {
839
- S_advance_offset(parser, &input, 1, false);
954
+ S_advance_offset(parser, input, 1, true);
840
955
  }
841
956
  } else {
842
957
  data->padding = matched + i;
843
- S_advance_offset(parser, &input, i, true);
844
958
  }
845
959
 
846
960
  // check container; if it's a list, see if this list item
@@ -848,50 +962,57 @@ static void S_process_line(cmark_parser *parser, const unsigned char *buffer,
848
962
 
849
963
  data->marker_offset = parser->indent;
850
964
 
851
- if (container->type != CMARK_NODE_LIST ||
852
- !lists_match(&container->as.list, data)) {
853
- container = add_child(parser, container, CMARK_NODE_LIST,
965
+ if (cont_type != CMARK_NODE_LIST ||
966
+ !lists_match(&((*container)->as.list), data)) {
967
+ *container = add_child(parser, *container, CMARK_NODE_LIST,
854
968
  parser->first_nonspace + 1);
855
969
 
856
- memcpy(&container->as.list, data, sizeof(*data));
970
+ memcpy(&((*container)->as.list), data, sizeof(*data));
857
971
  }
858
972
 
859
973
  // add the list item
860
- container = add_child(parser, container, CMARK_NODE_ITEM,
974
+ *container = add_child(parser, *container, CMARK_NODE_ITEM,
861
975
  parser->first_nonspace + 1);
862
976
  /* TODO: static */
863
- memcpy(&container->as.list, data, sizeof(*data));
977
+ memcpy(&((*container)->as.list), data, sizeof(*data));
864
978
  free(data);
865
-
866
979
  } else if (indented && !maybe_lazy && !parser->blank) {
867
- S_advance_offset(parser, &input, CODE_INDENT, true);
868
- container = add_child(parser, container, CMARK_NODE_CODE_BLOCK,
980
+ S_advance_offset(parser, input, CODE_INDENT, true);
981
+ *container = add_child(parser, *container, CMARK_NODE_CODE_BLOCK,
869
982
  parser->offset + 1);
870
- container->as.code.fenced = false;
871
- container->as.code.fence_char = 0;
872
- container->as.code.fence_length = 0;
873
- container->as.code.fence_offset = 0;
874
- container->as.code.info = cmark_chunk_literal("");
983
+ (*container)->as.code.fenced = false;
984
+ (*container)->as.code.fence_char = 0;
985
+ (*container)->as.code.fence_length = 0;
986
+ (*container)->as.code.fence_offset = 0;
987
+ (*container)->as.code.info = cmark_chunk_literal("");
875
988
 
876
989
  } else {
877
990
  break;
878
991
  }
879
992
 
880
- if (accepts_lines(container->type)) {
993
+ if (accepts_lines((*container)->type)) {
881
994
  // if it's a line container, it can't contain other containers
882
995
  break;
883
996
  }
997
+
998
+ cont_type = (*container)->type;
884
999
  maybe_lazy = false;
885
1000
  }
1001
+ }
886
1002
 
1003
+ static void add_text_to_container (cmark_parser *parser,
1004
+ cmark_node *container,
1005
+ cmark_node *last_matched_container,
1006
+ cmark_chunk *input)
1007
+ {
1008
+ cmark_node *tmp;
887
1009
  // what remains at parser->offset is a text line. add the text to the
888
1010
  // appropriate container.
889
1011
 
890
- S_find_first_nonspace(parser, &input);
1012
+ S_find_first_nonspace(parser, input);
891
1013
 
892
- if (parser->blank && container->last_child) {
1014
+ if (parser->blank && container->last_child)
893
1015
  container->last_child->last_line_blank = true;
894
- }
895
1016
 
896
1017
  // block quote lines are never blank as they start with >
897
1018
  // and we don't count blanks in fenced code for purposes of tight/loose
@@ -906,61 +1027,61 @@ static void S_process_line(cmark_parser *parser, const unsigned char *buffer,
906
1027
  !(container->type == CMARK_NODE_ITEM && container->first_child == NULL &&
907
1028
  container->start_line == parser->line_number));
908
1029
 
909
- cmark_node *cont = container;
910
- while (cont->parent) {
911
- cont->parent->last_line_blank = false;
912
- cont = cont->parent;
1030
+ tmp = container;
1031
+ while (tmp->parent) {
1032
+ tmp->parent->last_line_blank = false;
1033
+ tmp = tmp->parent;
913
1034
  }
914
1035
 
1036
+ // If the last line processed belonged to a paragraph node,
1037
+ // and we didn't match all of the line prefixes for the open containers,
1038
+ // and we didn't start any new containers,
1039
+ // and the line isn't blank,
1040
+ // then treat this as a "lazy continuation line" and add it to
1041
+ // the open paragraph.
915
1042
  if (parser->current != last_matched_container &&
916
- container == last_matched_container && !parser->blank &&
917
- parser->current->type == CMARK_NODE_PARAGRAPH &&
918
- cmark_strbuf_len(&parser->current->string_content) > 0) {
919
-
920
- add_line(parser->current, &input, parser->offset);
921
-
1043
+ container == last_matched_container &&
1044
+ !parser->blank &&
1045
+ parser->current->type == CMARK_NODE_PARAGRAPH) {
1046
+ add_line(parser->current, input, parser);
922
1047
  } else { // not a lazy continuation
923
-
924
- // finalize any blocks that were not matched and set cur to container:
1048
+ // Finalize any blocks that were not matched and set cur to container:
925
1049
  while (parser->current != last_matched_container) {
926
1050
  parser->current = finalize(parser, parser->current);
927
1051
  assert(parser->current != NULL);
928
1052
  }
929
1053
 
930
1054
  if (container->type == CMARK_NODE_CODE_BLOCK) {
931
-
932
- add_line(container, &input, parser->offset);
933
-
1055
+ add_line(container, input, parser);
934
1056
  } else if (container->type == CMARK_NODE_HTML_BLOCK) {
935
-
936
- add_line(container, &input, parser->offset);
1057
+ add_line(container, input, parser);
937
1058
 
938
1059
  int matches_end_condition;
939
1060
  switch (container->as.html_block_type) {
940
1061
  case 1:
941
1062
  // </script>, </style>, </pre>
942
1063
  matches_end_condition =
943
- scan_html_block_end_1(&input, parser->first_nonspace);
1064
+ scan_html_block_end_1(input, parser->first_nonspace);
944
1065
  break;
945
1066
  case 2:
946
1067
  // -->
947
1068
  matches_end_condition =
948
- scan_html_block_end_2(&input, parser->first_nonspace);
1069
+ scan_html_block_end_2(input, parser->first_nonspace);
949
1070
  break;
950
1071
  case 3:
951
1072
  // ?>
952
1073
  matches_end_condition =
953
- scan_html_block_end_3(&input, parser->first_nonspace);
1074
+ scan_html_block_end_3(input, parser->first_nonspace);
954
1075
  break;
955
1076
  case 4:
956
1077
  // >
957
1078
  matches_end_condition =
958
- scan_html_block_end_4(&input, parser->first_nonspace);
1079
+ scan_html_block_end_4(input, parser->first_nonspace);
959
1080
  break;
960
1081
  case 5:
961
1082
  // ]]>
962
1083
  matches_end_condition =
963
- scan_html_block_end_5(&input, parser->first_nonspace);
1084
+ scan_html_block_end_5(input, parser->first_nonspace);
964
1085
  break;
965
1086
  default:
966
1087
  matches_end_condition = 0;
@@ -971,28 +1092,69 @@ static void S_process_line(cmark_parser *parser, const unsigned char *buffer,
971
1092
  container = finalize(parser, container);
972
1093
  assert(parser->current != NULL);
973
1094
  }
974
-
975
1095
  } else if (parser->blank) {
976
-
977
1096
  // ??? do nothing
978
-
979
1097
  } else if (accepts_lines(container->type)) {
980
-
981
1098
  if (container->type == CMARK_NODE_HEADING &&
982
1099
  container->as.heading.setext == false) {
983
- chop_trailing_hashtags(&input);
1100
+ chop_trailing_hashtags(input);
984
1101
  }
985
- add_line(container, &input, parser->first_nonspace);
986
-
1102
+ S_advance_offset(parser, input, parser->first_nonspace - parser->offset, false);
1103
+ add_line(container, input, parser);
987
1104
  } else {
988
1105
  // create paragraph container for line
989
1106
  container = add_child(parser, container, CMARK_NODE_PARAGRAPH,
990
1107
  parser->first_nonspace + 1);
991
- add_line(container, &input, parser->first_nonspace);
1108
+ S_advance_offset(parser, input, parser->first_nonspace - parser->offset, false);
1109
+ add_line(container, input, parser);
992
1110
  }
993
1111
 
994
1112
  parser->current = container;
995
1113
  }
1114
+ }
1115
+
1116
+ /* See http://spec.commonmark.org/0.24/#phase-1-block-structure */
1117
+ static void S_process_line(cmark_parser *parser, const unsigned char *buffer,
1118
+ bufsize_t bytes) {
1119
+ cmark_node *last_matched_container;
1120
+ bool all_matched = true;
1121
+ cmark_node *container;
1122
+ cmark_chunk input;
1123
+
1124
+ if (parser->options & CMARK_OPT_VALIDATE_UTF8)
1125
+ cmark_utf8proc_check(parser->curline, buffer, bytes);
1126
+ else
1127
+ cmark_strbuf_put(parser->curline, buffer, bytes);
1128
+
1129
+ // ensure line ends with a newline:
1130
+ if (bytes == 0 || !S_is_line_end_char(parser->curline->ptr[bytes - 1]))
1131
+ cmark_strbuf_putc(parser->curline, '\n');
1132
+
1133
+ parser->offset = 0;
1134
+ parser->column = 0;
1135
+ parser->blank = false;
1136
+ parser->partially_consumed_tab = false;
1137
+
1138
+ input.data = parser->curline->ptr;
1139
+ input.len = parser->curline->size;
1140
+
1141
+ parser->line_number++;
1142
+
1143
+ last_matched_container = check_open_blocks(parser, &input, &all_matched);
1144
+
1145
+ if (!last_matched_container)
1146
+ goto finished;
1147
+
1148
+ container = last_matched_container;
1149
+
1150
+ // check to see if we've hit 2nd blank line, break out of list:
1151
+ if (parser->blank && container->last_line_blank)
1152
+ break_out_of_lists(parser, &container);
1153
+
1154
+ open_new_blocks(parser, &container, &input, all_matched);
1155
+
1156
+ add_text_to_container(parser, container, last_matched_container, &input);
1157
+
996
1158
  finished:
997
1159
  parser->last_line_length = input.len;
998
1160
  if (parser->last_line_length &&