diff --git a/index.compiler.spec.tsx b/index.compiler.spec.tsx
index 190137d0..ea860d8e 100644
--- a/index.compiler.spec.tsx
+++ b/index.compiler.spec.tsx
@@ -3529,6 +3529,149 @@ describe('footnotes', () => {
`)
})
+
+ it('should handle multiline footnotes', () => {
+ render(
+ compiler(theredoc`
+ foo[^abc] bar
+
+ [^abc]: Baz
+ line2
+ line3
+
+ After footnotes content
+ `)
+ )
+
+ expect(root.innerHTML).toMatchInlineSnapshot(`
+
+
+
+ foo
+
+
+ abc
+
+
+ bar
+
+
+ After footnotes content
+
+
+
+
+ `)
+ })
+
+ 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(`
+
+ `)
+ })
+
+ 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(`
+
+
+ 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.
+
+
+
+ `)
+ })
})
describe('options.namedCodesToUnicode', () => {
diff --git a/index.tsx b/index.tsx
index 0a8e5b48..e6839eee 100644
--- a/index.tsx
+++ b/index.tsx
@@ -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/