md4c

C Markdown parser. Fast. SAX-like interface. Compliant to CommonMark specification.
git clone https://noulin.net/git/md4c.git
Log | Files | Refs | README | LICENSE

commit 684c80ced0bf978e90fa5bee9fab1d639abdcae9
parent 296c8318f82b14e37af41dbd95238272c737ba29
Author: Martin Mitas <mity@morous.org>
Date:   Thu, 13 Oct 2016 22:38:16 +0200

Implement "rule of three".

Since 0.26, CommonMark specifies intraword '*' or '_' marks cannot close
if sume of opening and closing mark chracters can be divided by three.

Diffstat:
Mmd4c/md4c.c | 24++++++++++++++++++++----
1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/md4c/md4c.c b/md4c/md4c.c @@ -807,7 +807,8 @@ struct MD_MARK_tag { /* Mark flags. */ #define MD_MARK_POTENTIAL_OPENER 0x01 /* Maybe opener. */ #define MD_MARK_POTENTIAL_CLOSER 0x02 /* Maybe closer. */ -#define MD_MARK_AUTOLINK 0x04 /* Distinguisher for '<', '>'. */ +#define MD_MARK_INTRAWORD 0x04 /* Helper for emphasis (the rule of 3). */ +#define MD_MARK_AUTOLINK 0x08 /* Distinguisher for '<', '>'. */ #define MD_MARK_RESOLVED 0x10 /* Yes, the special meaning is indeed recognized. */ #define MD_MARK_OPENER 0x20 /* This opens a span. */ #define MD_MARK_CLOSER 0x40 /* This closes a span. */ @@ -1062,6 +1063,8 @@ md_collect_marks(MD_CTX* ctx, const MD_LINE* lines, int n_lines) flags |= MD_MARK_POTENTIAL_CLOSER; if(right_level > 0 && right_level >= left_level) flags |= MD_MARK_POTENTIAL_OPENER; + if(left_level == 2 && right_level == 2) + flags |= MD_MARK_INTRAWORD; if(flags != 0) { PUSH_MARK(ch, off, tmp, flags); @@ -1323,7 +1326,8 @@ md_analyze_entity(MD_CTX* ctx, int mark_index) } static void -md_analyze_simple_pairing_mark(MD_CTX* ctx, MD_MARKCHAIN* chain, int mark_index) +md_analyze_simple_pairing_mark(MD_CTX* ctx, MD_MARKCHAIN* chain, int mark_index, + int apply_rule_of_three) { MD_MARK* mark = &ctx->marks[mark_index]; @@ -1334,6 +1338,17 @@ md_analyze_simple_pairing_mark(MD_CTX* ctx, MD_MARKCHAIN* chain, int mark_index) SZ opener_size = opener->end - opener->beg; SZ closer_size = mark->end - mark->beg; + if(apply_rule_of_three && (mark->flags & MD_MARK_INTRAWORD)) { + while((opener_size + closer_size) % 3 == 0) { + if(opener->prev < 0) + goto cannot_resolve; + + opener = &ctx->marks[opener->prev]; + opener_size = opener->end - opener->beg; + closer_size = mark->end - mark->beg; + } + } + if(opener_size > closer_size) { opener_index = md_split_mark(ctx, opener_index, closer_size); md_mark_chain_append(ctx, chain, opener_index); @@ -1346,6 +1361,7 @@ md_analyze_simple_pairing_mark(MD_CTX* ctx, MD_MARKCHAIN* chain, int mark_index) return; } +cannot_resolve: /* If not resolved, and we can be an opener, remember the mark for * the future. */ if(mark->flags & MD_MARK_POTENTIAL_OPENER) @@ -1355,13 +1371,13 @@ md_analyze_simple_pairing_mark(MD_CTX* ctx, MD_MARKCHAIN* chain, int mark_index) static inline void md_analyze_asterisk(MD_CTX* ctx, int mark_index) { - md_analyze_simple_pairing_mark(ctx, &ASTERISK_OPENERS, mark_index); + md_analyze_simple_pairing_mark(ctx, &ASTERISK_OPENERS, mark_index, 1); } static inline void md_analyze_underscore(MD_CTX* ctx, int mark_index) { - md_analyze_simple_pairing_mark(ctx, &UNDERSCORE_OPENERS, mark_index); + md_analyze_simple_pairing_mark(ctx, &UNDERSCORE_OPENERS, mark_index, 1); } /* Table of precedence of various span types. */