Skip to content

Commit 6475e37

Browse files
committed
Generate “return to reference” links in footnotes
1 parent fe3d386 commit 6475e37

File tree

3 files changed

+61
-24
lines changed

3 files changed

+61
-24
lines changed

blog/build/render/scribble.rkt

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -226,18 +226,24 @@
226226
(get-current-site-path)
227227
(tag->anchor-name (add-current-tag-prefix key)))))
228228

229-
(define/override (collect-nested-flow i ci)
229+
(define/private (collect-link-target-from-style style ci)
230230
(cond
231-
[(findf link-target? (style-properties (nested-flow-style i)))
232-
=> (λ (target) (collect-link-target (link-target-tag target) ci))])
231+
[(findf link-target? (style-properties style))
232+
=> (λ (target) (collect-link-target (link-target-tag target) ci))]))
233+
234+
(define/override (collect-nested-flow i ci)
235+
(collect-link-target-from-style (nested-flow-style i) ci)
233236
(super collect-nested-flow i ci))
234237

235238
(define/override (collect-paragraph i ci)
236-
(cond
237-
[(findf link-target? (style-properties (paragraph-style i)))
238-
=> (λ (target) (collect-link-target (link-target-tag target) ci))])
239+
(collect-link-target-from-style (paragraph-style i) ci)
239240
(super collect-paragraph i ci))
240241

242+
(define/override (collect-content i ci)
243+
(when (and (element? i) (style? (element-style i)))
244+
(collect-link-target-from-style (element-style i) ci))
245+
(super collect-content i ci))
246+
241247
(define/override (collect-target-element i ci)
242248
(when (redirect-target-element? i)
243249
(raise-arguments-error 'collect-target-element "redirect targets not supported"

blog/lang/footnote.rkt

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,21 @@
2222
tag?)]
2323
[footnote-ref (-> string? content?)]
2424
[footnote-decl (-> string? pre-flow? ... part-collect-decl?)]
25+
[footnote-collect-element (-> string? (listof block?) content?)]
2526
[footnotes-section (-> part?)]))
2627

2728
(define (make-footnote-tag tag-str
2829
#:post [post-path #f]
2930
#:tag-prefixes [tag-prefixes '()])
30-
`(footnote ,(taglet-add-prefix (cons 'prefixable
31-
(if post-path
32-
(cons post-path tag-prefixes)
33-
tag-prefixes))
34-
tag-str)))
31+
`(footnote ,(taglet-add-prefix
32+
(cons 'prefixable
33+
(if post-path
34+
(cons (blog-post-path->tag-prefix post-path) tag-prefixes)
35+
tag-prefixes))
36+
tag-str)))
3537

3638
(define footnote-refs-key (gensym 'footnote-refs))
39+
(define footnote-ref-targets-key (gensym 'footnote-ref-targets))
3740
(define footnote-flows-key (gensym 'footnote-flows))
3841

3942
(define (footnote-ref tag)
@@ -46,35 +49,63 @@
4649
[else
4750
(set footnote-refs-key (cons tag refs))
4851
(add1 (length refs))]))
49-
(link-element (style 'superscript '())
52+
53+
(define all-ref-targets (get footnote-ref-targets-key (hash)))
54+
(define ref-targets (hash-ref all-ref-targets tag '()))
55+
(define ref-target `(footnote-ref (prefixable ,tag ,(~a (add1 (length ref-targets))))))
56+
(set footnote-ref-targets-key
57+
(hash-set all-ref-targets
58+
tag
59+
(cons ref-target ref-targets)))
60+
61+
(link-element (style 'superscript (list (link-target ref-target)))
5062
(~a number)
5163
(make-footnote-tag tag)))))
5264

5365
(define (footnote-decl tag . pre-flows)
5466
(part-collect-decl
55-
(element
56-
#f
57-
(traverse-element
58-
(λ (get set)
59-
(set footnote-flows-key
60-
(cons (cons tag (decode-flow pre-flows))
61-
(get footnote-flows-key '())))
62-
'())))))
67+
(element #f (footnote-collect-element tag (decode-flow pre-flows)))))
68+
69+
(define (footnote-collect-element tag blocks)
70+
(traverse-element
71+
(λ (get set)
72+
(set footnote-flows-key
73+
(cons (cons tag blocks)
74+
(get footnote-flows-key '())))
75+
'())))
6376

6477
(define (footnotes-section)
6578
(define (generate get set)
6679
(define refs (get footnote-refs-key '()))
80+
(define ref-targets (get footnote-ref-targets-key (hash)))
6781
(define-values [referenced-flows other-flows]
6882
(partition (λ~> car (member refs)) (get footnote-flows-key '())))
6983

84+
; Tacks the ↩ “return to reference” links onto the end of the footnote’s
85+
; flow, folding them into a trailing paragraph if at all possible.
86+
(define (add-ref-links blocks ref-tags)
87+
(cond
88+
[(empty? ref-tags) blocks]
89+
[else
90+
(define ref-links (~> (for/list ([ref-tag (in-list ref-tags)])
91+
(link-element #f "" ref-tag))
92+
(add-between " ")))
93+
(reverse
94+
(match (reverse blocks)
95+
[(cons (paragraph p-style p-content) blocks)
96+
(cons (paragraph p-style (list* p-content " " ref-links)) blocks)]
97+
[blocks
98+
(cons (paragraph plain ref-links) blocks)]))]))
99+
70100
(define (build-item number tag+blocks)
101+
(match-define (cons tag blocks) tag+blocks)
71102
(nested-flow
72103
(style #f (list* (alt-tag "li")
73-
(link-target (make-footnote-tag (car tag+blocks)))
104+
(link-target (make-footnote-tag tag))
74105
(if number
75106
(list (attributes `([value . ,(~a number)])))
76107
'())))
77-
(cdr tag+blocks)))
108+
(add-ref-links blocks (reverse (hash-ref ref-targets tag '())))))
78109

79110
; Build the footnote items, starting with the ones that were actually
80111
; referenced. If a footnote was referenced that doesn’t actually exist, we

blog/markdown/to-scribble.rkt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
(only-in "../lang/post-language.rkt"
1414
code
1515
code-block
16-
footnote-decl
16+
footnote-collect-element
1717
footnote-ref
1818
footnotes-section
1919
pygments-block)
@@ -48,7 +48,7 @@
4848
(define (footnotes->decl-elements notes)
4949
(for/list ([note (in-list notes)])
5050
(match-define (cons name md-blocks) note)
51-
(part-collect-decl-element (footnote-decl name (blocks->blocks md-blocks)))))
51+
(footnote-collect-element name (blocks->blocks md-blocks))))
5252

5353
(define (blocks->part md-blocks part-info)
5454
(define (collect-blocks blocks md-blocks)

0 commit comments

Comments
 (0)