|
22 | 22 | tag?)] |
23 | 23 | [footnote-ref (-> string? content?)] |
24 | 24 | [footnote-decl (-> string? pre-flow? ... part-collect-decl?)] |
| 25 | + [footnote-collect-element (-> string? (listof block?) content?)] |
25 | 26 | [footnotes-section (-> part?)])) |
26 | 27 |
|
27 | 28 | (define (make-footnote-tag tag-str |
28 | 29 | #:post [post-path #f] |
29 | 30 | #: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))) |
35 | 37 |
|
36 | 38 | (define footnote-refs-key (gensym 'footnote-refs)) |
| 39 | +(define footnote-ref-targets-key (gensym 'footnote-ref-targets)) |
37 | 40 | (define footnote-flows-key (gensym 'footnote-flows)) |
38 | 41 |
|
39 | 42 | (define (footnote-ref tag) |
|
46 | 49 | [else |
47 | 50 | (set footnote-refs-key (cons tag refs)) |
48 | 51 | (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))) |
50 | 62 | (~a number) |
51 | 63 | (make-footnote-tag tag))))) |
52 | 64 |
|
53 | 65 | (define (footnote-decl tag . pre-flows) |
54 | 66 | (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 | + '()))) |
63 | 76 |
|
64 | 77 | (define (footnotes-section) |
65 | 78 | (define (generate get set) |
66 | 79 | (define refs (get footnote-refs-key '())) |
| 80 | + (define ref-targets (get footnote-ref-targets-key (hash))) |
67 | 81 | (define-values [referenced-flows other-flows] |
68 | 82 | (partition (λ~> car (member refs)) (get footnote-flows-key '()))) |
69 | 83 |
|
| 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 | + |
70 | 100 | (define (build-item number tag+blocks) |
| 101 | + (match-define (cons tag blocks) tag+blocks) |
71 | 102 | (nested-flow |
72 | 103 | (style #f (list* (alt-tag "li") |
73 | | - (link-target (make-footnote-tag (car tag+blocks))) |
| 104 | + (link-target (make-footnote-tag tag)) |
74 | 105 | (if number |
75 | 106 | (list (attributes `([value . ,(~a number)]))) |
76 | 107 | '()))) |
77 | | - (cdr tag+blocks))) |
| 108 | + (add-ref-links blocks (reverse (hash-ref ref-targets tag '()))))) |
78 | 109 |
|
79 | 110 | ; Build the footnote items, starting with the ones that were actually |
80 | 111 | ; referenced. If a footnote was referenced that doesn’t actually exist, we |
|
0 commit comments