Fossil SCM

Handle unreferenced footnotes. If a labeled footnote is defined but there are no references to it, then add a special item at the end of footnotes. This item includes a label and the text of the strayed footnote - both rendered verbatim via <tt>html_escape()</tt>. Default skin makes such items visible and easily distinguishable. The order of such items match the order in the underlying source code.

george 2022-02-09 22:59 markdown-footnotes
Commit ada55cd45ae34dfdf3317b3eb22551680ed6e900006668b4f99eb8e180847021
+15 -2
--- src/default.css
+++ src/default.css
@@ -1671,19 +1671,32 @@
16711671
font-size: 90%;
16721672
}
16731673
div.content div.markdown > ol.footnotes > li {
16741674
margin-bottom: 0.5em;
16751675
}
1676
-div.markdown ol.footnotes > li.unreferenced-footnote,
16771676
div.markdown ol.footnotes > li.misreferences {
16781677
background: #ffdddd;
16791678
}
1680
-div.markdown ol.footnotes > li.unreferenced-footnote:first-child,
1679
+div.markdown ol.footnotes > li.unreferenced:first-child,
16811680
div.markdown ol.footnotes > li.misreferences {
16821681
margin-top: 0.75em;
16831682
padding-top: 0.25em;
16841683
padding-bottom: 0.25em;
1684
+}
1685
+div.markdown ol.footnotes > li.unreferenced {
1686
+ padding-left: 0.5em;
1687
+ color: gray;
1688
+}
1689
+div.markdown ol.footnotes > li.unreferenced > code {
1690
+ color: red;
1691
+ font-weight: bold;
1692
+}
1693
+div.markdown ol.footnotes > li.unreferenced > pre {
1694
+ color: gray;
1695
+ padding-left: 0.5em;
1696
+ margin-top: 0.25em;
1697
+ border-left: 3px solid red;
16851698
}
16861699
div.content div.markdown > ol.footnotes > li > .footnote-backrefs {
16871700
margin-right: 0.5em;
16881701
font-weight: bold;
16891702
}
16901703
--- src/default.css
+++ src/default.css
@@ -1671,19 +1671,32 @@
1671 font-size: 90%;
1672 }
1673 div.content div.markdown > ol.footnotes > li {
1674 margin-bottom: 0.5em;
1675 }
1676 div.markdown ol.footnotes > li.unreferenced-footnote,
1677 div.markdown ol.footnotes > li.misreferences {
1678 background: #ffdddd;
1679 }
1680 div.markdown ol.footnotes > li.unreferenced-footnote:first-child,
1681 div.markdown ol.footnotes > li.misreferences {
1682 margin-top: 0.75em;
1683 padding-top: 0.25em;
1684 padding-bottom: 0.25em;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1685 }
1686 div.content div.markdown > ol.footnotes > li > .footnote-backrefs {
1687 margin-right: 0.5em;
1688 font-weight: bold;
1689 }
1690
--- src/default.css
+++ src/default.css
@@ -1671,19 +1671,32 @@
1671 font-size: 90%;
1672 }
1673 div.content div.markdown > ol.footnotes > li {
1674 margin-bottom: 0.5em;
1675 }
 
