Fossil SCM

Improvements to help-text HTML formatting.

drh 2020-08-26 21:43 trunk
Commit 517223eca965c361d6619aae668786be1203aa783c97fd517a3d32ba3e9e417b
2 files changed +83 -55 +1 -1
+83 -55
--- src/dispatch.c
+++ src/dispatch.c
@@ -229,45 +229,10 @@
229229
if( z[i]==' ' && z[i+1]!=' ' && z[i-1]==' ' && z[i-2]!='.' ) return i+1;
230230
}
231231
return 0 ;
232232
}
233233
234
-/*
235
-** Append text to pOut, adding formatting markup. Terms that
236
-** have all lower-case letters are within <tt>..</tt>. Terms
237
-** that have all upper-case letters are within <i>..</i>.
238
-*/
239
-static void appendMixedFont(Blob *pOut, const char *z, int n){
240
- const char *zEnd = "";
241
- int i = 0;
242
- int j;
243
- while( i<n ){
244
- if( z[i]==' ' || z[i]=='=' ){
245
- for(j=i+1; j<n && (z[j]==' ' || z[j]=='='); j++){}
246
- blob_append(pOut, z+i, j-i);
247
- i = j;
248
- }else{
249
- for(j=i; j<n && z[j]!=' ' && z[j]!='=' && !fossil_isalpha(z[j]); j++){}
250
- if( j>=n || z[j]==' ' || z[j]=='=' ){
251
- zEnd = "";
252
- }else{
253
- if( fossil_isupper(z[j]) && z[i]!='-' ){
254
- blob_append(pOut, "<i>",3);
255
- zEnd = "</i>";
256
- }else{
257
- blob_append(pOut, "<tt>", 4);
258
- zEnd = "</tt>";
259
- }
260
- }
261
- while( j<n && z[j]!=' ' && z[j]!='=' ){ j++; }
262
- blob_appendf(pOut, "%#h", j-i, z+i);
263
- if( zEnd[0] ) blob_append(pOut, zEnd, -1);
264
- i = j;
265
- }
266
- }
267
-}
268
-
269234
/*
270235
** Input string zIn starts with '['. If the content is a hyperlink of the
271236
** form [[...]] then return the index of the closing ']'. Otherwise return 0.
272237
*/
273238
static int help_is_link(const char *z, int n){
@@ -280,31 +245,95 @@
280245
}
281246
return 0;
282247
}
283248
284249
/*
285
-** Append text to pOut, adding hyperlink markup for [...].
250
+** Append text to pOut with changes:
251
+**
252
+** * Add hyperlink markup for [[...]]
253
+** * Escape HTML characters: < > & and "
254
+** * Change "%fossil" to just "fossil"
286255
*/
287256
static void appendLinked(Blob *pOut, const char *z, int n){
288257
int i = 0;
289258
int j;
290259
while( i<n ){
291
- if( z[i]=='[' && (j = help_is_link(z+i, n-i))>0 ){
260
+ char c = z[i];
261
+ if( c=='[' && (j = help_is_link(z+i, n-i))>0 ){
292262
if( i ) blob_append(pOut, z, i);
293263
z += i+2;
294264
n -= i+2;
295265
blob_appendf(pOut, "<a href='%R/help?cmd=%.*s'>%.*s</a>",
296266
j-3, z, j-3, z);
297267
z += j-1;
298268
n -= j-1;
299269
i = 0;
270
+ }else if( c=='%' && n-i>=7 && strncmp(z+i,"%fossil",7)==0 ){
271
+ if( i ) blob_append(pOut, z, i);
272
+ z += i+7;
273
+ n -= i+7;
274
+ blob_append(pOut, "fossil", 6);
275
+ i = 0;
276
+ }else if( c=='<' ){
277
+ if( i ) blob_append(pOut, z, i);
278
+ blob_append(pOut, "&lt;", 4);
279
+ z += i+1;
280
+ n -= i+1;
281
+ i = 0;
282
+ }else if( c=='>' ){
283
+ if( i ) blob_append(pOut, z, i);
284
+ blob_append(pOut, "&gt;", 4);
285
+ z += i+1;
286
+ n -= i+1;
287
+ i = 0;
288
+ }else if( c=='&' ){
289
+ if( i ) blob_append(pOut, z, i);
290
+ blob_append(pOut, "&amp;", 5);
291
+ z += i+1;
292
+ n -= i+1;
293
+ i = 0;
300294
}else{
301295
i++;
302296
}
303297
}
304298
blob_append(pOut, z, i);
305299
}
300
+
301
+/*
302
+** Append text to pOut, adding formatting markup. Terms that
303
+** have all lower-case letters are within <tt>..</tt>. Terms
304
+** that have all upper-case letters are within <i>..</i>.
305
+*/
306
+static void appendMixedFont(Blob *pOut, const char *z, int n){
307
+ const char *zEnd = "";
308
+ int i = 0;
309
+ int j;
310
+ while( i<n ){
311
+ if( z[i]==' ' || z[i]=='=' ){
312
+ for(j=i+1; j<n && (z[j]==' ' || z[j]=='='); j++){}
313
+ appendLinked(pOut, z+i, j-i);
314
+ i = j;
315
+ }else{
316
+ for(j=i; j<n && z[j]!=' ' && z[j]!='=' && !fossil_isalpha(z[j]); j++){}
317
+ if( j>=n || z[j]==' ' || z[j]=='=' ){
318
+ zEnd = "";
319
+ }else{
320
+ if( fossil_isupper(z[j]) && z[i]!='-' ){
321
+ blob_append(pOut, "<i>",3);
322
+ zEnd = "</i>";
323
+ }else{
324
+ blob_append(pOut, "<tt>", 4);
325
+ zEnd = "</tt>";
326
+ }
327
+ }
328
+ while( j<n && z[j]!=' ' && z[j]!='=' ){ j++; }
329
+ appendLinked(pOut, z+i, j-i);
330
+ if( zEnd[0] ) blob_append(pOut, zEnd, -1);
331
+ i = j;
332
+ }
333
+ }
334
+}
306335
307336
/*
308337
** Attempt to reformat plain-text help into HTML for display on a webpage.
309338
**
310339
** The HTML output is appended to Blob pHtml, which should already be
@@ -341,25 +370,19 @@
341370
342371
aIndent[0] = 0;
343372
azEnd[0] = "";
344373
while( zHelp[0] ){
345374
i = 0;
346
- while( (c = zHelp[i])!=0
347
- && c!='\n'
348
- && c!='<'
349
- && (c!='%' || strncmp(zHelp+i,"%fossil",7)!=0)
350
- ){ i++; }
351
- if( c=='%' ){
352
- if( i ) blob_appendf(pHtml, "%#h", i, zHelp);
353
- zHelp += i + 1;
354
- wantBR = 1;
355
- continue;
356
- }else if( c=='<' ){
357
- if( i ) blob_appendf(pHtml, "%#h", i, zHelp);
358
- blob_append(pHtml, "&amp;", 5);
359
- zHelp += i + 1;
360
- continue;
375
+ while( (c = zHelp[i])!=0 && c!='\n' ){
376
+ if( c=='%' && i>2 && zHelp[i-2]==':' && strncmp(zHelp+i,"%fossil",7)==0 ){
377
+ appendLinked(pHtml, zHelp, i);
378
+ zHelp += i+1;
379
+ i = 0;
380
+ wantBR = 1;
381
+ continue;
382
+ }
383
+ i++;
361384
}
362385
if( i>2 && zHelp[0]=='>' && zHelp[1]==' ' ){
363386
isDT = 1;
364387
for(nIndent=1; nIndent<i && zHelp[nIndent]==' '; nIndent++){}
365388
}else{
@@ -366,11 +389,15 @@
366389
isDT = 0;
367390
for(nIndent=0; nIndent<i && zHelp[nIndent]==' '; nIndent++){}
368391
}
369392
if( nIndent==i ){
370393
if( c==0 ) break;
371
- blob_append(pHtml, "\n", 1);
394
+ if( iLevel && azEnd[iLevel]==zEndPRE ){
395
+ /* Skip the newline at the end of a <pre> */
396
+ }else{
397
+ blob_append_char(pHtml, '\n');
398
+ }
372399
wantP = 1;
373400
wantBR = 0;
374401
zHelp += i+1;
375402
continue;
376403
}
@@ -427,15 +454,16 @@
427454
assert( iLevel<ArraySize(aIndent)-1 );
428455
iLevel++;
429456
aIndent[iLevel] = x = nIndent+iDD;
430457
azEnd[iLevel] = zEndDD;
431458
appendMixedFont(pHtml, zHelp+nIndent, iDD-2);
432
- blob_appendf(pHtml, "</dt><dd>%#h\n", i-x, zHelp+x);
459
+ blob_append(pHtml, "</dt><dd>",9);
460
+ appendLinked(pHtml, zHelp+x, i-x);
433461
}else{
434462
appendMixedFont(pHtml, zHelp+nIndent, i-nIndent);
435
- blob_append(pHtml, "</dt>\n", 6);
436463
}
464
+ blob_append(pHtml, "</dt>\n", 6);
437465
}else if( wantBR ){
438466
appendMixedFont(pHtml, zHelp+nIndent, i-nIndent);
439467
blob_append(pHtml, "<br>\n", 5);
440468
wantBR = 0;
441469
}else{
442470
--- src/dispatch.c
+++ src/dispatch.c
@@ -229,45 +229,10 @@
229 if( z[i]==' ' && z[i+1]!=' ' && z[i-1]==' ' && z[i-2]!='.' ) return i+1;
230 }
231 return 0 ;
232 }
233
234 /*
235 ** Append text to pOut, adding formatting markup. Terms that
236 ** have all lower-case letters are within <tt>..</tt>. Terms
237 ** that have all upper-case letters are within <i>..</i>.
238 */
239 static void appendMixedFont(Blob *pOut, const char *z, int n){
240 const char *zEnd = "";
241 int i = 0;
242 int j;
243 while( i<n ){
244 if( z[i]==' ' || z[i]=='=' ){
245 for(j=i+1; j<n && (z[j]==' ' || z[j]=='='); j++){}
246 blob_append(pOut, z+i, j-i);
247 i = j;
248 }else{
249 for(j=i; j<n && z[j]!=' ' && z[j]!='=' && !fossil_isalpha(z[j]); j++){}
250 if( j>=n || z[j]==' ' || z[j]=='=' ){
251 zEnd = "";
252 }else{
253 if( fossil_isupper(z[j]) && z[i]!='-' ){
254 blob_append(pOut, "<i>",3);
255 zEnd = "</i>";
256 }else{
257 blob_append(pOut, "<tt>", 4);
258 zEnd = "</tt>";
259 }
260 }
261 while( j<n && z[j]!=' ' && z[j]!='=' ){ j++; }
262 blob_appendf(pOut, "%#h", j-i, z+i);
263 if( zEnd[0] ) blob_append(pOut, zEnd, -1);
264 i = j;
265 }
266 }
267 }
268
269 /*
270 ** Input string zIn starts with '['. If the content is a hyperlink of the
271 ** form [[...]] then return the index of the closing ']'. Otherwise return 0.
272 */
273 static int help_is_link(const char *z, int n){
@@ -280,31 +245,95 @@
280 }
281 return 0;
282 }
283
284 /*
285 ** Append text to pOut, adding hyperlink markup for [...].
 
 
 
 
286 */
287 static void appendLinked(Blob *pOut, const char *z, int n){
288 int i = 0;
289 int j;
290 while( i<n ){
291 if( z[i]=='[' && (j = help_is_link(z+i, n-i))>0 ){
 
292 if( i ) blob_append(pOut, z, i);
293 z += i+2;
294 n -= i+2;
295 blob_appendf(pOut, "<a href='%R/help?cmd=%.*s'>%.*s</a>",
296 j-3, z, j-3, z);
297 z += j-1;
298 n -= j-1;
299 i = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
300 }else{
301 i++;
302 }
303 }
304 blob_append(pOut, z, i);
305 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
306
307 /*
308 ** Attempt to reformat plain-text help into HTML for display on a webpage.
309 **
310 ** The HTML output is appended to Blob pHtml, which should already be
@@ -341,25 +370,19 @@
341
342 aIndent[0] = 0;
343 azEnd[0] = "";
344 while( zHelp[0] ){
345 i = 0;
346 while( (c = zHelp[i])!=0
347 && c!='\n'
348 && c!='<'
349 && (c!='%' || strncmp(zHelp+i,"%fossil",7)!=0)
350 ){ i++; }
351 if( c=='%' ){
352 if( i ) blob_appendf(pHtml, "%#h", i, zHelp);
353 zHelp += i + 1;
354 wantBR = 1;
355 continue;
356 }else if( c=='<' ){
357 if( i ) blob_appendf(pHtml, "%#h", i, zHelp);
358 blob_append(pHtml, "&amp;", 5);
359 zHelp += i + 1;
360 continue;
361 }
362 if( i>2 && zHelp[0]=='>' && zHelp[1]==' ' ){
363 isDT = 1;
364 for(nIndent=1; nIndent<i && zHelp[nIndent]==' '; nIndent++){}
365 }else{
@@ -366,11 +389,15 @@
366 isDT = 0;
367 for(nIndent=0; nIndent<i && zHelp[nIndent]==' '; nIndent++){}
368 }
369 if( nIndent==i ){
370 if( c==0 ) break;
371 blob_append(pHtml, "\n", 1);
 
 
 
 
372 wantP = 1;
373 wantBR = 0;
374 zHelp += i+1;
375 continue;
376 }
@@ -427,15 +454,16 @@
427 assert( iLevel<ArraySize(aIndent)-1 );
428 iLevel++;
429 aIndent[iLevel] = x = nIndent+iDD;
430 azEnd[iLevel] = zEndDD;
431 appendMixedFont(pHtml, zHelp+nIndent, iDD-2);
432 blob_appendf(pHtml, "</dt><dd>%#h\n", i-x, zHelp+x);
 
433 }else{
434 appendMixedFont(pHtml, zHelp+nIndent, i-nIndent);
435 blob_append(pHtml, "</dt>\n", 6);
436 }
 
437 }else if( wantBR ){
438 appendMixedFont(pHtml, zHelp+nIndent, i-nIndent);
439 blob_append(pHtml, "<br>\n", 5);
440 wantBR = 0;
441 }else{
442
--- src/dispatch.c
+++ src/dispatch.c
@@ -229,45 +229,10 @@
229 if( z[i]==' ' && z[i+1]!=' ' && z[i-1]==' ' && z[i-2]!='.' ) return i+1;
230 }
231 return 0 ;
232 }
233
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
234 /*
235 ** Input string zIn starts with '['. If the content is a hyperlink of the
236 ** form [[...]] then return the index of the closing ']'. Otherwise return 0.
237 */
238 static int help_is_link(const char *z, int n){
@@ -280,31 +245,95 @@
245 }
246 return 0;
247 }
248
249 /*
250 ** Append text to pOut with changes:
251 **
252 ** * Add hyperlink markup for [[...]]
253 ** * Escape HTML characters: < > & and "
254 ** * Change "%fossil" to just "fossil"
255 */
256 static void appendLinked(Blob *pOut, const char *z, int n){
257 int i = 0;
258 int j;
259 while( i<n ){
260 char c = z[i];
261 if( c=='[' && (j = help_is_link(z+i, n-i))>0 ){
262 if( i ) blob_append(pOut, z, i);
263 z += i+2;
264 n -= i+2;
265 blob_appendf(pOut, "<a href='%R/help?cmd=%.*s'>%.*s</a>",
266 j-3, z, j-3, z);
267 z += j-1;
268 n -= j-1;
269 i = 0;
270 }else if( c=='%' && n-i>=7 && strncmp(z+i,"%fossil",7)==0 ){
271 if( i ) blob_append(pOut, z, i);
272 z += i+7;
273 n -= i+7;
274 blob_append(pOut, "fossil", 6);
275 i = 0;
276 }else if( c=='<' ){
277 if( i ) blob_append(pOut, z, i);
278 blob_append(pOut, "&lt;", 4);
279 z += i+1;
280 n -= i+1;
281 i = 0;
282 }else if( c=='>' ){
283 if( i ) blob_append(pOut, z, i);
284 blob_append(pOut, "&gt;", 4);
285 z += i+1;
286 n -= i+1;
287 i = 0;
288 }else if( c=='&' ){
289 if( i ) blob_append(pOut, z, i);
290 blob_append(pOut, "&amp;", 5);
291 z += i+1;
292 n -= i+1;
293 i = 0;
294 }else{
295 i++;
296 }
297 }
298 blob_append(pOut, z, i);
299 }
300
301 /*
302 ** Append text to pOut, adding formatting markup. Terms that
303 ** have all lower-case letters are within <tt>..</tt>. Terms
304 ** that have all upper-case letters are within <i>..</i>.
305 */
306 static void appendMixedFont(Blob *pOut, const char *z, int n){
307 const char *zEnd = "";
308 int i = 0;
309 int j;
310 while( i<n ){
311 if( z[i]==' ' || z[i]=='=' ){
312 for(j=i+1; j<n && (z[j]==' ' || z[j]=='='); j++){}
313 appendLinked(pOut, z+i, j-i);
314 i = j;
315 }else{
316 for(j=i; j<n && z[j]!=' ' && z[j]!='=' && !fossil_isalpha(z[j]); j++){}
317 if( j>=n || z[j]==' ' || z[j]=='=' ){
318 zEnd = "";
319 }else{
320 if( fossil_isupper(z[j]) && z[i]!='-' ){
321 blob_append(pOut, "<i>",3);
322 zEnd = "</i>";
323 }else{
324 blob_append(pOut, "<tt>", 4);
325 zEnd = "</tt>";
326 }
327 }
328 while( j<n && z[j]!=' ' && z[j]!='=' ){ j++; }
329 appendLinked(pOut, z+i, j-i);
330 if( zEnd[0] ) blob_append(pOut, zEnd, -1);
331 i = j;
332 }
333 }
334 }
335
336 /*
337 ** Attempt to reformat plain-text help into HTML for display on a webpage.
338 **
339 ** The HTML output is appended to Blob pHtml, which should already be
@@ -341,25 +370,19 @@
370
371 aIndent[0] = 0;
372 azEnd[0] = "";
373 while( zHelp[0] ){
374 i = 0;
375 while( (c = zHelp[i])!=0 && c!='\n' ){
376 if( c=='%' && i>2 && zHelp[i-2]==':' && strncmp(zHelp+i,"%fossil",7)==0 ){
377 appendLinked(pHtml, zHelp, i);
378 zHelp += i+1;
379 i = 0;
380 wantBR = 1;
381 continue;
382 }
383 i++;
 
 
 
 
 
 
384 }
385 if( i>2 && zHelp[0]=='>' && zHelp[1]==' ' ){
386 isDT = 1;
387 for(nIndent=1; nIndent<i && zHelp[nIndent]==' '; nIndent++){}
388 }else{
@@ -366,11 +389,15 @@
389 isDT = 0;
390 for(nIndent=0; nIndent<i && zHelp[nIndent]==' '; nIndent++){}
391 }
392 if( nIndent==i ){
393 if( c==0 ) break;
394 if( iLevel && azEnd[iLevel]==zEndPRE ){
395 /* Skip the newline at the end of a <pre> */
396 }else{
397 blob_append_char(pHtml, '\n');
398 }
399 wantP = 1;
400 wantBR = 0;
401 zHelp += i+1;
402 continue;
403 }
@@ -427,15 +454,16 @@
454 assert( iLevel<ArraySize(aIndent)-1 );
455 iLevel++;
456 aIndent[iLevel] = x = nIndent+iDD;
457 azEnd[iLevel] = zEndDD;
458 appendMixedFont(pHtml, zHelp+nIndent, iDD-2);
459 blob_append(pHtml, "</dt><dd>",9);
460 appendLinked(pHtml, zHelp+x, i-x);
461 }else{
462 appendMixedFont(pHtml, zHelp+nIndent, i-nIndent);
 
463 }
464 blob_append(pHtml, "</dt>\n", 6);
465 }else if( wantBR ){
466 appendMixedFont(pHtml, zHelp+nIndent, i-nIndent);
467 blob_append(pHtml, "<br>\n", 5);
468 wantBR = 0;
469 }else{
470
+1 -1
--- src/main.c
+++ src/main.c
@@ -2098,11 +2098,11 @@
20982098
** value of "name", then redirect to URL. There
20992099
** can be multiple "redirect:" lines that are
21002100
** processed in order. If the REPO is "*", then
21012101
** an unconditional redirect to URL is taken.
21022102
**
2103
-** jsmode: VALUE Specifies the delivery mode for JavaScript
2103
+** jsmode: VALUE Specifies the delivery mode for JavaScript
21042104
** files. See the help text for the --jsmode
21052105
** flag of the http command.
21062106
**
21072107
** Most CGI files contain only a "repository:" line. It is uncommon to
21082108
** use any other option.
21092109
--- src/main.c
+++ src/main.c
@@ -2098,11 +2098,11 @@
2098 ** value of "name", then redirect to URL. There
2099 ** can be multiple "redirect:" lines that are
2100 ** processed in order. If the REPO is "*", then
2101 ** an unconditional redirect to URL is taken.
2102 **
2103 ** jsmode: VALUE Specifies the delivery mode for JavaScript
2104 ** files. See the help text for the --jsmode
2105 ** flag of the http command.
2106 **
2107 ** Most CGI files contain only a "repository:" line. It is uncommon to
2108 ** use any other option.
2109
--- src/main.c
+++ src/main.c
@@ -2098,11 +2098,11 @@
2098 ** value of "name", then redirect to URL. There
2099 ** can be multiple "redirect:" lines that are
2100 ** processed in order. If the REPO is "*", then
2101 ** an unconditional redirect to URL is taken.
2102 **
2103 ** jsmode: VALUE Specifies the delivery mode for JavaScript
2104 ** files. See the help text for the --jsmode
2105 ** flag of the http command.
2106 **
2107 ** Most CGI files contain only a "repository:" line. It is uncommon to
2108 ** use any other option.
2109

Keyboard Shortcuts

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