Fossil

Check-in [ada55cd4]
Login

Check-in [ada55cd4]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment: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 html_escape(). Default skin makes such items visible and easily distinguishable. The order of such items match the order in the underlying source code.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | markdown-footnotes
Files: files | file ages | folders
SHA3-256: ada55cd45ae34dfdf3317b3eb22551680ed6e900006668b4f99eb8e180847021
User & Date: george 2022-02-09 22:59:40
Context
2022-02-10
23:00
Clean-up and polish relevant CSS and HTML's class names. Insure visual spacing between footnotes' markers so that numbers are distinguishable when multiple footnotes in a row are used. Factor out auxiliary decorations from HTML into the default CSS, to enable customization via skins. ... (check-in: 2b1375ab user: george tags: markdown-footnotes)
2022-02-09
22:59
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 html_escape(). Default skin makes such items visible and easily distinguishable. The order of such items match the order in the underlying source code. ... (check-in: ada55cd4 user: george tags: markdown-footnotes)
20:09
Join duplicated footnotes slightly faster. Fix a comment about auxiliary cmp_footnote_id() function. ... (check-in: 7f6a6418 user: george tags: markdown-footnotes)
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/default.css.

1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684














1685
1686
1687
1688
1689
1690
1691
}
div.content  div.markdown > ol.footnotes {
  font-size: 90%;
}
div.content  div.markdown > ol.footnotes > li {
  margin-bottom: 0.5em;
}
div.markdown ol.footnotes > li.unreferenced-footnote,
div.markdown ol.footnotes > li.misreferences {
  background: #ffdddd;
}
div.markdown ol.footnotes > li.unreferenced-footnote:first-child,
div.markdown ol.footnotes > li.misreferences {
  margin-top:     0.75em;
  padding-top:    0.25em;
  padding-bottom: 0.25em;














}
div.content  div.markdown > ol.footnotes > li > .footnote-backrefs {
  margin-right: 0.5em;
  font-weight: bold;
}
div.markdown > ol.footnotes > li > .footnote-backrefs > a:target {
  background: gold;







<



|




>
>
>
>
>
>
>
>
>
>
>
>
>
>







1669
1670
1671
1672
1673
1674
1675

1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
}
div.content  div.markdown > ol.footnotes {
  font-size: 90%;
}
div.content  div.markdown > ol.footnotes > li {
  margin-bottom: 0.5em;
}

div.markdown ol.footnotes > li.misreferences {
  background: #ffdddd;
}
div.markdown ol.footnotes > li.unreferenced:first-child,
div.markdown ol.footnotes > li.misreferences {
  margin-top:     0.75em;
  padding-top:    0.25em;
  padding-bottom: 0.25em;
}
div.markdown ol.footnotes > li.unreferenced {
  padding-left: 0.5em;
  color: gray;
}
div.markdown ol.footnotes > li.unreferenced > code {
  color: red;
  font-weight: bold;
}
div.markdown ol.footnotes > li.unreferenced > pre {
  color: gray;
  padding-left: 0.5em;
  margin-top:  0.25em;
  border-left: 3px solid red;
}
div.content  div.markdown > ol.footnotes > li > .footnote-backrefs {
  margin-right: 0.5em;
  font-weight: bold;
}
div.markdown > ol.footnotes > li > .footnote-backrefs > a:target {
  background: gold;

Changes to src/markdown.c.

2668
2669
2670
2671
2672
2673
2674

2675
2676
2677
2678
2679

2680
2681
2682
2683
2684
2685

2686




2687
2688
2689
2690
2691
2692
2693
2694
      }
    }
    release_work_buffer(&rndr,tmp);

    /* footnotes rendering */
    if( rndr.make.footnote_item && rndr.make.footnotes ){
      Blob *all_items = new_work_buffer(&rndr);

      for(i=0; i<COUNT_FOOTNOTES(notes); i++){
        const struct footnote* x = CAST_AS_FOOTNOTES(notes) + i;
        if( x->bRndred ){
          rndr.make.footnote_item(all_items, &x->text, x->iMark,
                                  x->nUsed, rndr.make.opaque);

        }
      }
      if( rndr.notes.misref.nUsed ){
        rndr.make.footnote_item(all_items, 0, -1,
                    rndr.notes.misref.nUsed, rndr.make.opaque);
      }

      /* TODO: handle unreferenced (defined but not used) footnotes */





      rndr.make.footnotes(ob, all_items, rndr.make.opaque);
      release_work_buffer(&rndr, all_items);
    }
    release_work_buffer(&rndr, notes);
  }
  if( rndr.make.epilog ) rndr.make.epilog(ob, rndr.make.opaque);








