Fossil SCM

Add the WIKI_LINKSONLY formatting option for the wiki formatter.

drh 2012-11-21 15:11 trunk
Commit 4615bc8faf85010b7f5e0444be1fad713e5fd095
2 files changed +34 +48 -32
+34
--- src/encode.c
+++ src/encode.c
@@ -83,10 +83,44 @@
8383
zIn++;
8484
}
8585
zOut[i] = 0;
8686
return zOut;
8787
}
88
+
89
+/*
90
+** Append HTML-escaped text to a Blob.
91
+*/
92
+void htmlize_to_blob(Blob *p, const char *zIn, int n){
93
+ int c, i, j;
94
+ if( n<0 ) n = strlen(zIn);
95
+ for(i=j=0; i<n; i++){
96
+ c = zIn[i];
97
+ switch( c ){
98
+ case '<':
99
+ if( j<i ) blob_append(p, zIn+j, i-j);
100
+ blob_append(p, "&lt;", 4);
101
+ j = i+1;
102
+ break;
103
+ case '>':
104
+ if( j<i ) blob_append(p, zIn+j, i-j);
105
+ blob_append(p, "&gt;", 4);
106
+ j = i+1;
107
+ break;
108
+ case '&':
109
+ if( j<i ) blob_append(p, zIn+j, i-j);
110
+ blob_append(p, "&amp;", 5);
111
+ j = i+1;
112
+ break;
113
+ case '"':
114
+ if( j<i ) blob_append(p, zIn+j, i-j);
115
+ blob_append(p, "&quot;", 6);
116
+ j = i+1;
117
+ break;
118
+ }
119
+ }
120
+ if( j<i ) blob_append(p, zIn+j, i-j);
121
+}
88122
89123
90124
/*
91125
** Encode a string for HTTP. This means converting lots of
92126
** characters into the "%HH" where H is a hex digit. It also
93127
--- src/encode.c
+++ src/encode.c
@@ -83,10 +83,44 @@
83 zIn++;
84 }
85 zOut[i] = 0;
86 return zOut;
87 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
89
90 /*
91 ** Encode a string for HTTP. This means converting lots of
92 ** characters into the "%HH" where H is a hex digit. It also
93
--- src/encode.c
+++ src/encode.c
@@ -83,10 +83,44 @@
83 zIn++;
84 }
85 zOut[i] = 0;
86 return zOut;
87 }
88
89 /*
90 ** Append HTML-escaped text to a Blob.
91 */
92 void htmlize_to_blob(Blob *p, const char *zIn, int n){
93 int c, i, j;
94 if( n<0 ) n = strlen(zIn);
95 for(i=j=0; i<n; i++){
96 c = zIn[i];
97 switch( c ){
98 case '<':
99 if( j<i ) blob_append(p, zIn+j, i-j);
100 blob_append(p, "&lt;", 4);
101 j = i+1;
102 break;
103 case '>':
104 if( j<i ) blob_append(p, zIn+j, i-j);
105 blob_append(p, "&gt;", 4);
106 j = i+1;
107 break;
108 case '&':
109 if( j<i ) blob_append(p, zIn+j, i-j);
110 blob_append(p, "&amp;", 5);
111 j = i+1;
112 break;
113 case '"':
114 if( j<i ) blob_append(p, zIn+j, i-j);
115 blob_append(p, "&quot;", 6);
116 j = i+1;
117 break;
118 }
119 }
120 if( j<i ) blob_append(p, zIn+j, i-j);
121 }
122
123
124 /*
125 ** Encode a string for HTTP. This means converting lots of
126 ** characters into the "%HH" where H is a hex digit. It also
127
+48 -32
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -23,17 +23,16 @@
2323
2424
#if INTERFACE
2525
/*
2626
** Allowed wiki transformation operations
2727
*/
28
-#define WIKI_NOFOLLOW 0x001
29
-#define WIKI_HTML 0x002
30
-#define WIKI_INLINE 0x004 /* Do not surround with <p>..</p> */
31
-#define WIKI_NOBLOCK 0x008 /* No block markup of any kind */
32
-#define WIKI_BUTTONS 0x010 /* Allow sub-menu buttons */
33
-#define WIKI_NOBADLINKS 0x020 /* Ignore broken hyperlinks */
34
-#define WIKI_DECORATEONLY 0x040 /* No markup. Only decorate links */
28
+#define WIKI_HTMLONLY 0x001 /* HTML markup only. No wiki */
29
+#define WIKI_INLINE 0x002 /* Do not surround with <p>..</p> */
30
+#define WIKI_NOBLOCK 0x004 /* No block markup of any kind */
31
+#define WIKI_BUTTONS 0x008 /* Allow sub-menu buttons */
32
+#define WIKI_NOBADLINKS 0x010 /* Ignore broken hyperlinks */
33
+#define WIKI_LINKSONLY 0x020 /* No markup. Only decorate links */
3534
#endif
3635
3736
3837
/*
3938
** These are the only markup attributes allowed.
@@ -389,11 +388,10 @@
389388
#define AT_PARAGRAPH 0x0020000 /* At start of a paragraph */
390389
#define ALLOW_WIKI 0x0040000 /* Allow wiki markup */
391390
#define FONT_MARKUP_ONLY 0x0080000 /* Only allow MUTYPE_FONT markup */
392391
#define INLINE_MARKUP_ONLY 0x0100000 /* Allow only "inline" markup */
393392
#define IN_LIST 0x0200000 /* Within wiki <ul> or <ol> */
394
-#define WIKI_USE_HTML 0x0400000 /* wiki-use-html option = on */
395393
396394
/*
397395
** Current state of the rendering engine
398396
*/
399397
typedef struct Renderer Renderer;
@@ -985,10 +983,11 @@
985983
/*
986984
** Begin a new paragraph if that something that is needed.
987985
*/
988986
static void startAutoParagraph(Renderer *p){
989987
if( p->wantAutoParagraph==0 ) return;
988
+ if( p->state & WIKI_LINKSONLY ) return;
990989
if( p->wikiList==MARKUP_OL || p->wikiList==MARKUP_UL ) return;
991990
blob_appendf(p->pOut, "<p>", -1);
992991
pushStack(p, MARKUP_P);
993992
p->wantAutoParagraph = 0;
994993
p->inAutoParagraph = 1;
@@ -1147,19 +1146,14 @@
11471146
|| strncmp(zTarget, "https:", 6)==0
11481147
|| strncmp(zTarget, "ftp:", 4)==0
11491148
|| strncmp(zTarget, "mailto:", 7)==0
11501149
){
11511150
blob_appendf(p->pOut, "<a href=\"%s\">", zTarget);
1152
- /* zTerm = "&#x27FE;</a>"; // doesn't work on windows */
11531151
}else if( zTarget[0]=='/' ){
11541152
blob_appendf(p->pOut, "<a href=\"%s%h\">", g.zTop, zTarget);
11551153
}else if( zTarget[0]=='.' || zTarget[0]=='#' ){
1156
- if( 1 ){
1157
- blob_appendf(p->pOut, "<a href=\"%h\">", zTarget);
1158
- }else{
1159
- zTerm = "";
1160
- }
1154
+ blob_appendf(p->pOut, "<a href=\"%h\">", zTarget);
11611155
}else if( is_valid_uuid(zTarget) ){
11621156
int isClosed = 0;
11631157
if( is_ticket(zTarget, &isClosed) ){
11641158
/* Special display processing for tickets. Display the hyperlink
11651159
** as crossed out if the ticket is closed.
@@ -1183,11 +1177,11 @@
11831177
blob_appendf(p->pOut, "[");
11841178
zTerm = "]";
11851179
}
11861180
}
11871181
}else if( !in_this_repo(zTarget) ){
1188
- if( (p->state & (WIKI_DECORATEONLY|WIKI_NOBADLINKS))!=0 ){
1182
+ if( (p->state & (WIKI_LINKSONLY|WIKI_NOBADLINKS))!=0 ){
11891183
zTerm = "";
11901184
}else{
11911185
blob_appendf(p->pOut, "<span class=\"brokenlink\">[", zTarget);
11921186
zTerm = "]</span>";
11931187
}
@@ -1201,11 +1195,11 @@
12011195
}else if( (z = validWikiPageName(p, zTarget))!=0 ){
12021196
blob_appendf(p->pOut, "<a href=\"%R/wiki?name=%T\">", z);
12031197
}else if( zTarget>=&zOrig[2] && !fossil_isspace(zTarget[-2]) ){
12041198
/* Probably an array subscript in code */
12051199
zTerm = "";
1206
- }else if( (p->state & (WIKI_NOBADLINKS|WIKI_DECORATEONLY))!=0 ){
1200
+ }else if( (p->state & (WIKI_NOBADLINKS|WIKI_LINKSONLY))!=0 ){
12071201
zTerm = "";
12081202
}else{
12091203
blob_appendf(p->pOut, "<span class=\"brokenlink\">[%h]", zTarget);
12101204
zTerm = "</span>";
12111205
}
@@ -1245,19 +1239,20 @@
12451239
static void wiki_render(Renderer *p, char *z){
12461240
int tokenType;
12471241
ParsedMarkup markup;
12481242
int n;
12491243
int inlineOnly = (p->state & INLINE_MARKUP_ONLY)!=0;
1250
- int wikiUseHtml = (p->state & WIKI_USE_HTML)!=0;
1244
+ int wikiHtmlOnly = (p->state & (WIKI_HTMLONLY | WIKI_LINKSONLY))!=0;
1245
+ int linksOnly = (p->state & WIKI_LINKSONLY)!=0;
12511246
char *zOrig = z;
12521247
12531248
/* Make sure the attribute constants and names still align
12541249
** following changes in the attribute list. */
12551250
assert( fossil_strcmp(aAttribute[ATTR_WIDTH].zName, "width")==0 );
12561251
12571252
while( z[0] ){
1258
- if( wikiUseHtml ){
1253
+ if( wikiHtmlOnly ){
12591254
n = nextRawToken(z, p, &tokenType);
12601255
}else{
12611256
n = nextWikiToken(z, p, &tokenType);
12621257
}
12631258
p->state &= ~(AT_NEWLINE|AT_PARAGRAPH);
@@ -1374,33 +1369,37 @@
13741369
startAutoParagraph(p);
13751370
zTarget = &z[1];
13761371
for(i=1; z[i] && z[i]!=']'; i++){
13771372
if( z[i]=='|' && zDisplay==0 ){
13781373
zDisplay = &z[i+1];
1379
- iS1 = i;
1380
- cS1 = z[i];
1381
- z[i] = 0;
1382
- for(j=i-1; j>0 && fossil_isspace(z[j]); j--){ z[j] = 0; }
1374
+ for(j=i; j>0 && fossil_isspace(z[j-1]); j--){}
1375
+ iS1 = j;
1376
+ cS1 = z[j];
1377
+ z[j] = 0;
13831378
}
13841379
}
13851380
z[i] = 0;
13861381
if( zDisplay==0 ){
13871382
zDisplay = zTarget;
13881383
}else{
13891384
while( fossil_isspace(*zDisplay) ) zDisplay++;
13901385
}
13911386
openHyperlink(p, zTarget, zClose, sizeof(zClose), zOrig);
1392
- if( zClose[0] ){
1387
+ if( linksOnly || zClose[0]==0 ){
1388
+ if( cS1 ) z[iS1] = cS1;
1389
+ if( zClose[0]!=']' ){
1390
+ blob_appendf(p->pOut, "[%h]%s", zTarget, zClose);
1391
+ }else{
1392
+ blob_appendf(p->pOut, "%h%s", zTarget, zClose);
1393
+ }
1394
+ }else{
13931395
savedState = p->state;
13941396
p->state &= ~ALLOW_WIKI;
13951397
p->state |= FONT_MARKUP_ONLY;
13961398
wiki_render(p, zDisplay);
13971399
p->state = savedState;
13981400
blob_append(p->pOut, zClose, -1);
1399
- }else{
1400
- if( cS1 ) z[iS1] = cS1;
1401
- blob_appendf(p->pOut, "[%h]", zTarget);
14021401
}
14031402
break;
14041403
}
14051404
case TOKEN_TEXT: {
14061405
int i;
@@ -1408,11 +1407,15 @@
14081407
if( i<n ) startAutoParagraph(p);
14091408
blob_append(p->pOut, z, n);
14101409
break;
14111410
}
14121411
case TOKEN_RAW: {
1413
- blob_append(p->pOut, z, n);
1412
+ if( linksOnly ){
1413
+ htmlize_to_blob(p->pOut, z, n);
1414
+ }else{
1415
+ blob_append(p->pOut, z, n);
1416
+ }
14141417
break;
14151418
}
14161419
case TOKEN_MARKUP: {
14171420
const char *zId;
14181421
int iDiv;
@@ -1606,24 +1609,26 @@
16061609
renderer.wantAutoParagraph = 0;
16071610
}else{
16081611
renderer.wantAutoParagraph = 1;
16091612
}
16101613
if( wikiUsesHtml() ){
1611
- renderer.state |= WIKI_USE_HTML;
1614
+ renderer.state |= WIKI_HTMLONLY;
16121615
}
16131616
if( pOut ){
16141617
renderer.pOut = pOut;
16151618
}else{
16161619
renderer.pOut = cgi_output_blob();
16171620
}
16181621
16191622
blob_strip_bom(pIn, 0);
1623
+ if( flags & WIKI_LINKSONLY ) blob_append(renderer.pOut, "<pre>", 5);
16201624
wiki_render(&renderer, blob_str(pIn));
16211625
endAutoParagraph(&renderer);
16221626
while( renderer.nStack ){
16231627
popStack(&renderer);
16241628
}
1629
+ if( flags & WIKI_LINKSONLY ) blob_append(renderer.pOut, "</pre>", 5);
16251630
blob_append(renderer.pOut, "\n", 1);
16261631
free(renderer.aStack);
16271632
}
16281633
16291634
/*
@@ -1631,15 +1636,26 @@
16311636
**
16321637
** %fossil test-wiki-render FILE [OPTIONS]
16331638
**
16341639
** Options:
16351640
** --buttons Set the WIKI_BUTTONS flag
1641
+** --htmlonly Set the WIKI_HTMLONLY flag
1642
+** --linksonly Set the WIKI_LINKSONLY flag
1643
+** --nobadlinks Set the WIKI_NOBADLINKS flag
1644
+** --inline Set the WIKI_INLINE flag
1645
+** --noblock Set the WIKI_NOBLOCK flag
16361646
*/
16371647
void test_wiki_render(void){
16381648
Blob in, out;
16391649
int flags = 0;
16401650
if( find_option("buttons",0,0)!=0 ) flags |= WIKI_BUTTONS;
1651
+ if( find_option("htmlonly",0,0)!=0 ) flags |= WIKI_HTMLONLY;
1652
+ if( find_option("linksonly",0,0)!=0 ) flags |= WIKI_LINKSONLY;
1653
+ if( find_option("nobadlinks",0,0)!=0 ) flags |= WIKI_NOBADLINKS;
1654
+ if( find_option("inline",0,0)!=0 ) flags |= WIKI_INLINE;
1655
+ if( find_option("noblock",0,0)!=0 ) flags |= WIKI_NOBLOCK;
1656
+ db_find_and_open_repository(0,0);
16411657
verify_all_options();
16421658
if( g.argc!=3 ) usage("FILE");
16431659
blob_zero(&out);
16441660
blob_read_from_file(&in, g.argv[2]);
16451661
wiki_convert(&in, &out, flags);
@@ -1694,29 +1710,29 @@
16941710
Renderer renderer;
16951711
int tokenType;
16961712
ParsedMarkup markup;
16971713
int n;
16981714
int inlineOnly;
1699
- int wikiUseHtml = 0;
1715
+ int wikiHtmlOnly = 0;
17001716
17011717
memset(&renderer, 0, sizeof(renderer));
17021718
renderer.state = ALLOW_WIKI|AT_NEWLINE|AT_PARAGRAPH;
17031719
if( flags & WIKI_NOBLOCK ){
17041720
renderer.state |= INLINE_MARKUP_ONLY;
17051721
}
17061722
if( wikiUsesHtml() ){
1707
- renderer.state |= WIKI_USE_HTML;
1708
- wikiUseHtml = 1;
1723
+ renderer.state |= WIKI_HTMLONLY;
1724
+ wikiHtmlOnly = 1;
17091725
}
17101726
inlineOnly = (renderer.state & INLINE_MARKUP_ONLY)!=0;
17111727
if( replaceFlag ){
17121728
db_multi_exec("DELETE FROM backlink WHERE srctype=%d AND srcid=%d",
17131729
srctype, srcid);
17141730
}
17151731
17161732
while( z[0] ){
1717
- if( wikiUseHtml ){
1733
+ if( wikiHtmlOnly ){
17181734
n = nextRawToken(z, &renderer, &tokenType);
17191735
}else{
17201736
n = nextWikiToken(z, &renderer, &tokenType);
17211737
}
17221738
switch( tokenType ){
17231739
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -23,17 +23,16 @@
23
24 #if INTERFACE
25 /*
26 ** Allowed wiki transformation operations
27 */
28 #define WIKI_NOFOLLOW 0x001
29 #define WIKI_HTML 0x002
30 #define WIKI_INLINE 0x004 /* Do not surround with <p>..</p> */
31 #define WIKI_NOBLOCK 0x008 /* No block markup of any kind */
32 #define WIKI_BUTTONS 0x010 /* Allow sub-menu buttons */
33 #define WIKI_NOBADLINKS 0x020 /* Ignore broken hyperlinks */
34 #define WIKI_DECORATEONLY 0x040 /* No markup. Only decorate links */
35 #endif
36
37
38 /*
39 ** These are the only markup attributes allowed.
@@ -389,11 +388,10 @@
389 #define AT_PARAGRAPH 0x0020000 /* At start of a paragraph */
390 #define ALLOW_WIKI 0x0040000 /* Allow wiki markup */
391 #define FONT_MARKUP_ONLY 0x0080000 /* Only allow MUTYPE_FONT markup */
392 #define INLINE_MARKUP_ONLY 0x0100000 /* Allow only "inline" markup */
393 #define IN_LIST 0x0200000 /* Within wiki <ul> or <ol> */
394 #define WIKI_USE_HTML 0x0400000 /* wiki-use-html option = on */
395
396 /*
397 ** Current state of the rendering engine
398 */
399 typedef struct Renderer Renderer;
@@ -985,10 +983,11 @@
985 /*
986 ** Begin a new paragraph if that something that is needed.
987 */
988 static void startAutoParagraph(Renderer *p){
989 if( p->wantAutoParagraph==0 ) return;
 
990 if( p->wikiList==MARKUP_OL || p->wikiList==MARKUP_UL ) return;
991 blob_appendf(p->pOut, "<p>", -1);
992 pushStack(p, MARKUP_P);
993 p->wantAutoParagraph = 0;
994 p->inAutoParagraph = 1;
@@ -1147,19 +1146,14 @@
1147 || strncmp(zTarget, "https:", 6)==0
1148 || strncmp(zTarget, "ftp:", 4)==0
1149 || strncmp(zTarget, "mailto:", 7)==0
1150 ){
1151 blob_appendf(p->pOut, "<a href=\"%s\">", zTarget);
1152 /* zTerm = "&#x27FE;</a>"; // doesn't work on windows */
1153 }else if( zTarget[0]=='/' ){
1154 blob_appendf(p->pOut, "<a href=\"%s%h\">", g.zTop, zTarget);
1155 }else if( zTarget[0]=='.' || zTarget[0]=='#' ){
1156 if( 1 ){
1157 blob_appendf(p->pOut, "<a href=\"%h\">", zTarget);
1158 }else{
1159 zTerm = "";
1160 }
1161 }else if( is_valid_uuid(zTarget) ){
1162 int isClosed = 0;
1163 if( is_ticket(zTarget, &isClosed) ){
1164 /* Special display processing for tickets. Display the hyperlink
1165 ** as crossed out if the ticket is closed.
@@ -1183,11 +1177,11 @@
1183 blob_appendf(p->pOut, "[");
1184 zTerm = "]";
1185 }
1186 }
1187 }else if( !in_this_repo(zTarget) ){
1188 if( (p->state & (WIKI_DECORATEONLY|WIKI_NOBADLINKS))!=0 ){
1189 zTerm = "";
1190 }else{
1191 blob_appendf(p->pOut, "<span class=\"brokenlink\">[", zTarget);
1192 zTerm = "]</span>";
1193 }
@@ -1201,11 +1195,11 @@
1201 }else if( (z = validWikiPageName(p, zTarget))!=0 ){
1202 blob_appendf(p->pOut, "<a href=\"%R/wiki?name=%T\">", z);
1203 }else if( zTarget>=&zOrig[2] && !fossil_isspace(zTarget[-2]) ){
1204 /* Probably an array subscript in code */
1205 zTerm = "";
1206 }else if( (p->state & (WIKI_NOBADLINKS|WIKI_DECORATEONLY))!=0 ){
1207 zTerm = "";
1208 }else{
1209 blob_appendf(p->pOut, "<span class=\"brokenlink\">[%h]", zTarget);
1210 zTerm = "</span>";
1211 }
@@ -1245,19 +1239,20 @@
1245 static void wiki_render(Renderer *p, char *z){
1246 int tokenType;
1247 ParsedMarkup markup;
1248 int n;
1249 int inlineOnly = (p->state & INLINE_MARKUP_ONLY)!=0;
1250 int wikiUseHtml = (p->state & WIKI_USE_HTML)!=0;
 
1251 char *zOrig = z;
1252
1253 /* Make sure the attribute constants and names still align
1254 ** following changes in the attribute list. */
1255 assert( fossil_strcmp(aAttribute[ATTR_WIDTH].zName, "width")==0 );
1256
1257 while( z[0] ){
1258 if( wikiUseHtml ){
1259 n = nextRawToken(z, p, &tokenType);
1260 }else{
1261 n = nextWikiToken(z, p, &tokenType);
1262 }
1263 p->state &= ~(AT_NEWLINE|AT_PARAGRAPH);
@@ -1374,33 +1369,37 @@
1374 startAutoParagraph(p);
1375 zTarget = &z[1];
1376 for(i=1; z[i] && z[i]!=']'; i++){
1377 if( z[i]=='|' && zDisplay==0 ){
1378 zDisplay = &z[i+1];
1379 iS1 = i;
1380 cS1 = z[i];
1381 z[i] = 0;
1382 for(j=i-1; j>0 && fossil_isspace(z[j]); j--){ z[j] = 0; }
1383 }
1384 }
1385 z[i] = 0;
1386 if( zDisplay==0 ){
1387 zDisplay = zTarget;
1388 }else{
1389 while( fossil_isspace(*zDisplay) ) zDisplay++;
1390 }
1391 openHyperlink(p, zTarget, zClose, sizeof(zClose), zOrig);
1392 if( zClose[0] ){
 
 
 
 
 
 
 
1393 savedState = p->state;
1394 p->state &= ~ALLOW_WIKI;
1395 p->state |= FONT_MARKUP_ONLY;
1396 wiki_render(p, zDisplay);
1397 p->state = savedState;
1398 blob_append(p->pOut, zClose, -1);
1399 }else{
1400 if( cS1 ) z[iS1] = cS1;
1401 blob_appendf(p->pOut, "[%h]", zTarget);
1402 }
1403 break;
1404 }
1405 case TOKEN_TEXT: {
1406 int i;
@@ -1408,11 +1407,15 @@
1408 if( i<n ) startAutoParagraph(p);
1409 blob_append(p->pOut, z, n);
1410 break;
1411 }
1412 case TOKEN_RAW: {
1413 blob_append(p->pOut, z, n);
 
 
 
 
1414 break;
1415 }
1416 case TOKEN_MARKUP: {
1417 const char *zId;
1418 int iDiv;
@@ -1606,24 +1609,26 @@
1606 renderer.wantAutoParagraph = 0;
1607 }else{
1608 renderer.wantAutoParagraph = 1;
1609 }
1610 if( wikiUsesHtml() ){
1611 renderer.state |= WIKI_USE_HTML;
1612 }
1613 if( pOut ){
1614 renderer.pOut = pOut;
1615 }else{
1616 renderer.pOut = cgi_output_blob();
1617 }
1618
1619 blob_strip_bom(pIn, 0);
 
1620 wiki_render(&renderer, blob_str(pIn));
1621 endAutoParagraph(&renderer);
1622 while( renderer.nStack ){
1623 popStack(&renderer);
1624 }
 
1625 blob_append(renderer.pOut, "\n", 1);
1626 free(renderer.aStack);
1627 }
1628
1629 /*
@@ -1631,15 +1636,26 @@
1631 **
1632 ** %fossil test-wiki-render FILE [OPTIONS]
1633 **
1634 ** Options:
1635 ** --buttons Set the WIKI_BUTTONS flag
 
 
 
 
 
1636 */
1637 void test_wiki_render(void){
1638 Blob in, out;
1639 int flags = 0;
1640 if( find_option("buttons",0,0)!=0 ) flags |= WIKI_BUTTONS;
 
 
 
 
 
 
1641 verify_all_options();
1642 if( g.argc!=3 ) usage("FILE");
1643 blob_zero(&out);
1644 blob_read_from_file(&in, g.argv[2]);
1645 wiki_convert(&in, &out, flags);
@@ -1694,29 +1710,29 @@
1694 Renderer renderer;
1695 int tokenType;
1696 ParsedMarkup markup;
1697 int n;
1698 int inlineOnly;
1699 int wikiUseHtml = 0;
1700
1701 memset(&renderer, 0, sizeof(renderer));
1702 renderer.state = ALLOW_WIKI|AT_NEWLINE|AT_PARAGRAPH;
1703 if( flags & WIKI_NOBLOCK ){
1704 renderer.state |= INLINE_MARKUP_ONLY;
1705 }
1706 if( wikiUsesHtml() ){
1707 renderer.state |= WIKI_USE_HTML;
1708 wikiUseHtml = 1;
1709 }
1710 inlineOnly = (renderer.state & INLINE_MARKUP_ONLY)!=0;
1711 if( replaceFlag ){
1712 db_multi_exec("DELETE FROM backlink WHERE srctype=%d AND srcid=%d",
1713 srctype, srcid);
1714 }
1715
1716 while( z[0] ){
1717 if( wikiUseHtml ){
1718 n = nextRawToken(z, &renderer, &tokenType);
1719 }else{
1720 n = nextWikiToken(z, &renderer, &tokenType);
1721 }
1722 switch( tokenType ){
1723
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -23,17 +23,16 @@
23
24 #if INTERFACE
25 /*
26 ** Allowed wiki transformation operations
27 */
28 #define WIKI_HTMLONLY 0x001 /* HTML markup only. No wiki */
29 #define WIKI_INLINE 0x002 /* Do not surround with <p>..</p> */
30 #define WIKI_NOBLOCK 0x004 /* No block markup of any kind */
31 #define WIKI_BUTTONS 0x008 /* Allow sub-menu buttons */
32 #define WIKI_NOBADLINKS 0x010 /* Ignore broken hyperlinks */
33 #define WIKI_LINKSONLY 0x020 /* No markup. Only decorate links */
 
34 #endif
35
36
37 /*
38 ** These are the only markup attributes allowed.
@@ -389,11 +388,10 @@
388 #define AT_PARAGRAPH 0x0020000 /* At start of a paragraph */
389 #define ALLOW_WIKI 0x0040000 /* Allow wiki markup */
390 #define FONT_MARKUP_ONLY 0x0080000 /* Only allow MUTYPE_FONT markup */
391 #define INLINE_MARKUP_ONLY 0x0100000 /* Allow only "inline" markup */
392 #define IN_LIST 0x0200000 /* Within wiki <ul> or <ol> */
 
393
394 /*
395 ** Current state of the rendering engine
396 */
397 typedef struct Renderer Renderer;
@@ -985,10 +983,11 @@
983 /*
984 ** Begin a new paragraph if that something that is needed.
985 */
986 static void startAutoParagraph(Renderer *p){
987 if( p->wantAutoParagraph==0 ) return;
988 if( p->state & WIKI_LINKSONLY ) return;
989 if( p->wikiList==MARKUP_OL || p->wikiList==MARKUP_UL ) return;
990 blob_appendf(p->pOut, "<p>", -1);
991 pushStack(p, MARKUP_P);
992 p->wantAutoParagraph = 0;
993 p->inAutoParagraph = 1;
@@ -1147,19 +1146,14 @@
1146 || strncmp(zTarget, "https:", 6)==0
1147 || strncmp(zTarget, "ftp:", 4)==0
1148 || strncmp(zTarget, "mailto:", 7)==0
1149 ){
1150 blob_appendf(p->pOut, "<a href=\"%s\">", zTarget);
 
1151 }else if( zTarget[0]=='/' ){
1152 blob_appendf(p->pOut, "<a href=\"%s%h\">", g.zTop, zTarget);
1153 }else if( zTarget[0]=='.' || zTarget[0]=='#' ){
1154 blob_appendf(p->pOut, "<a href=\"%h\">", zTarget);
 
 
 
 
1155 }else if( is_valid_uuid(zTarget) ){
1156 int isClosed = 0;
1157 if( is_ticket(zTarget, &isClosed) ){
1158 /* Special display processing for tickets. Display the hyperlink
1159 ** as crossed out if the ticket is closed.
@@ -1183,11 +1177,11 @@
1177 blob_appendf(p->pOut, "[");
1178 zTerm = "]";
1179 }
1180 }
1181 }else if( !in_this_repo(zTarget) ){
1182 if( (p->state & (WIKI_LINKSONLY|WIKI_NOBADLINKS))!=0 ){
1183 zTerm = "";
1184 }else{
1185 blob_appendf(p->pOut, "<span class=\"brokenlink\">[", zTarget);
1186 zTerm = "]</span>";
1187 }
@@ -1201,11 +1195,11 @@
1195 }else if( (z = validWikiPageName(p, zTarget))!=0 ){
1196 blob_appendf(p->pOut, "<a href=\"%R/wiki?name=%T\">", z);
1197 }else if( zTarget>=&zOrig[2] && !fossil_isspace(zTarget[-2]) ){
1198 /* Probably an array subscript in code */
1199 zTerm = "";
1200 }else if( (p->state & (WIKI_NOBADLINKS|WIKI_LINKSONLY))!=0 ){
1201 zTerm = "";
1202 }else{
1203 blob_appendf(p->pOut, "<span class=\"brokenlink\">[%h]", zTarget);
1204 zTerm = "</span>";
1205 }
@@ -1245,19 +1239,20 @@
1239 static void wiki_render(Renderer *p, char *z){
1240 int tokenType;
1241 ParsedMarkup markup;
1242 int n;
1243 int inlineOnly = (p->state & INLINE_MARKUP_ONLY)!=0;
1244 int wikiHtmlOnly = (p->state & (WIKI_HTMLONLY | WIKI_LINKSONLY))!=0;
1245 int linksOnly = (p->state & WIKI_LINKSONLY)!=0;
1246 char *zOrig = z;
1247
1248 /* Make sure the attribute constants and names still align
1249 ** following changes in the attribute list. */
1250 assert( fossil_strcmp(aAttribute[ATTR_WIDTH].zName, "width")==0 );
1251
1252 while( z[0] ){
1253 if( wikiHtmlOnly ){
1254 n = nextRawToken(z, p, &tokenType);
1255 }else{
1256 n = nextWikiToken(z, p, &tokenType);
1257 }
1258 p->state &= ~(AT_NEWLINE|AT_PARAGRAPH);
@@ -1374,33 +1369,37 @@
1369 startAutoParagraph(p);
1370 zTarget = &z[1];
1371 for(i=1; z[i] && z[i]!=']'; i++){
1372 if( z[i]=='|' && zDisplay==0 ){
1373 zDisplay = &z[i+1];
1374 for(j=i; j>0 && fossil_isspace(z[j-1]); j--){}
1375 iS1 = j;
1376 cS1 = z[j];
1377 z[j] = 0;
1378 }
1379 }
1380 z[i] = 0;
1381 if( zDisplay==0 ){
1382 zDisplay = zTarget;
1383 }else{
1384 while( fossil_isspace(*zDisplay) ) zDisplay++;
1385 }
1386 openHyperlink(p, zTarget, zClose, sizeof(zClose), zOrig);
1387 if( linksOnly || zClose[0]==0 ){
1388 if( cS1 ) z[iS1] = cS1;
1389 if( zClose[0]!=']' ){
1390 blob_appendf(p->pOut, "[%h]%s", zTarget, zClose);
1391 }else{
1392 blob_appendf(p->pOut, "%h%s", zTarget, zClose);
1393 }
1394 }else{
1395 savedState = p->state;
1396 p->state &= ~ALLOW_WIKI;
1397 p->state |= FONT_MARKUP_ONLY;
1398 wiki_render(p, zDisplay);
1399 p->state = savedState;
1400 blob_append(p->pOut, zClose, -1);
 
 
 
1401 }
1402 break;
1403 }
1404 case TOKEN_TEXT: {
1405 int i;
@@ -1408,11 +1407,15 @@
1407 if( i<n ) startAutoParagraph(p);
1408 blob_append(p->pOut, z, n);
1409 break;
1410 }
1411 case TOKEN_RAW: {
1412 if( linksOnly ){
1413 htmlize_to_blob(p->pOut, z, n);
1414 }else{
1415 blob_append(p->pOut, z, n);
1416 }
1417 break;
1418 }
1419 case TOKEN_MARKUP: {
1420 const char *zId;
1421 int iDiv;
@@ -1606,24 +1609,26 @@
1609 renderer.wantAutoParagraph = 0;
1610 }else{
1611 renderer.wantAutoParagraph = 1;
1612 }
1613 if( wikiUsesHtml() ){
1614 renderer.state |= WIKI_HTMLONLY;
1615 }
1616 if( pOut ){
1617 renderer.pOut = pOut;
1618 }else{
1619 renderer.pOut = cgi_output_blob();
1620 }
1621
1622 blob_strip_bom(pIn, 0);
1623 if( flags & WIKI_LINKSONLY ) blob_append(renderer.pOut, "<pre>", 5);
1624 wiki_render(&renderer, blob_str(pIn));
1625 endAutoParagraph(&renderer);
1626 while( renderer.nStack ){
1627 popStack(&renderer);
1628 }
1629 if( flags & WIKI_LINKSONLY ) blob_append(renderer.pOut, "</pre>", 5);
1630 blob_append(renderer.pOut, "\n", 1);
1631 free(renderer.aStack);
1632 }
1633
1634 /*
@@ -1631,15 +1636,26 @@
1636 **
1637 ** %fossil test-wiki-render FILE [OPTIONS]
1638 **
1639 ** Options:
1640 ** --buttons Set the WIKI_BUTTONS flag
1641 ** --htmlonly Set the WIKI_HTMLONLY flag
1642 ** --linksonly Set the WIKI_LINKSONLY flag
1643 ** --nobadlinks Set the WIKI_NOBADLINKS flag
1644 ** --inline Set the WIKI_INLINE flag
1645 ** --noblock Set the WIKI_NOBLOCK flag
1646 */
1647 void test_wiki_render(void){
1648 Blob in, out;
1649 int flags = 0;
1650 if( find_option("buttons",0,0)!=0 ) flags |= WIKI_BUTTONS;
1651 if( find_option("htmlonly",0,0)!=0 ) flags |= WIKI_HTMLONLY;
1652 if( find_option("linksonly",0,0)!=0 ) flags |= WIKI_LINKSONLY;
1653 if( find_option("nobadlinks",0,0)!=0 ) flags |= WIKI_NOBADLINKS;
1654 if( find_option("inline",0,0)!=0 ) flags |= WIKI_INLINE;
1655 if( find_option("noblock",0,0)!=0 ) flags |= WIKI_NOBLOCK;
1656 db_find_and_open_repository(0,0);
1657 verify_all_options();
1658 if( g.argc!=3 ) usage("FILE");
1659 blob_zero(&out);
1660 blob_read_from_file(&in, g.argv[2]);
1661 wiki_convert(&in, &out, flags);
@@ -1694,29 +1710,29 @@
1710 Renderer renderer;
1711 int tokenType;
1712 ParsedMarkup markup;
1713 int n;
1714 int inlineOnly;
1715 int wikiHtmlOnly = 0;
1716
1717 memset(&renderer, 0, sizeof(renderer));
1718 renderer.state = ALLOW_WIKI|AT_NEWLINE|AT_PARAGRAPH;
1719 if( flags & WIKI_NOBLOCK ){
1720 renderer.state |= INLINE_MARKUP_ONLY;
1721 }
1722 if( wikiUsesHtml() ){
1723 renderer.state |= WIKI_HTMLONLY;
1724 wikiHtmlOnly = 1;
1725 }
1726 inlineOnly = (renderer.state & INLINE_MARKUP_ONLY)!=0;
1727 if( replaceFlag ){
1728 db_multi_exec("DELETE FROM backlink WHERE srctype=%d AND srcid=%d",
1729 srctype, srcid);
1730 }
1731
1732 while( z[0] ){
1733 if( wikiHtmlOnly ){
1734 n = nextRawToken(z, &renderer, &tokenType);
1735 }else{
1736 n = nextWikiToken(z, &renderer, &tokenType);
1737 }
1738 switch( tokenType ){
1739

Keyboard Shortcuts

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