Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Proof-of-concept code that allows markdown-style hyperlinks to appear in check-in comments. Markdown-style hyperlinks are not allowed in ordinary text/x-fossil-wiki for backwards compatibility. This simply change reduces the need to provide full markdown support for check-in comments. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | comment-markdown-links |
| Files: | files | file ages | folders |
| SHA3-256: |
e7bc33f0801e47ac9be846ed614d9c29 |
| User & Date: | drh 2025-03-04 00:39:34.646 |
Context
|
2025-03-04
| ||
| 11:48 | Change the rendering option to WIKI_MARKDOWN_SPAN with the idea of eventually supporting all kinds of span-markdown, just not block-markdown. Add support for auto-links. check-in: f80b892178 user: drh tags: comment-markdown-links | |
| 00:39 | Proof-of-concept code that allows markdown-style hyperlinks to appear in check-in comments. Markdown-style hyperlinks are not allowed in ordinary text/x-fossil-wiki for backwards compatibility. This simply change reduces the need to provide full markdown support for check-in comments. check-in: e7bc33f080 user: drh tags: comment-markdown-links | |
|
2025-03-03
| ||
| 23:23 | Fix the printf() %W and %!W conversions so that they can both be used during the same Fossil run. check-in: adbb0b9255 user: drh tags: trunk | |
Changes
Changes to src/backlink.c.
| ︙ | ︙ | |||
368 369 370 371 372 373 374 |
}
bklnk.srcid = srcid;
assert( ValidBklnk(srctype) );
assert( ValidMTC(mimetype) );
bklnk.srctype = srctype;
bklnk.mtime = mtime;
if( mimetype==MT_NONE || mimetype==MT_WIKI ){
| > > > > > > | | 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 |
}
bklnk.srcid = srcid;
assert( ValidBklnk(srctype) );
assert( ValidMTC(mimetype) );
bklnk.srctype = srctype;
bklnk.mtime = mtime;
if( mimetype==MT_NONE || mimetype==MT_WIKI ){
int flags;
if( srctype==BKLNK_COMMENT ){
flags = WIKI_INLINE | WIKI_MARKDOWN_LINK;
}else{
flags = 0;
}
wiki_extract_links(zSrc, &bklnk, flags);
}else if( mimetype==MT_MARKDOWN ){
markdown_extract_links(zSrc, &bklnk);
}
}
/*
** COMMAND: test-backlinks
|
| ︙ | ︙ |
Changes to src/markdown_html.c.
| ︙ | ︙ | |||
813 814 815 816 817 818 819 |
char zClose[20];
if( zLink==0 || zLink[0]==0 ){
zClose[0] = 0;
}else{
static const int flags =
WIKI_NOBADLINKS |
| | | 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 |
char zClose[20];
if( zLink==0 || zLink[0]==0 ){
zClose[0] = 0;
}else{
static const int flags =
WIKI_NOBADLINKS |
WIKI_MARKDOWN_URL
;
wiki_resolve_hyperlink(ob, flags, zLink, zClose, sizeof(zClose), 0, zTitle);
}
if( blob_size(content)==0 ){
if( link ) blob_appendb(ob, link);
}else{
blob_appendb(ob, content);
|
| ︙ | ︙ |
Changes to src/printf.c.
| ︙ | ︙ | |||
262 263 264 265 266 267 268 269 270 271 272 273 274 275 |
}
if( db_get_boolean("timeline-plaintext", 0) ){
wikiFlags |= WIKI_LINKSONLY;
}
if( db_get_boolean("timeline-hard-newlines", 0) ){
wikiFlags |= WIKI_NEWLINE;
}
}
if( altForm2 ){
/* block markup (ex: <p>, <table>) allowed */
return wikiFlags & ~WIKI_NOBLOCK;
}else{
/* Do not allow any block format. Everything in a <span> */
return wikiFlags;
| > | 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 |
}
if( db_get_boolean("timeline-plaintext", 0) ){
wikiFlags |= WIKI_LINKSONLY;
}
if( db_get_boolean("timeline-hard-newlines", 0) ){
wikiFlags |= WIKI_NEWLINE;
}
wikiFlags |= WIKI_MARKDOWN_LINK;
}
if( altForm2 ){
/* block markup (ex: <p>, <table>) allowed */
return wikiFlags & ~WIKI_NOBLOCK;
}else{
/* Do not allow any block format. Everything in a <span> */
return wikiFlags;
|
| ︙ | ︙ |
Changes to src/wikiformat.c.
| ︙ | ︙ | |||
28 29 30 31 32 33 34 | #define WIKI_HTMLONLY 0x001 /* HTML markup only. No wiki */ #define WIKI_INLINE 0x002 /* Do not surround with <p>..</p> */ #define WIKI_NOBLOCK 0x004 /* No block markup of any kind */ #define WIKI_BUTTONS 0x008 /* Allow sub-menu buttons */ #define WIKI_NOBADLINKS 0x010 /* Ignore broken hyperlinks */ #define WIKI_LINKSONLY 0x020 /* No markup. Only decorate links */ #define WIKI_NEWLINE 0x040 /* Honor \n - break lines at each \n */ | | > | 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
#define WIKI_HTMLONLY 0x001 /* HTML markup only. No wiki */
#define WIKI_INLINE 0x002 /* Do not surround with <p>..</p> */
#define WIKI_NOBLOCK 0x004 /* No block markup of any kind */
#define WIKI_BUTTONS 0x008 /* Allow sub-menu buttons */
#define WIKI_NOBADLINKS 0x010 /* Ignore broken hyperlinks */
#define WIKI_LINKSONLY 0x020 /* No markup. Only decorate links */
#define WIKI_NEWLINE 0x040 /* Honor \n - break lines at each \n */
#define WIKI_MARKDOWN_URL 0x080 /* Hyperlink targets as in markdown */
#define WIKI_SAFE 0x100 /* Make the result safe for embedding */
#define WIKI_TARGET_BLANK 0x200 /* Hyperlinks go to a new window */
#define WIKI_NOBRACKET 0x400 /* Omit extra [..] around hyperlinks */
#define WIKI_MARKDOWN_LINK 0x800 /* Markdown link syntax: [display](URL) */
#endif
/*
** These are the only markup attributes allowed.
*/
enum allowed_attr_t {
|
| ︙ | ︙ | |||
1341 1342 1343 1344 1345 1346 1347 |
blob_appendf(pOut, "<a href=\"%R/wiki?name=%T\"%s>", z, zExtra);
}
}else if( strlen(zTarget)>=10 && fossil_isdigit(zTarget[0]) && zTarget[4]=='-'
&& db_int(0, "SELECT datetime(%Q) NOT NULL", zTarget) ){
/* Dates or date-and-times in ISO8610 resolve to a link to the
** timeline for that date */
blob_appendf(pOut, "<a href=\"%R/timeline?c=%T\"%s>", zTarget, zExtra);
| | | | | 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 |
blob_appendf(pOut, "<a href=\"%R/wiki?name=%T\"%s>", z, zExtra);
}
}else if( strlen(zTarget)>=10 && fossil_isdigit(zTarget[0]) && zTarget[4]=='-'
&& db_int(0, "SELECT datetime(%Q) NOT NULL", zTarget) ){
/* Dates or date-and-times in ISO8610 resolve to a link to the
** timeline for that date */
blob_appendf(pOut, "<a href=\"%R/timeline?c=%T\"%s>", zTarget, zExtra);
}else if( mFlags & WIKI_MARKDOWN_URL ){
/* If none of the above, and if rendering link references for markdown,
** then create a link to the literal text of the target */
blob_appendf(pOut, "<a href=\"%h\"%s>", zTarget, zExtra);
}else if( zOrig && zTarget>=&zOrig[2]
&& zTarget[-1]=='[' && !fossil_isspace(zTarget[-2]) ){
/* If the hyperlink markup is not preceded by whitespace, then it
** is probably a C-language subscript or similar, not really a
** hyperlink. Just ignore it. */
zTerm = "";
|
| ︙ | ︙ | |||
1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 |
blob_append_string(p->pOut, "&");
}
break;
}
case TOKEN_LINK: {
char *zTarget;
char *zDisplay = 0;
int i, j;
int savedState;
char zClose[20];
char cS1 = 0;
int iS1 = 0;
startAutoParagraph(p);
| > > > > > > > > > > > > > > > > > | | | | | | | | > | 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 |
blob_append_string(p->pOut, "&");
}
break;
}
case TOKEN_LINK: {
char *zTarget;
char *zDisplay = 0;
char *zEnd;
int i, j;
int savedState;
char zClose[20];
char cS1 = 0;
int iS1 = 0;
startAutoParagraph(p);
if( z[n]=='('
&& (p->state & WIKI_MARKDOWN_LINK)!=0
&& (zEnd = strchr(z+n+1,')'))!=0
){
/* Markdown-style hyperlinks: [display-text](URL) or [](URL) */
if( n>2 ){
zDisplay = &z[1];
z[n] = 0;
}else{
zDisplay = 0;
}
zTarget = &z[n+1];
for(i=n+1; z[i] && z[i]!=')' && z[i]!=' '; i++){}
n = (int)(zEnd - z) + 1;
}else{
/* Wiki-style hyperlinks: [URL|display-text] or [URL] */
zTarget = &z[1];
for(i=1; z[i] && z[i]!=']'; i++){
if( z[i]=='|' && zDisplay==0 ){
zDisplay = &z[i+1];
for(j=i; j>0 && fossil_isspace(z[j-1]); j--){}
iS1 = j;
cS1 = z[j];
z[j] = 0;
}
}
}
z[i] = 0;
if( zDisplay==0 ){
zDisplay = zTarget + interwiki_removable_prefix(zTarget);
}else{
while( fossil_isspace(*zDisplay) ) zDisplay++;
|
| ︙ | ︙ | |||
1872 1873 1874 1875 1876 1877 1878 1879 1880 | ** ** Options: ** --buttons Set the WIKI_BUTTONS flag ** --dark-pikchr Render pikchrs in dark mode ** --htmlonly Set the WIKI_HTMLONLY flag ** --inline Set the WIKI_INLINE flag ** --linksonly Set the WIKI_LINKSONLY flag ** --nobadlinks Set the WIKI_NOBADLINKS flag ** --noblock Set the WIKI_NOBLOCK flag | > | > | 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 |
**
** Options:
** --buttons Set the WIKI_BUTTONS flag
** --dark-pikchr Render pikchrs in dark mode
** --htmlonly Set the WIKI_HTMLONLY flag
** --inline Set the WIKI_INLINE flag
** --linksonly Set the WIKI_LINKSONLY flag
** --md-links Allow markdown link syntax
** --nobadlinks Set the WIKI_NOBADLINKS flag
** --noblock Set the WIKI_NOBLOCK flag
** --text Run the output through html_to_plaintext().
*/
void test_wiki_render(void){
Blob in, out;
int flags = 0;
int bText;
if( find_option("buttons",0,0)!=0 ) flags |= WIKI_BUTTONS;
if( find_option("htmlonly",0,0)!=0 ) flags |= WIKI_HTMLONLY;
if( find_option("linksonly",0,0)!=0 ) flags |= WIKI_LINKSONLY;
if( find_option("nobadlinks",0,0)!=0 ) flags |= WIKI_NOBADLINKS;
if( find_option("inline",0,0)!=0 ) flags |= WIKI_INLINE;
if( find_option("noblock",0,0)!=0 ) flags |= WIKI_NOBLOCK;
if( find_option("md-links",0,0)!=0 ) flags |= WIKI_MARKDOWN_LINK;
if( find_option("dark-pikchr",0,0)!=0 ){
pikchr_to_html_add_flags( PIKCHR_PROCESS_DARK_MODE );
}
bText = find_option("text",0,0)!=0;
db_find_and_open_repository(OPEN_OK_NOT_FOUND|OPEN_SUBSTITUTE,0);
verify_all_options();
if( g.argc!=3 ) usage("FILE");
|
| ︙ | ︙ | |||
2039 2040 2041 2042 2043 2044 2045 |
if( wikiHtmlOnly ){
n = nextRawToken(z, &renderer, &tokenType);
}else{
n = nextWikiToken(z, &renderer, &tokenType);
}
switch( tokenType ){
case TOKEN_LINK: {
| | > > > > > > > > > > > | | | > | 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 |
if( wikiHtmlOnly ){
n = nextRawToken(z, &renderer, &tokenType);
}else{
n = nextWikiToken(z, &renderer, &tokenType);
}
switch( tokenType ){
case TOKEN_LINK: {
char *zTarget, *zEnd;
int i;
if( z[n]=='('
&& (flags & WIKI_MARKDOWN_LINK)!=0
&& (zEnd = strchr(z+n+1,')'))!=0
){
/* Markdown-style hyperlinks: [display-text](URL) or [](URL) */
z += n+1;
zTarget = z;
for(i=1; z[i] && z[i]!=')' && z[i]!=' '; i++){}
n = (int)(zEnd - z) + 1;
}else{
/* Wiki-style hyperlinks: [URL|display-text] or [URL] */
zTarget = &z[1];
for(i=0; zTarget[i] && zTarget[i]!='|' && zTarget[i]!=']'; i++){}
while(i>1 && zTarget[i-1]==' '){ i--; }
}
backlink_create(pBklnk, zTarget, i);
break;
}
case TOKEN_MARKUP: {
const char *zId;
int iDiv;
parseMarkup(&markup, z);
|
| ︙ | ︙ |