From c50197bab81d7105c9c790548821b61bcb97a62a Mon Sep 17 00:00:00 2001 From: John MacFarlane Date: Wed, 13 Apr 2016 16:50:38 -0700 Subject: Changed `process_emphasis` to get better results in corner cases. This will need corresponding spec changes. The change is this: when considering matches between an interior delimiter run (one that can open and can close) and another delimiter run, we require that the sum of the lengths of the two delimiter runs mod 3 is not 0. Thus, for example, in *a**b* 1 23 4 delimiter 1 cannot match 2, since the sum of the lengths of the first delimiter run (1) and the second (1,2) == 3. Thus we get `a**b` instead of `ab`. This gives better behavior on things like *a**b**c* which previously got parsed as abc and now would be parsed as abc With this change we get four spec test failures, but in each case the output seems more "intuitive": ``` Example 386 (lines 6490-6494) Emphasis and strong emphasis *foo**bar**baz* --- expected HTML +++ actual HTML @@ -1 +1 @@ -

foobarbaz

+

foobarbaz

Example 389 (lines 6518-6522) Emphasis and strong emphasis *foo**bar*** --- expected HTML +++ actual HTML @@ -1 +1 @@ -

foobar**

+

foobar

Example 401 (lines 6620-6624) Emphasis and strong emphasis **foo*bar*baz** --- expected HTML +++ actual HTML @@ -1 +1 @@ -

foobarbaz**

+

foobarbaz

Example 442 (lines 6944-6948) Emphasis and strong emphasis **foo*bar** --- expected HTML +++ actual HTML @@ -1 +1 @@ -

foobar*

+

foo*bar

``` --- src/inlines.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/inlines.c b/src/inlines.c index 41c7140..6ed0661 100644 --- a/src/inlines.c +++ b/src/inlines.c @@ -483,6 +483,7 @@ static void process_emphasis(subject *subj, delimiter *stack_bottom) { delimiter *opener; delimiter *old_closer; bool opener_found; + bool odd_match; delimiter *openers_bottom[128]; // initialize openers_bottom: @@ -502,9 +503,18 @@ static void process_emphasis(subject *subj, delimiter *stack_bottom) { // Now look backwards for first matching opener: opener = closer->previous; opener_found = false; + odd_match = false; while (opener != NULL && opener != stack_bottom && opener != openers_bottom[closer->delim_char]) { - if (opener->delim_char == closer->delim_char && opener->can_open) { + // interior closer of size 2 can't match opener of size 1 + // or of size 1 can't match 2 + odd_match = (closer->can_open || opener->can_close) && + opener->inl_text->as.literal.len != + closer->inl_text->as.literal.len && + ((opener->inl_text->as.literal.len + + closer->inl_text->as.literal.len) % 3 == 0); + if (opener->delim_char == closer->delim_char && opener->can_open && + !odd_match) { opener_found = true; break; } @@ -534,8 +544,12 @@ static void process_emphasis(subject *subj, delimiter *stack_bottom) { } closer = closer->next; } - if (!opener_found) { - // set lower bound for future searches for openers: + if (!opener_found && !odd_match) { + // set lower bound for future searches for openers + // (we don't do this with 'odd_match' set because + // a ** that didn't match an earlier * might turn into + // an opener, and the * might be matched by something + // else. openers_bottom[old_closer->delim_char] = old_closer->previous; if (!old_closer->can_open) { // we can remove a closer that can't be an -- cgit v1.2.3