commonmarker 0.9.1 → 0.9.2
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 +4 -4
- data/README.md +1 -0
- data/Rakefile +9 -9
- data/ext/commonmarker/cmark/api_test/main.c +5 -0
- data/ext/commonmarker/cmark/build/CMakeCache.txt +459 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/3.5.2/CMakeCCompiler.cmake +67 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/3.5.2/CMakeCXXCompiler.cmake +68 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/3.5.2/CMakeDetermineCompilerABI_C.bin +0 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/3.5.2/CMakeDetermineCompilerABI_CXX.bin +0 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/3.5.2/CMakeSystem.cmake +15 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/3.5.2/CompilerIdC/CMakeCCompilerId.c +544 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/3.5.2/CompilerIdC/a.out +0 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/3.5.2/CompilerIdCXX/CMakeCXXCompilerId.cpp +533 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/3.5.2/CompilerIdCXX/a.out +0 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/CMakeDirectoryInformation.cmake +16 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/CMakeError.log +14 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/CMakeOutput.log +562 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/Makefile.cmake +150 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/Makefile2 +295 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/TargetDirectories.txt +39 -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 +250 -0
- data/ext/commonmarker/cmark/build/api_test/CMakeFiles/CMakeDirectoryInformation.cmake +16 -0
- data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/DependInfo.cmake +35 -0
- data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/build.make +168 -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/depend.make +2 -0
- data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/flags.make +17 -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/progress.make +5 -0
- data/ext/commonmarker/cmark/build/api_test/CMakeFiles/progress.marks +1 -0
- data/ext/commonmarker/cmark/build/api_test/Makefile +300 -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 +194 -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/DependInfo.cmake +41 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/build.make +626 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/cmake_clean.cmake +29 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/depend.make +2 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/flags.make +10 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/link.txt +1 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/progress.make +22 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/DependInfo.cmake +46 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/build.make +603 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/cmake_clean.cmake +29 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/depend.make +2 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/flags.make +10 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/link.txt +1 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/progress.make +21 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/C.includecache +468 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/DependInfo.cmake +40 -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 +600 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/cmake_clean.cmake +28 -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 +211 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/depend.make +211 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/flags.make +10 -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/latex.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 +21 -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/render.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 +956 -0
- data/ext/commonmarker/cmark/build/src/cmake_install.cmake +77 -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 +84 -0
- data/ext/commonmarker/cmark/build/src/libcmark.a +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 +14 -0
- data/ext/commonmarker/cmark/build/testdir/Makefile +194 -0
- data/ext/commonmarker/cmark/build/testdir/cmake_install.cmake +29 -0
- data/ext/commonmarker/cmark/man/man1/cmark.1 +11 -4
- data/ext/commonmarker/cmark/man/man3/cmark.3 +66 -11
- data/ext/commonmarker/cmark/src/blocks.c +232 -235
- data/ext/commonmarker/cmark/src/buffer.c +19 -56
- data/ext/commonmarker/cmark/src/buffer.h +7 -20
- data/ext/commonmarker/cmark/src/chunk.h +19 -19
- data/ext/commonmarker/cmark/src/cmark.c +14 -0
- data/ext/commonmarker/cmark/src/cmark.h +45 -6
- data/ext/commonmarker/cmark/src/cmark_ctype.c +2 -0
- data/ext/commonmarker/cmark/src/cmark_ctype.h +2 -0
- data/ext/commonmarker/cmark/src/commonmark.c +42 -29
- data/ext/commonmarker/cmark/src/config.h.in +8 -0
- data/ext/commonmarker/cmark/src/html.c +3 -1
- data/ext/commonmarker/cmark/src/inlines.c +111 -150
- data/ext/commonmarker/cmark/src/inlines.h +4 -4
- data/ext/commonmarker/cmark/src/iterator.c +6 -7
- data/ext/commonmarker/cmark/src/iterator.h +2 -0
- data/ext/commonmarker/cmark/src/latex.c +10 -8
- data/ext/commonmarker/cmark/src/main.c +6 -2
- data/ext/commonmarker/cmark/src/man.c +9 -5
- data/ext/commonmarker/cmark/src/node.c +38 -29
- data/ext/commonmarker/cmark/src/node.h +15 -11
- data/ext/commonmarker/cmark/src/parser.h +4 -2
- data/ext/commonmarker/cmark/src/references.c +23 -22
- data/ext/commonmarker/cmark/src/references.h +3 -1
- data/ext/commonmarker/cmark/src/render.c +9 -7
- data/ext/commonmarker/cmark/src/render.h +3 -1
- data/ext/commonmarker/cmark/src/scanners.c +30 -22
- data/ext/commonmarker/cmark/src/xml.c +1 -1
- data/ext/commonmarker/cmark/test/CMakeLists.txt +8 -8
- data/ext/commonmarker/cmark/test/cmark.py +34 -14
- data/ext/commonmarker/cmark/test/roundtrip_tests.py +47 -0
- data/ext/commonmarker/cmark/test/spec.txt +96 -6
- data/ext/commonmarker/cmark/test/spec_tests.py +5 -8
- data/ext/commonmarker/commonmarker.c +14 -8
- data/lib/commonmarker/config.rb +2 -2
- data/lib/commonmarker/renderer.rb +17 -7
- data/lib/commonmarker/renderer/html_renderer.rb +16 -21
- data/lib/commonmarker/version.rb +1 -1
- data/test/test_pathological_inputs.rb +11 -11
- metadata +99 -4
- data/ext/commonmarker/cmark/test/roundtrip.bat +0 -1
- data/ext/commonmarker/cmark/test/roundtrip.sh +0 -2
@@ -0,0 +1,29 @@
|
|
1
|
+
# Install script for directory: /Users/gjtorikian/Development/commonmarker/ext/commonmarker/cmark/test
|
2
|
+
|
3
|
+
# Set the install prefix
|
4
|
+
if(NOT DEFINED CMAKE_INSTALL_PREFIX)
|
5
|
+
set(CMAKE_INSTALL_PREFIX "/usr/local")
|
6
|
+
endif()
|
7
|
+
string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
|
8
|
+
|
9
|
+
# Set the install configuration name.
|
10
|
+
if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
|
11
|
+
if(BUILD_TYPE)
|
12
|
+
string(REGEX REPLACE "^[^A-Za-z0-9_]+" ""
|
13
|
+
CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
|
14
|
+
else()
|
15
|
+
set(CMAKE_INSTALL_CONFIG_NAME "Release")
|
16
|
+
endif()
|
17
|
+
message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
|
18
|
+
endif()
|
19
|
+
|
20
|
+
# Set the component getting installed.
|
21
|
+
if(NOT CMAKE_INSTALL_COMPONENT)
|
22
|
+
if(COMPONENT)
|
23
|
+
message(STATUS "Install component: \"${COMPONENT}\"")
|
24
|
+
set(CMAKE_INSTALL_COMPONENT "${COMPONENT}")
|
25
|
+
else()
|
26
|
+
set(CMAKE_INSTALL_COMPONENT)
|
27
|
+
endif()
|
28
|
+
endif()
|
29
|
+
|
@@ -25,13 +25,20 @@ 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
26
|
commonmark, latex, and man renderers.
|
27
27
|
.TP 12n
|
28
|
+
.B \-\-hardbreaks
|
29
|
+
Render soft breaks (newlines inside paragraphs in the CommonMark source)
|
30
|
+
as hard line breaks in the target format. If this option is specified,
|
31
|
+
hard wrapping is disabled for CommonMark output, regardless of the value
|
32
|
+
given with \-\-width.
|
33
|
+
.TP 12n
|
34
|
+
.B \-\-nobreaks
|
35
|
+
Render soft breaks as spaces. If this option is specified,
|
36
|
+
hard wrapping is disabled for all output formats, regardless of the value
|
37
|
+
given with \-\-width.
|
38
|
+
.TP 12n
|
28
39
|
.B \-\-sourcepos
|
29
40
|
Include source position attribute.
|
30
41
|
.TP 12n
|
31
|
-
.B \-\-hardbreaks
|
32
|
-
Treat newlines as hard line breaks. If this option is specified,
|
33
|
-
hard wrapping is disabled, regardless of the value given with \-\-width.
|
34
|
-
.TP 12n
|
35
42
|
.B \-\-normalize
|
36
43
|
Consolidate adjacent text nodes.
|
37
44
|
.TP 12n
|
@@ -1,4 +1,4 @@
|
|
1
|
-
.TH cmark 3 "
|
1
|
+
.TH cmark 3 "June 06, 2016" "LOCAL" "Library Functions Manual"
|
2
2
|
.SH
|
3
3
|
NAME
|
4
4
|
.PP
|
@@ -15,7 +15,8 @@ Simple Interface
|
|
15
15
|
.PP
|
16
16
|
Convert \f[I]text\f[] (assumed to be a UTF\-8 encoded string with length
|
17
17
|
\f[I]len\f[]) from CommonMark Markdown to HTML, returning a
|
18
|
-
null\-terminated, UTF\-8\-encoded string.
|
18
|
+
null\-terminated, UTF\-8\-encoded string. It is the caller\[cq]s
|
19
|
+
responsibility to free the returned buffer.
|
19
20
|
|
20
21
|
.SS
|
21
22
|
Node Structure
|
@@ -94,6 +95,26 @@ typedef enum {
|
|
94
95
|
|
95
96
|
|
96
97
|
|
98
|
+
.SS
|
99
|
+
Custom memory allocator support
|
100
|
+
|
101
|
+
.PP
|
102
|
+
.nf
|
103
|
+
\fC
|
104
|
+
.RS 0n
|
105
|
+
typedef struct cmark_mem {
|
106
|
+
void *(*calloc)(size_t, size_t);
|
107
|
+
void *(*realloc)(void *, size_t);
|
108
|
+
void (*free)(void *);
|
109
|
+
} cmark_mem;
|
110
|
+
.RE
|
111
|
+
\f[]
|
112
|
+
.fi
|
113
|
+
|
114
|
+
.PP
|
115
|
+
Defines the memory allocation functions to be used by CMark when parsing
|
116
|
+
and allocating a document tree
|
117
|
+
|
97
118
|
.SS
|
98
119
|
Creating and Destroying Nodes
|
99
120
|
|
@@ -105,6 +126,13 @@ Creates a new node of type \f[I]type\f[]. Note that the node may have
|
|
105
126
|
other required properties, which it is the caller\[cq]s responsibility
|
106
127
|
to assign.
|
107
128
|
|
129
|
+
.PP
|
130
|
+
\fIcmark_node *\f[] \fBcmark_node_new_with_mem\f[](\fIcmark_node_type type\f[], \fIcmark_mem *mem\f[])
|
131
|
+
|
132
|
+
.PP
|
133
|
+
Same as \f[C]cmark_node_new\f[], but explicitly listing the memory
|
134
|
+
allocator used to allocate the node
|
135
|
+
|
108
136
|
.PP
|
109
137
|
\fIvoid\f[] \fBcmark_node_free\f[](\fIcmark_node *node\f[])
|
110
138
|
|
@@ -224,8 +252,9 @@ typedef enum {
|
|
224
252
|
|
225
253
|
.PP
|
226
254
|
Creates a new iterator starting at \f[I]root\f[]. The current node and
|
227
|
-
event type are undefined until \f[
|
228
|
-
the first time.
|
255
|
+
event type are undefined until \f[I]cmark_iter_next\f[] is called for
|
256
|
+
the first time. The memory allocated for the iterator should be released
|
257
|
+
using \f[I]cmark_iter_free\f[] when it is no longer needed.
|
229
258
|
|
230
259
|
.PP
|
231
260
|
\fIvoid\f[] \fBcmark_iter_free\f[](\fIcmark_iter *iter\f[])
|
@@ -561,6 +590,12 @@ cmark_parser_free(parser);
|
|
561
590
|
.PP
|
562
591
|
Creates a new parser object.
|
563
592
|
|
593
|
+
.PP
|
594
|
+
\fIcmark_parser *\f[] \fBcmark_parser_new_with_mem\f[](\fIint options\f[], \fIcmark_mem *mem\f[])
|
595
|
+
|
596
|
+
.PP
|
597
|
+
Creates a new parser object with the given memory allocator
|
598
|
+
|
564
599
|
.PP
|
565
600
|
\fIvoid\f[] \fBcmark_parser_free\f[](\fIcmark_parser *parser\f[])
|
566
601
|
|
@@ -584,14 +619,17 @@ Finish parsing and return a pointer to a tree of nodes.
|
|
584
619
|
|
585
620
|
.PP
|
586
621
|
Parse a CommonMark document in \f[I]buffer\f[] of length \f[I]len\f[].
|
587
|
-
Returns a pointer to a tree of nodes.
|
622
|
+
Returns a pointer to a tree of nodes. The memory allocated for the node
|
623
|
+
tree should be released using \f[I]cmark_node_free\f[] when it is no
|
624
|
+
longer needed.
|
588
625
|
|
589
626
|
.PP
|
590
627
|
\fIcmark_node *\f[] \fBcmark_parse_file\f[](\fIFILE *f\f[], \fIint options\f[])
|
591
628
|
|
592
629
|
.PP
|
593
630
|
Parse a CommonMark document in file \f[I]f\f[], returning a pointer to a
|
594
|
-
tree of nodes.
|
631
|
+
tree of nodes. The memory allocated for the node tree should be released
|
632
|
+
using \f[I]cmark_node_free\f[] when it is no longer needed.
|
595
633
|
|
596
634
|
.SS
|
597
635
|
Rendering
|
@@ -600,32 +638,37 @@ Rendering
|
|
600
638
|
\fIchar *\f[] \fBcmark_render_xml\f[](\fIcmark_node *root\f[], \fIint options\f[])
|
601
639
|
|
602
640
|
.PP
|
603
|
-
Render a \f[I]node\f[] tree as XML.
|
641
|
+
Render a \f[I]node\f[] tree as XML. It is the caller\[cq]s
|
642
|
+
responsibility to free the returned buffer.
|
604
643
|
|
605
644
|
.PP
|
606
645
|
\fIchar *\f[] \fBcmark_render_html\f[](\fIcmark_node *root\f[], \fIint options\f[])
|
607
646
|
|
608
647
|
.PP
|
609
648
|
Render a \f[I]node\f[] tree as an HTML fragment. It is up to the user to
|
610
|
-
add an appropriate header and footer.
|
649
|
+
add an appropriate header and footer. It is the caller\[cq]s
|
650
|
+
responsibility to free the returned buffer.
|
611
651
|
|
612
652
|
.PP
|
613
653
|
\fIchar *\f[] \fBcmark_render_man\f[](\fIcmark_node *root\f[], \fIint options\f[], \fIint width\f[])
|
614
654
|
|
615
655
|
.PP
|
616
|
-
Render a \f[I]node\f[] tree as a groff man page, without the header.
|
656
|
+
Render a \f[I]node\f[] tree as a groff man page, without the header. It
|
657
|
+
is the caller\[cq]s responsibility to free the returned buffer.
|
617
658
|
|
618
659
|
.PP
|
619
660
|
\fIchar *\f[] \fBcmark_render_commonmark\f[](\fIcmark_node *root\f[], \fIint options\f[], \fIint width\f[])
|
620
661
|
|
621
662
|
.PP
|
622
|
-
Render a \f[I]node\f[] tree as a commonmark document.
|
663
|
+
Render a \f[I]node\f[] tree as a commonmark document. It is the
|
664
|
+
caller\[cq]s responsibility to free the returned buffer.
|
623
665
|
|
624
666
|
.PP
|
625
667
|
\fIchar *\f[] \fBcmark_render_latex\f[](\fIcmark_node *root\f[], \fIint options\f[], \fIint width\f[])
|
626
668
|
|
627
669
|
.PP
|
628
|
-
Render a \f[I]node\f[] tree as a LaTeX document.
|
670
|
+
Render a \f[I]node\f[] tree as a LaTeX document. It is the caller\[cq]s
|
671
|
+
responsibility to free the returned buffer.
|
629
672
|
|
630
673
|
.SS
|
631
674
|
Options
|
@@ -685,6 +728,18 @@ Suppress raw HTML and unsafe links (\f[C]javascript:\f[],
|
|
685
728
|
\f[C]image/webp\f[] mime types). Raw HTML is replaced by a placeholder
|
686
729
|
HTML comment. Unsafe links are replaced by empty strings.
|
687
730
|
|
731
|
+
.PP
|
732
|
+
.nf
|
733
|
+
\fC
|
734
|
+
.RS 0n
|
735
|
+
#define CMARK_OPT_NOBREAKS (1 << 4)
|
736
|
+
.RE
|
737
|
+
\f[]
|
738
|
+
.fi
|
739
|
+
|
740
|
+
.PP
|
741
|
+
Render \f[C]softbreak\f[] elements as spaces.
|
742
|
+
|
688
743
|
.SS
|
689
744
|
Options affecting parsing
|
690
745
|
|
@@ -30,6 +30,21 @@
|
|
30
30
|
|
31
31
|
#define peek_at(i, n) (i)->data[n]
|
32
32
|
|
33
|
+
static bool S_last_line_blank(const cmark_node *node) {
|
34
|
+
return (node->flags & CMARK_NODE__LAST_LINE_BLANK) != 0;
|
35
|
+
}
|
36
|
+
|
37
|
+
static CMARK_INLINE cmark_node_type S_type(const cmark_node *node) {
|
38
|
+
return (cmark_node_type)node->type;
|
39
|
+
}
|
40
|
+
|
41
|
+
static void S_set_last_line_blank(cmark_node *node, bool is_blank) {
|
42
|
+
if (is_blank)
|
43
|
+
node->flags |= CMARK_NODE__LAST_LINE_BLANK;
|
44
|
+
else
|
45
|
+
node->flags &= ~CMARK_NODE__LAST_LINE_BLANK;
|
46
|
+
}
|
47
|
+
|
33
48
|
static CMARK_INLINE bool S_is_line_end_char(char c) {
|
34
49
|
return (c == '\n' || c == '\r');
|
35
50
|
}
|
@@ -44,38 +59,37 @@ static void S_parser_feed(cmark_parser *parser, const unsigned char *buffer,
|
|
44
59
|
static void S_process_line(cmark_parser *parser, const unsigned char *buffer,
|
45
60
|
bufsize_t bytes);
|
46
61
|
|
47
|
-
static cmark_node *make_block(cmark_node_type tag, int start_line,
|
62
|
+
static cmark_node *make_block(cmark_mem *mem, cmark_node_type tag, int start_line,
|
48
63
|
int start_column) {
|
49
64
|
cmark_node *e;
|
50
65
|
|
51
|
-
e = (cmark_node *)calloc(1, sizeof(*e));
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
cmark_strbuf_init(&e->string_content, 32);
|
59
|
-
}
|
66
|
+
e = (cmark_node *)mem->calloc(1, sizeof(*e));
|
67
|
+
cmark_strbuf_init(mem, &e->content, 32);
|
68
|
+
e->type = (uint16_t)tag;
|
69
|
+
e->flags = CMARK_NODE__OPEN;
|
70
|
+
e->start_line = start_line;
|
71
|
+
e->start_column = start_column;
|
72
|
+
e->end_line = start_line;
|
60
73
|
|
61
74
|
return e;
|
62
75
|
}
|
63
76
|
|
64
77
|
// Create a root document node.
|
65
|
-
static cmark_node *make_document() {
|
66
|
-
cmark_node *e = make_block(CMARK_NODE_DOCUMENT, 1, 1);
|
78
|
+
static cmark_node *make_document(cmark_mem *mem) {
|
79
|
+
cmark_node *e = make_block(mem, CMARK_NODE_DOCUMENT, 1, 1);
|
67
80
|
return e;
|
68
81
|
}
|
69
82
|
|
70
|
-
cmark_parser *
|
71
|
-
cmark_parser *parser = (cmark_parser *)
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
cmark_strbuf_init(
|
77
|
-
|
78
|
-
|
83
|
+
cmark_parser *cmark_parser_new_with_mem(int options, cmark_mem *mem) {
|
84
|
+
cmark_parser *parser = (cmark_parser *)mem->calloc(1, sizeof(cmark_parser));
|
85
|
+
parser->mem = mem;
|
86
|
+
|
87
|
+
cmark_node *document = make_document(mem);
|
88
|
+
|
89
|
+
cmark_strbuf_init(mem, &parser->curline, 256);
|
90
|
+
cmark_strbuf_init(mem, &parser->linebuf, 0);
|
91
|
+
|
92
|
+
parser->refmap = cmark_reference_map_new(mem);
|
79
93
|
parser->root = document;
|
80
94
|
parser->current = document;
|
81
95
|
parser->line_number = 0;
|
@@ -86,22 +100,24 @@ cmark_parser *cmark_parser_new(int options) {
|
|
86
100
|
parser->indent = 0;
|
87
101
|
parser->blank = false;
|
88
102
|
parser->partially_consumed_tab = false;
|
89
|
-
parser->curline = line;
|
90
103
|
parser->last_line_length = 0;
|
91
|
-
parser->linebuf = buf;
|
92
104
|
parser->options = options;
|
93
105
|
parser->last_buffer_ended_with_cr = false;
|
94
106
|
|
95
107
|
return parser;
|
96
108
|
}
|
97
109
|
|
110
|
+
cmark_parser *cmark_parser_new(int options) {
|
111
|
+
extern cmark_mem DEFAULT_MEM_ALLOCATOR;
|
112
|
+
return cmark_parser_new_with_mem(options, &DEFAULT_MEM_ALLOCATOR);
|
113
|
+
}
|
114
|
+
|
98
115
|
void cmark_parser_free(cmark_parser *parser) {
|
99
|
-
|
100
|
-
|
101
|
-
cmark_strbuf_free(parser->linebuf);
|
102
|
-
free(parser->linebuf);
|
116
|
+
cmark_mem *mem = parser->mem;
|
117
|
+
cmark_strbuf_free(&parser->curline);
|
118
|
+
cmark_strbuf_free(&parser->linebuf);
|
103
119
|
cmark_reference_map_free(parser->refmap);
|
104
|
-
free(parser);
|
120
|
+
mem->free(parser);
|
105
121
|
}
|
106
122
|
|
107
123
|
static cmark_node *finalize(cmark_parser *parser, cmark_node *b);
|
@@ -128,7 +144,7 @@ static bool is_blank(cmark_strbuf *s, bufsize_t offset) {
|
|
128
144
|
}
|
129
145
|
|
130
146
|
static CMARK_INLINE bool can_contain(cmark_node_type parent_type,
|
131
|
-
|
147
|
+
cmark_node_type child_type) {
|
132
148
|
return (parent_type == CMARK_NODE_DOCUMENT ||
|
133
149
|
parent_type == CMARK_NODE_BLOCK_QUOTE ||
|
134
150
|
parent_type == CMARK_NODE_ITEM ||
|
@@ -149,18 +165,17 @@ static CMARK_INLINE bool contains_inlines(cmark_node_type block_type) {
|
|
149
165
|
static void add_line(cmark_node *node, cmark_chunk *ch, cmark_parser *parser) {
|
150
166
|
int chars_to_tab;
|
151
167
|
int i;
|
152
|
-
assert(node->
|
168
|
+
assert(node->flags & CMARK_NODE__OPEN);
|
153
169
|
if (parser->partially_consumed_tab) {
|
154
170
|
parser->offset += 1; // skip over tab
|
155
171
|
// add space characters:
|
156
172
|
chars_to_tab = TAB_STOP - (parser->column % TAB_STOP);
|
157
173
|
for (i = 0; i < chars_to_tab; i++) {
|
158
|
-
cmark_strbuf_putc(&node->
|
174
|
+
cmark_strbuf_putc(&node->content, ' ');
|
159
175
|
}
|
160
176
|
}
|
161
|
-
cmark_strbuf_put(&node->
|
162
|
-
|
163
|
-
ch->len - parser->offset);
|
177
|
+
cmark_strbuf_put(&node->content, ch->data + parser->offset,
|
178
|
+
ch->len - parser->offset);
|
164
179
|
}
|
165
180
|
|
166
181
|
static void remove_trailing_blank_lines(cmark_strbuf *ln) {
|
@@ -195,10 +210,10 @@ static void remove_trailing_blank_lines(cmark_strbuf *ln) {
|
|
195
210
|
static bool ends_with_blank_line(cmark_node *node) {
|
196
211
|
cmark_node *cur = node;
|
197
212
|
while (cur != NULL) {
|
198
|
-
if (cur
|
213
|
+
if (S_last_line_blank(cur)) {
|
199
214
|
return true;
|
200
215
|
}
|
201
|
-
if (cur
|
216
|
+
if (S_type(cur) == CMARK_NODE_LIST || S_type(cur) == CMARK_NODE_ITEM) {
|
202
217
|
cur = cur->last_child;
|
203
218
|
} else {
|
204
219
|
cur = NULL;
|
@@ -212,7 +227,7 @@ static int break_out_of_lists(cmark_parser *parser, cmark_node **bptr) {
|
|
212
227
|
cmark_node *container = *bptr;
|
213
228
|
cmark_node *b = parser->root;
|
214
229
|
// find first containing NODE_LIST:
|
215
|
-
while (b && b
|
230
|
+
while (b && S_type(b) != CMARK_NODE_LIST) {
|
216
231
|
b = b->last_child;
|
217
232
|
}
|
218
233
|
if (b) {
|
@@ -232,37 +247,38 @@ static cmark_node *finalize(cmark_parser *parser, cmark_node *b) {
|
|
232
247
|
cmark_node *parent;
|
233
248
|
|
234
249
|
parent = b->parent;
|
250
|
+
assert(b->flags & CMARK_NODE__OPEN); // shouldn't call finalize on closed blocks
|
251
|
+
b->flags &= ~CMARK_NODE__OPEN;
|
235
252
|
|
236
|
-
|
237
|
-
b->open = false;
|
238
|
-
|
239
|
-
if (parser->curline->size == 0) {
|
253
|
+
if (parser->curline.size == 0) {
|
240
254
|
// end of input - line number has not been incremented
|
241
255
|
b->end_line = parser->line_number;
|
242
256
|
b->end_column = parser->last_line_length;
|
243
|
-
} else if (b
|
244
|
-
(b
|
245
|
-
(b
|
257
|
+
} else if (S_type(b) == CMARK_NODE_DOCUMENT ||
|
258
|
+
(S_type(b) == CMARK_NODE_CODE_BLOCK && b->as.code.fenced) ||
|
259
|
+
(S_type(b) == CMARK_NODE_HEADING && b->as.heading.setext)) {
|
246
260
|
b->end_line = parser->line_number;
|
247
|
-
b->end_column = parser->curline
|
248
|
-
if (b->end_column && parser->curline
|
261
|
+
b->end_column = parser->curline.size;
|
262
|
+
if (b->end_column && parser->curline.ptr[b->end_column - 1] == '\n')
|
249
263
|
b->end_column -= 1;
|
250
|
-
if (b->end_column && parser->curline
|
264
|
+
if (b->end_column && parser->curline.ptr[b->end_column - 1] == '\r')
|
251
265
|
b->end_column -= 1;
|
252
266
|
} else {
|
253
267
|
b->end_line = parser->line_number - 1;
|
254
268
|
b->end_column = parser->last_line_length;
|
255
269
|
}
|
256
270
|
|
257
|
-
|
271
|
+
cmark_strbuf *node_content = &b->content;
|
272
|
+
|
273
|
+
switch (S_type(b)) {
|
258
274
|
case CMARK_NODE_PARAGRAPH:
|
259
|
-
while (cmark_strbuf_at(
|
260
|
-
(pos = cmark_parse_reference_inline(
|
275
|
+
while (cmark_strbuf_at(node_content, 0) == '[' &&
|
276
|
+
(pos = cmark_parse_reference_inline(parser->mem, node_content,
|
261
277
|
parser->refmap))) {
|
262
278
|
|
263
|
-
cmark_strbuf_drop(
|
279
|
+
cmark_strbuf_drop(node_content, pos);
|
264
280
|
}
|
265
|
-
if (is_blank(
|
281
|
+
if (is_blank(node_content, 0)) {
|
266
282
|
// remove blank node (former reference def)
|
267
283
|
cmark_node_free(b);
|
268
284
|
}
|
@@ -270,34 +286,33 @@ static cmark_node *finalize(cmark_parser *parser, cmark_node *b) {
|
|
270
286
|
|
271
287
|
case CMARK_NODE_CODE_BLOCK:
|
272
288
|
if (!b->as.code.fenced) { // indented code
|
273
|
-
remove_trailing_blank_lines(
|
274
|
-
cmark_strbuf_putc(
|
289
|
+
remove_trailing_blank_lines(node_content);
|
290
|
+
cmark_strbuf_putc(node_content, '\n');
|
275
291
|
} else {
|
276
|
-
|
277
292
|
// first line of contents becomes info
|
278
|
-
for (pos = 0; pos <
|
279
|
-
if (S_is_line_end_char(
|
293
|
+
for (pos = 0; pos < node_content->size; ++pos) {
|
294
|
+
if (S_is_line_end_char(node_content->ptr[pos]))
|
280
295
|
break;
|
281
296
|
}
|
282
|
-
assert(pos <
|
297
|
+
assert(pos < node_content->size);
|
283
298
|
|
284
|
-
cmark_strbuf tmp =
|
285
|
-
houdini_unescape_html_f(&tmp,
|
299
|
+
cmark_strbuf tmp = CMARK_BUF_INIT(parser->mem);
|
300
|
+
houdini_unescape_html_f(&tmp, node_content->ptr, pos);
|
286
301
|
cmark_strbuf_trim(&tmp);
|
287
302
|
cmark_strbuf_unescape(&tmp);
|
288
303
|
b->as.code.info = cmark_chunk_buf_detach(&tmp);
|
289
304
|
|
290
|
-
if (
|
305
|
+
if (node_content->ptr[pos] == '\r')
|
291
306
|
pos += 1;
|
292
|
-
if (
|
307
|
+
if (node_content->ptr[pos] == '\n')
|
293
308
|
pos += 1;
|
294
|
-
cmark_strbuf_drop(
|
309
|
+
cmark_strbuf_drop(node_content, pos);
|
295
310
|
}
|
296
|
-
b->as.code.literal = cmark_chunk_buf_detach(
|
311
|
+
b->as.code.literal = cmark_chunk_buf_detach(node_content);
|
297
312
|
break;
|
298
313
|
|
299
314
|
case CMARK_NODE_HTML_BLOCK:
|
300
|
-
b->as.literal = cmark_chunk_buf_detach(
|
315
|
+
b->as.literal = cmark_chunk_buf_detach(node_content);
|
301
316
|
break;
|
302
317
|
|
303
318
|
case CMARK_NODE_LIST: // determine tight/loose status
|
@@ -306,7 +321,7 @@ static cmark_node *finalize(cmark_parser *parser, cmark_node *b) {
|
|
306
321
|
|
307
322
|
while (item) {
|
308
323
|
// check for non-final non-empty list item ending with blank line:
|
309
|
-
if (item
|
324
|
+
if (S_last_line_blank(item) && item->next) {
|
310
325
|
b->as.list.tight = false;
|
311
326
|
break;
|
312
327
|
}
|
@@ -331,6 +346,7 @@ static cmark_node *finalize(cmark_parser *parser, cmark_node *b) {
|
|
331
346
|
default:
|
332
347
|
break;
|
333
348
|
}
|
349
|
+
|
334
350
|
return parent;
|
335
351
|
}
|
336
352
|
|
@@ -341,11 +357,11 @@ static cmark_node *add_child(cmark_parser *parser, cmark_node *parent,
|
|
341
357
|
|
342
358
|
// if 'parent' isn't the kind of node that can accept this child,
|
343
359
|
// then back up til we hit a node that can.
|
344
|
-
while (!can_contain(parent
|
360
|
+
while (!can_contain(S_type(parent), block_type)) {
|
345
361
|
parent = finalize(parser, parent);
|
346
362
|
}
|
347
363
|
|
348
|
-
cmark_node *child = make_block(block_type, parser->line_number, start_column);
|
364
|
+
cmark_node *child = make_block(parser->mem, block_type, parser->line_number, start_column);
|
349
365
|
child->parent = parent;
|
350
366
|
|
351
367
|
if (parent->last_child) {
|
@@ -361,7 +377,7 @@ static cmark_node *add_child(cmark_parser *parser, cmark_node *parent,
|
|
361
377
|
|
362
378
|
// Walk through node and all children, recursively, parsing
|
363
379
|
// string content into inline content where appropriate.
|
364
|
-
static void process_inlines(cmark_node *root, cmark_reference_map *refmap,
|
380
|
+
static void process_inlines(cmark_mem *mem, cmark_node *root, cmark_reference_map *refmap,
|
365
381
|
int options) {
|
366
382
|
cmark_iter *iter = cmark_iter_new(root);
|
367
383
|
cmark_node *cur;
|
@@ -370,8 +386,8 @@ static void process_inlines(cmark_node *root, cmark_reference_map *refmap,
|
|
370
386
|
while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
|
371
387
|
cur = cmark_iter_get_node(iter);
|
372
388
|
if (ev_type == CMARK_EVENT_ENTER) {
|
373
|
-
if (contains_inlines(cur
|
374
|
-
cmark_parse_inlines(cur, refmap, options);
|
389
|
+
if (contains_inlines(S_type(cur))) {
|
390
|
+
cmark_parse_inlines(mem, cur, refmap, options);
|
375
391
|
}
|
376
392
|
}
|
377
393
|
}
|
@@ -382,7 +398,7 @@ static void process_inlines(cmark_node *root, cmark_reference_map *refmap,
|
|
382
398
|
// Attempts to parse a list item marker (bullet or enumerated).
|
383
399
|
// On success, returns length of the marker, and populates
|
384
400
|
// data with the details. On failure, returns 0.
|
385
|
-
static bufsize_t parse_list_marker(cmark_chunk *input, bufsize_t pos,
|
401
|
+
static bufsize_t parse_list_marker(cmark_mem *mem, cmark_chunk *input, bufsize_t pos,
|
386
402
|
cmark_list **dataptr) {
|
387
403
|
unsigned char c;
|
388
404
|
bufsize_t startpos;
|
@@ -396,17 +412,13 @@ static bufsize_t parse_list_marker(cmark_chunk *input, bufsize_t pos,
|
|
396
412
|
if (!cmark_isspace(peek_at(input, pos))) {
|
397
413
|
return 0;
|
398
414
|
}
|
399
|
-
data = (cmark_list *)calloc(1, sizeof(*data));
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
data->start = 1;
|
407
|
-
data->delimiter = CMARK_PERIOD_DELIM;
|
408
|
-
data->tight = false;
|
409
|
-
}
|
415
|
+
data = (cmark_list *)mem->calloc(1, sizeof(*data));
|
416
|
+
data->marker_offset = 0; // will be adjusted later
|
417
|
+
data->list_type = CMARK_BULLET_LIST;
|
418
|
+
data->bullet_char = c;
|
419
|
+
data->start = 1;
|
420
|
+
data->delimiter = CMARK_PERIOD_DELIM;
|
421
|
+
data->tight = false;
|
410
422
|
} else if (cmark_isdigit(c)) {
|
411
423
|
int start = 0;
|
412
424
|
int digits = 0;
|
@@ -426,21 +438,16 @@ static bufsize_t parse_list_marker(cmark_chunk *input, bufsize_t pos,
|
|
426
438
|
if (!cmark_isspace(peek_at(input, pos))) {
|
427
439
|
return 0;
|
428
440
|
}
|
429
|
-
data = (cmark_list *)calloc(1, sizeof(*data));
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
data->start = start;
|
437
|
-
data->delimiter = (c == '.' ? CMARK_PERIOD_DELIM : CMARK_PAREN_DELIM);
|
438
|
-
data->tight = false;
|
439
|
-
}
|
441
|
+
data = (cmark_list *)mem->calloc(1, sizeof(*data));
|
442
|
+
data->marker_offset = 0; // will be adjusted later
|
443
|
+
data->list_type = CMARK_ORDERED_LIST;
|
444
|
+
data->bullet_char = 0;
|
445
|
+
data->start = start;
|
446
|
+
data->delimiter = (c == '.' ? CMARK_PERIOD_DELIM : CMARK_PAREN_DELIM);
|
447
|
+
data->tight = false;
|
440
448
|
} else {
|
441
449
|
return 0;
|
442
450
|
}
|
443
|
-
|
444
451
|
} else {
|
445
452
|
return 0;
|
446
453
|
}
|
@@ -463,7 +470,7 @@ static cmark_node *finalize_document(cmark_parser *parser) {
|
|
463
470
|
}
|
464
471
|
|
465
472
|
finalize(parser, parser->root);
|
466
|
-
process_inlines(parser->root, parser->refmap, parser->options);
|
473
|
+
process_inlines(parser->mem, parser->root, parser->refmap, parser->options);
|
467
474
|
|
468
475
|
return parser->root;
|
469
476
|
}
|
@@ -529,24 +536,24 @@ static void S_parser_feed(cmark_parser *parser, const unsigned char *buffer,
|
|
529
536
|
process = true;
|
530
537
|
}
|
531
538
|
|
532
|
-
chunk_len =
|
539
|
+
chunk_len = (eol - buffer);
|
533
540
|
if (process) {
|
534
|
-
if (parser->linebuf
|
535
|
-
cmark_strbuf_put(parser->linebuf, buffer, chunk_len);
|
536
|
-
S_process_line(parser, parser->linebuf
|
537
|
-
cmark_strbuf_clear(parser->linebuf);
|
541
|
+
if (parser->linebuf.size > 0) {
|
542
|
+
cmark_strbuf_put(&parser->linebuf, buffer, chunk_len);
|
543
|
+
S_process_line(parser, parser->linebuf.ptr, parser->linebuf.size);
|
544
|
+
cmark_strbuf_clear(&parser->linebuf);
|
538
545
|
} else {
|
539
546
|
S_process_line(parser, buffer, chunk_len);
|
540
547
|
}
|
541
548
|
} else {
|
542
549
|
if (eol < end && *eol == '\0') {
|
543
550
|
// omit NULL byte
|
544
|
-
cmark_strbuf_put(parser->linebuf, buffer, chunk_len);
|
551
|
+
cmark_strbuf_put(&parser->linebuf, buffer, chunk_len);
|
545
552
|
// add replacement character
|
546
|
-
cmark_strbuf_put(parser->linebuf, repl, 3);
|
553
|
+
cmark_strbuf_put(&parser->linebuf, repl, 3);
|
547
554
|
chunk_len += 1; // so we advance the buffer past NULL
|
548
555
|
} else {
|
549
|
-
cmark_strbuf_put(parser->linebuf, buffer, chunk_len);
|
556
|
+
cmark_strbuf_put(&parser->linebuf, buffer, chunk_len);
|
550
557
|
}
|
551
558
|
}
|
552
559
|
|
@@ -555,7 +562,7 @@ static void S_parser_feed(cmark_parser *parser, const unsigned char *buffer,
|
|
555
562
|
if (buffer < end && *buffer == '\r') {
|
556
563
|
buffer++;
|
557
564
|
if (buffer == end)
|
558
|
-
|
565
|
+
parser->last_buffer_ended_with_cr = true;
|
559
566
|
}
|
560
567
|
if (buffer < end && *buffer == '\n')
|
561
568
|
buffer++;
|
@@ -627,16 +634,16 @@ static void S_advance_offset(cmark_parser *parser, cmark_chunk *input,
|
|
627
634
|
if (c == '\t') {
|
628
635
|
chars_to_tab = TAB_STOP - (parser->column % TAB_STOP);
|
629
636
|
if (columns) {
|
630
|
-
|
631
|
-
|
632
|
-
|
637
|
+
parser->partially_consumed_tab = chars_to_tab > count;
|
638
|
+
chars_to_advance = MIN(count, chars_to_tab);
|
639
|
+
parser->column += chars_to_advance;
|
633
640
|
parser->offset += (parser->partially_consumed_tab ? 0 : 1);
|
634
|
-
|
641
|
+
count -= chars_to_advance;
|
635
642
|
} else {
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
643
|
+
parser->partially_consumed_tab = false;
|
644
|
+
parser->column += chars_to_tab;
|
645
|
+
parser->offset += 1;
|
646
|
+
count -= 1;
|
640
647
|
}
|
641
648
|
} else {
|
642
649
|
parser->partially_consumed_tab = false;
|
@@ -648,12 +655,10 @@ static void S_advance_offset(cmark_parser *parser, cmark_chunk *input,
|
|
648
655
|
}
|
649
656
|
|
650
657
|
static bool S_last_child_is_open(cmark_node *container) {
|
651
|
-
return container->last_child && container->last_child->
|
658
|
+
return container->last_child && (container->last_child->flags & CMARK_NODE__OPEN);
|
652
659
|
}
|
653
660
|
|
654
|
-
static bool parse_block_quote_prefix(cmark_parser *parser,
|
655
|
-
cmark_chunk *input)
|
656
|
-
{
|
661
|
+
static bool parse_block_quote_prefix(cmark_parser *parser, cmark_chunk *input) {
|
657
662
|
bool res = false;
|
658
663
|
bufsize_t matched = 0;
|
659
664
|
|
@@ -672,34 +677,30 @@ static bool parse_block_quote_prefix(cmark_parser *parser,
|
|
672
677
|
return res;
|
673
678
|
}
|
674
679
|
|
675
|
-
static bool parse_node_item_prefix(cmark_parser *parser,
|
676
|
-
|
677
|
-
cmark_node *container)
|
678
|
-
{
|
680
|
+
static bool parse_node_item_prefix(cmark_parser *parser, cmark_chunk *input,
|
681
|
+
cmark_node *container) {
|
679
682
|
bool res = false;
|
680
683
|
|
681
684
|
if (parser->indent >=
|
682
685
|
container->as.list.marker_offset + container->as.list.padding) {
|
683
686
|
S_advance_offset(parser, input, container->as.list.marker_offset +
|
684
|
-
|
687
|
+
container->as.list.padding,
|
685
688
|
true);
|
686
689
|
res = true;
|
687
690
|
} else if (parser->blank && container->first_child != NULL) {
|
688
691
|
// if container->first_child is NULL, then the opening line
|
689
692
|
// of the list item was blank after the list marker; in this
|
690
693
|
// case, we are done with the list item.
|
691
|
-
S_advance_offset(parser, input,
|
692
|
-
|
694
|
+
S_advance_offset(parser, input, parser->first_nonspace - parser->offset,
|
695
|
+
false);
|
693
696
|
res = true;
|
694
697
|
}
|
695
698
|
return res;
|
696
699
|
}
|
697
700
|
|
698
|
-
static bool parse_code_block_prefix(cmark_parser *parser,
|
699
|
-
|
700
|
-
|
701
|
-
bool *should_continue)
|
702
|
-
{
|
701
|
+
static bool parse_code_block_prefix(cmark_parser *parser, cmark_chunk *input,
|
702
|
+
cmark_node *container,
|
703
|
+
bool *should_continue) {
|
703
704
|
bool res = false;
|
704
705
|
|
705
706
|
if (!container->as.code.fenced) { // indented
|
@@ -707,8 +708,8 @@ static bool parse_code_block_prefix(cmark_parser *parser,
|
|
707
708
|
S_advance_offset(parser, input, CODE_INDENT, true);
|
708
709
|
res = true;
|
709
710
|
} else if (parser->blank) {
|
710
|
-
S_advance_offset(parser, input,
|
711
|
-
|
711
|
+
S_advance_offset(parser, input, parser->first_nonspace - parser->offset,
|
712
|
+
false);
|
712
713
|
res = true;
|
713
714
|
}
|
714
715
|
} else { // fenced
|
@@ -741,25 +742,24 @@ static bool parse_code_block_prefix(cmark_parser *parser,
|
|
741
742
|
}
|
742
743
|
|
743
744
|
static bool parse_html_block_prefix(cmark_parser *parser,
|
744
|
-
|
745
|
-
{
|
745
|
+
cmark_node *container) {
|
746
746
|
bool res = false;
|
747
747
|
int html_block_type = container->as.html_block_type;
|
748
748
|
|
749
749
|
assert(html_block_type >= 1 && html_block_type <= 7);
|
750
750
|
switch (html_block_type) {
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
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
763
|
}
|
764
764
|
|
765
765
|
return res;
|
@@ -773,10 +773,8 @@ static bool parse_html_block_prefix(cmark_parser *parser,
|
|
773
773
|
*
|
774
774
|
* Returns: The last matching node, or NULL
|
775
775
|
*/
|
776
|
-
static cmark_node *check_open_blocks(cmark_parser *parser,
|
777
|
-
|
778
|
-
bool *all_matched)
|
779
|
-
{
|
776
|
+
static cmark_node *check_open_blocks(cmark_parser *parser, cmark_chunk *input,
|
777
|
+
bool *all_matched) {
|
780
778
|
bool should_continue = true;
|
781
779
|
*all_matched = false;
|
782
780
|
cmark_node *container = parser->root;
|
@@ -784,36 +782,36 @@ static cmark_node *check_open_blocks(cmark_parser *parser,
|
|
784
782
|
|
785
783
|
while (S_last_child_is_open(container)) {
|
786
784
|
container = container->last_child;
|
787
|
-
cont_type = container
|
785
|
+
cont_type = S_type(container);
|
788
786
|
|
789
787
|
S_find_first_nonspace(parser, input);
|
790
788
|
|
791
789
|
switch (cont_type) {
|
792
|
-
|
793
|
-
|
794
|
-
goto done;
|
795
|
-
break;
|
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
|
790
|
+
case CMARK_NODE_BLOCK_QUOTE:
|
791
|
+
if (!parse_block_quote_prefix(parser, input))
|
806
792
|
goto done;
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
793
|
+
break;
|
794
|
+
case CMARK_NODE_ITEM:
|
795
|
+
if (!parse_node_item_prefix(parser, input, container))
|
796
|
+
goto done;
|
797
|
+
break;
|
798
|
+
case CMARK_NODE_CODE_BLOCK:
|
799
|
+
if (!parse_code_block_prefix(parser, input, container, &should_continue))
|
800
|
+
goto done;
|
801
|
+
break;
|
802
|
+
case CMARK_NODE_HEADING:
|
803
|
+
// a heading can never contain more than one line
|
804
|
+
goto done;
|
805
|
+
case CMARK_NODE_HTML_BLOCK:
|
806
|
+
if (!parse_html_block_prefix(parser, container))
|
807
|
+
goto done;
|
808
|
+
break;
|
809
|
+
case CMARK_NODE_PARAGRAPH:
|
810
|
+
if (parser->blank)
|
811
|
+
goto done;
|
812
|
+
break;
|
813
|
+
default:
|
814
|
+
break;
|
817
815
|
}
|
818
816
|
}
|
819
817
|
|
@@ -831,15 +829,12 @@ done:
|
|
831
829
|
return container;
|
832
830
|
}
|
833
831
|
|
834
|
-
static void open_new_blocks(cmark_parser *parser,
|
835
|
-
|
836
|
-
cmark_chunk *input,
|
837
|
-
bool all_matched)
|
838
|
-
{
|
832
|
+
static void open_new_blocks(cmark_parser *parser, cmark_node **container,
|
833
|
+
cmark_chunk *input, bool all_matched) {
|
839
834
|
bool indented;
|
840
835
|
cmark_list *data = NULL;
|
841
|
-
bool maybe_lazy = parser->current
|
842
|
-
cmark_node_type cont_type = (*container)
|
836
|
+
bool maybe_lazy = S_type(parser->current) == CMARK_NODE_PARAGRAPH;
|
837
|
+
cmark_node_type cont_type = S_type(*container);
|
843
838
|
bufsize_t matched = 0;
|
844
839
|
int lev = 0;
|
845
840
|
bool save_partially_consumed_tab;
|
@@ -861,7 +856,7 @@ static void open_new_blocks(cmark_parser *parser,
|
|
861
856
|
S_advance_offset(parser, input, 1, true);
|
862
857
|
}
|
863
858
|
*container = add_child(parser, *container, CMARK_NODE_BLOCK_QUOTE,
|
864
|
-
|
859
|
+
parser->offset + 1);
|
865
860
|
|
866
861
|
} else if (!indented && (matched = scan_atx_heading_start(
|
867
862
|
input, parser->first_nonspace))) {
|
@@ -887,10 +882,10 @@ static void open_new_blocks(cmark_parser *parser,
|
|
887
882
|
} else if (!indented && (matched = scan_open_code_fence(
|
888
883
|
input, parser->first_nonspace))) {
|
889
884
|
*container = add_child(parser, *container, CMARK_NODE_CODE_BLOCK,
|
890
|
-
|
885
|
+
parser->first_nonspace + 1);
|
891
886
|
(*container)->as.code.fenced = true;
|
892
887
|
(*container)->as.code.fence_char = peek_at(input, parser->first_nonspace);
|
893
|
-
(*container)->as.code.fence_length = matched;
|
888
|
+
(*container)->as.code.fence_length = (matched > 255) ? 255 : matched;
|
894
889
|
(*container)->as.code.fence_offset =
|
895
890
|
(int8_t)(parser->first_nonspace - parser->offset);
|
896
891
|
(*container)->as.code.info = cmark_chunk_literal("");
|
@@ -904,27 +899,26 @@ static void open_new_blocks(cmark_parser *parser,
|
|
904
899
|
(matched = scan_html_block_start_7(
|
905
900
|
input, parser->first_nonspace))))) {
|
906
901
|
*container = add_child(parser, *container, CMARK_NODE_HTML_BLOCK,
|
907
|
-
|
902
|
+
parser->first_nonspace + 1);
|
908
903
|
(*container)->as.html_block_type = matched;
|
909
904
|
// note, we don't adjust parser->offset because the tag is part of the
|
910
905
|
// text
|
911
906
|
} else if (!indented && cont_type == CMARK_NODE_PARAGRAPH &&
|
912
907
|
(lev =
|
913
908
|
scan_setext_heading_line(input, parser->first_nonspace))) {
|
914
|
-
(*container)->type = CMARK_NODE_HEADING;
|
909
|
+
(*container)->type = (uint16_t)CMARK_NODE_HEADING;
|
915
910
|
(*container)->as.heading.level = lev;
|
916
911
|
(*container)->as.heading.setext = true;
|
917
912
|
S_advance_offset(parser, input, input->len - 1 - parser->offset, false);
|
918
913
|
} else if (!indented &&
|
919
914
|
!(cont_type == CMARK_NODE_PARAGRAPH && !all_matched) &&
|
920
|
-
(matched =
|
921
|
-
scan_thematic_break(input, parser->first_nonspace))) {
|
915
|
+
(matched = scan_thematic_break(input, parser->first_nonspace))) {
|
922
916
|
// it's only now that we know the line is not part of a setext heading:
|
923
917
|
*container = add_child(parser, *container, CMARK_NODE_THEMATIC_BREAK,
|
924
|
-
|
918
|
+
parser->first_nonspace + 1);
|
925
919
|
S_advance_offset(parser, input, input->len - 1 - parser->offset, false);
|
926
920
|
} else if ((matched =
|
927
|
-
parse_list_marker(input, parser->first_nonspace, &data)) &&
|
921
|
+
parse_list_marker(parser->mem, input, parser->first_nonspace, &data)) &&
|
928
922
|
(!indented || cont_type == CMARK_NODE_LIST)) {
|
929
923
|
// Note that we can have new list items starting with >= 4
|
930
924
|
// spaces indent, as long as the list container is still open.
|
@@ -940,16 +934,18 @@ static void open_new_blocks(cmark_parser *parser,
|
|
940
934
|
save_column = parser->column;
|
941
935
|
|
942
936
|
while (parser->column - save_column <= 5 &&
|
943
|
-
|
937
|
+
S_is_space_or_tab(peek_at(input, parser->offset))) {
|
944
938
|
S_advance_offset(parser, input, 1, true);
|
945
939
|
}
|
946
940
|
|
947
941
|
i = parser->column - save_column;
|
948
|
-
if (i >= 5 || i < 1
|
942
|
+
if (i >= 5 || i < 1 ||
|
943
|
+
// only spaces after list marker:
|
944
|
+
S_is_line_end_char(peek_at(input, parser->offset))) {
|
949
945
|
data->padding = matched + 1;
|
950
|
-
|
951
|
-
|
952
|
-
|
946
|
+
parser->offset = save_offset;
|
947
|
+
parser->column = save_column;
|
948
|
+
parser->partially_consumed_tab = save_partially_consumed_tab;
|
953
949
|
if (i > 0) {
|
954
950
|
S_advance_offset(parser, input, 1, true);
|
955
951
|
}
|
@@ -965,21 +961,21 @@ static void open_new_blocks(cmark_parser *parser,
|
|
965
961
|
if (cont_type != CMARK_NODE_LIST ||
|
966
962
|
!lists_match(&((*container)->as.list), data)) {
|
967
963
|
*container = add_child(parser, *container, CMARK_NODE_LIST,
|
968
|
-
|
964
|
+
parser->first_nonspace + 1);
|
969
965
|
|
970
966
|
memcpy(&((*container)->as.list), data, sizeof(*data));
|
971
967
|
}
|
972
968
|
|
973
969
|
// add the list item
|
974
970
|
*container = add_child(parser, *container, CMARK_NODE_ITEM,
|
975
|
-
|
971
|
+
parser->first_nonspace + 1);
|
976
972
|
/* TODO: static */
|
977
973
|
memcpy(&((*container)->as.list), data, sizeof(*data));
|
978
974
|
free(data);
|
979
975
|
} else if (indented && !maybe_lazy && !parser->blank) {
|
980
976
|
S_advance_offset(parser, input, CODE_INDENT, true);
|
981
977
|
*container = add_child(parser, *container, CMARK_NODE_CODE_BLOCK,
|
982
|
-
|
978
|
+
parser->offset + 1);
|
983
979
|
(*container)->as.code.fenced = false;
|
984
980
|
(*container)->as.code.fence_char = 0;
|
985
981
|
(*container)->as.code.fence_length = 0;
|
@@ -990,21 +986,19 @@ static void open_new_blocks(cmark_parser *parser,
|
|
990
986
|
break;
|
991
987
|
}
|
992
988
|
|
993
|
-
if (accepts_lines((*container)
|
989
|
+
if (accepts_lines(S_type(*container))) {
|
994
990
|
// if it's a line container, it can't contain other containers
|
995
991
|
break;
|
996
992
|
}
|
997
993
|
|
998
|
-
cont_type = (*container)
|
994
|
+
cont_type = S_type(*container);
|
999
995
|
maybe_lazy = false;
|
1000
996
|
}
|
1001
997
|
}
|
1002
998
|
|
1003
|
-
static void add_text_to_container
|
1004
|
-
|
1005
|
-
|
1006
|
-
cmark_chunk *input)
|
1007
|
-
{
|
999
|
+
static void add_text_to_container(cmark_parser *parser, cmark_node *container,
|
1000
|
+
cmark_node *last_matched_container,
|
1001
|
+
cmark_chunk *input) {
|
1008
1002
|
cmark_node *tmp;
|
1009
1003
|
// what remains at parser->offset is a text line. add the text to the
|
1010
1004
|
// appropriate container.
|
@@ -1012,24 +1006,26 @@ static void add_text_to_container (cmark_parser *parser,
|
|
1012
1006
|
S_find_first_nonspace(parser, input);
|
1013
1007
|
|
1014
1008
|
if (parser->blank && container->last_child)
|
1015
|
-
container->last_child
|
1009
|
+
S_set_last_line_blank(container->last_child, true);
|
1016
1010
|
|
1017
1011
|
// block quote lines are never blank as they start with >
|
1018
1012
|
// and we don't count blanks in fenced code for purposes of tight/loose
|
1019
1013
|
// lists or breaking out of lists. we also don't set last_line_blank
|
1020
1014
|
// on an empty list item.
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
!(
|
1015
|
+
const cmark_node_type ctype = S_type(container);
|
1016
|
+
const bool last_line_blank =
|
1017
|
+
(parser->blank && ctype != CMARK_NODE_BLOCK_QUOTE &&
|
1018
|
+
ctype != CMARK_NODE_HEADING &&
|
1019
|
+
ctype != CMARK_NODE_THEMATIC_BREAK &&
|
1020
|
+
!(ctype == CMARK_NODE_CODE_BLOCK && container->as.code.fenced) &&
|
1021
|
+
!(ctype == CMARK_NODE_ITEM && container->first_child == NULL &&
|
1028
1022
|
container->start_line == parser->line_number));
|
1029
1023
|
|
1024
|
+
S_set_last_line_blank(container, last_line_blank);
|
1025
|
+
|
1030
1026
|
tmp = container;
|
1031
1027
|
while (tmp->parent) {
|
1032
|
-
tmp->parent
|
1028
|
+
S_set_last_line_blank(tmp->parent, false);
|
1033
1029
|
tmp = tmp->parent;
|
1034
1030
|
}
|
1035
1031
|
|
@@ -1040,9 +1036,8 @@ static void add_text_to_container (cmark_parser *parser,
|
|
1040
1036
|
// then treat this as a "lazy continuation line" and add it to
|
1041
1037
|
// the open paragraph.
|
1042
1038
|
if (parser->current != last_matched_container &&
|
1043
|
-
container == last_matched_container &&
|
1044
|
-
|
1045
|
-
parser->current->type == CMARK_NODE_PARAGRAPH) {
|
1039
|
+
container == last_matched_container && !parser->blank &&
|
1040
|
+
S_type(parser->current) == CMARK_NODE_PARAGRAPH) {
|
1046
1041
|
add_line(parser->current, input, parser);
|
1047
1042
|
} else { // not a lazy continuation
|
1048
1043
|
// Finalize any blocks that were not matched and set cur to container:
|
@@ -1051,9 +1046,9 @@ static void add_text_to_container (cmark_parser *parser,
|
|
1051
1046
|
assert(parser->current != NULL);
|
1052
1047
|
}
|
1053
1048
|
|
1054
|
-
if (container
|
1049
|
+
if (S_type(container) == CMARK_NODE_CODE_BLOCK) {
|
1055
1050
|
add_line(container, input, parser);
|
1056
|
-
} else if (container
|
1051
|
+
} else if (S_type(container) == CMARK_NODE_HTML_BLOCK) {
|
1057
1052
|
add_line(container, input, parser);
|
1058
1053
|
|
1059
1054
|
int matches_end_condition;
|
@@ -1094,18 +1089,20 @@ static void add_text_to_container (cmark_parser *parser,
|
|
1094
1089
|
}
|
1095
1090
|
} else if (parser->blank) {
|
1096
1091
|
// ??? do nothing
|
1097
|
-
} else if (accepts_lines(container
|
1098
|
-
if (container
|
1092
|
+
} else if (accepts_lines(S_type(container))) {
|
1093
|
+
if (S_type(container) == CMARK_NODE_HEADING &&
|
1099
1094
|
container->as.heading.setext == false) {
|
1100
1095
|
chop_trailing_hashtags(input);
|
1101
1096
|
}
|
1102
|
-
S_advance_offset(parser, input, parser->first_nonspace - parser->offset,
|
1097
|
+
S_advance_offset(parser, input, parser->first_nonspace - parser->offset,
|
1098
|
+
false);
|
1103
1099
|
add_line(container, input, parser);
|
1104
1100
|
} else {
|
1105
1101
|
// create paragraph container for line
|
1106
1102
|
container = add_child(parser, container, CMARK_NODE_PARAGRAPH,
|
1107
1103
|
parser->first_nonspace + 1);
|
1108
|
-
S_advance_offset(parser, input, parser->first_nonspace - parser->offset,
|
1104
|
+
S_advance_offset(parser, input, parser->first_nonspace - parser->offset,
|
1105
|
+
false);
|
1109
1106
|
add_line(container, input, parser);
|
1110
1107
|
}
|
1111
1108
|
|
@@ -1122,21 +1119,21 @@ static void S_process_line(cmark_parser *parser, const unsigned char *buffer,
|
|
1122
1119
|
cmark_chunk input;
|
1123
1120
|
|
1124
1121
|
if (parser->options & CMARK_OPT_VALIDATE_UTF8)
|
1125
|
-
cmark_utf8proc_check(parser->curline, buffer, bytes);
|
1122
|
+
cmark_utf8proc_check(&parser->curline, buffer, bytes);
|
1126
1123
|
else
|
1127
|
-
cmark_strbuf_put(parser->curline, buffer, bytes);
|
1124
|
+
cmark_strbuf_put(&parser->curline, buffer, bytes);
|
1128
1125
|
|
1129
1126
|
// ensure line ends with a newline:
|
1130
|
-
if (bytes == 0 || !S_is_line_end_char(parser->curline
|
1131
|
-
cmark_strbuf_putc(parser->curline, '\n');
|
1127
|
+
if (bytes == 0 || !S_is_line_end_char(parser->curline.ptr[bytes - 1]))
|
1128
|
+
cmark_strbuf_putc(&parser->curline, '\n');
|
1132
1129
|
|
1133
1130
|
parser->offset = 0;
|
1134
1131
|
parser->column = 0;
|
1135
1132
|
parser->blank = false;
|
1136
1133
|
parser->partially_consumed_tab = false;
|
1137
1134
|
|
1138
|
-
input.data = parser->curline
|
1139
|
-
input.len = parser->curline
|
1135
|
+
input.data = parser->curline.ptr;
|
1136
|
+
input.len = parser->curline.size;
|
1140
1137
|
|
1141
1138
|
parser->line_number++;
|
1142
1139
|
|
@@ -1148,7 +1145,7 @@ static void S_process_line(cmark_parser *parser, const unsigned char *buffer,
|
|
1148
1145
|
container = last_matched_container;
|
1149
1146
|
|
1150
1147
|
// check to see if we've hit 2nd blank line, break out of list:
|
1151
|
-
if (parser->blank && container
|
1148
|
+
if (parser->blank && S_last_line_blank(container))
|
1152
1149
|
break_out_of_lists(parser, &container);
|
1153
1150
|
|
1154
1151
|
open_new_blocks(parser, &container, &input, all_matched);
|
@@ -1164,13 +1161,13 @@ finished:
|
|
1164
1161
|
input.data[parser->last_line_length - 1] == '\r')
|
1165
1162
|
parser->last_line_length -= 1;
|
1166
1163
|
|
1167
|
-
cmark_strbuf_clear(parser->curline);
|
1164
|
+
cmark_strbuf_clear(&parser->curline);
|
1168
1165
|
}
|
1169
1166
|
|
1170
1167
|
cmark_node *cmark_parser_finish(cmark_parser *parser) {
|
1171
|
-
if (parser->linebuf
|
1172
|
-
S_process_line(parser, parser->linebuf
|
1173
|
-
cmark_strbuf_clear(parser->linebuf);
|
1168
|
+
if (parser->linebuf.size) {
|
1169
|
+
S_process_line(parser, parser->linebuf.ptr, parser->linebuf.size);
|
1170
|
+
cmark_strbuf_clear(&parser->linebuf);
|
1174
1171
|
}
|
1175
1172
|
|
1176
1173
|
finalize_document(parser);
|
@@ -1179,7 +1176,7 @@ cmark_node *cmark_parser_finish(cmark_parser *parser) {
|
|
1179
1176
|
cmark_consolidate_text_nodes(parser->root);
|
1180
1177
|
}
|
1181
1178
|
|
1182
|
-
cmark_strbuf_free(parser->curline);
|
1179
|
+
cmark_strbuf_free(&parser->curline);
|
1183
1180
|
|
1184
1181
|
#if CMARK_DEBUG_NODES
|
1185
1182
|
if (cmark_node_check(parser->root, stderr)) {
|