>





>






>
|
>
>
>
>
|







2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
      }
    }
    release_work_buffer(&rndr,tmp);

    /* footnotes rendering */
    if( rndr.make.footnote_item && rndr.make.footnotes ){
      Blob *all_items = new_work_buffer(&rndr);
      int j = -1;
      for(i=0; i<COUNT_FOOTNOTES(notes); i++){
        const struct footnote* x = CAST_AS_FOOTNOTES(notes) + i;
        if( x->bRndred ){
          rndr.make.footnote_item(all_items, &x->text, x->iMark,
                                  x->nUsed, rndr.make.opaque);
          j = i;
        }
      }
      if( rndr.notes.misref.nUsed ){
        rndr.make.footnote_item(all_items, 0, -1,
                    rndr.notes.misref.nUsed, rndr.make.opaque);
      }
      while( ++j < COUNT_FOOTNOTES(notes) ){
        const struct footnote* x = CAST_AS_FOOTNOTES(notes) + j;
        assert( !x->nUsed );
        assert( !x->bRndred );
        assert( (&x->id) + 1 == &x->text ); /* see html_footnote_item() */
        rndr.make.footnote_item(all_items,&x->text,0,0,rndr.make.opaque);
      }
      rndr.make.footnotes(ob, all_items, rndr.make.opaque);
      release_work_buffer(&rndr, all_items);
    }
    release_work_buffer(&rndr, notes);
  }
  if( rndr.make.epilog ) rndr.make.epilog(ob, rndr.make.opaque);

Changes to src/markdown_html.c.

433
434
435
436
437
438
439


440
441
442
443



444
445

