Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Provide the ability to control markdown styling and markdown hyperlinks for check-in cmments separately and independently. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | comment-markdown-links |
| Files: | files | file ages | folders |
| SHA3-256: |
34f36bc211906c9e45ccfd0b815d6887 |
| User & Date: | drh 2025-03-05 20:16:36.539 |
Context
|
2025-03-05
| ||
| 20:52 | Fix minor issues with markdown rendering in wiki. check-in: 4be82a52a5 user: drh tags: comment-markdown-links | |
| 20:16 | Provide the ability to control markdown styling and markdown hyperlinks for check-in cmments separately and independently. check-in: 34f36bc211 user: drh tags: comment-markdown-links | |
|
2025-03-04
| ||
| 14:50 | Implement `...` verbatim sections for the WIKI_MARKDOWN_SPAN option. check-in: c903885574 user: drh tags: comment-markdown-links | |
Changes
Changes to src/backlink.c.
| ︙ | ︙ | |||
370 371 372 373 374 375 376 |
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 ){
| | | 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 |
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);
}
|
| ︙ | ︙ |
Changes to src/configure.c.
| ︙ | ︙ | |||
104 105 106 107 108 109 110 |
{ "icon-image", CONFIGSET_SKIN },
{ "timeline-block-markup", CONFIGSET_SKIN },
{ "timeline-date-format", CONFIGSET_SKIN },
{ "timeline-default-style", CONFIGSET_SKIN },
{ "timeline-dwelltime", CONFIGSET_SKIN },
{ "timeline-closetime", CONFIGSET_SKIN },
{ "timeline-hard-newlines", CONFIGSET_SKIN },
| | | 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
{ "icon-image", CONFIGSET_SKIN },
{ "timeline-block-markup", CONFIGSET_SKIN },
{ "timeline-date-format", CONFIGSET_SKIN },
{ "timeline-default-style", CONFIGSET_SKIN },
{ "timeline-dwelltime", CONFIGSET_SKIN },
{ "timeline-closetime", CONFIGSET_SKIN },
{ "timeline-hard-newlines", CONFIGSET_SKIN },
{ "timeline-markdown", CONFIGSET_SKIN },
{ "timeline-max-comment", CONFIGSET_SKIN },
{ "timeline-plaintext", CONFIGSET_SKIN },
{ "timeline-truncate-at-blank", CONFIGSET_SKIN },
{ "timeline-tslink-info", CONFIGSET_SKIN },
{ "timeline-utc", CONFIGSET_SKIN },
{ "adunit", CONFIGSET_SKIN },
{ "adunit-omit-if-admin", CONFIGSET_SKIN },
|
| ︙ | ︙ |
Changes to src/printf.c.
| ︙ | ︙ | |||
256 257 258 259 260 261 262 |
static int wikiFlags = 0;
if( wikiFlags==0 ){
if( db_get_boolean("timeline-block-markup", 0) ){
wikiFlags = WIKI_INLINE | WIKI_NOBADLINKS;
}else{
wikiFlags = WIKI_INLINE | WIKI_NOBLOCK | WIKI_NOBADLINKS;
}
| | | > | | | | | 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 |
static int wikiFlags = 0;
if( wikiFlags==0 ){
if( db_get_boolean("timeline-block-markup", 0) ){
wikiFlags = WIKI_INLINE | WIKI_NOBADLINKS;
}else{
wikiFlags = WIKI_INLINE | WIKI_NOBLOCK | WIKI_NOBADLINKS;
}
if( db_get_boolean("timeline-plaintext", 0) ){
wikiFlags |= WIKI_LINKSONLY;
wikiFlags &= ~WIKI_MARKDOWN_INLINE;
}else{
int x = db_get_boolean("timeline-markdown", 0);
if( x & 1 ) wikiFlags |= WIKI_MARKDOWN_LINK;
if( x & 2 ) wikiFlags |= WIKI_MARKDOWN_FONT;
}
if( db_get_boolean("timeline-hard-newlines", 0) ){
wikiFlags |= WIKI_NEWLINE;
}
}
if( altForm2 ){
/* block markup (ex: <p>, <table>) allowed */
|
| ︙ | ︙ |
Changes to src/setup.c.
| ︙ | ︙ | |||
983 984 985 986 987 988 989 990 991 992 993 994 995 996 |
static const char *const azTimeFormats[] = {
"0", "HH:MM",
"1", "HH:MM:SS",
"2", "YYYY-MM-DD HH:MM",
"3", "YYMMDD HH:MM",
"4", "(off)"
};
login_check_credentials();
if( !g.perm.Admin ){
login_needed(0);
return;
}
style_set_current_feature("setup");
| > > > > > > | 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 |
static const char *const azTimeFormats[] = {
"0", "HH:MM",
"1", "HH:MM:SS",
"2", "YYYY-MM-DD HH:MM",
"3", "YYMMDD HH:MM",
"4", "(off)"
};
static const char *const azMarkdown[] = {
"0", "none",
"1", "hyperlinks only",
"2", "styling only",
"3", "links and styling",
};
login_check_credentials();
if( !g.perm.Admin ){
login_needed(0);
return;
}
style_set_current_feature("setup");
|
| ︙ | ︙ | |||
1004 1005 1006 1007 1008 1009 1010 |
onoff_attribute("Allow block-markup in timeline",
"timeline-block-markup", "tbm", 0, 0);
@ <p>In timeline displays, check-in comments can be displayed with or
@ without block markup such as paragraphs, tables, etc.
@ (Property: "timeline-block-markup")</p>
@ <hr>
| | | | | | | | > > > > | | | 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 |
onoff_attribute("Allow block-markup in timeline",
"timeline-block-markup", "tbm", 0, 0);
@ <p>In timeline displays, check-in comments can be displayed with or
@ without block markup such as paragraphs, tables, etc.
@ (Property: "timeline-block-markup")</p>
@ <hr>
multiple_choice_attribute("Allow Markdown in timeline comments",
"timeline-markdown", "tmkdn", "0",
count(azMarkdown)/2, azMarkdown);
@ <p>Allow or disallow a limited amount of Markdown-style format marks
@ for check-in comments displayed in the timeline. Normally check-in
@ comments use only <a href="%R/wiki_rules">Fossil Wiki</a>. This option
@ allows some types of Markdown to be used as well:
@ <ul><li>hyperlinks: <b>(</b><i>display</i><b>)[</b><i>target</i><b>]</b> \
@ and <b><</b><i>URL</i><b>></b>.
@ <li>styling: *<i>emphasis</i>*, **<b>bold</b>**, `<tt>literal</tt>`, \
@ <b>\</b>-escapes</ul>
@ (Property: "timeline-markdown")</p>
@ <hr>
onoff_attribute("Plaintext comments on timelines",
"timeline-plaintext", "tpt", 0, 0);
@ <p>In timeline displays, check-in comments are displayed literally,
@ without any wiki or HTML interpretation. This setting takes priority
@ over the timeline-block-markup and timeline-markdown settings
@ above.
@ (Property: "timeline-plaintext")</p>
@ <hr>
onoff_attribute("Truncate comment at first blank line (Git-style)",
"timeline-truncate-at-blank", "ttb", 0, 0);
@ <p>In timeline displays, check-in comments are displayed only through
|
| ︙ | ︙ |
Changes to src/wikiformat.c.
| ︙ | ︙ | |||
21 22 23 24 25 26 27 | #include <assert.h> #include "wikiformat.h" #if INTERFACE /* ** Allowed wiki transformation operations */ | | | | | | | | < | | | > > > | | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
#include <assert.h>
#include "wikiformat.h"
#if INTERFACE
/*
** Allowed wiki transformation operations
*/
#define WIKI_HTMLONLY 0x0001 /* HTML markup only. No wiki */
#define WIKI_INLINE 0x0002 /* Do not surround with <p>..</p> */
#define WIKI_NOBLOCK 0x0004 /* No block markup of any kind */
#define WIKI_BUTTONS 0x0008 /* Allow sub-menu buttons */
#define WIKI_NOBADLINKS 0x0010 /* Ignore broken hyperlinks */
#define WIKI_LINKSONLY 0x0020 /* No markup. Only decorate links */
#define WIKI_NEWLINE 0x0040 /* Honor \n - break lines at each \n */
#define WIKI_SAFE 0x0080 /* Make the result safe for embedding */
#define WIKI_TARGET_BLANK 0x0100 /* Hyperlinks go to a new window */
#define WIKI_NOBRACKET 0x0200 /* Omit extra [..] around hyperlinks */
#define WIKI_MARKDOWN_URL 0x0400 /* Process link targets as in markdown */
#define WIKI_MARKDOWN_FONT 0x0800 /* Accept markdown font/style markup */
#define WIKI_MARKDOWN_LINK 0x1000 /* Accept markdown hyperlinks */
#define WIKI_MARKDOWN_INLINE 0x1800 /* Combo of _FONT and _LINK */
#endif
/*
** These are the only markup attributes allowed.
*/
enum allowed_attr_t {
|
| ︙ | ︙ | |||
567 568 569 570 571 572 573 | ** ** Interesting characters are: ** ** < ** & ** \n ** [ | | | | | 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 |
**
** Interesting characters are:
**
** <
** &
** \n
** [
** _ * ` \ <-- WIKI_MARKDOWN_FONT only.
**
** The "[" is only considered if flags contain ALLOW_LINKS or ALLOW_WIKI.
** The "\n" is only considered interesting if the flags constains ALLOW_WIKI.
** The markdown span characters, _ * ` and \, are only considered if both
** ALLOW_WIKI and WIKI_MARKDOWN_FONT are set.
*/
static int textLength(const char *z, int flags){
const char *zReject;
if( flags & ALLOW_WIKI ){
if( flags & WIKI_MARKDOWN_FONT ){
zReject = "_*`\\\n[<&";
}else{
zReject = "\n[<&";
}
}else if( flags & ALLOW_LINKS ){
zReject = "[<&";
}else{
|
| ︙ | ︙ | |||
1673 1674 1675 1676 1677 1678 1679 |
int savedState;
char zClose[20];
char cS1 = 0;
int iS1 = 0;
startAutoParagraph(p);
if( z[n]=='('
| | | 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 |
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{
|
| ︙ | ︙ | |||
1725 1726 1727 1728 1729 1730 1731 |
wiki_render(p, zDisplay);
p->state = savedState;
blob_append(p->pOut, zClose, -1);
}
break;
}
case TOKEN_BACKSLASH: {
| | | | 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 |
wiki_render(p, zDisplay);
p->state = savedState;
blob_append(p->pOut, zClose, -1);
}
break;
}
case TOKEN_BACKSLASH: {
if( (p->state & WIKI_MARKDOWN_FONT)==0 ){
/* Ignore backslashes in traditional Wiki */
blob_append_char(p->pOut, '\\');
n = 1;
}else{
blob_append_char(p->pOut, z[1]);
}
break;
}
case TOKEN_MDCODE: {
if( (p->state & WIKI_MARKDOWN_FONT)==0 ){
blob_append(p->pOut, z, n);
}else{
int x = verbatimLength(p, z+n, n);
if( x==0 ){
blob_append(p->pOut, z, n);
}else{
z[x+n] = 0;
|
| ︙ | ︙ | |||
1785 1786 1787 1788 1789 1790 1791 |
/* URL enclosed in <...>
**
** Originally, Fossil-Wiki would just display this as literal
** text, but as of 2025-03-04, it actually inserts an <a>..</a>
** for the hyperlink. The <...> delimiters are retained, however.
** Except in markdown-span mode, the <...> delimiters are omitted.
*/
| | | | 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 |
/* URL enclosed in <...>
**
** Originally, Fossil-Wiki would just display this as literal
** text, but as of 2025-03-04, it actually inserts an <a>..</a>
** for the hyperlink. The <...> delimiters are retained, however.
** Except in markdown-span mode, the <...> delimiters are omitted.
*/
if( (p->state & WIKI_MARKDOWN_LINK)==0 ){
blob_append(p->pOut, "<", 4);
}
z[n-1] = 0;
blob_appendf(p->pOut, "<a href=\"%h\">%h</a>", z+1, z+1);
z[n-1] = '>';
if( (p->state & WIKI_MARKDOWN_LINK)==0 ){
blob_append(p->pOut, ">", 4);
}
break;
}
case TOKEN_MARKUP: {
const char *zId;
int iDiv;
|
| ︙ | ︙ | |||
2069 2070 2071 2072 2073 2074 2075 | ** Usage: %fossil test-wiki-render FILE [OPTIONS] ** ** Translate the input FILE from Fossil-wiki into HTML and write ** the resulting HTML on standard output. ** ** Options: ** --buttons Set the WIKI_BUTTONS flag | | | | | > | > | | | | | > > | 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 |
** Usage: %fossil test-wiki-render FILE [OPTIONS]
**
** Translate the input FILE from Fossil-wiki into HTML and write
** the resulting HTML on standard output.
**
** 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
** --markdown Allow all in-line markdown syntax
** --markdown-link Allow markdown hyperlink syntax
** --markdown-style Allow markdown font and style markup
** --nobadlinks Set the WIKI_NOBADLINKS flag
** --noblock Set the WIKI_NOBLOCK flag
** --text Run the output through html_to_plaintext().
** --tokenize Output a tokenization of the input file
*/
void test_wiki_render(void){
Blob in, out;
int flags = 0;
int bText, bTokenize;
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("markdown",0,0)!=0 ) flags |= WIKI_MARKDOWN_INLINE;
if( find_option("markdown-style",0,0)!=0 ) flags |= WIKI_MARKDOWN_FONT;
if( find_option("markdown-link",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;
bTokenize = find_option("tokenize",0,0)!=0;
db_find_and_open_repository(OPEN_OK_NOT_FOUND|OPEN_SUBSTITUTE,0);
verify_all_options();
|
| ︙ | ︙ | |||
2252 2253 2254 2255 2256 2257 2258 |
}
switch( tokenType ){
case TOKEN_LINK: {
char *zTarget, *zEnd;
int i;
if( z[n]=='('
| | | 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 |
}
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;
|
| ︙ | ︙ |