Fossil SCM
In the Markdown formatter, bring emphasis markup into closer alignment with the CommonMark spec. In particular, this should allow underscores in the middle of identifiers to be rendered correctly without escapes.
Commit
37806e85d2601bfbf3f4689a78de9a239873299c54034652742fdfdf67312b54
Parent
7d61b68208ba162…
2 files changed
+48
-17
+55
-25
+48
-17
| --- src/markdown.c | ||
| +++ src/markdown.c | ||
| @@ -555,10 +555,43 @@ | ||
| 555 | 555 | } |
| 556 | 556 | } |
| 557 | 557 | return 0; |
| 558 | 558 | } |
| 559 | 559 | |
| 560 | +/* CommonMark defines separate "right-flanking" and "left-flanking" | |
| 561 | +** deliminators for emphasis. Whether a deliminator is left- or | |
| 562 | +** right-flanking, or both, or neither depends on the characters | |
| 563 | +** immediately before and after. | |
| 564 | +** | |
| 565 | +** before after example left-flanking right-flanking | |
| 566 | +** ------ ----- ------- ------------- -------------- | |
| 567 | +** space space * no no | |
| 568 | +** space punct *) yes no | |
| 569 | +** space alnum *x yes no | |
| 570 | +** punct space (* no yes | |
| 571 | +** punct punct (*) yes yes | |
| 572 | +** punct alnum (*x yes no | |
| 573 | +** alnum space a* no yes | |
| 574 | +** alnum punct a*( no yes | |
| 575 | +** alnum alnum a*x yes yes | |
| 576 | +** | |
| 577 | +** The following routines determine whether a delimitor is left | |
| 578 | +** or right flanking. | |
| 579 | +*/ | |
| 580 | +static int left_flanking(char before, char after){ | |
| 581 | + if( fossil_isspace(after) ) return 0; | |
| 582 | + if( fossil_isalnum(after) ) return 1; | |
| 583 | + if( fossil_isalnum(before) ) return 0; | |
| 584 | + return 1; | |
| 585 | +} | |
| 586 | +static int right_flanking(char before, char after){ | |
| 587 | + if( fossil_isspace(before) ) return 0; | |
| 588 | + if( fossil_isalnum(before) ) return 1; | |
| 589 | + if( fossil_isalnum(after) ) return 0; | |
| 590 | + return 1; | |
| 591 | +} | |
| 592 | + | |
| 560 | 593 | |
| 561 | 594 | /* parse_emph1 -- parsing single emphasis */ |
| 562 | 595 | /* closed by a symbol not preceded by whitespace and not followed by symbol */ |
| 563 | 596 | static size_t parse_emph1( |
| 564 | 597 | struct Blob *ob, |
| @@ -568,10 +601,11 @@ | ||
| 568 | 601 | char c |
| 569 | 602 | ){ |
| 570 | 603 | size_t i = 0, len; |
| 571 | 604 | struct Blob *work = 0; |
| 572 | 605 | int r; |
| 606 | + char after; | |
| 573 | 607 | |
| 574 | 608 | if( !rndr->make.emphasis ) return 0; |
| 575 | 609 | |
| 576 | 610 | /* skipping one symbol if coming from emph3 */ |
| 577 | 611 | if( size>1 && data[0]==c && data[1]==c ) i = 1; |
| @@ -584,14 +618,14 @@ | ||
| 584 | 618 | |
| 585 | 619 | if( i+1<size && data[i+1]==c ){ |
| 586 | 620 | i++; |
| 587 | 621 | continue; |
| 588 | 622 | } |
| 623 | + after = i+1<size ? data[i+1] : ' '; | |
| 589 | 624 | if( data[i]==c |
| 590 | - && data[i-1]!=' ' | |
| 591 | - && data[i-1]!='\t' | |
| 592 | - && data[i-1]!='\n' | |
| 625 | + && right_flanking(data[i-1],after) | |
| 626 | + && (c!='_' || !fossil_isalnum(after)) | |
| 593 | 627 | && !too_deep(rndr) |
| 594 | 628 | ){ |
| 595 | 629 | work = new_work_buffer(rndr); |
| 596 | 630 | parse_inline(work, rndr, data, i); |
| 597 | 631 | r = rndr->make.emphasis(ob, work, c, rndr->make.opaque); |
| @@ -612,24 +646,24 @@ | ||
| 612 | 646 | char c |
| 613 | 647 | ){ |
| 614 | 648 | size_t i = 0, len; |
| 615 | 649 | struct Blob *work = 0; |
| 616 | 650 | int r; |
| 651 | + char after; | |
| 617 | 652 | |
| 618 | 653 | if( !rndr->make.double_emphasis ) return 0; |
| 619 | 654 | |
| 620 | 655 | while( i<size ){ |
| 621 | 656 | len = find_emph_char(data+i, size-i, c); |
| 622 | 657 | if( !len ) return 0; |
| 623 | 658 | i += len; |
| 659 | + after = i+2<size ? data[i+2] : ' '; | |
| 624 | 660 | if( i+1<size |
| 625 | 661 | && data[i]==c |
| 626 | 662 | && data[i+1]==c |
| 627 | - && i | |
| 628 | - && data[i-1]!=' ' | |
| 629 | - && data[i-1]!='\t' | |
| 630 | - && data[i-1]!='\n' | |
| 663 | + && right_flanking(data[i-1],after) | |
| 664 | + && (c!='_' || !fossil_isalnum(after)) | |
| 631 | 665 | && !too_deep(rndr) |
| 632 | 666 | ){ |
| 633 | 667 | work = new_work_buffer(rndr); |
| 634 | 668 | parse_inline(work, rndr, data, i); |
| 635 | 669 | r = rndr->make.double_emphasis(ob, work, c, rndr->make.opaque); |
| @@ -697,39 +731,36 @@ | ||
| 697 | 731 | char *data, |
| 698 | 732 | size_t offset, |
| 699 | 733 | size_t size |
| 700 | 734 | ){ |
| 701 | 735 | char c = data[0]; |
| 736 | + char before = offset>0 ? data[-1] : ' '; | |
| 702 | 737 | size_t ret; |
| 703 | 738 | |
| 704 | 739 | if( size>2 && data[1]!=c ){ |
| 705 | - /* whitespace cannot follow an opening emphasis */ | |
| 706 | - if( data[1]==' ' | |
| 707 | - || data[1]=='\t' | |
| 708 | - || data[1]=='\n' | |
| 740 | + if( !left_flanking(before, data[1]) | |
| 741 | + || (c=='_' && fossil_isalnum(before)) | |
| 709 | 742 | || (ret = parse_emph1(ob, rndr, data+1, size-1, c))==0 |
| 710 | 743 | ){ |
| 711 | 744 | return 0; |
| 712 | 745 | } |
| 713 | 746 | return ret+1; |
| 714 | 747 | } |
| 715 | 748 | |
| 716 | 749 | if( size>3 && data[1]==c && data[2]!=c ){ |
| 717 | - if( data[2]==' ' | |
| 718 | - || data[2]=='\t' | |
| 719 | - || data[2]=='\n' | |
| 750 | + if( !left_flanking(before, data[2]) | |
| 751 | + || (c=='_' && fossil_isalnum(before)) | |
| 720 | 752 | || (ret = parse_emph2(ob, rndr, data+2, size-2, c))==0 |
| 721 | 753 | ){ |
| 722 | 754 | return 0; |
| 723 | 755 | } |
| 724 | 756 | return ret+2; |
| 725 | 757 | } |
| 726 | 758 | |
| 727 | 759 | if( size>4 && data[1]==c && data[2]==c && data[3]!=c ){ |
| 728 | - if( data[3]==' ' | |
| 729 | - || data[3]=='\t' | |
| 730 | - || data[3]=='\n' | |
| 760 | + if( !left_flanking(before, data[3]) | |
| 761 | + || (c=='_' && fossil_isalnum(before)) | |
| 731 | 762 | || (ret = parse_emph3(ob, rndr, data+3, size-3, c))==0 |
| 732 | 763 | ){ |
| 733 | 764 | return 0; |
| 734 | 765 | } |
| 735 | 766 | return ret+3; |
| 736 | 767 |
| --- src/markdown.c | |
| +++ src/markdown.c | |
| @@ -555,10 +555,43 @@ | |
| 555 | } |
| 556 | } |
| 557 | return 0; |
| 558 | } |
| 559 | |
| 560 | |
| 561 | /* parse_emph1 -- parsing single emphasis */ |
| 562 | /* closed by a symbol not preceded by whitespace and not followed by symbol */ |
| 563 | static size_t parse_emph1( |
| 564 | struct Blob *ob, |
| @@ -568,10 +601,11 @@ | |
| 568 | char c |
| 569 | ){ |
| 570 | size_t i = 0, len; |
| 571 | struct Blob *work = 0; |
| 572 | int r; |
| 573 | |
| 574 | if( !rndr->make.emphasis ) return 0; |
| 575 | |
| 576 | /* skipping one symbol if coming from emph3 */ |
| 577 | if( size>1 && data[0]==c && data[1]==c ) i = 1; |
| @@ -584,14 +618,14 @@ | |
| 584 | |
| 585 | if( i+1<size && data[i+1]==c ){ |
| 586 | i++; |
| 587 | continue; |
| 588 | } |
| 589 | if( data[i]==c |
| 590 | && data[i-1]!=' ' |
| 591 | && data[i-1]!='\t' |
| 592 | && data[i-1]!='\n' |
| 593 | && !too_deep(rndr) |
| 594 | ){ |
| 595 | work = new_work_buffer(rndr); |
| 596 | parse_inline(work, rndr, data, i); |
| 597 | r = rndr->make.emphasis(ob, work, c, rndr->make.opaque); |
| @@ -612,24 +646,24 @@ | |
| 612 | char c |
| 613 | ){ |
| 614 | size_t i = 0, len; |
| 615 | struct Blob *work = 0; |
| 616 | int r; |
| 617 | |
| 618 | if( !rndr->make.double_emphasis ) return 0; |
| 619 | |
| 620 | while( i<size ){ |
| 621 | len = find_emph_char(data+i, size-i, c); |
| 622 | if( !len ) return 0; |
| 623 | i += len; |
| 624 | if( i+1<size |
| 625 | && data[i]==c |
| 626 | && data[i+1]==c |
| 627 | && i |
| 628 | && data[i-1]!=' ' |
| 629 | && data[i-1]!='\t' |
| 630 | && data[i-1]!='\n' |
| 631 | && !too_deep(rndr) |
| 632 | ){ |
| 633 | work = new_work_buffer(rndr); |
| 634 | parse_inline(work, rndr, data, i); |
| 635 | r = rndr->make.double_emphasis(ob, work, c, rndr->make.opaque); |
| @@ -697,39 +731,36 @@ | |
| 697 | char *data, |
| 698 | size_t offset, |
| 699 | size_t size |
| 700 | ){ |
| 701 | char c = data[0]; |
| 702 | size_t ret; |
| 703 | |
| 704 | if( size>2 && data[1]!=c ){ |
| 705 | /* whitespace cannot follow an opening emphasis */ |
| 706 | if( data[1]==' ' |
| 707 | || data[1]=='\t' |
| 708 | || data[1]=='\n' |
| 709 | || (ret = parse_emph1(ob, rndr, data+1, size-1, c))==0 |
| 710 | ){ |
| 711 | return 0; |
| 712 | } |
| 713 | return ret+1; |
| 714 | } |
| 715 | |
| 716 | if( size>3 && data[1]==c && data[2]!=c ){ |
| 717 | if( data[2]==' ' |
| 718 | || data[2]=='\t' |
| 719 | || data[2]=='\n' |
| 720 | || (ret = parse_emph2(ob, rndr, data+2, size-2, c))==0 |
| 721 | ){ |
| 722 | return 0; |
| 723 | } |
| 724 | return ret+2; |
| 725 | } |
| 726 | |
| 727 | if( size>4 && data[1]==c && data[2]==c && data[3]!=c ){ |
| 728 | if( data[3]==' ' |
| 729 | || data[3]=='\t' |
| 730 | || data[3]=='\n' |
| 731 | || (ret = parse_emph3(ob, rndr, data+3, size-3, c))==0 |
| 732 | ){ |
| 733 | return 0; |
| 734 | } |
| 735 | return ret+3; |
| 736 |
| --- src/markdown.c | |
| +++ src/markdown.c | |
| @@ -555,10 +555,43 @@ | |
| 555 | } |
| 556 | } |
| 557 | return 0; |
| 558 | } |
| 559 | |
| 560 | /* CommonMark defines separate "right-flanking" and "left-flanking" |
| 561 | ** deliminators for emphasis. Whether a deliminator is left- or |
| 562 | ** right-flanking, or both, or neither depends on the characters |
| 563 | ** immediately before and after. |
| 564 | ** |
| 565 | ** before after example left-flanking right-flanking |
| 566 | ** ------ ----- ------- ------------- -------------- |
| 567 | ** space space * no no |
| 568 | ** space punct *) yes no |
| 569 | ** space alnum *x yes no |
| 570 | ** punct space (* no yes |
| 571 | ** punct punct (*) yes yes |
| 572 | ** punct alnum (*x yes no |
| 573 | ** alnum space a* no yes |
| 574 | ** alnum punct a*( no yes |
| 575 | ** alnum alnum a*x yes yes |
| 576 | ** |
| 577 | ** The following routines determine whether a delimitor is left |
| 578 | ** or right flanking. |
| 579 | */ |
| 580 | static int left_flanking(char before, char after){ |
| 581 | if( fossil_isspace(after) ) return 0; |
| 582 | if( fossil_isalnum(after) ) return 1; |
| 583 | if( fossil_isalnum(before) ) return 0; |
| 584 | return 1; |
| 585 | } |
| 586 | static int right_flanking(char before, char after){ |
| 587 | if( fossil_isspace(before) ) return 0; |
| 588 | if( fossil_isalnum(before) ) return 1; |
| 589 | if( fossil_isalnum(after) ) return 0; |
| 590 | return 1; |
| 591 | } |
| 592 | |
| 593 | |
| 594 | /* parse_emph1 -- parsing single emphasis */ |
| 595 | /* closed by a symbol not preceded by whitespace and not followed by symbol */ |
| 596 | static size_t parse_emph1( |
| 597 | struct Blob *ob, |
| @@ -568,10 +601,11 @@ | |
| 601 | char c |
| 602 | ){ |
| 603 | size_t i = 0, len; |
| 604 | struct Blob *work = 0; |
| 605 | int r; |
| 606 | char after; |
| 607 | |
| 608 | if( !rndr->make.emphasis ) return 0; |
| 609 | |
| 610 | /* skipping one symbol if coming from emph3 */ |
| 611 | if( size>1 && data[0]==c && data[1]==c ) i = 1; |
| @@ -584,14 +618,14 @@ | |
| 618 | |
| 619 | if( i+1<size && data[i+1]==c ){ |
| 620 | i++; |
| 621 | continue; |
| 622 | } |
| 623 | after = i+1<size ? data[i+1] : ' '; |
| 624 | if( data[i]==c |
| 625 | && right_flanking(data[i-1],after) |
| 626 | && (c!='_' || !fossil_isalnum(after)) |
| 627 | && !too_deep(rndr) |
| 628 | ){ |
| 629 | work = new_work_buffer(rndr); |
| 630 | parse_inline(work, rndr, data, i); |
| 631 | r = rndr->make.emphasis(ob, work, c, rndr->make.opaque); |
| @@ -612,24 +646,24 @@ | |
| 646 | char c |
| 647 | ){ |
| 648 | size_t i = 0, len; |
| 649 | struct Blob *work = 0; |
| 650 | int r; |
| 651 | char after; |
| 652 | |
| 653 | if( !rndr->make.double_emphasis ) return 0; |
| 654 | |
| 655 | while( i<size ){ |
| 656 | len = find_emph_char(data+i, size-i, c); |
| 657 | if( !len ) return 0; |
| 658 | i += len; |
| 659 | after = i+2<size ? data[i+2] : ' '; |
| 660 | if( i+1<size |
| 661 | && data[i]==c |
| 662 | && data[i+1]==c |
| 663 | && right_flanking(data[i-1],after) |
| 664 | && (c!='_' || !fossil_isalnum(after)) |
| 665 | && !too_deep(rndr) |
| 666 | ){ |
| 667 | work = new_work_buffer(rndr); |
| 668 | parse_inline(work, rndr, data, i); |
| 669 | r = rndr->make.double_emphasis(ob, work, c, rndr->make.opaque); |
| @@ -697,39 +731,36 @@ | |
| 731 | char *data, |
| 732 | size_t offset, |
| 733 | size_t size |
| 734 | ){ |
| 735 | char c = data[0]; |
| 736 | char before = offset>0 ? data[-1] : ' '; |
| 737 | size_t ret; |
| 738 | |
| 739 | if( size>2 && data[1]!=c ){ |
| 740 | if( !left_flanking(before, data[1]) |
| 741 | || (c=='_' && fossil_isalnum(before)) |
| 742 | || (ret = parse_emph1(ob, rndr, data+1, size-1, c))==0 |
| 743 | ){ |
| 744 | return 0; |
| 745 | } |
| 746 | return ret+1; |
| 747 | } |
| 748 | |
| 749 | if( size>3 && data[1]==c && data[2]!=c ){ |
| 750 | if( !left_flanking(before, data[2]) |
| 751 | || (c=='_' && fossil_isalnum(before)) |
| 752 | || (ret = parse_emph2(ob, rndr, data+2, size-2, c))==0 |
| 753 | ){ |
| 754 | return 0; |
| 755 | } |
| 756 | return ret+2; |
| 757 | } |
| 758 | |
| 759 | if( size>4 && data[1]==c && data[2]==c && data[3]!=c ){ |
| 760 | if( !left_flanking(before, data[3]) |
| 761 | || (c=='_' && fossil_isalnum(before)) |
| 762 | || (ret = parse_emph3(ob, rndr, data+3, size-3, c))==0 |
| 763 | ){ |
| 764 | return 0; |
| 765 | } |
| 766 | return ret+3; |
| 767 |
+55
-25
| --- test/markdown-test2.md | ||
| +++ test/markdown-test2.md | ||
| @@ -20,31 +20,60 @@ | ||
| 20 | 20 | } |
| 21 | 21 | </style> |
| 22 | 22 | |
| 23 | 23 | See <https://spec.commonmark.org/0.29/#emphasis-and-strong-emphasis> |
| 24 | 24 | |
| 25 | -| Id | Source Text | Actual Rendering | Correct Rendering | | |
| ---------------------------------------------------------------------------- | ||
| 26 | -| 1:| `*foo bar*` | *foo bar* | <em>foo bar</em> | | |
| 27 | -| 2:| `a * foo bar*` | a * foo bar* | a * foo bar* | | |
| 28 | -| 3:| `a*"foo"*` | a*"foo"* | a*"foo"* | | |
| 29 | -| 4:| `* a *` | * a * | * a * | | |
| 30 | -| 5:| `foo*bar*` | foo*bar* | foo<em>bar</em> | | |
| 31 | -| 6:| `5*6*78` | 5*6*78 | 5<em>6</em>78 | | |
| 32 | -| 7:| `_foo bar_` | _foo bar_ | <em>foo bar</em> | | |
| 33 | -| 8:| `_ foo bar_` | _ foo bar_ | _ foo bar_ | | |
| 34 | -| 9:| `a_"foo"_` | a_"foo"_ | a_"foo"_ | | |
| 35 | -| 10:| `foo_bar_` | foo_bar_ | foo_bar_ | | |
| 36 | -| 11:| `5_6_78` | 5_6_78 | 5_6_78 | | |
| 37 | -| 12:| `пристаням_стремятся_` | пристаням_стремятся_ | пристаням_стремятся_ | | |
| 38 | -| 13:| `aa_"bb"_cc` | aa_"bb"_cc | aa_"bb"_cc | | |
| 39 | -| 14:| `foo-_(bar)_` | foo-_(bar)_ | foo-<em>(bar)</em> | | |
| 40 | -| 15:| `*(*foo` | *(*foo | *(*foo | | |
| 41 | -| 16:| `*(*foo*)*` | *(*foo*)* | <em>(</em>foo<em>)</em> | | |
| 42 | -| 17:| `*foo*bar` | *foo*bar | <em>foo</em>bar | | |
| 43 | -| 18:| `_foo bar _` | _foo bar _ | _foo bar _ | | |
| 44 | -| 19:| `_(_foo)` | _(_foo) | _(_foo) | | |
| 45 | -| 20:| `_(_foo_)_` | _(_foo_)_ | <em>(</em>foo<em>)</em> | | |
| 46 | -| 21:| `_foo_bar` | _foo_bar | _foo_bar | | |
| 47 | -| 22:| `_пристаням_стремятся` | _пристаням_стремятся | \_пристаням\_стремятся | | |
| 48 | -| 23:| `_foo_bar_baz_` | _foo_bar_baz_ | <em>foo_bar_baz</em> | | |
| 49 | -| 24:| `_(bar)_` | _(bar)_ | <em>(bar)</em> | | |
| 25 | +| Id | Source Text | Actual Rendering | Correct Rendering | | |
| 26 | +----------------------------------------------------------------------------- | |
| 27 | +| 1:| `*foo bar*` | *foo bar* | <em>foo bar</em> | | |
| 28 | +| 2:| `a * foo bar*` | a * foo bar* | a * foo bar* | | |
| 29 | +| 3:| `a*"foo"*` | a*"foo"* | a*"foo"* | | |
| 30 | +| 4:| `* a *` | * a * | * a * | | |
| 31 | +| 5:| `foo*bar*` | foo*bar* | foo<em>bar</em> | | |
| 32 | +| 6:| `5*6*78` | 5*6*78 | 5<em>6</em>78 | | |
| 33 | +| 7:| `_foo bar_` | _foo bar_ | <em>foo bar</em> | | |
| 34 | +| 8:| `_ foo bar_` | _ foo bar_ | _ foo bar_ | | |
| 35 | +| 9:| `a_"foo"_` | a_"foo"_ | a_"foo"_ | | |
| 36 | +| 10:| `foo_bar_` | foo_bar_ | foo_bar_ | | |
| 37 | +| 11:| `5_6_78` | 5_6_78 | 5_6_78 | | |
| 38 | +| 12:| `aa_"bb"_cc` | aa_"bb"_cc | aa_"bb"_cc | | |
| 39 | +| 13:| `foo-_(bar)_` | foo-_(bar)_ | foo-<em>(bar)</em> | | |
| 40 | +| 14:| `*(*foo` | *(*foo | *(*foo | | |
| 41 | +| 15:| `*(*foo*)*` | *(*foo*)* | <em>(<em>foo</em>)</em> | | |
| 42 | +| 16:| `*foo*bar` | *foo*bar | <em>foo</em>bar | | |
| 43 | +| 17:| `_foo bar _` | _foo bar _ | _foo bar _ | | |
| 44 | +| 18:| `_(_foo)` | _(_foo) | _(_foo) | | |
| 45 | +| 19:| `_(_foo_)_` | _(_foo_)_ | <em>(</em>foo<em>)</em> | | |
| 46 | +| 20:| `_foo_bar` | _foo_bar | _foo_bar | | |
| 47 | +| 21:| `_foo_bar_baz_` | _foo_bar_baz_ | <em>foo_bar_baz</em> | | |
| 48 | +| 22:| `foo_bar_baz` | foo_bar_baz | foo_bar_baz | | |
| 49 | +| 23:| `_(bar)_` | _(bar)_ | <em>(bar)</em> | | |
| 50 | + | |
| 51 | + | |
| 52 | +# Strong emphasis | |
| 53 | + | |
| 54 | + | |
| 55 | +| Id | Source Text | Actual Rendering | Correct Rendering | | |
| 56 | +------------------------------------------------------------------------------------------- | |
| 57 | +| 1:| `**foo bar**` | **foo bar** | <strong>foo bar</strong> | | |
| 58 | +| 2:| `a ** foo bar**` | a ** foo bar** | a ** foo bar** | | |
| 59 | +| 3:| `a**"foo"**` | a**"foo"** | a**"foo"** | | |
| 60 | +| 4:| `** a **` | ** a ** | ** a ** | | |
| 61 | +| 5:| `foo**bar**` | foo**bar** | foo<strong>bar</strong> | | |
| 62 | +| 6:| `5**6**78` | 5**6**78 | 5<strong>6</strong>78 | | |
| 63 | +| 7:| `__foo bar__` | __foo bar__ | <strong>foo bar</strong> | | |
| 64 | +| 8:| `__ foo bar__` | __ foo bar__ | __ foo bar__ | | |
| 65 | +| 9:| `a__"foo"__` | a__"foo"__ | a__"foo"__ | | |
| 66 | +| 10:| `foo__bar__` | foo__bar__ | foo__bar__ | | |
| 67 | +| 11:| `5__6__78` | 5__6__78 | 5__6__78 | | |
| 68 | +| 12:| `aa__"bb"__cc` | aa__"bb"__cc | aa__"bb"__cc | | |
| 69 | +| 13:| `foo-__(bar)__` | foo-__(bar)__ | foo-<strong>(bar)</strong> | | |
| 70 | +| 14:| `**(**foo` | **(**foo | **(**foo | | |
| 71 | +| 15:| `**(**foo**)**` | **(**foo**)** | <strong>(<strong>foo</strong>)</strong> | | |
| 72 | +| 16:| `**foo**bar` | **foo**bar | <strong>foo</strong>bar | | |
| 73 | +| 17:| `__foo bar __` | __foo bar __ | __foo bar __ | | |
| 74 | +| 18:| `__(__foo)` | __(__foo) | __(__foo) | | |
| 75 | +| 19:| `__(__foo__)__` | __(__foo__)__ | <strong>(</strong>foo<strong>)</strong> | | |
| 76 | +| 20:| `__foo__bar` | __foo__bar | __foo__bar | | |
| 77 | +| 21:| `__foo__bar__baz__` | __foo__bar__baz__ | <strong>foo__bar__baz</strong> | | |
| 78 | +| 22:| `foo__bar__baz` | foo__bar__baz | foo__bar__baz | | |
| 79 | +| 23:| `__(bar)__` | __(bar)__ | <strong>(bar)</strong> | | |
| 50 | 80 |
| --- test/markdown-test2.md | |
| +++ test/markdown-test2.md | |
| @@ -20,31 +20,60 @@ | |
| 20 | } |
| 21 | </style> |
| 22 | |
| 23 | See <https://spec.commonmark.org/0.29/#emphasis-and-strong-emphasis> |
| 24 | |
| 25 | | Id | Source Text | Actual Rendering | Correct Rendering | |
| ---------------------------------------------------------------------------- | |
| 26 | | 1:| `*foo bar*` | *foo bar* | <em>foo bar</em> | |
| 27 | | 2:| `a * foo bar*` | a * foo bar* | a * foo bar* | |
| 28 | | 3:| `a*"foo"*` | a*"foo"* | a*"foo"* | |
| 29 | | 4:| `* a *` | * a * | * a * | |
| 30 | | 5:| `foo*bar*` | foo*bar* | foo<em>bar</em> | |
| 31 | | 6:| `5*6*78` | 5*6*78 | 5<em>6</em>78 | |
| 32 | | 7:| `_foo bar_` | _foo bar_ | <em>foo bar</em> | |
| 33 | | 8:| `_ foo bar_` | _ foo bar_ | _ foo bar_ | |
| 34 | | 9:| `a_"foo"_` | a_"foo"_ | a_"foo"_ | |
| 35 | | 10:| `foo_bar_` | foo_bar_ | foo_bar_ | |
| 36 | | 11:| `5_6_78` | 5_6_78 | 5_6_78 | |
| 37 | | 12:| `пристаням_стремятся_` | пристаням_стремятся_ | пристаням_стремятся_ | |
| 38 | | 13:| `aa_"bb"_cc` | aa_"bb"_cc | aa_"bb"_cc | |
| 39 | | 14:| `foo-_(bar)_` | foo-_(bar)_ | foo-<em>(bar)</em> | |
| 40 | | 15:| `*(*foo` | *(*foo | *(*foo | |
| 41 | | 16:| `*(*foo*)*` | *(*foo*)* | <em>(</em>foo<em>)</em> | |
| 42 | | 17:| `*foo*bar` | *foo*bar | <em>foo</em>bar | |
| 43 | | 18:| `_foo bar _` | _foo bar _ | _foo bar _ | |
| 44 | | 19:| `_(_foo)` | _(_foo) | _(_foo) | |
| 45 | | 20:| `_(_foo_)_` | _(_foo_)_ | <em>(</em>foo<em>)</em> | |
| 46 | | 21:| `_foo_bar` | _foo_bar | _foo_bar | |
| 47 | | 22:| `_пристаням_стремятся` | _пристаням_стремятся | \_пристаням\_стремятся | |
| 48 | | 23:| `_foo_bar_baz_` | _foo_bar_baz_ | <em>foo_bar_baz</em> | |
| 49 | | 24:| `_(bar)_` | _(bar)_ | <em>(bar)</em> | |
| 50 |
| --- test/markdown-test2.md | |
| +++ test/markdown-test2.md | |
| @@ -20,31 +20,60 @@ | |
| 20 | } |
| 21 | </style> |
| 22 | |
| 23 | See <https://spec.commonmark.org/0.29/#emphasis-and-strong-emphasis> |
| 24 | |
| ---------------------------------------------------------------------------- | |
| 25 | | Id | Source Text | Actual Rendering | Correct Rendering | |
| 26 | ----------------------------------------------------------------------------- |
| 27 | | 1:| `*foo bar*` | *foo bar* | <em>foo bar</em> | |
| 28 | | 2:| `a * foo bar*` | a * foo bar* | a * foo bar* | |
| 29 | | 3:| `a*"foo"*` | a*"foo"* | a*"foo"* | |
| 30 | | 4:| `* a *` | * a * | * a * | |
| 31 | | 5:| `foo*bar*` | foo*bar* | foo<em>bar</em> | |
| 32 | | 6:| `5*6*78` | 5*6*78 | 5<em>6</em>78 | |
| 33 | | 7:| `_foo bar_` | _foo bar_ | <em>foo bar</em> | |
| 34 | | 8:| `_ foo bar_` | _ foo bar_ | _ foo bar_ | |
| 35 | | 9:| `a_"foo"_` | a_"foo"_ | a_"foo"_ | |
| 36 | | 10:| `foo_bar_` | foo_bar_ | foo_bar_ | |
| 37 | | 11:| `5_6_78` | 5_6_78 | 5_6_78 | |
| 38 | | 12:| `aa_"bb"_cc` | aa_"bb"_cc | aa_"bb"_cc | |
| 39 | | 13:| `foo-_(bar)_` | foo-_(bar)_ | foo-<em>(bar)</em> | |
| 40 | | 14:| `*(*foo` | *(*foo | *(*foo | |
| 41 | | 15:| `*(*foo*)*` | *(*foo*)* | <em>(<em>foo</em>)</em> | |
| 42 | | 16:| `*foo*bar` | *foo*bar | <em>foo</em>bar | |
| 43 | | 17:| `_foo bar _` | _foo bar _ | _foo bar _ | |
| 44 | | 18:| `_(_foo)` | _(_foo) | _(_foo) | |
| 45 | | 19:| `_(_foo_)_` | _(_foo_)_ | <em>(</em>foo<em>)</em> | |
| 46 | | 20:| `_foo_bar` | _foo_bar | _foo_bar | |
| 47 | | 21:| `_foo_bar_baz_` | _foo_bar_baz_ | <em>foo_bar_baz</em> | |
| 48 | | 22:| `foo_bar_baz` | foo_bar_baz | foo_bar_baz | |
| 49 | | 23:| `_(bar)_` | _(bar)_ | <em>(bar)</em> | |
| 50 | |
| 51 | |
| 52 | # Strong emphasis |
| 53 | |
| 54 | |
| 55 | | Id | Source Text | Actual Rendering | Correct Rendering | |
| 56 | ------------------------------------------------------------------------------------------- |
| 57 | | 1:| `**foo bar**` | **foo bar** | <strong>foo bar</strong> | |
| 58 | | 2:| `a ** foo bar**` | a ** foo bar** | a ** foo bar** | |
| 59 | | 3:| `a**"foo"**` | a**"foo"** | a**"foo"** | |
| 60 | | 4:| `** a **` | ** a ** | ** a ** | |
| 61 | | 5:| `foo**bar**` | foo**bar** | foo<strong>bar</strong> | |
| 62 | | 6:| `5**6**78` | 5**6**78 | 5<strong>6</strong>78 | |
| 63 | | 7:| `__foo bar__` | __foo bar__ | <strong>foo bar</strong> | |
| 64 | | 8:| `__ foo bar__` | __ foo bar__ | __ foo bar__ | |
| 65 | | 9:| `a__"foo"__` | a__"foo"__ | a__"foo"__ | |
| 66 | | 10:| `foo__bar__` | foo__bar__ | foo__bar__ | |
| 67 | | 11:| `5__6__78` | 5__6__78 | 5__6__78 | |
| 68 | | 12:| `aa__"bb"__cc` | aa__"bb"__cc | aa__"bb"__cc | |
| 69 | | 13:| `foo-__(bar)__` | foo-__(bar)__ | foo-<strong>(bar)</strong> | |
| 70 | | 14:| `**(**foo` | **(**foo | **(**foo | |
| 71 | | 15:| `**(**foo**)**` | **(**foo**)** | <strong>(<strong>foo</strong>)</strong> | |
| 72 | | 16:| `**foo**bar` | **foo**bar | <strong>foo</strong>bar | |
| 73 | | 17:| `__foo bar __` | __foo bar __ | __foo bar __ | |
| 74 | | 18:| `__(__foo)` | __(__foo) | __(__foo) | |
| 75 | | 19:| `__(__foo__)__` | __(__foo__)__ | <strong>(</strong>foo<strong>)</strong> | |
| 76 | | 20:| `__foo__bar` | __foo__bar | __foo__bar | |
| 77 | | 21:| `__foo__bar__baz__` | __foo__bar__baz__ | <strong>foo__bar__baz</strong> | |
| 78 | | 22:| `foo__bar__baz` | foo__bar__baz | foo__bar__baz | |
| 79 | | 23:| `__(bar)__` | __(bar)__ | <strong>(bar)</strong> | |
| 80 |