2323#include "houdini.h"
2424#include "buffer.h"
2525#include "footnotes.h"
26+ #include "front_matter.h"
2627
2728#define CODE_INDENT 4
2829#define TAB_STOP 4
@@ -68,16 +69,12 @@ static CMARK_INLINE bool S_is_line_end_char(char c) {
6869 return (c == '\n' || c == '\r' );
6970}
7071
71- static CMARK_INLINE bool S_is_space_or_tab (char c ) {
72- return (c == ' ' || c == '\t' );
73- }
74-
7572// Returns true if block is being finalized on the same line it ends.
7673// This happens for:
7774// - Document node (special case)
7875// - Fenced code blocks (end on the closing fence line)
7976// - Setext headings (end on the underline)
80- // - HTML blocks types 1-5 per CommonMark spec §4.6 (end on the line
77+ // - HTML block types 1-5 per CommonMark spec §4.6 (end on the line
8178// containing the closing marker)
8279// - Any block finalized on the same line it started (e.g., single-line blocks)
8380static CMARK_INLINE bool S_ends_on_current_line (cmark_parser * parser , cmark_node * b ) {
@@ -100,6 +97,10 @@ static CMARK_INLINE bool S_ends_on_current_line(cmark_parser *parser, cmark_node
10097 b -> start_line == parser -> line_number ;
10198}
10299
100+ static CMARK_INLINE bool S_is_space_or_tab (char c ) {
101+ return (c == ' ' || c == '\t' );
102+ }
103+
103104static void S_parser_feed (cmark_parser * parser , const unsigned char * buffer ,
104105 size_t len , bool eof );
105106
@@ -159,6 +160,8 @@ static void cmark_parser_reset(cmark_parser *parser) {
159160
160161 cmark_strbuf_init (parser -> mem , & parser -> curline , 256 );
161162 cmark_strbuf_init (parser -> mem , & parser -> linebuf , 0 );
163+ cmark_strbuf_init (parser -> mem , & parser -> front_matter_buf , 0 );
164+ cmark_strbuf_init (parser -> mem , & parser -> front_matter_info , 0 );
162165
163166 cmark_node * document = make_document (parser -> mem );
164167
@@ -189,6 +192,8 @@ void cmark_parser_free(cmark_parser *parser) {
189192 cmark_parser_dispose (parser );
190193 cmark_strbuf_free (& parser -> curline );
191194 cmark_strbuf_free (& parser -> linebuf );
195+ cmark_strbuf_free (& parser -> front_matter_buf );
196+ cmark_strbuf_free (& parser -> front_matter_info );
192197 cmark_llist_free (parser -> mem , parser -> syntax_extensions );
193198 cmark_llist_free (parser -> mem , parser -> inline_syntax_extensions );
194199 mem -> free (parser );
@@ -1244,7 +1249,8 @@ static void open_new_blocks(cmark_parser *parser, cmark_node **container,
12441249 parser -> first_nonspace + 1 );
12451250 S_advance_offset (parser , input , input -> len - 1 - parser -> offset , false);
12461251 } else if (!indented &&
1247- parser -> options & CMARK_OPT_FOOTNOTES &&
1252+ (parser -> options & CMARK_OPT_FOOTNOTES ) &&
1253+ depth < MAX_LIST_DEPTH &&
12481254 (matched = scan_footnote_definition (input , parser -> first_nonspace ))) {
12491255 cmark_chunk c = cmark_chunk_dup (input , parser -> first_nonspace + 2 , matched - 2 );
12501256
@@ -1516,6 +1522,10 @@ static void S_process_line(cmark_parser *parser, const unsigned char *buffer,
15161522
15171523 parser -> line_number ++ ;
15181524
1525+ if ((parser -> options & CMARK_OPT_FRONT_MATTER ) &&
1526+ cmark_front_matter_process_line (parser , & input ))
1527+ goto finished ;
1528+
15191529 last_matched_container = check_open_blocks (parser , & input , & all_matched );
15201530
15211531 if (!last_matched_container )
@@ -1556,12 +1566,20 @@ cmark_node *cmark_parser_finish(cmark_parser *parser) {
15561566 cmark_strbuf_clear (& parser -> linebuf );
15571567 }
15581568
1569+ // If front matter scanning was still active when the document ended, no
1570+ // closing delimiter was found. The entire document (after the opening ---)
1571+ // is treated as front matter.
1572+ if ((parser -> options & CMARK_OPT_FRONT_MATTER ) && parser -> front_matter_scanning )
1573+ cmark_front_matter_process_line (parser , NULL );
1574+
15591575 finalize_document (parser );
15601576
15611577 cmark_consolidate_text_nodes (parser -> root );
15621578
15631579 cmark_strbuf_free (& parser -> curline );
15641580 cmark_strbuf_free (& parser -> linebuf );
1581+ cmark_strbuf_free (& parser -> front_matter_buf );
1582+ cmark_strbuf_free (& parser -> front_matter_info );
15651583
15661584#if CMARK_DEBUG_NODES
15671585 if (cmark_node_check (parser -> root , stderr )) {
0 commit comments