Skip to content

Commit

Permalink
Multiline footnotes (#553)
Browse files Browse the repository at this point in the history
  • Loading branch information
zegl authored Mar 21, 2024
1 parent c54d30d commit 1565e99
Show file tree
Hide file tree
Showing 2 changed files with 178 additions and 1 deletion.
143 changes: 143 additions & 0 deletions index.compiler.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3529,6 +3529,149 @@ describe('footnotes', () => {
</span>
`)
})

it('should handle multiline footnotes', () => {
render(
compiler(theredoc`
foo[^abc] bar
[^abc]: Baz
line2
line3
After footnotes content
`)
)

expect(root.innerHTML).toMatchInlineSnapshot(`
<div>
<div>
<p>
foo
<a href="#abc">
<sup>
abc
</sup>
</a>
bar
</p>
<p>
After footnotes content
</p>
</div>
<footer>
<div id="abc">
abc: Baz
line2
line3
</div>
</footer>
</div>
`)
})

it('should handle mixed multiline and singleline footnotes', () => {
render(
compiler(theredoc`
a[^a] b[^b] c[^c]
[^a]: single
[^b]: bbbb
bbbb
bbbb
[^c]: single-c
`)
)

expect(root.innerHTML).toMatchInlineSnapshot(`
<div>
<p>
a
<a href="#a">
<sup>
a
</sup>
</a>
b
<a href="#b">
<sup>
b
</sup>
</a>
c
<a href="#c">
<sup>
c
</sup>
</a>
</p>
<footer>
<div id="a">
a: single
</div>
<div id="b">
b: bbbb
bbbb
bbbb
</div>
<div id="c">
c: single-c
</div>
</footer>
</div>
`)
})

it('should handle indented multiline footnote', () => {
render(
compiler(theredoc`
Here's a simple footnote,[^1] and here's a longer one.[^bignote]
[^1]: This is the first footnote.
[^bignote]: Here's one with multiple paragraphs and code.
Indent paragraphs to include them in the footnote.
\`{ my code }\`
Add as many paragraphs as you like.
`)
)

expect(root.innerHTML).toMatchInlineSnapshot(`
<div>
<p>
Here's a simple footnote,
<a href="#1">
<sup>
1
</sup>
</a>
and here's a longer one.
<a href="#bignote">
<sup>
bignote
</sup>
</a>
</p>
<footer>
<div id="1">
1: This is the first footnote.
</div>
<div id="bignote">
bignote: Here's one with multiple paragraphs and code.
Indent paragraphs to include them in the footnote.
<code>
{ my code }
</code>
Add as many paragraphs as you like.
</div>
</footer>
</div>
`)
})
})

describe('options.namedCodesToUnicode', () => {
Expand Down
36 changes: 35 additions & 1 deletion index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,41 @@ const CODE_BLOCK_R = /^(?: {4}[^\n]+\n*)+(?:\n *)+\n?/
const CODE_INLINE_R = /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/
const CONSECUTIVE_NEWLINE_R = /^(?:\n *)*\n/
const CR_NEWLINE_R = /\r\n?/g
const FOOTNOTE_R = /^\[\^([^\]]+)](:.*)\n/

/**
* Matches footnotes on the format:
*
* [^key]: value
*
* Matches multiline footnotes
*
* [^key]: row
* row
* row
*
* And empty lines in indented multiline footnotes
*
* [^key]: indented with
* row
*
* row
*
* Explanation:
*
* 1. Look for the starting tag, eg: [^key]
* ^\[\^([^\]]+)]
*
* 2. The first line starts with a colon, and continues for the rest of the line
* :(.*)
*
* 3. Parse as many additional lines as possible. Matches new non-empty lines that doesn't begin with a new footnote definition.
* (\n(?!\[\^).+)
*
* 4. ...or allows for repeated newlines if the next line begins with at least four whitespaces.
* (\n+ {4,}.*)
*/
const FOOTNOTE_R = /^\[\^([^\]]+)](:(.*)((\n+ {4,}.*)|(\n(?!\[\^).+))*)/

const FOOTNOTE_REFERENCE_R = /^\[\^([^\]]+)]/
const FORMFEED_R = /\f/g
const FRONT_MATTER_R = /^---[ \t]*\n(.|\n)*\n---[ \t]*\n/
Expand Down

0 comments on commit 1565e99

Please sign in to comment.