1676 div.markdown ol.footnotes > li.misreferences {
1677 background: #ffdddd;
1678 }
1679 div.markdown ol.footnotes > li.unreferenced:first-child,
1680 div.markdown ol.footnotes > li.misreferences {
1681 margin-top: 0.75em;
1682 padding-top: 0.25em;
1683 padding-bottom: 0.25em;
1684 }
1685 div.markdown ol.footnotes > li.unreferenced {
1686 padding-left: 0.5em;
1687 color: gray;
1688 }
1689 div.markdown ol.footnotes > li.unreferenced > code {
1690 color: red;
1691 font-weight: bold;
1692 }
1693 div.markdown ol.footnotes > li.unreferenced > pre {
1694 color: gray;
1695 padding-left: 0.5em;
1696 margin-top: 0.25em;
1697 border-left: 3px solid red;
1698 }
1699 div.content div.markdown > ol.footnotes > li > .footnote-backrefs {
1700 margin-right: 0.5em;
1701 font-weight: bold;
1702 }
1703
+9 -2
--- src/markdown.c
+++ src/markdown.c
@@ -2670,23 +2670,30 @@
26702670
release_work_buffer(&rndr,tmp);
26712671
26722672
/* footnotes rendering */
26732673
if( rndr.make.footnote_item && rndr.make.footnotes ){
26742674
Blob *all_items = new_work_buffer(&rndr);
2675
+ int j = -1;
26752676
for(i=0; i<COUNT_FOOTNOTES(notes); i++){
26762677
const struct footnote* x = CAST_AS_FOOTNOTES(notes) + i;
26772678
if( x->bRndred ){
26782679
rndr.make.footnote_item(all_items, &x->text, x->iMark,
26792680
x->nUsed, rndr.make.opaque);
2681
+ j = i;
26802682
}
26812683
}
26822684
if( rndr.notes.misref.nUsed ){
26832685
rndr.make.footnote_item(all_items, 0, -1,
26842686
rndr.notes.misref.nUsed, rndr.make.opaque);
26852687
}
2686
- /* TODO: handle unreferenced (defined but not used) footnotes */
2687
-
2688
+ while( ++j < COUNT_FOOTNOTES(notes) ){
2689
+ const struct footnote* x = CAST_AS_FOOTNOTES(notes) + j;
2690
+ assert( !x->nUsed );
2691
+ assert( !x->bRndred );
2692
+ assert( (&x->id) + 1 == &x->text ); /* see html_footnote_item() */
2693
+ rndr.make.footnote_item(all_items,&x->text,0,0,rndr.make.opaque);
2694
+ }
26882695
rndr.make.footnotes(ob, all_items, rndr.make.opaque);
26892696
release_work_buffer(&rndr, all_items);
26902697
}
26912698
release_work_buffer(&rndr, notes);
26922699
}
26932700
--- src/markdown.c
+++ src/markdown.c
@@ -2670,23 +2670,30 @@
2670 release_work_buffer(&rndr,tmp);
2671
2672 /* footnotes rendering */
2673 if( rndr.make.footnote_item && rndr.make.footnotes ){
2674 Blob *all_items = new_work_buffer(&rndr);
 
2675 for(i=0; i<COUNT_FOOTNOTES(notes); i++){
2676 const struct footnote* x = CAST_AS_FOOTNOTES(notes) + i;
2677 if( x->bRndred ){
2678 rndr.make.footnote_item(all_items, &x->text, x->iMark,
2679 x->nUsed, rndr.make.opaque);
 
2680 }
2681 }
2682 if( rndr.notes.misref.nUsed ){
2683 rndr.make.footnote_item(all_items, 0, -1,
2684 rndr.notes.misref.nUsed, rndr.make.opaque);
2685 }
2686 /* TODO: handle unreferenced (defined but not used) footnotes */
2687
 
 
 
 
 
2688 rndr.make.footnotes(ob, all_items, rndr.make.opaque);
2689 release_work_buffer(&rndr, all_items);
2690 }
2691 release_work_buffer(&rndr, notes);
2692 }
2693
--- src/markdown.c
+++ src/markdown.c
@@ -2670,23 +2670,30 @@
2670 release_work_buffer(&rndr,tmp);
2671
2672 /* footnotes rendering */
2673 if( rndr.make.footnote_item && rndr.make.footnotes ){
2674 Blob *all_items = new_work_buffer(&rndr);
2675 int j = -1;
2676 for(i=0; i<COUNT_FOOTNOTES(notes); i++){
2677 const struct footnote* x = CAST_AS_FOOTNOTES(notes) + i;
2678 if( x->bRndred ){
2679 rndr.make.footnote_item(all_items, &x->text, x->iMark,
2680 x->nUsed, rndr.make.opaque);
2681 j = i;
2682 }
2683 }
2684 if( rndr.notes.misref.nUsed ){
2685 rndr.make.footnote_item(all_items, 0, -1,
2686 rndr.notes.misref.nUsed, rndr.make.opaque);
2687 }
2688 while( ++j < COUNT_FOOTNOTES(notes) ){
2689 const struct footnote* x = CAST_AS_FOOTNOTES(notes) + j;
2690 assert( !x->nUsed );
2691 assert( !x->bRndred );
2692 assert( (&x->id) + 1 == &x->text ); /* see html_footnote_item() */
2693 rndr.make.footnote_item(all_items,&x->text,0,0,rndr.make.opaque);
2694 }
2695 rndr.make.footnotes(ob, all_items, rndr.make.opaque);
2696 release_work_buffer(&rndr, all_items);
2697 }
2698 release_work_buffer(&rndr, notes);
2699 }
2700
--- src/markdown_html.c
+++ src/markdown_html.c
@@ -435,18 +435,22 @@
435435
}
436436
BLOB_APPEND_LITERAL(ob,"</sup>\n");
437437
BLOB_APPEND_BLOB(ob, text);
438438
}else{
439439
/* a footnote was defined but wasn't used */
440
+ /* make.footnote_item() invocations should pass args accordingly */
441
+ const struct Blob * id = text-1;
440442
assert( text );
441443
assert( blob_size(text) );
442
- /* FIXME: not yet implemented */
443
- return;
444
- BLOB_APPEND_LITERAL(ob,
445
- "<li class='unreferenced-footnote' id='unreferenced-footnote");
446
- blob_appendf(ob,"%s-%i'>\n", unique, iMark);
447
- BLOB_APPEND_BLOB(ob, text);
444
+ assert( blob_size(id) );
445
+ BLOB_APPEND_LITERAL(ob,"<li class='unreferenced'>\n[^&nbsp;<code>");
446
+ html_escape(ob, blob_buffer(id), blob_size(id));
447
+ BLOB_APPEND_LITERAL(ob, "</code>&nbsp;] "
448
+ "<i>was defined but is not referenced</i>\n"
449
+ "<pre><code class='language-markdown'>");
450
+ html_escape(ob, blob_buffer(text), blob_size(text));
451
+ BLOB_APPEND_LITERAL(ob,"</code></pre>");
448452
}
449453
BLOB_APPEND_LITERAL(ob, "\n</li>\n");
450454
}
451455
static void html_footnotes(
452456
struct Blob *ob, const struct Blob *items, void *opaque
453457
--- src/markdown_html.c
+++ src/markdown_html.c
@@ -435,18 +435,22 @@
435 }
436 BLOB_APPEND_LITERAL(ob,"</sup>\n");
437 BLOB_APPEND_BLOB(ob, text);
438 }else{
439 /* a footnote was defined but wasn't used */
 
 
440 assert( text );
441 assert( blob_size(text) );
442 /* FIXME: not yet implemented */
443 return;
444 BLOB_APPEND_LITERAL(ob,
445 "<li class='unreferenced-footnote' id='unreferenced-footnote");
446 blob_appendf(ob,"%s-%i'>\n", unique, iMark);
447 BLOB_APPEND_BLOB(ob, text);
 
 
448 }
449 BLOB_APPEND_LITERAL(ob, "\n</li>\n");
450 }
451 static void html_footnotes(
452 struct Blob *ob, const struct Blob *items, void *opaque
453
--- src/markdown_html.c
+++ src/markdown_html.c
@@ -435,18 +435,22 @@
435 }
436 BLOB_APPEND_LITERAL(ob,"</sup>\n");
437 BLOB_APPEND_BLOB(ob, text);
438 }else{
439 /* a footnote was defined but wasn't used */
440 /* make.footnote_item() invocations should pass args accordingly */
441 const struct Blob * id = text-1;
442 assert( text );
443 assert( blob_size(text) );
444 assert( blob_size(id) );
445 BLOB_APPEND_LITERAL(ob,"<li class='unreferenced'>\n[^&nbsp;<code>");
446 html_escape(ob, blob_buffer(id), blob_size(id));
447 BLOB_APPEND_LITERAL(ob, "</code>&nbsp;] "
448 "<i>was defined but is not referenced</i>\n"
449 "<pre><code class='language-markdown'>");
450 html_escape(ob, blob_buffer(text), blob_size(text));
451 BLOB_APPEND_LITERAL(ob,"</code></pre>");
452 }
453 BLOB_APPEND_LITERAL(ob, "\n</li>\n");
454 }
455 static void html_footnotes(
456 struct Blob *ob, const struct Blob *items, void *opaque
457
--- test/markdown-test3.md
+++ test/markdown-test3.md
@@ -3,15 +3,19 @@
33
================================
44
55
**This document** should help with testing of footnotes support that
66
is introduced by the ["`markdown-footnotes`"][branch] branch.
77
It **might look pretty misformatted unless rendered by the proper Fossil
8
-executable that incorporates the abovementioned branch.**[^1]
8
+executable** that incorporates the abovementioned branch.[^1]
9
+That is also a humble attempt to explore the robustness of the Markdown parser.
10
+So please excuse for the mess in the [source code of this document][src].
11
+By no means the normal use of footnotes should look that scarry.
912
1013
Developers are invited to add test cases here[^here].
1114
It is suggested that the more simple is a test case the earlier it should
1215
appear in this document.[^ if glitch occurs ]
16
+
1317
1418
[^lost3]: This note was defined at the begining of the document.
1519
1620
[^duplicate]: This came from the begining of the document.
1721
@@ -28,12 +32,16 @@
2832
2933
[^lost2]: This note was defined in the middle of the document.
3034
It references [its previous][^lost3]
3135
and [the forthcoming][^lost1] siblings.
3236
33
-[^i am unreferenced]: If this is rendered wihin footnotes,
34
- then there is a BUG!
37
+[^i am strayed]:
38
+ This should be presented **verbatim** (without any [markup][^])
39
+ in the end of the footnotes.
40
+
41
+ Default skin renders label in red bold font and the main text as gray.
42
+ Other styling may also apply.
3543
3644
Inline footnotes are supported.(^These may be usefull for adding
3745
<s>small</s> comments.)
3846
3947
If [undefined label is used][^] then red "`misref`" is emited instead of
@@ -52,10 +60,12 @@
5260
5361
[^ 1]: Footnotes is a Fossil' extention of
5462
Markdown. Your other tools may have limited support for these.
5563
5664
[^here]: [History of test/markdown-test3.md](/finfo/test/markdown-test3.md)
65
+
66
+[src]: /file/test/markdown-test3.md?ci=markdown-footnotes&txt&ln
5767
5868
[^if glitch occurs]:
5969
So that simple cases are processed even if
6070
a glitch happens for more tricky cases.
6171
@@ -76,8 +86,10 @@
7686
It defines an inline note.
7787
7888
(^This is inline note defined inside of [a labeled note][^lost1].)
7989
8090
[^markup]: E.g. *emphasis*, and [so on](/md_rules).
91
+ BTW, this note may not have a backreference to the "stray".
8192
8293
[^undefined label is used]: For example due to a typo.
8394
95
+[^another stray]: Just to verify the correctness of ordering and styling.
8496
--- test/markdown-test3.md
+++ test/markdown-test3.md
@@ -3,15 +3,19 @@
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 [^lost3]: This note was defined at the begining of the document.
15
16 [^duplicate]: This came from the begining of the document.
17
@@ -28,12 +32,16 @@
28
29 [^lost2]: This note was defined in the middle of the document.
30 It references [its previous][^lost3]
31 and [the forthcoming][^lost1] siblings.
32
33 [^i am unreferenced]: If this is rendered wihin footnotes,
34 then there is a BUG!
 
 
 
 
35
36 Inline footnotes are supported.(^These may be usefull for adding
37 <s>small</s> comments.)
38
39 If [undefined label is used][^] then red "`misref`" is emited instead of
@@ -52,10 +60,12 @@
52
53 [^ 1]: Footnotes is a Fossil' extention of
54 Markdown. Your other tools may have limited support for these.
55
56 [^here]: [History of test/markdown-test3.md](/finfo/test/markdown-test3.md)
 
 
57
58 [^if glitch occurs]:
59 So that simple cases are processed even if
60 a glitch happens for more tricky cases.
61
@@ -76,8 +86,10 @@
76 It defines an inline note.
77
78 (^This is inline note defined inside of [a labeled note][^lost1].)
79
80 [^markup]: E.g. *emphasis*, and [so on](/md_rules).
 
81
82 [^undefined label is used]: For example due to a typo.
83
 
84
--- test/markdown-test3.md
+++ test/markdown-test3.md
@@ -3,15 +3,19 @@
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 That is also a humble attempt to explore the robustness of the Markdown parser.
10 So please excuse for the mess in the [source code of this document][src].
11 By no means the normal use of footnotes should look that scarry.
12
13 Developers are invited to add test cases here[^here].
14 It is suggested that the more simple is a test case the earlier it should
15 appear in this document.[^ if glitch occurs ]
16
17
18 [^lost3]: This note was defined at the begining of the document.
19
20 [^duplicate]: This came from the begining of the document.
21
@@ -28,12 +32,16 @@
32
33 [^lost2]: This note was defined in the middle of the document.
34 It references [its previous][^lost3]
35 and [the forthcoming][^lost1] siblings.
36
37 [^i am strayed]:
38 This should be presented **verbatim** (without any [markup][^])
39 in the end of the footnotes.
40
41 Default skin renders label in red bold font and the main text as gray.
42 Other styling may also apply.
43
44 Inline footnotes are supported.(^These may be usefull for adding
45 <s>small</s> comments.)
46
47 If [undefined label is used][^] then red "`misref`" is emited instead of
@@ -52,10 +60,12 @@
60
61 [^ 1]: Footnotes is a Fossil' extention of
62 Markdown. Your other tools may have limited support for these.
63
64 [^here]: [History of test/markdown-test3.md](/finfo/test/markdown-test3.md)
65
66 [src]: /file/test/markdown-test3.md?ci=markdown-footnotes&txt&ln
67
68 [^if glitch occurs]:
69 So that simple cases are processed even if
70 a glitch happens for more tricky cases.
71
@@ -76,8 +86,10 @@
86 It defines an inline note.
87
88 (^This is inline note defined inside of [a labeled note][^lost1].)
89
90 [^markup]: E.g. *emphasis*, and [so on](/md_rules).
91 BTW, this note may not have a backreference to the "stray".
92
93 [^undefined label is used]: For example due to a typo.
94
95 [^another stray]: Just to verify the correctness of ordering and styling.
96

Keyboard Shortcuts

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