', md.toc[:17])
+ self.assertEqual(len(md.toc_tokens), 1)
+ md.reset()
+ self.assertEqual(md.toc, '')
+ self.assertEqual(md.toc_tokens, [])
+
+ def testUniqueIds(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ '''
+ #Header
+ #Header
+ #Header
+ '''
+ ),
+ self.dedent(
+ '''
+
+
+
+ '''
+ ),
+ expected_attrs={
+ 'toc': (
+ '
\n'
+ ),
+ 'toc_tokens': [
+ {
+ 'level': 1,
+ 'id': 'header',
+ 'name': 'Header',
+ 'html': 'Header',
+ 'data-toc-label': '',
+ 'children': []
+ },
+ {
+ 'level': 1,
+ 'id': 'header_1',
+ 'name': 'Header',
+ 'html': 'Header',
+ 'data-toc-label': '',
+ 'children': []
+ },
+ {
+ 'level': 1,
+ 'id': 'header_2',
+ 'name': 'Header',
+ 'html': 'Header',
+ 'data-toc-label': '',
+ 'children': []
+ },
+ ]
+ }
+ )
+
+ def testHtmlEntitiesInTOC(self):
+ self.assertMarkdownRenders(
+ '# Foo & bar',
+ '
Foo & bar
',
+ expected_attrs={
+ 'toc': (
+ '
\n'
+ ),
+ 'toc_tokens': [{
+ 'level': 1,
+ 'id': 'foo-bar',
+ 'name': 'Foo & bar',
+ 'html': 'Foo & bar',
+ 'data-toc-label': '',
+ 'children': []
+ }]
+ }
+ )
+
+ def testHtmlSpecialCharsInTOC(self):
+ self.assertMarkdownRenders(
+ '# Foo > & bar',
+ '
Foo > & bar
',
+ expected_attrs={
+ 'toc': (
+ '
\n'
+ ),
+ 'toc_tokens': [{
+ 'level': 1,
+ 'id': 'foo-bar',
+ 'name': 'Foo > & bar',
+ 'html': 'Foo > & bar',
+ 'data-toc-label': '',
+ 'children': []
+ }]
+ }
+ )
+
+ def testRawHtmlInTOC(self):
+ self.assertMarkdownRenders(
+ '# Foo
Bar Baz.',
+ '
Foo Bar Baz.
',
+ expected_attrs={
+ 'toc': (
+ '
\n'
+ ),
+ 'toc_tokens': [{
+ 'level': 1,
+ 'id': 'foo-bar-baz',
+ 'name': 'Foo Bar Baz.',
+ 'html': 'Foo
Bar Baz.',
+ 'data-toc-label': '',
+ 'children': []
+ }]
+ }
+ )
+
+ def testTOCBaseLevel(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ '''
+ # Some Header
+ ## Next Level
+ ### Too High
+ '''
+ ),
+ self.dedent(
+ '''
+
+
Next Level
+
Too High
+ '''
+ ),
+ expected_attrs={
+ 'toc': (
+ '
\n'
+ '
\n' # noqa
+ '- Some Header' # noqa
+ '\n' # noqa
+ '
\n' # noqa
+ '
\n' # noqa
+ '
\n'
+ ),
+ 'toc_tokens': [{
+ 'level': 5,
+ 'id': 'some-header',
+ 'name': 'Some Header',
+ 'html': 'Some Header',
+ 'data-toc-label': '',
+ 'children': [
+ {
+ 'level': 6,
+ 'id': 'next-level',
+ 'name': 'Next Level',
+ 'html': 'Next Level',
+ 'data-toc-label': '',
+ 'children': []
+ },
+ {
+ 'level': 6,
+ 'id': 'too-high',
+ 'name': 'Too High',
+ 'html': 'Too High',
+ 'data-toc-label': '',
+ 'children': []
+ }
+ ]
+ }]
+ },
+ extensions=[TocExtension(baselevel=5)]
+ )
+
+ def testHeaderInlineMarkup(self):
+ self.assertMarkdownRenders(
+ '#Some *Header* with [markup](http://example.com).',
+ '',
+ expected_attrs={
+ 'toc': (
+ '
\n'
+ ),
+ 'toc_tokens': [{
+ 'level': 1,
+ 'id': 'some-header-with-markup',
+ 'name': 'Some Header with markup.',
+ 'html': 'Some
Header with
markup.',
+ 'data-toc-label': '',
+ 'children': []
+ }]
+ }
+ )
+
+ def testTOCTitle(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ '''
+ # Header 1
+
+ ## Header 2
+ '''
+ ),
+ self.dedent(
+ '''
+
+
+ '''
+ ),
+ expected_attrs={
+ 'toc': (
+ '
Table of Contents'
+ '
\n' # noqa
+ '- Header 1' # noqa
+ '\n' # noqa
+ '
\n' # noqa
+ '
\n' # noqa
+ '
\n'
+ )
+ },
+ extensions=[TocExtension(title='Table of Contents')]
+ )
+
+ def testTOCUniqueFunc(self):
+ ids = {'foo'}
+ self.assertEqual(unique('foo', ids), 'foo_1')
+ self.assertEqual(ids, {'foo', 'foo_1'})
+
+ def testTocInHeaders(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ '''
+ [TOC]
+ #[TOC]
+ '''
+ ),
+ '
\n' # noqa
+ '
\n' # noqa
+ '- [TOC]
\n' # noqa
+ '
\n' # noqa
+ '
\n' # noqa
+ '
[TOC]
' # noqa
+ )
+
+ self.assertMarkdownRenders(
+ self.dedent(
+ '''
+ #[TOC]
+ [TOC]
+ '''
+ ),
+ '
[TOC]
\n' # noqa
+ '
\n' # noqa
+ '
\n' # noqa
+ '- [TOC]
\n' # noqa
+ '
\n' # noqa
+ '
' # noqa
+ )
+
+ self.assertMarkdownRenders(
+ self.dedent(
+ '''
+ [TOC]
+ # *[TOC]*
+ '''
+ ),
+ '
\n' # noqa
+ '
\n' # noqa
+ '- [TOC]
\n' # noqa
+ '
\n' # noqa
+ '
\n' # noqa
+ '
[TOC]
' # noqa
+ )
+
+ def testTOCPermalink(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ '''
+ # Hd 1
+
+ ## Hd 2
+ '''
+ ),
+ '
'
+ 'Hd 1' # noqa
+ '' # noqa
+ '
\n'
+ '
'
+ 'Hd 2' # noqa
+ '' # noqa
+ '
',
+ extensions=[TocExtension(permalink=True, permalink_title="PL")]
+ )
+
+ def testTOCPermalinkLeading(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ '''
+ # Hd 1
+ ## Hd 2
+ '''
+ ),
+ '
'
+ '' # noqa
+ 'Hd 1' # noqa
+ '
\n'
+ '
'
+ '' # noqa
+ 'Hd 2' # noqa
+ '
',
+ extensions=[TocExtension(permalink=True, permalink_title="PL", permalink_leading=True)]
+ )
+
+ def testTOCInlineMarkupPermalink(self):
+ self.assertMarkdownRenders(
+ '# Code `in` hd',
+ '
'
+ 'Code in hd' # noqa
+ '' # noqa
+ '
',
+ extensions=[TocExtension(permalink=True, permalink_title="PL")]
+ )
+
+ def testTOCInlineMarkupPermalinkLeading(self):
+ self.assertMarkdownRenders(
+ '# Code `in` hd',
+ '
'
+ '' # noqa
+ 'Code in hd' # noqa
+ '
',
+ extensions=[TocExtension(permalink=True, permalink_title="PL", permalink_leading=True)]
+ )
def testAnchorLink(self):
self.assertMarkdownRenders(
@@ -140,11 +626,15 @@ def testMinMaxLevel(self):
'level': 3,
'id': 'header-3',
'name': 'Header 3',
+ 'html': 'Header 3',
+ 'data-toc-label': '',
'children': [
{
'level': 4,
'id': 'header-4',
'name': 'Header 4',
+ 'html': 'Header 4',
+ 'data-toc-label': '',
'children': []
}
]
@@ -189,11 +679,15 @@ def testMaxLevel(self):
'level': 1,
'id': 'header-1',
'name': 'Header 1',
+ 'html': 'Header 1',
+ 'data-toc-label': '',
'children': [
{
'level': 2,
'id': 'header-2',
'name': 'Header 2',
+ 'html': 'Header 2',
+ 'data-toc-label': '',
'children': []
}
]
@@ -245,11 +739,15 @@ def testMinMaxLevelwithAnchorLink(self):
'level': 3,
'id': 'header-3',
'name': 'Header 3',
+ 'html': 'Header 3',
+ 'data-toc-label': '',
'children': [
{
'level': 4,
'id': 'header-4',
'name': 'Header 4',
+ 'html': 'Header 4',
+ 'data-toc-label': '',
'children': []
}
]
@@ -301,11 +799,15 @@ def testMinMaxLevelwithPermalink(self):
'level': 3,
'id': 'header-3',
'name': 'Header 3',
+ 'html': 'Header 3',
+ 'data-toc-label': '',
'children': [
{
'level': 4,
'id': 'header-4',
'name': 'Header 4',
+ 'html': 'Header 4',
+ 'data-toc-label': '',
'children': []
}
]
@@ -353,11 +855,15 @@ def testMinMaxLevelwithBaseLevel(self):
'level': 4,
'id': 'second-level',
'name': 'Second Level',
+ 'html': 'Second Level',
+ 'data-toc-label': '',
'children': [
{
'level': 5,
'id': 'third-level',
'name': 'Third Level',
+ 'html': 'Third Level',
+ 'data-toc-label': '',
'children': []
}
]
@@ -402,11 +908,15 @@ def testMaxLevelwithBaseLevel(self):
'level': 2,
'id': 'some-header',
'name': 'Some Header',
+ 'html': 'Some Header',
+ 'data-toc-label': '',
'children': [
{
'level': 3,
'id': 'next-level',
'name': 'Next Level',
+ 'html': 'Next Level',
+ 'data-toc-label': '',
'children': []
}
]
@@ -455,6 +965,32 @@ def test_escaped_char_in_id(self):
'level': 1,
'id': 'escaped_character',
'name': 'escaped_character',
+ 'html': 'escaped_character',
+ 'data-toc-label': '',
+ 'children': []
+ }
+ ]
+ },
+ extensions=['toc']
+ )
+
+ def testAutoLinkEmail(self):
+ self.assertMarkdownRenders(
+ '##
',
+ '',
+ expected_attrs={
+ 'toc_tokens': [
+ {
+ 'level': 2,
+ 'id': 'fooexampleorg',
+ 'name': 'foo@exam'
+ 'ple.org',
+ 'html': 'foo'
+ '@example.org',
+ 'data-toc-label': '',
'children': []
}
]
@@ -671,3 +1207,247 @@ def testTOCWithCustomTitleClass(self):
),
extensions=[TocExtension(title_class="tocname", title='ToC')]
)
+
+ def testTocWithAttrList(self):
+
+ self.assertMarkdownRenders(
+ self.dedent(
+ '''
+ # Header 1
+
+ ## Header 2 { #foo }
+
+ ## Header 3 { data-toc-label="Foo Bar" }
+
+ # Header 4 { data-toc-label="Foo > & < Baz" }
+
+ # Header 5 { data-toc-label="Foo Quux" }
+ '''
+ ),
+ self.dedent(
+ '''
+
+ Header 2
+
+
+
+ '''
+ ),
+ expected_attrs={
+ 'toc': (
+ '\n'
+ ),
+ 'toc_tokens': [
+ {
+ 'level': 1,
+ 'id': 'header-1',
+ 'name': 'Header 1',
+ 'html': 'Header 1',
+ 'data-toc-label': '',
+ 'children': [
+ {
+ 'level': 2,
+ 'id': 'foo',
+ 'name': 'Header 2',
+ 'html': 'Header 2',
+ 'data-toc-label': '',
+ 'children': []
+ },
+ {
+ 'level': 2,
+ 'id': 'header-3',
+ 'name': 'Foo Bar',
+ 'html': 'Header 3',
+ 'data-toc-label': 'Foo Bar',
+ 'children': []
+ }
+ ]
+ },
+ {
+ 'level': 1,
+ 'id': 'header-4',
+ 'name': 'Foo > & < Baz',
+ 'html': 'Header 4',
+ 'data-toc-label': 'Foo > & < Baz',
+ 'children': []
+ },
+ {
+ 'level': 1,
+ 'id': 'header-5',
+ 'name': 'Foo Quux',
+ 'html': 'Header 5',
+ 'data-toc-label': 'Foo Quux',
+ 'children': []
+ },
+ ]
+ },
+ extensions=[TocExtension(), 'attr_list']
+ )
+
+ def testHeadingRemoveFootnoteRef(self):
+
+ self.assertMarkdownRenders(
+ self.dedent(
+ '''
+ # Header 1[^1]
+ # Header[^1] 2
+ # Header *subelement*[^1] 3
+ # Header[^1] double[^1] 4
+
+ [^1]: footnote
+ '''
+ ),
+ (
+ '\n'
+ '\n'
+ '\n'
+ '\n'
+ ''
+ ),
+ expected_attrs={
+ 'toc': (
+ '\n' # noqa
+ ),
+ 'toc_tokens': [
+ {
+ 'level': 1,
+ 'id': 'header-1',
+ 'name': 'Header 1',
+ 'html': 'Header 1',
+ 'data-toc-label': '',
+ 'children': []
+ },
+ {
+ 'level': 1,
+ 'id': 'header-2',
+ 'name': 'Header 2',
+ 'html': 'Header 2',
+ 'data-toc-label': '',
+ 'children': []
+ },
+ {
+ 'level': 1,
+ 'id': 'header-subelement-3',
+ 'name': 'Header subelement 3',
+ 'html': 'Header subelement 3',
+ 'data-toc-label': '',
+ 'children': []
+ },
+ {
+ 'level': 1,
+ 'id': 'header-double-4',
+ 'name': 'Header double 4',
+ 'html': 'Header double 4',
+ 'data-toc-label': '',
+ 'children': []
+ }
+ ]
+ },
+ extensions=[TocExtension(), 'footnotes']
+ )
+
+
+class testStripTags(TestCase):
+
+ def testStripElement(self):
+ self.assertEqual(
+ strip_tags('foo bar'),
+ 'foo bar'
+ )
+
+ def testStripOpenElement(self):
+ self.assertEqual(
+ strip_tags('foo bar'),
+ 'foo bar'
+ )
+
+ def testStripEmptyElement(self):
+ self.assertEqual(
+ strip_tags('foo
bar'),
+ 'foo bar'
+ )
+
+ def testDontStripOpenBracket(self):
+ self.assertEqual(
+ strip_tags('foo < bar'),
+ 'foo < bar'
+ )
+
+ def testDontStripCloseBracket(self):
+ self.assertEqual(
+ strip_tags('foo > bar'),
+ 'foo > bar'
+ )
+
+ def testStripCollapseWhitespace(self):
+ self.assertEqual(
+ strip_tags('foo \tbar\t'),
+ 'foo bar'
+ )
+
+ def testStripElementWithNewlines(self):
+ self.assertEqual(
+ strip_tags('foo bar'),
+ 'foo bar'
+ )
+
+ def testStripComment(self):
+ self.assertEqual(
+ strip_tags('foo bar'),
+ 'foo bar'
+ )
+
+ def testStripCommentWithInnerTags(self):
+ self.assertEqual(
+ strip_tags('foo bar'),
+ 'foo bar'
+ )
+
+ def testStripCommentInElement(self):
+ self.assertEqual(
+ strip_tags('foo bar'),
+ 'foo bar'
+ )
+
+ def testDontStripHTMLEntities(self):
+ self.assertEqual(
+ strip_tags('foo < & < bar'),
+ 'foo < & < bar'
+ )