Fossil SCM

Include `REQUEST_URI` into footnotes' hyperlinks. This should make links work even if base href (in a page's header) is not consistent with the `REQUEST_URI`. If `FOOTNOTES_WITHOUT_URI` macro is defined while compiling `src/markdown_html.c` then bare "#fragment" hyperlinks (without `REQUEST_URI`) are generated.

george 2022-02-16 22:11 markdown-footnotes
Commit 2c1f8f3592ef00e0455edc476a84d8ae1d6603f49d0a4ccde478d545dd47a212
2 files changed +30 +44 -22
+30
--- src/encode.c
+++ src/encode.c
@@ -205,10 +205,40 @@
205205
** by this routine.
206206
*/
207207
char *urlize(const char *z, int n){
208208
return EncodeHttp(z, n, 0);
209209
}
210
+
211
+/*
212
+** If input string does not contain quotes (niether ' nor ")
213
+** then return the argument itself. Otherwise return a newly allocated
214
+** copy of input with all quotes %-escaped.
215
+*/
216
+const char* escape_quotes(const char *zIn){
217
+ char *zRet, *zOut;
218
+ size_t i, n = 0;
219
+ for(i=0; zIn[i]; i++){
220
+ if( zIn[i]== '"' || zIn[i]== '\'' ) n++;
221
+ }
222
+ if( !n ) return zIn;
223
+ zRet = zOut = fossil_malloc( i + 2*n + 1 );
224
+ for(i=0; zIn[i]; i++){
225
+ if( zIn[i]=='"' ){
226
+ *(zOut++) = '%';
227
+ *(zOut++) = '2';
228
+ *(zOut++) = '2';
229
+ }else if( zIn[i]=='\'' ){
230
+ *(zOut++) = '%';
231
+ *(zOut++) = '2';
232
+ *(zOut++) = '7';
233
+ }else{
234
+ *(zOut++) = zIn[i];
235
+ }
236
+ }
237
+ *zOut = 0;
238
+ return zRet;
239
+}
210240
211241
/*
212242
** Convert a single HEX digit to an integer
213243
*/
214244
static int AsciiToHex(int c){
215245
--- src/encode.c
+++ src/encode.c
@@ -205,10 +205,40 @@
205 ** by this routine.
206 */
207 char *urlize(const char *z, int n){
208 return EncodeHttp(z, n, 0);
209 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
210
211 /*
212 ** Convert a single HEX digit to an integer
213 */
214 static int AsciiToHex(int c){
215
--- src/encode.c
+++ src/encode.c
@@ -205,10 +205,40 @@
205 ** by this routine.
206 */
207 char *urlize(const char *z, int n){
208 return EncodeHttp(z, n, 0);
209 }
210
211 /*
212 ** If input string does not contain quotes (niether ' nor ")
213 ** then return the argument itself. Otherwise return a newly allocated
214 ** copy of input with all quotes %-escaped.
215 */
216 const char* escape_quotes(const char *zIn){
217 char *zRet, *zOut;
218 size_t i, n = 0;
219 for(i=0; zIn[i]; i++){
220 if( zIn[i]== '"' || zIn[i]== '\'' ) n++;
221 }
222 if( !n ) return zIn;
223 zRet = zOut = fossil_malloc( i + 2*n + 1 );
224 for(i=0; zIn[i]; i++){
225 if( zIn[i]=='"' ){
226 *(zOut++) = '%';
227 *(zOut++) = '2';
228 *(zOut++) = '2';
229 }else if( zIn[i]=='\'' ){
230 *(zOut++) = '%';
231 *(zOut++) = '2';
232 *(zOut++) = '7';
233 }else{
234 *(zOut++) = zIn[i];
235 }
236 }
237 *zOut = 0;
238 return zRet;
239 }
240
241 /*
242 ** Convert a single HEX digit to an integer
243 */
244 static int AsciiToHex(int c){
245
--- src/markdown_html.c
+++ src/markdown_html.c
@@ -39,10 +39,14 @@
3939
*/
4040
typedef struct MarkdownToHtml MarkdownToHtml;
4141
struct MarkdownToHtml {
4242
Blob *output_title; /* Store the title here */
4343
bitfield64_t unique; /* Enables construction of unique #id elements */
44
+
45
+ #ifndef FOOTNOTES_WITHOUT_URI
46
+ Blob reqURI; /* REQUEST_URI with escaped quotes */
47
+ #endif
4448
};
4549
4650
4751
/* INTER_BLOCK -- skip a line between block level elements */
4852
#define INTER_BLOCK(ob) \
@@ -58,10 +62,16 @@
5862
*/
5963
6064
/* BLOB_APPEND_BLOB -- append blob contents to another */
6165
#define BLOB_APPEND_BLOB(dest, src) \
6266
blob_append((dest), blob_buffer(src), blob_size(src))
67
+
68
+#ifndef FOOTNOTES_WITHOUT_URI
69
+ #define BLOB_APPEND_URI(dest,ctx) BLOB_APPEND_BLOB(dest,&((ctx)->reqURI))
70
+#else
71
+ #define BLOB_APPEND_URI(dest,ctx)
72
+#endif
6373
6474
/* Converts an integer to a null-terminated base26 representation
6575
* Return empty string if that integer is negative. */
6676
static bitfield64_t to_base26(int i, int uppercase){
6777
bitfield64_t x;
@@ -341,16 +351,18 @@
341351
if(span && blob_size(span)) {
342352
BLOB_APPEND_LITERAL(ob,"<span class='notescope' id='noteref");
343353
blob_appendf(ob,"%s'>",pos);
344354
BLOB_APPEND_BLOB(ob, span);
345355
blob_trim(ob);
346
- BLOB_APPEND_LITERAL(ob,"<sup class='noteref'><a href='#footnote");
347
- blob_appendf(ob,"%s'>%i</a></sup></span>", pos, iMark);
356
+ BLOB_APPEND_LITERAL(ob,"<sup class='noteref'><a href='");
357
+ BLOB_APPEND_URI(ob, ctx);
358
+ blob_appendf(ob,"#footnote%s'>%i</a></sup></span>", pos, iMark);
348359
}else{
349360
blob_trim(ob);
350
- BLOB_APPEND_LITERAL(ob,"<sup class='noteref'><a href='#footnote");
351
- blob_appendf(ob,"%s' id='noteref%s'>%i</a></sup>",
361
+ BLOB_APPEND_LITERAL(ob,"<sup class='noteref'><a href='");
362
+ BLOB_APPEND_URI(ob, ctx);
363
+ blob_appendf(ob,"#footnote%s' id='noteref%s'>%i</a></sup>",
352364
pos, pos, iMark);
353365
}
354366
}else{ /* misreference */
355367
assert( iMark == -1 );
356368
@@ -357,18 +369,18 @@
357369
sprintf(pos, "%s-%s", ctx->unique.c, l.c);
358370
if(span && blob_size(span)) {
359371
blob_appendf(ob, "<span class='notescope' id='misref%s'>", pos);
360372
BLOB_APPEND_BLOB(ob, span);
361373
blob_trim(ob);
362
- BLOB_APPEND_LITERAL(ob,
363
- "<sup class='noteref misref'><a href='#misreference");
364
- blob_appendf(ob, "%s'>misref</a></sup></span>", pos);
374
+ BLOB_APPEND_LITERAL(ob, "<sup class='noteref misref'><a href='");
375
+ BLOB_APPEND_URI(ob, ctx);
376
+ blob_appendf(ob, "#misreference%s'>misref</a></sup></span>", pos);
365377
}else{
366378
blob_trim(ob);
367
- BLOB_APPEND_LITERAL(ob,
368
- "<sup class='noteref misref'><a href='#misreference");
369
- blob_appendf(ob, "%s' id='misref%s'>", pos, pos);
379
+ BLOB_APPEND_LITERAL(ob, "<sup class='noteref misref'><a href='");
380
+ BLOB_APPEND_URI(ob, ctx);
381
+ blob_appendf(ob, "#misreference%s' id='misref%s'>", pos, pos);
370382
BLOB_APPEND_LITERAL(ob, "misref</a></sup>");
371383
}
372384
}
373385
return 1;
374386
}
@@ -376,29 +388,32 @@
376388
/* Render a single item of the footnotes list.
377389
* Each backref gets a unique id to enable dynamic styling. */
378390
static void html_footnote_item(
379391
struct Blob *ob, const struct Blob *text, int iMark, int nUsed, void *opaque
380392
){
381
- const char * const unique = ((struct MarkdownToHtml*)opaque)->unique.c;
393
+ const struct MarkdownToHtml* ctx = (struct MarkdownToHtml*)opaque;
394
+ const char * const unique = ctx->unique.c;
382395
assert( nUsed >= 0 );
383396
/* expect BUGs if the following yields compiler warnings */
384397
385398
if( iMark < 0 ){ /* misreferences */
386399
assert( iMark == -1 );
387400
if( !nUsed ) return;
388401
BLOB_APPEND_LITERAL(ob,"<li class='fn-misreference'>"
389402
"<sup class='fn-backrefs'>");
390403
if( nUsed == 1 ){
391
- blob_appendf(ob,"<a id='misreference%s-a' "
392
- "href='#misref%s-a'>^</a>", unique, unique);
404
+ blob_appendf(ob,"<a id='misreference%s-a' href='", unique);
405
+ BLOB_APPEND_URI(ob, ctx);
406
+ blob_appendf(ob,"#misref%s-a'>^</a>", unique);
393407
}else{
394408
int i;
395409
blob_append_char(ob, '^');
396410
for(i=0; i<nUsed && i<26; i++){
397411
const int c = i + (unsigned)'a';
398
- blob_appendf(ob," <a id='misreference%s-%c' "
399
- "href='#misref%s-%c'>%c</a>", unique,c, unique,c, c);
412
+ blob_appendf(ob," <a id='misreference%s-%c' href='", unique,c);
413
+ BLOB_APPEND_URI(ob, ctx);
414
+ blob_appendf(ob,"#misref%s-%c'>%c</a>", unique,c, c);
400415
}
401416
if( i < nUsed ) BLOB_APPEND_LITERAL(ob," &hellip;");
402417
}
403418
BLOB_APPEND_LITERAL(ob,"</sup>\n<span>Misreference</span>");
404419
@@ -417,27 +432,29 @@
417432
sprintf(pos, "%s-%i", unique, iMark);
418433
blob_appendf(ob, "<li id='footnote%s' class='%s", pos, join);
419434
420435
if( nUsed == 1 ){
421436
BLOB_APPEND_LITERAL(ob, "fn-monoref'><sup class='fn-backrefs'>");
422
- blob_appendf(ob,"<a id='footnote%s-a' "
423
- "href='#noteref%s-a'>^</a>", pos, pos);
437
+ blob_appendf(ob,"<a id='footnote%s-a' href='", pos);
438
+ BLOB_APPEND_URI(ob, ctx);
439
+ blob_appendf(ob,"#noteref%s-a'>^</a>", pos);
424440
}else{
425441
int i;
426442
BLOB_APPEND_LITERAL(ob, "fn-polyref'><sup class='fn-backrefs'>^");
427443
for(i=0; i<nUsed && i<26; i++){
428444
const int c = i + (unsigned)'a';
429
- blob_appendf(ob," <a id='footnote%s-%c'"
430
- " href='#noteref%s-%c'>%c</a>", pos,c, pos,c, c);
445
+ blob_appendf(ob," <a id='footnote%s-%c' href='", pos,c);
446
+ BLOB_APPEND_URI(ob, ctx);
447
+ blob_appendf(ob,"#noteref%s-%c'>%c</a>", pos,c, c);
431448
}
432449
/* It's unlikely that so many backrefs will be usefull */
433450
/* but maybe for some machine generated documents... */
434451
for(; i<nUsed && i<676; i++){
435452
const bitfield64_t l = to_base26(i,0);
436
- blob_appendf(ob," <a id='footnote%s-%s'"
437
- " href='#noteref%s-%s'>%s</a>",
438
- pos,l.c, pos,l.c, l.c);
453
+ blob_appendf(ob," <a id='footnote%s-%s' href='", pos, l.c);
454
+ BLOB_APPEND_URI(ob, ctx);
455
+ blob_appendf(ob,"#noteref%s-%s'>%s</a>", pos,l.c, l.c);
439456
}
440457
if( i < nUsed ) BLOB_APPEND_LITERAL(ob," &hellip;");
441458
}
442459
BLOB_APPEND_LITERAL(ob,"</sup>\n");
443460
if( join[0] ){
@@ -768,14 +785,19 @@
768785
/* misc. parameters */
769786
"*_", /* emph_chars */
770787
0 /* opaque */
771788
};
772789
static int invocation = -1; /* no marker for the first document */
790
+ static const char* zRU = 0; /* REQUEST_URI with escaped quotes */
773791
MarkdownToHtml context;
774792
memset(&context, 0, sizeof(context));
775793
context.output_title = output_title;
776794
context.unique = to_base26(invocation++,1);
795
+ if( !zRU ) zRU = escape_quotes(PD("REQUEST_URI",""));
796
+ #ifndef FOOTNOTES_WITHOUT_URI
797
+ blob_set( &context.reqURI, zRU );
798
+ #endif
777799
html_renderer.opaque = &context;
778800
if( output_title ) blob_reset(output_title);
779801
blob_reset(output_body);
780802
markdown(output_body, input_markdown, &html_renderer);
781803
}
782804
--- src/markdown_html.c
+++ src/markdown_html.c
@@ -39,10 +39,14 @@
39 */
40 typedef struct MarkdownToHtml MarkdownToHtml;
41 struct MarkdownToHtml {
42 Blob *output_title; /* Store the title here */
43 bitfield64_t unique; /* Enables construction of unique #id elements */
 
 
 
 
44 };
45
46
47 /* INTER_BLOCK -- skip a line between block level elements */
48 #define INTER_BLOCK(ob) \
@@ -58,10 +62,16 @@
58 */
59
60 /* BLOB_APPEND_BLOB -- append blob contents to another */
61 #define BLOB_APPEND_BLOB(dest, src) \
62 blob_append((dest), blob_buffer(src), blob_size(src))
 
 
 
 
 
 
63
64 /* Converts an integer to a null-terminated base26 representation
65 * Return empty string if that integer is negative. */
66 static bitfield64_t to_base26(int i, int uppercase){
67 bitfield64_t x;
@@ -341,16 +351,18 @@
341 if(span && blob_size(span)) {
342 BLOB_APPEND_LITERAL(ob,"<span class='notescope' id='noteref");
343 blob_appendf(ob,"%s'>",pos);
344 BLOB_APPEND_BLOB(ob, span);
345 blob_trim(ob);
346 BLOB_APPEND_LITERAL(ob,"<sup class='noteref'><a href='#footnote");
347 blob_appendf(ob,"%s'>%i</a></sup></span>", pos, iMark);
 
348 }else{
349 blob_trim(ob);
350 BLOB_APPEND_LITERAL(ob,"<sup class='noteref'><a href='#footnote");
351 blob_appendf(ob,"%s' id='noteref%s'>%i</a></sup>",
 
352 pos, pos, iMark);
353 }
354 }else{ /* misreference */
355 assert( iMark == -1 );
356
@@ -357,18 +369,18 @@
357 sprintf(pos, "%s-%s", ctx->unique.c, l.c);
358 if(span && blob_size(span)) {
359 blob_appendf(ob, "<span class='notescope' id='misref%s'>", pos);
360 BLOB_APPEND_BLOB(ob, span);
361 blob_trim(ob);
362 BLOB_APPEND_LITERAL(ob,
363 "<sup class='noteref misref'><a href='#misreference");
364 blob_appendf(ob, "%s'>misref</a></sup></span>", pos);
365 }else{
366 blob_trim(ob);
367 BLOB_APPEND_LITERAL(ob,
368 "<sup class='noteref misref'><a href='#misreference");
369 blob_appendf(ob, "%s' id='misref%s'>", pos, pos);
370 BLOB_APPEND_LITERAL(ob, "misref</a></sup>");
371 }
372 }
373 return 1;
374 }
@@ -376,29 +388,32 @@
376 /* Render a single item of the footnotes list.
377 * Each backref gets a unique id to enable dynamic styling. */
378 static void html_footnote_item(
379 struct Blob *ob, const struct Blob *text, int iMark, int nUsed, void *opaque
380 ){
381 const char * const unique = ((struct MarkdownToHtml*)opaque)->unique.c;
 
382 assert( nUsed >= 0 );
383 /* expect BUGs if the following yields compiler warnings */
384
385 if( iMark < 0 ){ /* misreferences */
386 assert( iMark == -1 );
387 if( !nUsed ) return;
388 BLOB_APPEND_LITERAL(ob,"<li class='fn-misreference'>"
389 "<sup class='fn-backrefs'>");
390 if( nUsed == 1 ){
391 blob_appendf(ob,"<a id='misreference%s-a' "
392 "href='#misref%s-a'>^</a>", unique, unique);
 
393 }else{
394 int i;
395 blob_append_char(ob, '^');
396 for(i=0; i<nUsed && i<26; i++){
397 const int c = i + (unsigned)'a';
398 blob_appendf(ob," <a id='misreference%s-%c' "
399 "href='#misref%s-%c'>%c</a>", unique,c, unique,c, c);
 
400 }
401 if( i < nUsed ) BLOB_APPEND_LITERAL(ob," &hellip;");
402 }
403 BLOB_APPEND_LITERAL(ob,"</sup>\n<span>Misreference</span>");
404
@@ -417,27 +432,29 @@
417 sprintf(pos, "%s-%i", unique, iMark);
418 blob_appendf(ob, "<li id='footnote%s' class='%s", pos, join);
419
420 if( nUsed == 1 ){
421 BLOB_APPEND_LITERAL(ob, "fn-monoref'><sup class='fn-backrefs'>");
422 blob_appendf(ob,"<a id='footnote%s-a' "
423 "href='#noteref%s-a'>^</a>", pos, pos);
 
424 }else{
425 int i;
426 BLOB_APPEND_LITERAL(ob, "fn-polyref'><sup class='fn-backrefs'>^");
427 for(i=0; i<nUsed && i<26; i++){
428 const int c = i + (unsigned)'a';
429 blob_appendf(ob," <a id='footnote%s-%c'"
430 " href='#noteref%s-%c'>%c</a>", pos,c, pos,c, c);
 
431 }
432 /* It's unlikely that so many backrefs will be usefull */
433 /* but maybe for some machine generated documents... */
434 for(; i<nUsed && i<676; i++){
435 const bitfield64_t l = to_base26(i,0);
436 blob_appendf(ob," <a id='footnote%s-%s'"
437 " href='#noteref%s-%s'>%s</a>",
438 pos,l.c, pos,l.c, l.c);
439 }
440 if( i < nUsed ) BLOB_APPEND_LITERAL(ob," &hellip;");
441 }
442 BLOB_APPEND_LITERAL(ob,"</sup>\n");
443 if( join[0] ){
@@ -768,14 +785,19 @@
768 /* misc. parameters */
769 "*_", /* emph_chars */
770 0 /* opaque */
771 };
772 static int invocation = -1; /* no marker for the first document */
 
773 MarkdownToHtml context;
774 memset(&context, 0, sizeof(context));
775 context.output_title = output_title;
776 context.unique = to_base26(invocation++,1);
 
 
 
 
777 html_renderer.opaque = &context;
778 if( output_title ) blob_reset(output_title);
779 blob_reset(output_body);
780 markdown(output_body, input_markdown, &html_renderer);
781 }
782
--- src/markdown_html.c
+++ src/markdown_html.c
@@ -39,10 +39,14 @@
39 */
40 typedef struct MarkdownToHtml MarkdownToHtml;
41 struct MarkdownToHtml {
42 Blob *output_title; /* Store the title here */
43 bitfield64_t unique; /* Enables construction of unique #id elements */
44
45 #ifndef FOOTNOTES_WITHOUT_URI
46 Blob reqURI; /* REQUEST_URI with escaped quotes */
47 #endif
48 };
49
50
51 /* INTER_BLOCK -- skip a line between block level elements */
52 #define INTER_BLOCK(ob) \
@@ -58,10 +62,16 @@
62 */
63
64 /* BLOB_APPEND_BLOB -- append blob contents to another */
65 #define BLOB_APPEND_BLOB(dest, src) \
66 blob_append((dest), blob_buffer(src), blob_size(src))
67
68 #ifndef FOOTNOTES_WITHOUT_URI
69 #define BLOB_APPEND_URI(dest,ctx) BLOB_APPEND_BLOB(dest,&((ctx)->reqURI))
70 #else
71 #define BLOB_APPEND_URI(dest,ctx)
72 #endif
73
74 /* Converts an integer to a null-terminated base26 representation
75 * Return empty string if that integer is negative. */
76 static bitfield64_t to_base26(int i, int uppercase){
77 bitfield64_t x;
@@ -341,16 +351,18 @@
351 if(span && blob_size(span)) {
352 BLOB_APPEND_LITERAL(ob,"<span class='notescope' id='noteref");
353 blob_appendf(ob,"%s'>",pos);
354 BLOB_APPEND_BLOB(ob, span);
355 blob_trim(ob);
356 BLOB_APPEND_LITERAL(ob,"<sup class='noteref'><a href='");
357 BLOB_APPEND_URI(ob, ctx);
358 blob_appendf(ob,"#footnote%s'>%i</a></sup></span>", pos, iMark);
359 }else{
360 blob_trim(ob);
361 BLOB_APPEND_LITERAL(ob,"<sup class='noteref'><a href='");
362 BLOB_APPEND_URI(ob, ctx);
363 blob_appendf(ob,"#footnote%s' id='noteref%s'>%i</a></sup>",
364 pos, pos, iMark);
365 }
366 }else{ /* misreference */
367 assert( iMark == -1 );
368
@@ -357,18 +369,18 @@
369 sprintf(pos, "%s-%s", ctx->unique.c, l.c);
370 if(span && blob_size(span)) {
371 blob_appendf(ob, "<span class='notescope' id='misref%s'>", pos);
372 BLOB_APPEND_BLOB(ob, span);
373 blob_trim(ob);
374 BLOB_APPEND_LITERAL(ob, "<sup class='noteref misref'><a href='");
375 BLOB_APPEND_URI(ob, ctx);
376 blob_appendf(ob, "#misreference%s'>misref</a></sup></span>", pos);
377 }else{
378 blob_trim(ob);
379 BLOB_APPEND_LITERAL(ob, "<sup class='noteref misref'><a href='");
380 BLOB_APPEND_URI(ob, ctx);
381 blob_appendf(ob, "#misreference%s' id='misref%s'>", pos, pos);
382 BLOB_APPEND_LITERAL(ob, "misref</a></sup>");
383 }
384 }
385 return 1;
386 }
@@ -376,29 +388,32 @@
388 /* Render a single item of the footnotes list.
389 * Each backref gets a unique id to enable dynamic styling. */
390 static void html_footnote_item(
391 struct Blob *ob, const struct Blob *text, int iMark, int nUsed, void *opaque
392 ){
393 const struct MarkdownToHtml* ctx = (struct MarkdownToHtml*)opaque;
394 const char * const unique = ctx->unique.c;
395 assert( nUsed >= 0 );
396 /* expect BUGs if the following yields compiler warnings */
397
398 if( iMark < 0 ){ /* misreferences */
399 assert( iMark == -1 );
400 if( !nUsed ) return;
401 BLOB_APPEND_LITERAL(ob,"<li class='fn-misreference'>"
402 "<sup class='fn-backrefs'>");
403 if( nUsed == 1 ){
404 blob_appendf(ob,"<a id='misreference%s-a' href='", unique);
405 BLOB_APPEND_URI(ob, ctx);
406 blob_appendf(ob,"#misref%s-a'>^</a>", unique);
407 }else{
408 int i;
409 blob_append_char(ob, '^');
410 for(i=0; i<nUsed && i<26; i++){
411 const int c = i + (unsigned)'a';
412 blob_appendf(ob," <a id='misreference%s-%c' href='", unique,c);
413 BLOB_APPEND_URI(ob, ctx);
414 blob_appendf(ob,"#misref%s-%c'>%c</a>", unique,c, c);
415 }
416 if( i < nUsed ) BLOB_APPEND_LITERAL(ob," &hellip;");
417 }
418 BLOB_APPEND_LITERAL(ob,"</sup>\n<span>Misreference</span>");
419
@@ -417,27 +432,29 @@
432 sprintf(pos, "%s-%i", unique, iMark);
433 blob_appendf(ob, "<li id='footnote%s' class='%s", pos, join);
434
435 if( nUsed == 1 ){
436 BLOB_APPEND_LITERAL(ob, "fn-monoref'><sup class='fn-backrefs'>");
437 blob_appendf(ob,"<a id='footnote%s-a' href='", pos);
438 BLOB_APPEND_URI(ob, ctx);
439 blob_appendf(ob,"#noteref%s-a'>^</a>", pos);
440 }else{
441 int i;
442 BLOB_APPEND_LITERAL(ob, "fn-polyref'><sup class='fn-backrefs'>^");
443 for(i=0; i<nUsed && i<26; i++){
444 const int c = i + (unsigned)'a';
445 blob_appendf(ob," <a id='footnote%s-%c' href='", pos,c);
446 BLOB_APPEND_URI(ob, ctx);
447 blob_appendf(ob,"#noteref%s-%c'>%c</a>", pos,c, c);
448 }
449 /* It's unlikely that so many backrefs will be usefull */
450 /* but maybe for some machine generated documents... */
451 for(; i<nUsed && i<676; i++){
452 const bitfield64_t l = to_base26(i,0);
453 blob_appendf(ob," <a id='footnote%s-%s' href='", pos, l.c);
454 BLOB_APPEND_URI(ob, ctx);
455 blob_appendf(ob,"#noteref%s-%s'>%s</a>", pos,l.c, l.c);
456 }
457 if( i < nUsed ) BLOB_APPEND_LITERAL(ob," &hellip;");
458 }
459 BLOB_APPEND_LITERAL(ob,"</sup>\n");
460 if( join[0] ){
@@ -768,14 +785,19 @@
785 /* misc. parameters */
786 "*_", /* emph_chars */
787 0 /* opaque */
788 };
789 static int invocation = -1; /* no marker for the first document */
790 static const char* zRU = 0; /* REQUEST_URI with escaped quotes */
791 MarkdownToHtml context;
792 memset(&context, 0, sizeof(context));
793 context.output_title = output_title;
794 context.unique = to_base26(invocation++,1);
795 if( !zRU ) zRU = escape_quotes(PD("REQUEST_URI",""));
796 #ifndef FOOTNOTES_WITHOUT_URI
797 blob_set( &context.reqURI, zRU );
798 #endif
799 html_renderer.opaque = &context;
800 if( output_title ) blob_reset(output_title);
801 blob_reset(output_body);
802 markdown(output_body, input_markdown, &html_renderer);
803 }
804

Keyboard Shortcuts

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