Fossil SCM

Implement `...&#96 verbatim sections for the WIKI_MARKDOWN_SPAN option.

drh 2025-03-04 14:50 comment-markdown-links
Commit c903885574f6598e4e0433926a319de2dc79769be21cd9b81a87bbfbfebfeed1
1 file changed +59 -5
+59 -5
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -436,13 +436,14 @@
436436
#define TOKEN_NUM_LI 7 /* " # " */
437437
#define TOKEN_ENUM 8 /* " \(?\d+[.)]? " */
438438
#define TOKEN_INDENT 9 /* " " */
439439
#define TOKEN_RAW 10 /* Output exactly (used when wiki-use-html==1) */
440440
#define TOKEN_AUTOLINK 11 /* <URL> */
441
-#define TOKEN_MDSPAN 12 /* Markdown span characters: * _ ` */
442
-#define TOKEN_BACKSLASH 13 /* A backslash-escape */
443
-#define TOKEN_TEXT 14 /* None of the above */
441
+#define TOKEN_MDSPAN 12 /* Markdown span characters: * ** _ or __ */
442
+#define TOKEN_MDCODE 13 /* Markdown code characters: ` or `` */
443
+#define TOKEN_BACKSLASH 14 /* A backslash-escape */
444
+#define TOKEN_TEXT 15 /* None of the above */
444445
445446
static const char *wiki_token_names[] = { "",
446447
"MARKUP",
447448
"CHARACTER",
448449
"LINK",
@@ -453,10 +454,11 @@
453454
"ENUM",
454455
"INDENT",
455456
"RAW",
456457
"AUTOLINK",
457458
"MDSPAN",
459
+ "MDCODE",
458460
"BACKSLASH",
459461
"TEXT",
460462
};
461463
462464
/*
@@ -485,10 +487,13 @@
485487
int inAutoParagraph; /* True if within an automatic paragraph */
486488
int pikchrHtmlFlags; /* Flags for pikchr_to_html() */
487489
const char *zVerbatimId; /* The id= attribute of <verbatim> */
488490
int nStack; /* Number of elements on the stack */
489491
int nAlloc; /* Space allocated for aStack */
492
+ char inCode[2]; /* True if in `...` or ``...`` */
493
+ char inEmphS[2]; /* True if in *...* or **...** */
494
+ char inEmphU[2]; /* True if in _..._ or __***__ */
490495
struct sStack {
491496
short iCode; /* Markup code */
492497
short allowWiki; /* ALLOW_WIKI if wiki allowed before tag */
493498
const char *zId; /* ID attribute or NULL */
494499
} *aStack;
@@ -773,14 +778,18 @@
773778
}
774779
if( z[0]=='[' && (n = linkLength(z))>0 ){
775780
*pTokenType = TOKEN_LINK;
776781
return n;
777782
}
778
- if( z[0]=='*' || z[0]=='_' || z[0]=='`' ){
783
+ if( z[0]=='*' || z[0]=='_' ){
779784
*pTokenType = TOKEN_MDSPAN;
780785
return 1 + (z[1]==z[0]);
781786
}
787
+ if( z[0]=='`' ){
788
+ *pTokenType = TOKEN_MDCODE;
789
+ return 1 + (z[1]==z[0]);
790
+ }
782791
if( z[0]=='\\' ){
783792
if( z[1]==0 || fossil_isspace(z[1]) || (z[1]&0x80)!=0 ){
784793
*pTokenType = TOKEN_TEXT;
785794
return 1;
786795
}
@@ -1504,10 +1513,28 @@
15041513
*/
15051514
static int stackTopType(Renderer *p){
15061515
if( p->nStack<=0 ) return 0;
15071516
return aMarkup[p->aStack[p->nStack-1].iCode].iType;
15081517
}
1518
+
1519
+/*
1520
+** z[] is the first character past the start of a `...` literal
1521
+** section of a markdown span. Look ahead in z[] for the ` terminator
1522
+** mark. Return the offset into z[] of the terminator.
1523
+** Or return zero if there is no terminator.
1524
+*/
1525
+static int verbatimLength(Renderer *p, char *z, int sz){
1526
+ int i = 0, n;
1527
+ int tokenType;
1528
+ while( z[i] ){
1529
+ n = nextWikiToken(&z[i], p, &tokenType);
1530
+ if( tokenType==TOKEN_PARAGRAPH ) break;
1531
+ if( tokenType==TOKEN_MDCODE && n>=sz ) return i;
1532
+ i += n;
1533
+ }
1534
+ return 0;
1535
+}
15091536
15101537
/*
15111538
** Convert the wiki in z[] into html in the renderer p. The
15121539
** renderer has already been initialized.
15131540
**
@@ -1709,11 +1736,38 @@
17091736
}else{
17101737
blob_append_char(p->pOut, z[1]);
17111738
}
17121739
break;
17131740
}
1714
- case TOKEN_MDSPAN:
1741
+ case TOKEN_MDCODE: {
1742
+ if( (p->state & WIKI_MARKDOWN_SPAN)==0 ){
1743
+ blob_append(p->pOut, z, n);
1744
+ }else{
1745
+ int x = verbatimLength(p, z+n, n);
1746
+ if( x==0 ){
1747
+ blob_append(p->pOut, z, n);
1748
+ }else{
1749
+ z[x+n] = 0;
1750
+ blob_appendf(p->pOut, "<code>%h</code>", z+n);
1751
+ z[x+n] = '`';
1752
+ n += x + n;
1753
+ }
1754
+ }
1755
+ break;
1756
+ }
1757
+ case TOKEN_MDSPAN: {
1758
+#if 0
1759
+ if( (z[n]==0 || isspace(z[n]))
1760
+ && (z==zOrig || isspace(z[-1])) ){
1761
+ /* markdown emphasis markup surrounded by whitespace is ignored */
1762
+ blob_append(p->pOut, z, n);
1763
+ break;
1764
+ }
1765
+#endif
1766
+ blob_append(p->pOut, z, n);
1767
+ break;
1768
+ }
17151769
case TOKEN_TEXT: {
17161770
int i;
17171771
for(i=0; i<n && fossil_isspace(z[i]); i++){}
17181772
if( i<n ) startAutoParagraph(p);
17191773
blob_append(p->pOut, z, n);
17201774
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -436,13 +436,14 @@
436 #define TOKEN_NUM_LI 7 /* " # " */
437 #define TOKEN_ENUM 8 /* " \(?\d+[.)]? " */
438 #define TOKEN_INDENT 9 /* " " */
439 #define TOKEN_RAW 10 /* Output exactly (used when wiki-use-html==1) */
440 #define TOKEN_AUTOLINK 11 /* <URL> */
441 #define TOKEN_MDSPAN 12 /* Markdown span characters: * _ ` */
442 #define TOKEN_BACKSLASH 13 /* A backslash-escape */
443 #define TOKEN_TEXT 14 /* None of the above */
 
444
445 static const char *wiki_token_names[] = { "",
446 "MARKUP",
447 "CHARACTER",
448 "LINK",
@@ -453,10 +454,11 @@
453 "ENUM",
454 "INDENT",
455 "RAW",
456 "AUTOLINK",
457 "MDSPAN",
 
458 "BACKSLASH",
459 "TEXT",
460 };
461
462 /*
@@ -485,10 +487,13 @@
485 int inAutoParagraph; /* True if within an automatic paragraph */
486 int pikchrHtmlFlags; /* Flags for pikchr_to_html() */
487 const char *zVerbatimId; /* The id= attribute of <verbatim> */
488 int nStack; /* Number of elements on the stack */
489 int nAlloc; /* Space allocated for aStack */
 
 
 
490 struct sStack {
491 short iCode; /* Markup code */
492 short allowWiki; /* ALLOW_WIKI if wiki allowed before tag */
493 const char *zId; /* ID attribute or NULL */
494 } *aStack;
@@ -773,14 +778,18 @@
773 }
774 if( z[0]=='[' && (n = linkLength(z))>0 ){
775 *pTokenType = TOKEN_LINK;
776 return n;
777 }
778 if( z[0]=='*' || z[0]=='_' || z[0]=='`' ){
779 *pTokenType = TOKEN_MDSPAN;
780 return 1 + (z[1]==z[0]);
781 }
 
 
 
 
782 if( z[0]=='\\' ){
783 if( z[1]==0 || fossil_isspace(z[1]) || (z[1]&0x80)!=0 ){
784 *pTokenType = TOKEN_TEXT;
785 return 1;
786 }
@@ -1504,10 +1513,28 @@
1504 */
1505 static int stackTopType(Renderer *p){
1506 if( p->nStack<=0 ) return 0;
1507 return aMarkup[p->aStack[p->nStack-1].iCode].iType;
1508 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1509
1510 /*
1511 ** Convert the wiki in z[] into html in the renderer p. The
1512 ** renderer has already been initialized.
1513 **
@@ -1709,11 +1736,38 @@
1709 }else{
1710 blob_append_char(p->pOut, z[1]);
1711 }
1712 break;
1713 }
1714 case TOKEN_MDSPAN:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1715 case TOKEN_TEXT: {
1716 int i;
1717 for(i=0; i<n && fossil_isspace(z[i]); i++){}
1718 if( i<n ) startAutoParagraph(p);
1719 blob_append(p->pOut, z, n);
1720
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -436,13 +436,14 @@
436 #define TOKEN_NUM_LI 7 /* " # " */
437 #define TOKEN_ENUM 8 /* " \(?\d+[.)]? " */
438 #define TOKEN_INDENT 9 /* " " */
439 #define TOKEN_RAW 10 /* Output exactly (used when wiki-use-html==1) */
440 #define TOKEN_AUTOLINK 11 /* <URL> */
441 #define TOKEN_MDSPAN 12 /* Markdown span characters: * ** _ or __ */
442 #define TOKEN_MDCODE 13 /* Markdown code characters: ` or `` */
443 #define TOKEN_BACKSLASH 14 /* A backslash-escape */
444 #define TOKEN_TEXT 15 /* None of the above */
445
446 static const char *wiki_token_names[] = { "",
447 "MARKUP",
448 "CHARACTER",
449 "LINK",
@@ -453,10 +454,11 @@
454 "ENUM",
455 "INDENT",
456 "RAW",
457 "AUTOLINK",
458 "MDSPAN",
459 "MDCODE",
460 "BACKSLASH",
461 "TEXT",
462 };
463
464 /*
@@ -485,10 +487,13 @@
487 int inAutoParagraph; /* True if within an automatic paragraph */
488 int pikchrHtmlFlags; /* Flags for pikchr_to_html() */
489 const char *zVerbatimId; /* The id= attribute of <verbatim> */
490 int nStack; /* Number of elements on the stack */
491 int nAlloc; /* Space allocated for aStack */
492 char inCode[2]; /* True if in `...` or ``...`` */
493 char inEmphS[2]; /* True if in *...* or **...** */
494 char inEmphU[2]; /* True if in _..._ or __***__ */
495 struct sStack {
496 short iCode; /* Markup code */
497 short allowWiki; /* ALLOW_WIKI if wiki allowed before tag */
498 const char *zId; /* ID attribute or NULL */
499 } *aStack;
@@ -773,14 +778,18 @@
778 }
779 if( z[0]=='[' && (n = linkLength(z))>0 ){
780 *pTokenType = TOKEN_LINK;
781 return n;
782 }
783 if( z[0]=='*' || z[0]=='_' ){
784 *pTokenType = TOKEN_MDSPAN;
785 return 1 + (z[1]==z[0]);
786 }
787 if( z[0]=='`' ){
788 *pTokenType = TOKEN_MDCODE;
789 return 1 + (z[1]==z[0]);
790 }
791 if( z[0]=='\\' ){
792 if( z[1]==0 || fossil_isspace(z[1]) || (z[1]&0x80)!=0 ){
793 *pTokenType = TOKEN_TEXT;
794 return 1;
795 }
@@ -1504,10 +1513,28 @@
1513 */
1514 static int stackTopType(Renderer *p){
1515 if( p->nStack<=0 ) return 0;
1516 return aMarkup[p->aStack[p->nStack-1].iCode].iType;
1517 }
1518
1519 /*
1520 ** z[] is the first character past the start of a `...` literal
1521 ** section of a markdown span. Look ahead in z[] for the ` terminator
1522 ** mark. Return the offset into z[] of the terminator.
1523 ** Or return zero if there is no terminator.
1524 */
1525 static int verbatimLength(Renderer *p, char *z, int sz){
1526 int i = 0, n;
1527 int tokenType;
1528 while( z[i] ){
1529 n = nextWikiToken(&z[i], p, &tokenType);
1530 if( tokenType==TOKEN_PARAGRAPH ) break;
1531 if( tokenType==TOKEN_MDCODE && n>=sz ) return i;
1532 i += n;
1533 }
1534 return 0;
1535 }
1536
1537 /*
1538 ** Convert the wiki in z[] into html in the renderer p. The
1539 ** renderer has already been initialized.
1540 **
@@ -1709,11 +1736,38 @@
1736 }else{
1737 blob_append_char(p->pOut, z[1]);
1738 }
1739 break;
1740 }
1741 case TOKEN_MDCODE: {
1742 if( (p->state & WIKI_MARKDOWN_SPAN)==0 ){
1743 blob_append(p->pOut, z, n);
1744 }else{
1745 int x = verbatimLength(p, z+n, n);
1746 if( x==0 ){
1747 blob_append(p->pOut, z, n);
1748 }else{
1749 z[x+n] = 0;
1750 blob_appendf(p->pOut, "<code>%h</code>", z+n);
1751 z[x+n] = '`';
1752 n += x + n;
1753 }
1754 }
1755 break;
1756 }
1757 case TOKEN_MDSPAN: {
1758 #if 0
1759 if( (z[n]==0 || isspace(z[n]))
1760 && (z==zOrig || isspace(z[-1])) ){
1761 /* markdown emphasis markup surrounded by whitespace is ignored */
1762 blob_append(p->pOut, z, n);
1763 break;
1764 }
1765 #endif
1766 blob_append(p->pOut, z, n);
1767 break;
1768 }
1769 case TOKEN_TEXT: {
1770 int i;
1771 for(i=0; i<n && fossil_isspace(z[i]); i++){}
1772 if( i<n ) startAutoParagraph(p);
1773 blob_append(p->pOut, z, n);
1774

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button