446
447
448
449
450
451
452
453
454
      }
      if( i < nUsed ) BLOB_APPEND_LITERAL(ob," &hellip;");
    }
    BLOB_APPEND_LITERAL(ob,"</sup>\n");
    BLOB_APPEND_BLOB(ob, text);
  }else{
    /* a footnote was defined but wasn't used */


    assert( text );
    assert( blob_size(text) );
    /* FIXME: not yet implemented */
    return;



    BLOB_APPEND_LITERAL(ob,
      "<li class='unreferenced-footnote' id='unreferenced-footnote");

    blob_appendf(ob,"%s-%i'>\n", unique, iMark);
    BLOB_APPEND_BLOB(ob, text);
  }
  BLOB_APPEND_LITERAL(ob, "\n</li>\n");
}
static void html_footnotes(
  struct Blob *ob, const struct Blob *items, void *opaque
){
  if( items && blob_size(items) ){







>
>


<
<
>
>
>
|
|
>
|
|







433
434
435
436
437
438
439
440
441
442
443


444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
      }
      if( i < nUsed ) BLOB_APPEND_LITERAL(ob," &hellip;");
    }
    BLOB_APPEND_LITERAL(ob,"</sup>\n");
    BLOB_APPEND_BLOB(ob, text);
  }else{
    /* a footnote was defined but wasn't used */
    /* make.footnote_item() invocations should pass args accordingly */
    const struct Blob * id = text-1;
    assert( text );
    assert( blob_size(text) );


    assert( blob_size(id) );
    BLOB_APPEND_LITERAL(ob,"<li class='unreferenced'>\n[^&nbsp;<code>");
    html_escape(ob, blob_buffer(id), blob_size(id));
    BLOB_APPEND_LITERAL(ob, "</code>&nbsp;] "
        "<i>was defined but is not referenced</i>\n"
        "<pre><code class='language-markdown'>");
    html_escape(ob, blob_buffer(text), blob_size(text));
    BLOB_APPEND_LITERAL(ob,"</code></pre>");
  }
  BLOB_APPEND_LITERAL(ob, "\n</li>\n");
}
static void html_footnotes(
  struct Blob *ob, const struct Blob *items, void *opaque
){
  if( items && blob_size(items) ){

Changes to test/markdown-test3.md.

1
2
3
4
5
6
7
8



9
10
11
12

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33


34


35
36
37
38
39
40
41

Markdown Footnotes Test Document
================================

**This document** should help with testing of footnotes support that
is introduced by the ["`markdown-footnotes`"][branch] branch.
It **might look pretty misformatted unless rendered by the proper Fossil
executable that incorporates the abovementioned branch.**[^1]




Developers are invited to add test cases here[^here].
It is suggested that the more simple is a test case the earlier it should
appear in this document.[^ if glitch occurs	]


[^lost3]: This note was defined at the begining of the document.

[^duplicate]: This came from the begining of the document.

A footnote's label should be case insensitive[^ case INSENSITIVE ],
it is whitespace-savvy and can even contain newlines.[^ a
multiline
label]

A labeled footnote may be [referenced several times][^many-refs].

A footnote's text should support Markdown [markup][^].

Another reference[^many-refs] to the preveously used footnote.

[^lost2]: This note was defined in the middle of the document.
   It references [its previous][^lost3] 
   and [the forthcoming][^lost1] siblings.

[^i am unreferenced]: If this is rendered wihin footnotes,


  then there is a BUG!



Inline footnotes are supported.(^These may be usefull for adding
<s>small</s> comments.)

If [undefined label is used][^] then red "`misref`" is emited instead of
a numeric marker.[^ see it yourself ]
This can be overridden by the skin though.







|
>
>
>




>




















|
>
>
|
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

Markdown Footnotes Test Document
================================

**This document** should help with testing of footnotes support that
is introduced by the ["`markdown-footnotes`"][branch] branch.
It **might look pretty misformatted unless rendered by the proper Fossil
executable** that incorporates the abovementioned branch.[^1]  
That is also a humble attempt to explore the robustness of the Markdown parser.
So please excuse for the mess in the [source code of this document][src].
By no means the normal use of footnotes should look that scarry.

Developers are invited to add test cases here[^here].
It is suggested that the more simple is a test case the earlier it should
appear in this document.[^ if glitch occurs	]


[^lost3]: This note was defined at the begining of the document.

[^duplicate]: This came from the begining of the document.

A footnote's label should be case insensitive[^ case INSENSITIVE ],
it is whitespace-savvy and can even contain newlines.[^ a
multiline
label]

A labeled footnote may be [referenced several times][^many-refs].

A footnote's text should support Markdown [markup][^].

Another reference[^many-refs] to the preveously used footnote.

[^lost2]: This note was defined in the middle of the document.
   It references [its previous][^lost3] 
   and [the forthcoming][^lost1] siblings.

[^i am strayed]:
  This should be presented **verbatim** (without any [markup][^])
  in the end of the footnotes.
  
  Default skin renders label in red bold font and the main text as gray.
  Other styling may also apply.

Inline footnotes are supported.(^These may be usefull for adding
<s>small</s> comments.)

If [undefined label is used][^] then red "`misref`" is emited instead of
a numeric marker.[^ see it yourself ]
This can be overridden by the skin though.
50
51
52
53
54
55
56


57
58
59
60
61
62
63

[branch]: /timeline?r=markdown-footnotes&nowiki

[^ 1]:  Footnotes is a Fossil' extention of
        Markdown. Your other tools may have limited support for these.

[^here]: [History of test/markdown-test3.md](/finfo/test/markdown-test3.md)



[^if glitch occurs]:
        So that simple cases are processed even if
        a glitch happens for more tricky cases.

[^	CASE	 insensitive  	]: And also tolerate whitespaces.








>
>







58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

[branch]: /timeline?r=markdown-footnotes&nowiki

[^ 1]:  Footnotes is a Fossil' extention of
        Markdown. Your other tools may have limited support for these.

[^here]: [History of test/markdown-test3.md](/finfo/test/markdown-test3.md)

[src]: /file/test/markdown-test3.md?ci=markdown-footnotes&txt&ln

[^if glitch occurs]:
        So that simple cases are processed even if
        a glitch happens for more tricky cases.

[^	CASE	 insensitive  	]: And also tolerate whitespaces.

74
75
76
77
78
79
80

81
82
83


[^lost1]: This note was defined at the end of the document.
   It defines an inline note.
   
   (^This is inline note defined inside of [a labeled note][^lost1].)

[^markup]:   E.g. *emphasis*, and [so on](/md_rules).


[^undefined label is used]: For example due to a typo.









>



>
84
85
86
87
88
89
90
91
92
93
94
95

[^lost1]: This note was defined at the end of the document.
   It defines an inline note.
   
   (^This is inline note defined inside of [a labeled note][^lost1].)

[^markup]:   E.g. *emphasis*, and [so on](/md_rules).
   BTW, this note may not have a backreference to the "stray".

[^undefined label is used]: For example due to a typo.

[^another stray]: Just to verify the correctness of ordering and styling.