summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--md_tw.py42
-rw-r--r--tests/data/blexer-footnotes.md24
-rw-r--r--tests/test_md_tw.py97
3 files changed, 163 insertions, 0 deletions
diff --git a/md_tw.py b/md_tw.py
index 7f9b578..352805f 100644
--- a/md_tw.py
+++ b/md_tw.py
@@ -159,6 +159,48 @@ class TWBlockLexer(mistune.BlockLexer):
'text': m.group(0)
})
+ def parse_def_footnotes(self, m):
+ key = self._keyify(m.group(1))
+ if key in self.def_footnotes:
+ # footnote is already defined
+ return
+
+ self.def_footnotes[key] = 0
+
+ text = m.group(2)
+ multiline = False
+ spaces = 0
+ if '\n' in text:
+ multiline = True
+ lines = text.split('\n')
+ whitespace = None
+ for line in lines[1:]:
+ space = len(line) - len(line.lstrip())
+ if space and (not whitespace or space < whitespace):
+ whitespace = space
+ newlines = [lines[0]]
+ for line in lines[1:]:
+ newlines.append(line[whitespace:])
+ text = '\n'.join(newlines)
+
+ if whitespace:
+ spaces = whitespace
+
+ self.tokens.append({
+ 'type': 'footnote_start',
+ 'key': key,
+ 'multiline': multiline,
+ 'spaces': spaces
+ })
+
+ self.parse(text, self.footnote_rules)
+
+ self.tokens.append({
+ 'type': 'footnote_end',
+ 'key': key,
+ 'spaces': spaces
+ })
+
class TWInlineLexer(mistune.InlineLexer):
"""Text Wrap Inline level lexer for inline gramars."""
diff --git a/tests/data/blexer-footnotes.md b/tests/data/blexer-footnotes.md
new file mode 100644
index 0000000..0bd38b5
--- /dev/null
+++ b/tests/data/blexer-footnotes.md
@@ -0,0 +1,24 @@
+This phrase has a single line footnote[^foot1].
+
+[^foot1]: Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
+
+This other phrase has a multiline footnote[^foot2].
+
+[^foot2]: Vestibulum enim wisi, viverra nec, fringilla in, laoreet
+ vitae, risus. Donec sit amet nisl. Aliquam semper ipsum sit amet
+ velit.
+
+This phrase has a blockquote in its footnote[^foot3].
+
+[^foot3]: A footnote with blockquotes
+
+ Start of block quote in footnote:
+
+ > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
+ > consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
+ > Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
+ >
+ > Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
+ > id sem consectetuer libero luctus adipiscing.
+
+ End of block quote in foot note.
diff --git a/tests/test_md_tw.py b/tests/test_md_tw.py
index 467caaf..f821f0d 100644
--- a/tests/test_md_tw.py
+++ b/tests/test_md_tw.py
@@ -480,6 +480,103 @@ class TestTWBlockLexer(object):
]
self._validate(tokens, 'def_links', expected_dls)
+ def test_parse_def_footnotes(self):
+ tokens = self._parse('blexer-footnotes.md')
+
+ def process(tokens):
+ token = tokens.pop(0)
+ while token:
+ type_ = token['type']
+
+ expected_token = None
+ if type_ in expected:
+ expected_token = expected[type_].pop(0)
+
+ validate(token, expected_token)
+
+ if type_ == 'footnote_end':
+ break
+ else:
+ token = tokens.pop(0)
+
+ return tokens
+
+ def validate(token, expected_token=None):
+ type_ = token['type']
+
+ if type_ == 'footnote_start':
+ assert 'multiline' in token
+ assert 'spaces' in token
+ elif type_ == 'footnote_end':
+ assert 'spaces' in token
+
+ if not expected_token:
+ return
+
+ if 'text' in token:
+ assert_equal(token['text'], expected_token['text'])
+ if 'spaces' in token:
+ assert_equal(token['spaces'], expected_token['spaces'])
+
+ return
+
+ # test footnote 1
+ expected = {
+ 'footnote_start': [
+ {'multiline': False, 'spaces': 0},
+ ],
+ 'paragraph': [
+ {'text': 'This phrase has a single line footnote[^foot1].'},
+ {'text': 'Lorem ipsum dolor sit amet, consectetuer'
+ ' adipiscing elit.'},
+ ],
+ 'footnote_end': [
+ {'spaces': 0}
+ ]
+ }
+ tokens = process(tokens)
+
+ # test footnote 2
+ expected = {
+ 'footnote_start': [
+ {'multiline': True, 'spaces': 4},
+ ],
+ 'paragraph': [
+ {'text': 'This other phrase has a multiline footnote[^foot2].'},
+ {'text': 'Vestibulum enim wisi, viverra nec, fringilla in, '
+ 'laoreet\nvitae, risus. Donec sit amet nisl. Aliquam '
+ 'semper ipsum sit amet\nvelit.'},
+ ],
+ 'footnote_end': [
+ {'spaces': 4}
+ ]
+ }
+ tokens = process(tokens)
+
+ # test footnote 3
+ expected = {
+ 'footnote_start': [
+ {'multiline': True, 'spaces': 3},
+ ],
+ 'paragraph': [
+ {'text': 'This phrase has a blockquote in its footnote[^foot3].'},
+ {'text': 'A footnote with blockquotes'},
+ {'text': 'Start of block quote in footnote:'},
+ {'text': 'This is a blockquote with two paragraphs. Lorem'
+ ' ipsum dolor sit amet,\nconsectetuer adipiscing elit.'
+ ' Aliquam hendrerit mi posuere lectus.\nVestibulum enim wisi,'
+ ' viverra nec, fringilla in, laoreet vitae, risus.'},
+ {'text': 'Donec sit amet nisl. Aliquam semper ipsum sit amet '
+ 'velit. Suspendisse\nid sem consectetuer libero luctus '
+ 'adipiscing.'},
+ {'text': 'End of block quote in foot note.'},
+ ],
+ 'footnote_end': [
+ {'spaces': 3}
+ ]
+ }
+ tokens = process(tokens)
+
def teardown(self):
pass