Fossil SCM

Handle misreferences: a reference to undefined footnote.

george 2022-02-04 23:07 markdown-footnotes
Commit 28e6a9cd1355bb58d8644842e3906cbb2b6be171848d495f427b1bb9b103870b
--- src/default.css
+++ src/default.css
@@ -1680,10 +1680,14 @@
16801680
div.markdown > ol.footnotes > li > .footnote-backrefs > a:target {
16811681
background: gold;
16821682
}
16831683
div.markdown sup > a.noteref:target {
16841684
background: gold;
1685
+}
1686
+div.markdown sup.misref {
1687
+ color: red;
1688
+ font-size: 90%;
16851689
}
16861690
div.markdown span.notescope:hover,
16871691
div.markdown span.notescope:target {
16881692
border-bottom: 2px solid gold;
16891693
}
16901694
--- src/default.css
+++ src/default.css
@@ -1680,10 +1680,14 @@
1680 div.markdown > ol.footnotes > li > .footnote-backrefs > a:target {
1681 background: gold;
1682 }
1683 div.markdown sup > a.noteref:target {
1684 background: gold;
 
 
 
 
1685 }
1686 div.markdown span.notescope:hover,
1687 div.markdown span.notescope:target {
1688 border-bottom: 2px solid gold;
1689 }
1690
--- src/default.css
+++ src/default.css
@@ -1680,10 +1680,14 @@
1680 div.markdown > ol.footnotes > li > .footnote-backrefs > a:target {
1681 background: gold;
1682 }
1683 div.markdown sup > a.noteref:target {
1684 background: gold;
1685 }
1686 div.markdown sup.misref {
1687 color: red;
1688 font-size: 90%;
1689 }
1690 div.markdown span.notescope:hover,
1691 div.markdown span.notescope:target {
1692 border-bottom: 2px solid gold;
1693 }
1694
+17 -3
--- src/markdown.c
+++ src/markdown.c
@@ -174,11 +174,13 @@
174174
struct Blob *aBlobCache[20]; /* Cache of Blobs available for reuse */
175175
176176
struct {
177177
Blob all; /* array of footnotes */
178178
int nLbled; /* number of labeled footnotes found during the first pass */
179
- int nMarks; /* count distinct indices found in the second pass */
179
+ int nMarks; /* counts distinct indices found during the second pass */
180
+ struct footnote missing; /* a dummy footnote, its negative index
181
+ counts missing refs */
180182
} notes;
181183
};
182184
183185
/* html_tag -- structure for quick HTML tag search (inspired from discount) */
184186
struct html_tag {
@@ -208,10 +210,11 @@
208210
/***************************
209211
* STATIC HELPER FUNCTIONS *
210212
***************************/
211213
212214
/* build_ref_id -- collapse whitespace from input text to make it a ref id */
215
+/* FIXME: does this function handle non-Unix newlines? */
213216
static int build_ref_id(struct Blob *id, const char *data, size_t size){
214217
size_t beg, i;
215218
char *id_data;
216219
217220
/* skip leading whitespace */
@@ -1221,11 +1224,14 @@
12211224
}
12221225
}
12231226
12241227
if( bFootnote ){
12251228
fn = get_footnote(rndr, id_data, id_size);
1226
- if( !fn ) goto char_link_cleanup;
1229
+ if( !fn ) {
1230
+ rndr->notes.missing.index--;
1231
+ fn = &rndr->notes.missing;
1232
+ }
12271233
}else if( get_link_ref(rndr, link, title, id_data, id_size)<0 ){
12281234
goto char_link_cleanup;
12291235
}
12301236
12311237
i = id_end+1;
@@ -1233,11 +1239,14 @@
12331239
/* shortcut reference style link or free-standing footnote refernece */
12341240
}else{
12351241
if(!is_img && size>3 && data[1]=='^'){
12361242
/* free-standing footnote reference */
12371243
fn = get_footnote(rndr, data+2, txt_e-2);
1238
- if( !fn ) goto char_link_cleanup;
1244
+ if( !fn ) {
1245
+ rndr->notes.missing.index--;
1246
+ fn = &rndr->notes.missing;
1247
+ }
12391248
release_work_buffer(rndr, content);
12401249
content = 0;
12411250
}else if( get_link_ref(rndr, link, title, data+1, txt_e-1)<0 ){
12421251
goto char_link_cleanup;
12431252
}
@@ -2457,10 +2466,15 @@
24572466
rndr.nBlobCache = 0;
24582467
rndr.iDepth = 0;
24592468
rndr.refs = empty_blob;
24602469
rndr.notes.all = empty_blob;
24612470
rndr.notes.nMarks = 0;
2471
+ rndr.notes.missing.id = empty_blob;
2472
+ rndr.notes.missing.text = empty_blob;
2473
+ rndr.notes.missing.index = 0;
2474
+ rndr.notes.missing.nUsed = 0;
2475
+
24622476
for(i=0; i<256; i++) rndr.active_char[i] = 0;
24632477
if( (rndr.make.emphasis
24642478
|| rndr.make.double_emphasis
24652479
|| rndr.make.triple_emphasis)
24662480
&& rndr.make.emph_chars
24672481
--- src/markdown.c
+++ src/markdown.c
@@ -174,11 +174,13 @@
174 struct Blob *aBlobCache[20]; /* Cache of Blobs available for reuse */
175
176 struct {
177 Blob all; /* array of footnotes */
178 int nLbled; /* number of labeled footnotes found during the first pass */
179 int nMarks; /* count distinct indices found in the second pass */
 
 
180 } notes;
181 };
182
183 /* html_tag -- structure for quick HTML tag search (inspired from discount) */
184 struct html_tag {
@@ -208,10 +210,11 @@
208 /***************************
209 * STATIC HELPER FUNCTIONS *
210 ***************************/
211
212 /* build_ref_id -- collapse whitespace from input text to make it a ref id */
 
213 static int build_ref_id(struct Blob *id, const char *data, size_t size){
214 size_t beg, i;
215 char *id_data;
216
217 /* skip leading whitespace */
@@ -1221,11 +1224,14 @@
1221 }
1222 }
1223
1224 if( bFootnote ){
1225 fn = get_footnote(rndr, id_data, id_size);
1226 if( !fn ) goto char_link_cleanup;
 
 
 
1227 }else if( get_link_ref(rndr, link, title, id_data, id_size)<0 ){
1228 goto char_link_cleanup;
1229 }
1230
1231 i = id_end+1;
@@ -1233,11 +1239,14 @@
1233 /* shortcut reference style link or free-standing footnote refernece */
1234 }else{
1235 if(!is_img && size>3 && data[1]=='^'){
1236 /* free-standing footnote reference */
1237 fn = get_footnote(rndr, data+2, txt_e-2);
1238 if( !fn ) goto char_link_cleanup;
 
 
 
1239 release_work_buffer(rndr, content);
1240 content = 0;
1241 }else if( get_link_ref(rndr, link, title, data+1, txt_e-1)<0 ){
1242 goto char_link_cleanup;
1243 }
@@ -2457,10 +2466,15 @@
2457 rndr.nBlobCache = 0;
2458 rndr.iDepth = 0;
2459 rndr.refs = empty_blob;
2460 rndr.notes.all = empty_blob;
2461 rndr.notes.nMarks = 0;
 
 
 
 
 
2462 for(i=0; i<256; i++) rndr.active_char[i] = 0;
2463 if( (rndr.make.emphasis
2464 || rndr.make.double_emphasis
2465 || rndr.make.triple_emphasis)
2466 && rndr.make.emph_chars
2467
--- src/markdown.c
+++ src/markdown.c
@@ -174,11 +174,13 @@
174 struct Blob *aBlobCache[20]; /* Cache of Blobs available for reuse */
175
176 struct {
177 Blob all; /* array of footnotes */
178 int nLbled; /* number of labeled footnotes found during the first pass */
179 int nMarks; /* counts distinct indices found during the second pass */
180 struct footnote missing; /* a dummy footnote, its negative index
181 counts missing refs */
182 } notes;
183 };
184
185 /* html_tag -- structure for quick HTML tag search (inspired from discount) */
186 struct html_tag {
@@ -208,10 +210,11 @@
210 /***************************
211 * STATIC HELPER FUNCTIONS *
212 ***************************/
213
214 /* build_ref_id -- collapse whitespace from input text to make it a ref id */
215 /* FIXME: does this function handle non-Unix newlines? */
216 static int build_ref_id(struct Blob *id, const char *data, size_t size){
217 size_t beg, i;
218 char *id_data;
219
220 /* skip leading whitespace */
@@ -1221,11 +1224,14 @@
1224 }
1225 }
1226
1227 if( bFootnote ){
1228 fn = get_footnote(rndr, id_data, id_size);
1229 if( !fn ) {
1230 rndr->notes.missing.index--;
1231 fn = &rndr->notes.missing;
1232 }
1233 }else if( get_link_ref(rndr, link, title, id_data, id_size)<0 ){
1234 goto char_link_cleanup;
1235 }
1236
1237 i = id_end+1;
@@ -1233,11 +1239,14 @@
1239 /* shortcut reference style link or free-standing footnote refernece */
1240 }else{
1241 if(!is_img && size>3 && data[1]=='^'){
1242 /* free-standing footnote reference */
1243 fn = get_footnote(rndr, data+2, txt_e-2);
1244 if( !fn ) {
1245 rndr->notes.missing.index--;
1246 fn = &rndr->notes.missing;
1247 }
1248 release_work_buffer(rndr, content);
1249 content = 0;
1250 }else if( get_link_ref(rndr, link, title, data+1, txt_e-1)<0 ){
1251 goto char_link_cleanup;
1252 }
@@ -2457,10 +2466,15 @@
2466 rndr.nBlobCache = 0;
2467 rndr.iDepth = 0;
2468 rndr.refs = empty_blob;
2469 rndr.notes.all = empty_blob;
2470 rndr.notes.nMarks = 0;
2471 rndr.notes.missing.id = empty_blob;
2472 rndr.notes.missing.text = empty_blob;
2473 rndr.notes.missing.index = 0;
2474 rndr.notes.missing.nUsed = 0;
2475
2476 for(i=0; i<256; i++) rndr.active_char[i] = 0;
2477 if( (rndr.make.emphasis
2478 || rndr.make.double_emphasis
2479 || rndr.make.triple_emphasis)
2480 && rndr.make.emph_chars
2481
--- src/markdown_html.c
+++ src/markdown_html.c
@@ -328,28 +328,43 @@
328328
329329
static int html_footnote_ref(
330330
struct Blob *ob, const struct Blob *span, int index, int locus, void *opaque
331331
){
332332
const struct MarkdownToHtml *ctx = (struct MarkdownToHtml*)opaque;
333
- const bitfield64_t l = to_base26(locus-1,0);
334
- char pos[32];
335
-
336333
/* expect BUGs if the following yields compiler warnings */
337
- memset(pos,0,32);
338
- sprintf(pos, "%s-%i-%s", ctx->unique.c, index, l.c);
339
- if(span && blob_size(span)) {
340
- BLOB_APPEND_LITERAL(ob,"<span class='notescope' id='noteref");
341
- blob_appendf(ob,"%s'>",pos);
334
+
335
+ if( index>0 && locus>0 ){
336
+ const bitfield64_t l = to_base26(locus-1,0);
337
+ char pos[32];
338
+ memset(pos,0,32);
339
+ sprintf(pos, "%s-%i-%s", ctx->unique.c, index, l.c);
340
+
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><a class='noteref' href='#footnote");
347
+ blob_appendf(ob,"%s'>%i</a></sup></span>", pos, index);
348
+ }else{
349
+ blob_trim(ob);
350
+ BLOB_APPEND_LITERAL(ob,"<sup><a class='noteref' href='#footnote");
351
+ blob_appendf(ob,"%s' id='noteref%s'>%i</a></sup>",
352
+ pos, pos, index);
353
+ }
354
+ }else if(span && blob_size(span)) {
355
+ BLOB_APPEND_LITERAL(ob, "<span class='notescope' id='misref");
356
+ blob_appendf(ob, "%s-%i'>", ctx->unique.c, -index);
342357
BLOB_APPEND_BLOB(ob, span);
343358
blob_trim(ob);
344
- BLOB_APPEND_LITERAL(ob,"<sup><a class='noteref' href='#footnote");
345
- blob_appendf(ob,"%s'>%i</a></sup></span>", pos, index);
359
+ BLOB_APPEND_LITERAL(ob,
360
+ "<sup class='misref'>misreference</sup></span>");
346361
}else{
347362
blob_trim(ob);
348
- BLOB_APPEND_LITERAL(ob,"<sup><a class='noteref' href='#footnote");
349
- blob_appendf(ob,"%s' id='noteref%s'>%i</a></sup>",
350
- pos, pos, index);
363
+ BLOB_APPEND_LITERAL(ob, "<sup class='misref' id='misref");
364
+ blob_appendf(ob, "%s-%i", ctx->unique.c, -index);
365
+ BLOB_APPEND_LITERAL(ob, "'>misreference</sup>");
351366
}
352367
return 1;
353368
}
354369
355370
/* Render a single item of the footnotes list.
356371
--- src/markdown_html.c
+++ src/markdown_html.c
@@ -328,28 +328,43 @@
328
329 static int html_footnote_ref(
330 struct Blob *ob, const struct Blob *span, int index, int locus, void *opaque
331 ){
332 const struct MarkdownToHtml *ctx = (struct MarkdownToHtml*)opaque;
333 const bitfield64_t l = to_base26(locus-1,0);
334 char pos[32];
335
336 /* expect BUGs if the following yields compiler warnings */
337 memset(pos,0,32);
338 sprintf(pos, "%s-%i-%s", ctx->unique.c, index, l.c);
339 if(span && blob_size(span)) {
340 BLOB_APPEND_LITERAL(ob,"<span class='notescope' id='noteref");
341 blob_appendf(ob,"%s'>",pos);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
342 BLOB_APPEND_BLOB(ob, span);
343 blob_trim(ob);
344 BLOB_APPEND_LITERAL(ob,"<sup><a class='noteref' href='#footnote");
345 blob_appendf(ob,"%s'>%i</a></sup></span>", pos, index);
346 }else{
347 blob_trim(ob);
348 BLOB_APPEND_LITERAL(ob,"<sup><a class='noteref' href='#footnote");
349 blob_appendf(ob,"%s' id='noteref%s'>%i</a></sup>",
350 pos, pos, index);
351 }
352 return 1;
353 }
354
355 /* Render a single item of the footnotes list.
356
--- src/markdown_html.c
+++ src/markdown_html.c
@@ -328,28 +328,43 @@
328
329 static int html_footnote_ref(
330 struct Blob *ob, const struct Blob *span, int index, int locus, void *opaque
331 ){
332 const struct MarkdownToHtml *ctx = (struct MarkdownToHtml*)opaque;
 
 
 
333 /* expect BUGs if the following yields compiler warnings */
334
335 if( index>0 && locus>0 ){
336 const bitfield64_t l = to_base26(locus-1,0);
337 char pos[32];
338 memset(pos,0,32);
339 sprintf(pos, "%s-%i-%s", ctx->unique.c, index, l.c);
340
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><a class='noteref' href='#footnote");
347 blob_appendf(ob,"%s'>%i</a></sup></span>", pos, index);
348 }else{
349 blob_trim(ob);
350 BLOB_APPEND_LITERAL(ob,"<sup><a class='noteref' href='#footnote");
351 blob_appendf(ob,"%s' id='noteref%s'>%i</a></sup>",
352 pos, pos, index);
353 }
354 }else if(span && blob_size(span)) {
355 BLOB_APPEND_LITERAL(ob, "<span class='notescope' id='misref");
356 blob_appendf(ob, "%s-%i'>", ctx->unique.c, -index);
357 BLOB_APPEND_BLOB(ob, span);
358 blob_trim(ob);
359 BLOB_APPEND_LITERAL(ob,
360 "<sup class='misref'>misreference</sup></span>");
361 }else{
362 blob_trim(ob);
363 BLOB_APPEND_LITERAL(ob, "<sup class='misref' id='misref");
364 blob_appendf(ob, "%s-%i", ctx->unique.c, -index);
365 BLOB_APPEND_LITERAL(ob, "'>misreference</sup>");
366 }
367 return 1;
368 }
369
370 /* Render a single item of the footnotes list.
371
--- test/markdown-test3.md
+++ test/markdown-test3.md
@@ -1,18 +1,21 @@
11
22
Markdown Footnotes Test Document
33
================================
44
5
-This document should help with testing of footnotes support that
6
-is introduced by the ["`markdown-footnotes`"][branch] branch.[^1]
5
+**This document** should help with testing of footnotes support that
6
+is introduced by the ["`markdown-footnotes`"][branch] branch.
7
+It **might look pretty misformatted unless rendered by the proper Fossil
8
+executable that incorporates the abovementioned branch.**[^1]
79
810
Developers are invited to add test cases here[^here].
911
It is suggested that the more simple is a test case the earlier it should
1012
appear in this document.[^ if glitch occurs ]
1113
1214
A footnote's label should be case insensitive[^ case INSENSITIVE ],
13
-but may not contain newlines.[^broken
15
+it is whitespace-savvy and can even contain newlines.[^ a
16
+multiline
1417
label]
1518
1619
A labeled footnote may be [referenced several times][^many-refs].
1720
1821
A footnote's text should support Markdown [markup][^].
@@ -20,30 +23,38 @@
2023
Another reference[^many-refs] to the preveously used footnote.
2124
2225
Inline footnotes are supported.(^These may be usefull for adding
2326
<s>small</s> comments.)
2427
28
+If [undefined label is used][^] then red "`misreference`" is emited instead of
29
+a numeric marker.[^ see it yourself ]
30
+This can be overridden by the skin though.
2531
2632
2733
## Footnotes
2834
29
-[branch]: /timeline?t=markdown-footnotes
35
+[branch]: /timeline?r=markdown-footnotes&nowiki
3036
3137
[^ 1]: Footnotes is a Fossil' extention of
3238
Markdown. Your other tools may have limited support for these.
3339
34
-[^here]: [](/finfo/test/markdown-test3.md)
40
+[^here]: [History of test/markdown-test3.md](/finfo/test/markdown-test3.md)
3541
3642
[^if glitch occurs]:
3743
So that simple cases are processed even if
3844
a glitch happens for more tricky cases.
3945
4046
[^ CASE insensitive ]: And also tolerate whitespaces.
4147
42
-^[broken label]: This text should not render within a list of footnotes.
48
+[^ a multiline label ]: But at a footnote's definition it should still
49
+ be written within square brackets
50
+ on a single line.
4351
4452
4553
[^many-refs]:
4654
Each letter on the left is a back-reference to the place of use.
4755
Highlighted back-reference indicates a place from which navigation occurred.
4856
4957
[^markup]: E.g. *emphasis*, and [so on](/md_rules).
58
+
59
+[^undefined label is used]: For example due to a typo.
60
+
5061
--- test/markdown-test3.md
+++ test/markdown-test3.md
@@ -1,18 +1,21 @@
1
2 Markdown Footnotes Test Document
3 ================================
4
5 This document should help with testing of footnotes support that
6 is introduced by the ["`markdown-footnotes`"][branch] branch.[^1]
 
 
7
8 Developers are invited to add test cases here[^here].
9 It is suggested that the more simple is a test case the earlier it should
10 appear in this document.[^ if glitch occurs ]
11
12 A footnote's label should be case insensitive[^ case INSENSITIVE ],
13 but may not contain newlines.[^broken
 
14 label]
15
16 A labeled footnote may be [referenced several times][^many-refs].
17
18 A footnote's text should support Markdown [markup][^].
@@ -20,30 +23,38 @@
20 Another reference[^many-refs] to the preveously used footnote.
21
22 Inline footnotes are supported.(^These may be usefull for adding
23 <s>small</s> comments.)
24
 
 
 
25
26
27 ## Footnotes
28
29 [branch]: /timeline?t=markdown-footnotes
30
31 [^ 1]: Footnotes is a Fossil' extention of
32 Markdown. Your other tools may have limited support for these.
33
34 [^here]: [](/finfo/test/markdown-test3.md)
35
36 [^if glitch occurs]:
37 So that simple cases are processed even if
38 a glitch happens for more tricky cases.
39
40 [^ CASE insensitive ]: And also tolerate whitespaces.
41
42 ^[broken label]: This text should not render within a list of footnotes.
 
 
43
44
45 [^many-refs]:
46 Each letter on the left is a back-reference to the place of use.
47 Highlighted back-reference indicates a place from which navigation occurred.
48
49 [^markup]: E.g. *emphasis*, and [so on](/md_rules).
 
 
 
50
--- test/markdown-test3.md
+++ test/markdown-test3.md
@@ -1,18 +1,21 @@
1
2 Markdown Footnotes Test Document
3 ================================
4
5 **This document** should help with testing of footnotes support that
6 is introduced by the ["`markdown-footnotes`"][branch] branch.
7 It **might look pretty misformatted unless rendered by the proper Fossil
8 executable that incorporates the abovementioned branch.**[^1]
9
10 Developers are invited to add test cases here[^here].
11 It is suggested that the more simple is a test case the earlier it should
12 appear in this document.[^ if glitch occurs ]
13
14 A footnote's label should be case insensitive[^ case INSENSITIVE ],
15 it is whitespace-savvy and can even contain newlines.[^ a
16 multiline
17 label]
18
19 A labeled footnote may be [referenced several times][^many-refs].
20
21 A footnote's text should support Markdown [markup][^].
@@ -20,30 +23,38 @@
23 Another reference[^many-refs] to the preveously used footnote.
24
25 Inline footnotes are supported.(^These may be usefull for adding
26 <s>small</s> comments.)
27
28 If [undefined label is used][^] then red "`misreference`" is emited instead of
29 a numeric marker.[^ see it yourself ]
30 This can be overridden by the skin though.
31
32
33 ## Footnotes
34
35 [branch]: /timeline?r=markdown-footnotes&nowiki
36
37 [^ 1]: Footnotes is a Fossil' extention of
38 Markdown. Your other tools may have limited support for these.
39
40 [^here]: [History of test/markdown-test3.md](/finfo/test/markdown-test3.md)
41
42 [^if glitch occurs]:
43 So that simple cases are processed even if
44 a glitch happens for more tricky cases.
45
46 [^ CASE insensitive ]: And also tolerate whitespaces.
47
48 [^ a multiline label ]: But at a footnote's definition it should still
49 be written within square brackets
50 on a single line.
51
52
53 [^many-refs]:
54 Each letter on the left is a back-reference to the place of use.
55 Highlighted back-reference indicates a place from which navigation occurred.
56
57 [^markup]: E.g. *emphasis*, and [so on](/md_rules).
58
59 [^undefined label is used]: For example due to a typo.
60
61

Keyboard Shortcuts

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