From 07b8b2c90a92c20fb0740d5527c6a219d2afb7ae Mon Sep 17 00:00:00 2001 From: Waylan Limberg Date: Thu, 6 Apr 2023 19:21:46 -0400 Subject: Use pyspelling to check spelling. In addition to checking the spelling in our documentation, we are now also checking the spelling of the README.md and similar files as well as comments in our Python code. --- .pyspelling.yml | 88 +++++++++++++++++++++ .spell-dict | 28 ++++++- checkspelling.sh | 38 --------- docs/authors.md | 2 +- docs/change_log/index.md | 6 +- docs/change_log/release-3.3.md | 2 +- docs/contributing.md | 5 +- docs/test_tools.md | 4 +- markdown/__main__.py | 4 +- markdown/__meta__.py | 12 +-- markdown/blockparser.py | 22 +++--- markdown/blockprocessors.py | 99 ++++++++++++------------ markdown/core.py | 86 ++++++++++---------- markdown/extensions/__init__.py | 10 +-- markdown/extensions/abbr.py | 6 +- markdown/extensions/admonition.py | 6 +- markdown/extensions/attr_list.py | 22 +++--- markdown/extensions/codehilite.py | 48 ++++++------ markdown/extensions/def_list.py | 4 +- markdown/extensions/extra.py | 2 +- markdown/extensions/fenced_code.py | 20 ++--- markdown/extensions/footnotes.py | 24 +++--- markdown/extensions/legacy_attrs.py | 4 +- markdown/extensions/legacy_em.py | 2 +- markdown/extensions/md_in_html.py | 37 ++++----- markdown/extensions/meta.py | 2 +- markdown/extensions/nl2br.py | 4 +- markdown/extensions/smarty.py | 8 +- markdown/extensions/tables.py | 2 +- markdown/extensions/toc.py | 23 +++--- markdown/extensions/wikilinks.py | 4 +- markdown/htmlparser.py | 32 ++++---- markdown/inlinepatterns.py | 64 +++++++-------- markdown/postprocessors.py | 2 +- markdown/serializers.py | 10 +-- markdown/test_tools.py | 26 +++---- markdown/treeprocessors.py | 82 ++++++++++---------- markdown/util.py | 22 +++--- tests/test_apis.py | 72 ++++++++--------- tests/test_extensions.py | 20 ++--- tests/test_legacy.py | 26 +++---- tests/test_syntax/blocks/test_html_blocks.py | 2 +- tests/test_syntax/extensions/test_attr_list.py | 2 +- tests/test_syntax/extensions/test_code_hilite.py | 18 ++--- tests/test_syntax/extensions/test_fenced_code.py | 6 +- tests/test_syntax/extensions/test_footnotes.py | 4 +- tests/test_syntax/extensions/test_md_in_html.py | 4 +- tests/test_syntax/extensions/test_tables.py | 2 +- tox.ini | 6 +- 49 files changed, 544 insertions(+), 480 deletions(-) create mode 100644 .pyspelling.yml delete mode 100755 checkspelling.sh diff --git a/.pyspelling.yml b/.pyspelling.yml new file mode 100644 index 0000000..bede971 --- /dev/null +++ b/.pyspelling.yml @@ -0,0 +1,88 @@ +spellchecker: aspell + +matrix: +- name: mkdocs + group: docs + sources: + - site/**/*.html + aspell: + lang: en + d: en_US + dictionary: + wordlists: + - .spell-dict + output: build/dictionary/mkdocs.dic + pipeline: + - pyspelling.filters.html: + comments: false + attributes: + - title + - alt + ignores: + - 'code, pre' + captures: + - '[role=main] *|*:not(script,style)' + - pyspelling.filters.context: + context_visible_first: true + delimiters: + # Ignore possessive endings + - open: '(?<=\w)’s(?!\w)' + close: '\b' + - pyspelling.filters.url: + +- name: markdown + group: docs + sources: + - README.md + - INSTALL.md + - LICENSE.md + - CODE_OF_CONDUCT.md + aspell: + lang: en + d: en_US + mode: markdown + dictionary: + wordlists: + - .spell-dict + output: build/dictionary/markdown.dic + +- name: python + group: source + sources: + - '{markdown,tests}/**/*.py' + aspell: + lang: en + d: en_US + mode: markdown + dictionary: + wordlists: + - .spell-dict + output: build/dictionary/python.dic + pipeline: + - pyspelling.filters.python: + group_comments: true + - pyspelling.flow_control.wildcard: + allow: + - py-comment + - pyspelling.filters.context: + context_visible_first: true + delimiters: + # Ignore lint (noqa) and coverage (pragma) as well as shebang (#!) + - open: '^(?: *(?:noqa\b|pragma: no cover)|!)' + close: '$' + # Ignore Python encoding string -*- encoding stuff -*- + - open: '^ *-\*-' + close: '-\*-$' + # Ignore possessive endings + - open: '(?<=\w)''s(?!\w)' + close: '\b' + - pyspelling.filters.context: + context_visible_first: true + escapes: '\\[\\`]' + delimiters: + # Ignore lines which are inedented at least one level (Markdown code block) + # For some reason indented code blocks are not properly ignored by aspell in markdown mode. + # Warning: This could ignore a nested list item + - open: '^ {4,}' + close: '$' + - pyspelling.filters.url: diff --git a/.spell-dict b/.spell-dict index 6408100..539ae33 100644 --- a/.spell-dict +++ b/.spell-dict @@ -38,6 +38,7 @@ Fortin GitHub globals Gruber +Gruber's GSoC hacky HeaderId @@ -59,6 +60,7 @@ Manfed markdownFromFile Maruku md +merchantability metadata MkDocs multi @@ -88,6 +90,8 @@ PYTHONPATH PyTidyLib PyYAML rc +redistribution +redistributions refactor refactored refactors @@ -104,6 +108,7 @@ setuptools Sergej serializer serializers +sexualized Shachnev sitemap slugify @@ -119,7 +124,7 @@ SuperFences svn Swartz Szakmeister -Takteyev +Takhteyev Tiago toc tokenized @@ -161,3 +166,24 @@ plugins configs pre formatters + +dedented +Setext +unindented +monkeypatch +TODO +Nko +Thaana +Tifinagh +backport +Fredrik +Lundh +subclass +tortious +performantly +Seemant +Kulleen +Serafim +overridable +unescaped +APIs diff --git a/checkspelling.sh b/checkspelling.sh deleted file mode 100755 index acd504e..0000000 --- a/checkspelling.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash - -echo "Building docs..." -mkdocs build --strict -if [ $? -ne 0 ]; then - exit 1 -fi -echo "Compiling Dictionary..." -aspell --lang=en create master ./tmp <.spell-dict -if [ $? -ne 0 ]; then - exit 1 -fi -echo "Checking spelling..." - -let "fails=0" - -for file in $(find site/ -type f -name "*.html"); do - words=$(aspell list --lang=en --mode=html --add-html-skip=code --extra-dicts=./tmp <$file) - if [ "$words" ]; then - uniquewords=$(tr ' ' '\n' <<< "${words[@]}" | sort -u | tr '\n' ' ') - let "fails++" - echo "Misspelled words in '$file':" - echo "-----------------------------------------------------------------" - for word in ${uniquewords[@]}; do - echo $word - done - echo "-----------------------------------------------------------------" - fi -done -rm -f ./tmp -rm -rf site - -if [ $fails -gt 0 ]; then - echo "$fails files with misspelled words." - exit 1 -else - exit 0 -fi diff --git a/docs/authors.md b/docs/authors.md index 114227d..b929172 100644 --- a/docs/authors.md +++ b/docs/authors.md @@ -22,7 +22,7 @@ Primary Authors and has been assisting with maintenance, reviewing pull requests and ticket triage. -* __[Yuri Takteyev](https://github.com/yuri)__ +* __[Yuri Takhteyev](https://github.com/yuri)__ Yuri wrote most of the code found in version 1.x while procrastinating his Ph.D. Various pieces of his code still exist, most notably the basic diff --git a/docs/change_log/index.md b/docs/change_log/index.md index f6159d2..584583f 100644 --- a/docs/change_log/index.md +++ b/docs/change_log/index.md @@ -182,10 +182,10 @@ August 18 2008: Reorganized directory structure. Added a 'docs' directory and moved all extensions into a 'markdown-extensions' package. Added additional documentation and a few bug fixes. (v2.0-beta) -August 4 2008: Updated included extensions to ElementTree. Added a +August 4 2008: Updated included extensions to `ElementTree`. Added a separate command line script. (v2.0-alpha) -July 2008: Switched from home-grown NanoDOM to ElementTree and +July 2008: Switched from home-grown `NanoDOM` to `ElementTree` and various related bugs (thanks Artem Yunusov). June 2008: Fixed issues with nested inline patterns and cleaned @@ -310,7 +310,7 @@ syntax in headers (e.g. links) and got the lists to use p-tags correctly (v. 0.8) Aug. 29, 2005: Added flexible tabs, fixed a few small issues, added -basic support for footnotes. Got rid of xml.dom.minidom and added +basic support for footnotes. Got rid of `xml.dom.minidom` and added pretty-printing. (v. 0.7) Aug. 13, 2005: Fixed a number of small bugs in order to conform to the diff --git a/docs/change_log/release-3.3.md b/docs/change_log/release-3.3.md index 79e22b2..49b0bcf 100644 --- a/docs/change_log/release-3.3.md +++ b/docs/change_log/release-3.3.md @@ -66,7 +66,7 @@ The following new features have been included in the 3.3 release: blocks when the `attr_list` extension is enabled (#816). * The HTML parser has been completely replaced. The new HTML parser is built on Python's - [html.parser.HTMLParser](https://docs.python.org/3/library/html.parser.html), which + [`html.parser.HTMLParser`](https://docs.python.org/3/library/html.parser.html), which alleviates various bugs and simplify maintenance of the code (#803, #830). * The [Markdown in HTML](../extensions/md_in_html.md) extension has been rebuilt on the diff --git a/docs/contributing.md b/docs/contributing.md index 5022e45..b794e2f 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -421,8 +421,9 @@ following steps: - Deploy an update to the documentation using [MkDocs]. The following example assumes that local clones of the [Python-Markdown/markdown] and - [Python-Markdown/Python-Markdown.github.io] repositories are in sibling - directories named `markdown` and `Python-Markdown.github.io` respectively. + [`Python-Markdown/Python-Markdown.github.io`][Python-Markdown/Python-Markdown.github.io] + repositories are in sibling directories named `markdown` and `Python-Markdown.github.io` + respectively. cd Python-Markdown.github.io mkdocs gh-deploy --config-file ../markdown/mkdocs.yml --remote-branch master diff --git a/docs/test_tools.md b/docs/test_tools.md index f3ed4e5..ba8a0a8 100644 --- a/docs/test_tools.md +++ b/docs/test_tools.md @@ -12,7 +12,7 @@ Therefore, the tools are importable from `markdown.test_tools`. The test tools include two different `unittest.TestCase` subclasses: `markdown.test_tools.TestCase` and `markdown.test_tools.LegacyTestCase`. -## markdown.test_tools.TestCase +## `markdown.test_tools.TestCase` The `markdown.test_tools.TestCase` class is a `unittest.TestCase` subclass with a few additional helpers to make testing Markdown output easier. @@ -66,7 +66,7 @@ class TestHr(TestCase): ) ``` -## markdown.test_tools.LegacyTestCase +## `markdown.test_tools.LegacyTestCase` In the past Python-Markdown exclusively used file-based tests. Many of those tests still exist in Python-Markdown's test suite, including the test files from diff --git a/markdown/__main__.py b/markdown/__main__.py index 0184008..230ba34 100644 --- a/markdown/__main__.py +++ b/markdown/__main__.py @@ -146,6 +146,6 @@ def run(): # pragma: no cover if __name__ == '__main__': # pragma: no cover - # Support running module as a commandline command. - # `python -m markdown [options] [args]`. + # Support running module as a command line command. + # python -m markdown [options] [args] run() diff --git a/markdown/__meta__.py b/markdown/__meta__.py index 2914f68..4519911 100644 --- a/markdown/__meta__.py +++ b/markdown/__meta__.py @@ -20,12 +20,12 @@ License: BSD (see LICENSE.md for details). """ # __version_info__ format: -# (major, minor, patch, dev/alpha/beta/rc/final, #) -# (1, 1, 2, 'dev', 0) => "1.1.2.dev0" -# (1, 1, 2, 'alpha', 1) => "1.1.2a1" -# (1, 2, 0, 'beta', 2) => "1.2b2" -# (1, 2, 0, 'rc', 4) => "1.2rc4" -# (1, 2, 0, 'final', 0) => "1.2" +# (major, minor, patch, dev/alpha/beta/rc/final, #) +# (1, 1, 2, 'dev', 0) => "1.1.2.dev0" +# (1, 1, 2, 'alpha', 1) => "1.1.2a1" +# (1, 2, 0, 'beta', 2) => "1.2b2" +# (1, 2, 0, 'rc', 4) => "1.2rc4" +# (1, 2, 0, 'final', 0) => "1.2" __version_info__ = (3, 4, 3, 'final', 0) diff --git a/markdown/blockparser.py b/markdown/blockparser.py index b0ca4b1..501965e 100644 --- a/markdown/blockparser.py +++ b/markdown/blockparser.py @@ -26,7 +26,7 @@ from . import util class State(list): """ Track the current and nested state of the parser. - This utility class is used to track the state of the BlockParser and + This utility class is used to track the state of the `BlockParser` and support multiple levels if nesting. It's just a simple API wrapped around a list. Each time a state is set, that state is appended to the end of the list. Each time a state is reset, that state is removed from the end of @@ -58,10 +58,10 @@ class State(list): class BlockParser: - """ Parse Markdown blocks into an ElementTree object. + """ Parse Markdown blocks into an `ElementTree` object. - A wrapper class that stitches the various BlockProcessors together, - looping through them and creating an ElementTree object. + A wrapper class that stitches the various `BlockProcessors` together, + looping through them and creating an `ElementTree` object. """ def __init__(self, md): @@ -79,35 +79,35 @@ class BlockParser: This should only be called on an entire document, not pieces. """ - # Create a ElementTree from the lines + # Create an `ElementTree` from the lines self.root = etree.Element(self.md.doc_tag) self.parseChunk(self.root, '\n'.join(lines)) return etree.ElementTree(self.root) def parseChunk(self, parent, text): - """ Parse a chunk of markdown text and attach to given etree node. + """ Parse a chunk of markdown text and attach to given `etree` node. - While the ``text`` argument is generally assumed to contain multiple + While the `text` argument is generally assumed to contain multiple blocks which will be split on blank lines, it could contain only one block. Generally, this method would be called by extensions when block parsing is required. - The ``parent`` etree Element passed in is altered in place. + The `parent` `etree` Element passed in is altered in place. Nothing is returned. """ self.parseBlocks(parent, text.split('\n\n')) def parseBlocks(self, parent, blocks): - """ Process blocks of markdown text and attach to given etree node. + """ Process blocks of markdown text and attach to given `etree` node. - Given a list of ``blocks``, each blockprocessor is stepped through + Given a list of `blocks`, each `blockprocessor` is stepped through until there are no blocks left. While an extension could potentially call this method directly, it's generally expected to be used internally. This is a public method as an extension may need to add/alter - additional BlockProcessors which call this method to recursively + additional `BlockProcessors` which call this method to recursively parse a nested block. """ diff --git a/markdown/blockprocessors.py b/markdown/blockprocessors.py index 3d0ff86..e679e74 100644 --- a/markdown/blockprocessors.py +++ b/markdown/blockprocessors.py @@ -25,8 +25,8 @@ This parser handles basic parsing of Markdown blocks. It doesn't concern itself with inline elements such as **bold** or *italics*, but rather just catches blocks, lists, quotes, etc. -The BlockParser is made up of a bunch of BlockProcessors, each handling a -different type of block. Extensions may add/replace/remove BlockProcessors +The `BlockParser` is made up of a bunch of `BlockProcessors`, each handling a +different type of block. Extensions may add/replace/remove `BlockProcessors` as they need to alter how markdown blocks are parsed. """ @@ -60,10 +60,10 @@ class BlockProcessor: """ Base class for block processors. Each subclass will provide the methods below to work with the source and - tree. Each processor will need to define it's own ``test`` and ``run`` - methods. The ``test`` method should return True or False, to indicate + tree. Each processor will need to define it's own `test` and `run` + methods. The `test` method should return True or False, to indicate whether the current block should be processed by this processor. If the - test passes, the parser will call the processors ``run`` method. + test passes, the parser will call the processors `run` method. """ @@ -72,7 +72,7 @@ class BlockProcessor: self.tab_length = parser.md.tab_length def lastChild(self, parent): - """ Return the last child of an etree element. """ + """ Return the last child of an `etree` element. """ if len(parent): return parent[-1] else: @@ -104,18 +104,18 @@ class BlockProcessor: def test(self, parent, block): """ Test for block type. Must be overridden by subclasses. - As the parser loops through processors, it will call the ``test`` + As the parser loops through processors, it will call the `test` method on each to determine if the given block of text is of that - type. This method must return a boolean ``True`` or ``False``. The + type. This method must return a boolean `True` or `False`. The actual method of testing is left to the needs of that particular - block type. It could be as simple as ``block.startswith(some_string)`` + block type. It could be as simple as `block.startswith(some_string)` or a complex regular expression. As the block type may be different depending on the parent of the block (i.e. inside a list), the parent - etree element is also provided and may be used as part of the test. + `etree` element is also provided and may be used as part of the test. Keywords: - * ``parent``: A etree element which will be the parent of the block. + * ``parent``: An `etree` element which will be the parent of the block. * ``block``: A block of text from the source which has been split at blank lines. """ @@ -127,20 +127,20 @@ class BlockProcessor: When the parser determines the appropriate type of a block, the parser will call the corresponding processor's ``run`` method. This method should parse the individual lines of the block and append them to - the etree. + the `etree`. Note that both the ``parent`` and ``etree`` keywords are pointers to instances of the objects which should be edited in place. Each processor must make changes to the existing objects as there is no mechanism to return new/different objects to replace them. - This means that this method should be adding SubElements or adding text + This means that this method should be adding `SubElements` or adding text to the parent, and should remove (``pop``) or add (``insert``) items to the list of blocks. Keywords: - * ``parent``: A etree element which is the parent of the current block. + * ``parent``: An `etree` element which is the parent of the current block. * ``blocks``: A list of all remaining blocks of the document. """ pass # pragma: no cover @@ -178,26 +178,26 @@ class ListIndentProcessor(BlockProcessor): self.parser.state.set('detabbed') if parent.tag in self.ITEM_TYPES: - # It's possible that this parent has a 'ul' or 'ol' child list + # It's possible that this parent has a `ul` or `ol` child list # with a member. If that is the case, then that should be the # parent. This is intended to catch the edge case of an indented # list whose first member was parsed previous to this point - # see OListProcessor + # see `OListProcessor` if len(parent) and parent[-1].tag in self.LIST_TYPES: self.parser.parseBlocks(parent[-1], [block]) else: - # The parent is already a li. Just parse the child block. + # The parent is already a `li`. Just parse the child block. self.parser.parseBlocks(parent, [block]) elif sibling.tag in self.ITEM_TYPES: - # The sibling is a li. Use it as parent. + # The sibling is a `li`. Use it as parent. self.parser.parseBlocks(sibling, [block]) elif len(sibling) and sibling[-1].tag in self.ITEM_TYPES: # The parent is a list (``ol`` or ``ul``) which has children. - # Assume the last child li is the parent of this block. + # Assume the last child `li` is the parent of this block. if sibling[-1].text: - # If the parent li has text, that text needs to be moved to a p - # The p must be 'inserted' at beginning of list in the event - # that other children already exist i.e.; a nested sublist. + # If the parent `li` has text, that text needs to be moved to a `p` + # The `p` must be 'inserted' at beginning of list in the event + # that other children already exist i.e.; a nested sub-list. p = etree.Element('p') p.text = sibling[-1].text sibling[-1].text = '' @@ -208,7 +208,7 @@ class ListIndentProcessor(BlockProcessor): self.parser.state.reset() def create_item(self, parent, block): - """ Create a new li and parse the block with it as the parent. """ + """ Create a new `li` and parse the block with it as the parent. """ li = etree.SubElement(parent, 'li') self.parser.parseBlocks(li, [block]) @@ -221,10 +221,10 @@ class ListIndentProcessor(BlockProcessor): else: indent_level = 0 if self.parser.state.isstate('list'): - # We're in a tightlist - so we already are at correct parent. + # We're in a tight-list - so we already are at correct parent. level = 1 else: - # We're in a looselist - so we need to find parent. + # We're in a loose-list - so we need to find parent. level = 0 # Step through children of tree to find matching indent level. while indent_level > level: @@ -235,7 +235,7 @@ class ListIndentProcessor(BlockProcessor): level += 1 parent = child else: - # No more child levels. If we're short of indent_level, + # No more child levels. If we're short of `indent_level`, # we have a code block. So we stop here. break return level, parent @@ -255,14 +255,14 @@ class CodeBlockProcessor(BlockProcessor): len(sibling) and sibling[0].tag == "code"): # The previous block was a code block. As blank lines do not start # new code blocks, append this block to the previous, adding back - # linebreaks removed from the split into a list. + # line breaks removed from the split into a list. code = sibling[0] block, theRest = self.detab(block) code.text = util.AtomicString( '{}\n{}\n'.format(code.text, util.code_escape(block.rstrip())) ) else: - # This is a new codeblock. Create the elements and insert text. + # This is a new code block. Create the elements and insert text. pre = etree.SubElement(parent, 'pre') code = etree.SubElement(pre, 'code') block, theRest = self.detab(block) @@ -300,7 +300,7 @@ class BlockQuoteProcessor(BlockProcessor): # This is a new blockquote. Create a new parent element. quote = etree.SubElement(parent, 'blockquote') # Recursively parse block with blockquote as parent. - # change parser state so blockquotes embedded in lists use p tags + # change parser state so blockquotes embedded in lists use `p` tags self.parser.state.set('blockquote') self.parser.parseChunk(quote, block) self.parser.state.reset() @@ -321,11 +321,10 @@ class OListProcessor(BlockProcessor): TAG = 'ol' # The integer (python string) with which the lists starts (default=1) - # Eg: If list is initialized as) - # 3. Item - # The ol tag will get starts="3" attribute + # Example: If list is initialized as: `3. Item` + # The `ol` tag will get `starts="3"` attribute STARTSWITH = '1' - # Lazy ol - ignore startswith + # Lazy `ol` - ignore `startswith` LAZY_OL = True # List of allowed sibling tags. SIBLING_TAGS = ['ol', 'ul'] @@ -345,24 +344,24 @@ class OListProcessor(BlockProcessor): return bool(self.RE.match(block)) def run(self, parent, blocks): - # Check fr multiple items in one block. + # Check for multiple items in one block. items = self.get_items(blocks.pop(0)) sibling = self.lastChild(parent) if sibling is not None and sibling.tag in self.SIBLING_TAGS: # Previous block was a list item, so set that as parent lst = sibling - # make sure previous item is in a p- if the item has text, - # then it isn't in a p + # make sure previous item is in a `p` - if the item has text, + # then it isn't in a `p` if lst[-1].text: # since it's possible there are other children for this - # sibling, we can't just SubElement the p, we need to + # sibling, we can't just `SubElement` the `p`, we need to # insert it as the first item. p = etree.Element('p') p.text = lst[-1].text lst[-1].text = '' lst[-1].insert(0, p) - # if the last item has a tail, then the tail needs to be put in a p + # if the last item has a tail, then the tail needs to be put in a `p` # likely only when a header is not followed by a blank line lch = self.lastChild(lst[-1]) if lch is not None and lch.tail: @@ -370,7 +369,7 @@ class OListProcessor(BlockProcessor): p.text = lch.tail.lstrip() lch.tail = '' - # parse first block differently as it gets wrapped in a p. + # parse first block differently as it gets wrapped in a `p`. li = etree.SubElement(lst, 'li') self.parser.state.set('looselist') firstitem = items.pop(0) @@ -379,9 +378,9 @@ class OListProcessor(BlockProcessor): elif parent.tag in ['ol', 'ul']: # this catches the edge case of a multi-item indented list whose # first item is in a blank parent-list item: - # * * subitem1 - # * subitem2 - # see also ListIndentProcessor + # * * subitem1 + # * subitem2 + # see also `ListIndentProcessor` lst = parent else: # This is a new list so create parent with appropriate tag. @@ -398,7 +397,7 @@ class OListProcessor(BlockProcessor): # Item is indented. Parse with last item as parent self.parser.parseBlocks(lst[-1], [item]) else: - # New item. Create li and parse with it as parent + # New item. Create `li` and parse with it as parent li = etree.SubElement(lst, 'li') self.parser.parseBlocks(li, [item]) self.parser.state.reset() @@ -498,7 +497,7 @@ class SetextHeaderProcessor(BlockProcessor): class HRProcessor(BlockProcessor): """ Process Horizontal Rules. """ - # Python's re module doesn't officially support atomic grouping. However you can fake it. + # Python's `re` module doesn't officially support atomic grouping. However you can fake it. # See https://stackoverflow.com/a/13577411/866026 RE = r'^[ ]{0,3}(?=(?P(-+[ ]{0,2}){3,}|(_+[ ]{0,2}){3,}|(\*+[ ]{0,2}){3,}))(?P=atomicgroup)[ ]*$' # Detect hr on any line of a block. @@ -515,17 +514,17 @@ class HRProcessor(BlockProcessor): def run(self, parent, blocks): block = blocks.pop(0) match = self.match - # Check for lines in block before hr. + # Check for lines in block before `hr`. prelines = block[:match.start()].rstrip('\n') if prelines: - # Recursively parse lines before hr so they get parsed first. + # Recursively parse lines before `hr` so they get parsed first. self.parser.parseBlocks(parent, [prelines]) # create hr etree.SubElement(parent, 'hr') - # check for lines in block after hr. + # check for lines in block after `hr`. postlines = block[match.end():].lstrip('\n') if postlines: - # Add lines after hr to master blocks for later parsing. + # Add lines after `hr` to master blocks for later parsing. blocks.insert(0, postlines) @@ -550,7 +549,7 @@ class EmptyBlockProcessor(BlockProcessor): sibling = self.lastChild(parent) if (sibling is not None and sibling.tag == 'pre' and len(sibling) and sibling[0].tag == 'code'): - # Last block is a codeblock. Append to preserve whitespace. + # Last block is a code block. Append to preserve whitespace. sibling[0].text = util.AtomicString( '{}{}'.format(sibling[0].text, filler) ) @@ -606,7 +605,7 @@ class ParagraphProcessor(BlockProcessor): # Line 2 of list item - not part of header. sibling = self.lastChild(parent) if sibling is not None: - # Insetrt after sibling. + # Insert after sibling. if sibling.tail: sibling.tail = '{}\n{}'.format(sibling.tail, block) else: diff --git a/markdown/core.py b/markdown/core.py index c9da4be..77cd2d7 100644 --- a/markdown/core.py +++ b/markdown/core.py @@ -55,16 +55,16 @@ class Markdown: Keyword arguments: - * extensions: A list of extensions. + * `extensions`: A list of extensions. If an item is an instance of a subclass of `markdown.extension.Extension`, the instance will be used as-is. If an item is of type string, first an entry point will be loaded. If that fails, the string is - assumed to use Python dot notation (`path.to.module:ClassName`) to load a markdown.Extension subclass. If + assumed to use Python dot notation (`path.to.module:ClassName`) to load a `markdown.Extension` subclass. If no class is specified, then a `makeExtension` function is called within the specified module. - * extension_configs: Configuration settings for extensions. - * output_format: Format of output. Supported formats are: - * "xhtml": Outputs XHTML style tags. Default. - * "html": Outputs HTML style tags. - * tab_length: Length of tabs in the source. Default: 4 + * `extension_configs`: Configuration settings for extensions. + * `output_format`: Format of output. Supported formats are: + * `xhtml`: Outputs XHTML style tags. Default. + * `html`: Outputs HTML style tags. + * `tab_length`: Length of tabs in the source. Default: 4 """ @@ -103,9 +103,9 @@ class Markdown: Keyword arguments: - * extensions: A list of extensions, which can either + * `extensions`: A list of extensions, which can either be strings or objects. - * configs: A dictionary mapping extension names to config options. + * `configs`: A dictionary mapping extension names to `configs` options. """ for ext in extensions: @@ -136,7 +136,7 @@ class Markdown: If no entry point is found, assume dot notation (`path.to.module:ClassName`). Load the specified class and return an instance. If no class is specified, import the module and call a `makeExtension` function and return - the Extension instance returned by that function. + the `Extension` instance returned by that function. """ configs = dict(configs) @@ -162,7 +162,7 @@ class Markdown: # Load given class name from module. return getattr(module, class_name)(**configs) else: - # Expect makeExtension() function to return a class. + # Expect `makeExtension()` function to return a class. try: return module.makeExtension(**configs) except AttributeError as e: @@ -192,7 +192,7 @@ class Markdown: def set_output_format(self, format): """ Set the output format for the class instance. """ - self.output_format = format.lower().rstrip('145') # ignore num + self.output_format = format.lower().rstrip('145') # ignore number try: self.serializer = self.output_formats[self.output_format] except KeyError as e: @@ -218,31 +218,31 @@ class Markdown: Keyword arguments: - * source: Source text as a Unicode string. + * `source`: Source text as a Unicode string. Markdown processing takes place in five steps: - 1. A bunch of "preprocessors" munge the input text. - 2. BlockParser() parses the high-level structural elements of the - pre-processed text into an ElementTree. - 3. A bunch of "treeprocessors" are run against the ElementTree. One - such treeprocessor runs InlinePatterns against the ElementTree, + 1. A bunch of `preprocessors` munge the input text. + 2. `BlockParser()` parses the high-level structural elements of the + pre-processed text into an `ElementTree`. + 3. A bunch of `treeprocessors` are run against the `ElementTree`. One + such `treeprocessor` runs `InlinePatterns` against the `ElementTree`, detecting inline markup. - 4. Some post-processors are run against the text after the ElementTree + 4. Some post-processors are run against the text after the `ElementTree` has been serialized into text. 5. The output is written to a string. """ - # Fixup the source text + # Fix up the source text if not source.strip(): - return '' # a blank unicode string + return '' # a blank Unicode string try: source = str(source) except UnicodeDecodeError as e: # pragma: no cover - # Customise error message while maintaining original trackback - e.reason += '. -- Note: Markdown only accepts unicode input!' + # Customize error message while maintaining original traceback + e.reason += '. -- Note: Markdown only accepts Unicode input!' raise # Split into lines and run the line preprocessors. @@ -283,23 +283,23 @@ class Markdown: return output.strip() def convertFile(self, input=None, output=None, encoding=None): - """Converts a markdown file and returns the HTML as a unicode string. + """Converts a markdown file and returns the HTML as a Unicode string. - Decodes the file using the provided encoding (defaults to utf-8), + Decodes the file using the provided encoding (defaults to `utf-8`), passes the file content to markdown, and outputs the html to either the provided stream or the file with provided name, using the same - encoding as the source file. The 'xmlcharrefreplace' error handler is + encoding as the source file. The `xmlcharrefreplace` error handler is used when encoding the output. - **Note:** This is the only place that decoding and encoding of unicode - takes place in Python-Markdown. (All other code is unicode-in / - unicode-out.) + **Note:** This is the only place that decoding and encoding of Unicode + takes place in Python-Markdown. (All other code is Unicode-in / + Unicode-out.) Keyword arguments: - * input: File object or path. Reads from stdin if `None`. - * output: File object or path. Writes to stdout if `None`. - * encoding: Encoding of input and output files. Defaults to utf-8. + * `input`: File object or path. Reads from `stdin` if `None`. + * `output`: File object or path. Writes to `stdout` if `None`. + * `encoding`: Encoding of input and output files. Defaults to `utf-8`. """ @@ -353,21 +353,21 @@ class Markdown: EXPORTED FUNCTIONS ============================================================================= -Those are the two functions we really mean to export: markdown() and -markdownFromFile(). +Those are the two functions we really mean to export: `markdown()` and +`markdownFromFile()`. """ def markdown(text, **kwargs): - """Convert a markdown string to HTML and return HTML as a unicode string. + """Convert a markdown string to HTML and return HTML as a Unicode string. This is a shortcut function for `Markdown` class to cover the most - basic use case. It initializes an instance of Markdown, loads the + basic use case. It initializes an instance of `Markdown`, loads the necessary extensions and runs the parser on the given text. Keyword arguments: - * text: Markdown formatted text as Unicode or ASCII string. + * `text`: Markdown formatted text as Unicode or ASCII string. * Any arguments accepted by the Markdown class. Returns: An HTML document as a string. @@ -380,15 +380,15 @@ def markdown(text, **kwargs): def markdownFromFile(**kwargs): """Read markdown code from a file and write it to a file or a stream. - This is a shortcut function which initializes an instance of Markdown, - and calls the convertFile method rather than convert. + This is a shortcut function which initializes an instance of `Markdown`, + and calls the `convertFile` method rather than `convert`. Keyword arguments: - * input: a file name or readable object. - * output: a file name or writable object. - * encoding: Encoding of input and output. - * Any arguments accepted by the Markdown class. + * `input`: a file name or readable object. + * `output`: a file name or writable object. + * `encoding`: Encoding of input and output. + * Any arguments accepted by the `Markdown` class. """ md = Markdown(**kwargs) diff --git a/markdown/extensions/__init__.py b/markdown/extensions/__init__.py index 2d8d72a..7a32e1c 100644 --- a/markdown/extensions/__init__.py +++ b/markdown/extensions/__init__.py @@ -25,12 +25,12 @@ from ..util import parseBoolValue class Extension: """ Base class for extensions to subclass. """ - # Default config -- to be overridden by a subclass + # Default configuration -- to be overridden by a subclass # Must be of the following format: # { # 'key': ['value', 'description'] # } - # Note that Extension.setConfig will raise a KeyError + # Note that `Extension.setConfig` will raise a `KeyError` # if a default is not set here. config = {} @@ -50,11 +50,11 @@ class Extension: return {key: self.getConfig(key) for key in self.config.keys()} def getConfigInfo(self): - """ Return all config descriptions as a list of tuples. """ + """ Return all `config` descriptions as a list of tuples. """ return [(key, self.config[key][1]) for key in self.config.keys()] def setConfig(self, key, value): - """ Set a config setting for `key` with the given `value`. """ + """ Set a `config` setting for `key` with the given `value`. """ if isinstance(self.config[key][0], bool): value = parseBoolValue(value) if self.config[key][0] is None: @@ -62,7 +62,7 @@ class Extension: self.config[key][0] = value def setConfigs(self, items): - """ Set multiple config settings given a dict or list of tuples. """ + """ Set multiple `config` settings given a dict or list of tuples. """ if hasattr(items, 'items'): # it's a dict items = items.items() diff --git a/markdown/extensions/abbr.py b/markdown/extensions/abbr.py index 9879314..0649870 100644 --- a/markdown/extensions/abbr.py +++ b/markdown/extensions/abbr.py @@ -7,7 +7,7 @@ This extension adds abbreviation handling to Python-Markdown. See for documentation. -Oringinal code Copyright 2007-2008 [Waylan Limberg](http://achinghead.com/) and +Original code Copyright 2007-2008 [Waylan Limberg](http://achinghead.com/) and [Seemant Kulleen](http://www.kulleen.org/) All changes Copyright 2008-2014 The Python Markdown Project @@ -28,7 +28,7 @@ class AbbrExtension(Extension): """ Abbreviation Extension for Python-Markdown. """ def extendMarkdown(self, md): - """ Insert AbbrPreprocessor before ReferencePreprocessor. """ + """ Insert `AbbrPreprocessor` before `ReferencePreprocessor`. """ md.parser.blockprocessors.register(AbbrPreprocessor(md.parser), 'abbr', 16) @@ -43,7 +43,7 @@ class AbbrPreprocessor(BlockProcessor): def run(self, parent, blocks): ''' Find and remove all Abbreviation references from the text. - Each reference is set as a new AbbrPattern in the markdown instance. + Each reference is set as a new `AbbrPattern` in the markdown instance. ''' block = blocks.pop(0) diff --git a/markdown/extensions/admonition.py b/markdown/extensions/admonition.py index cb8d901..25bb19e 100644 --- a/markdown/extensions/admonition.py +++ b/markdown/extensions/admonition.py @@ -4,7 +4,7 @@ Admonition extension for Python-Markdown Adds rST-style admonitions. Inspired by [rST][] feature with the same name. -[rST]: http://docutils.sourceforge.net/docs/ref/rst/directives.html#specific-admonitions # noqa +[rST]: http://docutils.sourceforge.net/docs/ref/rst/directives.html#specific-admonitions See for documentation. @@ -82,7 +82,7 @@ class AdmonitionProcessor(BlockProcessor): last_child and last_child.tag in ('ul', 'ol', 'dl') ): - # The expectation is that we'll find an
  • or
    . + # The expectation is that we'll find an `
  • ` or `
    `. # We should get its last child as well. sibling = self.lastChild(last_child) last_child = self.lastChild(sibling) if sibling else None @@ -155,7 +155,7 @@ class AdmonitionProcessor(BlockProcessor): klass, title = match.group(1).lower(), match.group(2) klass = self.RE_SPACES.sub(' ', klass) if title is None: - # no title was provided, use the capitalized classname as title + # no title was provided, use the capitalized class name as title # e.g.: `!!! note` will render # `

    Note

    ` title = klass.split(' ', 1)[0].capitalize() diff --git a/markdown/extensions/attr_list.py b/markdown/extensions/attr_list.py index 9a67551..bc06786 100644 --- a/markdown/extensions/attr_list.py +++ b/markdown/extensions/attr_list.py @@ -3,7 +3,7 @@ Attribute List Extension for Python-Markdown ============================================ Adds attribute list syntax. Inspired by -[maruku](http://maruku.rubyforge.org/proposal.html#attribute_lists)'s +[Maruku](http://maruku.rubyforge.org/proposal.html#attribute_lists)'s feature of the same name. See @@ -77,33 +77,33 @@ class AttrListTreeprocessor(Treeprocessor): def run(self, doc): for elem in doc.iter(): if self.md.is_block_level(elem.tag): - # Block level: check for attrs on last line of text + # Block level: check for `attrs` on last line of text RE = self.BLOCK_RE if isheader(elem) or elem.tag in ['dt', 'td', 'th']: - # header, def-term, or table cell: check for attrs at end of element + # header, def-term, or table cell: check for attributes at end of element RE = self.HEADER_RE if len(elem) and elem.tag == 'li': - # special case list items. children may include a ul or ol. + # special case list items. children may include a `ul` or `ol`. pos = None - # find the ul or ol position + # find the `ul` or `ol` position for i, child in enumerate(elem): if child.tag in ['ul', 'ol']: pos = i break if pos is None and elem[-1].tail: - # use tail of last child. no ul or ol. + # use tail of last child. no `ul` or `ol`. m = RE.search(elem[-1].tail) if m: self.assign_attrs(elem, m.group(1)) elem[-1].tail = elem[-1].tail[:m.start()] elif pos is not None and pos > 0 and elem[pos-1].tail: - # use tail of last child before ul or ol + # use tail of last child before `ul` or `ol` m = RE.search(elem[pos-1].tail) if m: self.assign_attrs(elem, m.group(1)) elem[pos-1].tail = elem[pos-1].tail[:m.start()] elif elem.text: - # use text. ul is first child. + # use text. `ul` is first child. m = RE.search(elem.text) if m: self.assign_attrs(elem, m.group(1)) @@ -127,7 +127,7 @@ class AttrListTreeprocessor(Treeprocessor): # clean up trailing #s elem.text = elem.text.rstrip('#').rstrip() else: - # inline: check for attrs at start of tail + # inline: check for `attrs` at start of tail if elem.tail: m = self.INLINE_RE.match(elem.tail) if m: @@ -135,7 +135,7 @@ class AttrListTreeprocessor(Treeprocessor): elem.tail = elem.tail[m.end():] def assign_attrs(self, elem, attrs): - """ Assign attrs to element. """ + """ Assign `attrs` to element. """ for k, v in get_attrs(attrs): if k == '.': # add to class @@ -145,7 +145,7 @@ class AttrListTreeprocessor(Treeprocessor): else: elem.set('class', v) else: - # assign attr k with v + # assign attribute `k` with `v` elem.set(self.sanitize_name(k), v) def sanitize_name(self, name): diff --git a/markdown/extensions/codehilite.py b/markdown/extensions/codehilite.py index 00445ec..1941ce2 100644 --- a/markdown/extensions/codehilite.py +++ b/markdown/extensions/codehilite.py @@ -54,24 +54,24 @@ class CodeHilite: html = code.hilite() Arguments: - * src: Source string or any object with a .readline attribute. + * `src`: Source string or any object with a `.readline` attribute. - * lang: String name of Pygments lexer to use for highlighting. Default: `None`. + * `lang`: String name of Pygments lexer to use for highlighting. Default: `None`. - * guess_lang: Auto-detect which lexer to use. Ignored if `lang` is set to a valid + * `guess_lang`: Auto-detect which lexer to use. Ignored if `lang` is set to a valid value. Default: `True`. - * use_pygments: Pass code to pygments for code highlighting. If `False`, the code is + * `use_pygments`: Pass code to Pygments for code highlighting. If `False`, the code is instead wrapped for highlighting by a JavaScript library. Default: `True`. - * pygments_formatter: The name of a Pygments formatter or a formatter class used for + * `pygments_formatter`: The name of a Pygments formatter or a formatter class used for highlighting the code blocks. Default: `html`. - * linenums: An alias to Pygments `linenos` formatter option. Default: `None`. + * `linenums`: An alias to Pygments `linenos` formatter option. Default: `None`. - * css_class: An alias to Pygments `cssclass` formatter option. Default: 'codehilite'. + * `css_class`: An alias to Pygments `cssclass` formatter option. Default: 'codehilite'. - * lang_prefix: Prefix prepended to the language. Default: "language-". + * `lang_prefix`: Prefix prepended to the language. Default: "language-". Other Options: Any other options are accepted and passed on to the lexer and formatter. Therefore, @@ -85,7 +85,7 @@ class CodeHilite: Additionally, when Pygments is enabled, the code's language is passed to the formatter as an extra option `lang_str`, whose value being `{lang_prefix}{lang}`. - This option has no effect to the Pygments's builtin formatters. + This option has no effect to the Pygments' builtin formatters. Advanced Usage: code = CodeHilite( @@ -113,7 +113,7 @@ class CodeHilite: if 'cssclass' not in options: options['cssclass'] = options.pop('css_class', 'codehilite') if 'wrapcode' not in options: - # Override pygments default + # Override Pygments default options['wrapcode'] = True # Disallow use of `full` option options['full'] = False @@ -122,10 +122,10 @@ class CodeHilite: def hilite(self, shebang=True): """ - Pass code to the [Pygments](https://pygments.org/) highliter with - optional line numbers. The output should then be styled with css to + Pass code to the [Pygments](https://pygments.org/) highlighter with + optional line numbers. The output should then be styled with CSS to your liking. No styles are applied by default - only styling hooks - (i.e.: ). + (i.e.: ``). returns : A string of html. @@ -160,7 +160,7 @@ class CodeHilite: formatter = self.pygments_formatter(lang_str=lang_str, **self.options) return highlight(self.src, lexer, formatter) else: - # just escape and build markup usable by JS highlighting libs + # just escape and build markup usable by JavaScript highlighting libraries txt = self.src.replace('&', '&') txt = txt.replace('<', '<') txt = txt.replace('>', '>') @@ -185,11 +185,11 @@ class CodeHilite: said line should be removed or left in place. If the shebang line contains a path (even a single /) then it is assumed to be a real shebang line and left alone. However, if no path is given - (e.i.: #!python or :::python) then it is assumed to be a mock shebang + (e.i.: `#!python` or `:::python`) then it is assumed to be a mock shebang for language identification of a code fragment and removed from the code block prior to processing for code highlighting. When a mock - shebang (e.i: #!python) is found, line numbering is turned on. When - colons are found in place of a shebang (e.i.: :::python), line + shebang (e.i: `#!python`) is found, line numbering is turned on. When + colons are found in place of a shebang (e.i.: `:::python`), line numbering is left in the current state - off by default. Also parses optional list of highlight lines, like: @@ -251,7 +251,7 @@ class HiliteTreeprocessor(Treeprocessor): return text def run(self, root): - """ Find code blocks and store in htmlStash. """ + """ Find code blocks and store in `htmlStash`. """ blocks = root.iter('pre') for block in blocks: if len(block) == 1 and block[0].tag == 'code': @@ -263,16 +263,16 @@ class HiliteTreeprocessor(Treeprocessor): **local_config ) placeholder = self.md.htmlStash.store(code.hilite()) - # Clear codeblock in etree instance + # Clear code block in `etree` instance block.clear() - # Change to p element which will later + # Change to `p` element which will later # be removed when inserting raw html block.tag = 'p' block.text = placeholder class CodeHiliteExtension(Extension): - """ Add source code highlighting to markdown codeblocks. """ + """ Add source code highlighting to markdown code blocks. """ def __init__(self, **kwargs): # define default configs @@ -311,14 +311,14 @@ class CodeHiliteExtension(Extension): # manually set unknown keywords. if isinstance(value, str): try: - # Attempt to parse str as a bool value + # Attempt to parse `str` as a boolean value value = parseBoolValue(value, preserve_none=True) except ValueError: - pass # Assume it's not a bool value. Use as-is. + pass # Assume it's not a boolean value. Use as-is. self.config[key] = [value, ''] def extendMarkdown(self, md): - """ Add HilitePostprocessor to Markdown instance. """ + """ Add `HilitePostprocessor` to Markdown instance. """ hiliter = HiliteTreeprocessor(md) hiliter.config = self.getConfigs() md.treeprocessors.register(hiliter, 'hilite', 30) diff --git a/markdown/extensions/def_list.py b/markdown/extensions/def_list.py index 17549f0..c2f23a6 100644 --- a/markdown/extensions/def_list.py +++ b/markdown/extensions/def_list.py @@ -92,7 +92,7 @@ class DefListIndentProcessor(ListIndentProcessor): LIST_TYPES = ['dl', 'ol', 'ul'] def create_item(self, parent, block): - """ Create a new dd or li (depending on parent) and parse the block with it as the parent. """ + """ Create a new `dd` or `li` (depending on parent) and parse the block with it as the parent. """ dd = etree.SubElement(parent, 'dd') self.parser.parseBlocks(dd, [block]) @@ -102,7 +102,7 @@ class DefListExtension(Extension): """ Add definition lists to Markdown. """ def extendMarkdown(self, md): - """ Add an instance of DefListProcessor to BlockParser. """ + """ Add an instance of `DefListProcessor` to `BlockParser`. """ md.parser.blockprocessors.register(DefListIndentProcessor(md.parser), 'defindent', 85) md.parser.blockprocessors.register(DefListProcessor(md.parser), 'deflist', 25) diff --git a/markdown/extensions/extra.py b/markdown/extensions/extra.py index 909ba07..8f73806 100644 --- a/markdown/extensions/extra.py +++ b/markdown/extensions/extra.py @@ -46,7 +46,7 @@ class ExtraExtension(Extension): """ Add various extensions to Markdown class.""" def __init__(self, **kwargs): - """ config is a dumb holder which gets passed to actual ext later. """ + """ `config` is a dumb holder which gets passed to the actual extension later. """ self.config = kwargs def extendMarkdown(self, md): diff --git a/markdown/extensions/fenced_code.py b/markdown/extensions/fenced_code.py index 409166a..a0874d2 100644 --- a/markdown/extensions/fenced_code.py +++ b/markdown/extensions/fenced_code.py @@ -34,7 +34,7 @@ class FencedCodeExtension(Extension): super().__init__(**kwargs) def extendMarkdown(self, md): - """ Add FencedBlockPreprocessor to the Markdown instance. """ + """ Add `FencedBlockPreprocessor` to the Markdown instance. """ md.registerExtension(self) md.preprocessors.register(FencedBlockPreprocessor(md, self.getConfigs()), 'fenced_code_block', 25) @@ -60,7 +60,7 @@ class FencedBlockPreprocessor(Preprocessor): self.checked_for_deps = False self.codehilite_conf = {} self.use_attr_list = False - # List of options to convert to bool values + # List of options to convert to boolean values self.bool_options = [ 'linenums', 'guess_lang', @@ -69,7 +69,7 @@ class FencedBlockPreprocessor(Preprocessor): ] def run(self, lines): - """ Match and store Fenced Code Blocks in the HtmlStash. """ + """ Match and store Fenced Code Blocks in the `HtmlStash`. """ # Check for dependent extensions if not self.checked_for_deps: @@ -94,16 +94,16 @@ class FencedBlockPreprocessor(Preprocessor): if m.group('lang'): lang = m.group('lang') if m.group('hl_lines'): - # Support hl_lines outside of attrs for backward-compatibility + # Support `hl_lines` outside of `attrs` for backward-compatibility config['hl_lines'] = parse_hl_lines(m.group('hl_lines')) - # If config is not empty, then the codehighlite extension + # If `config` is not empty, then the `codehighlite` extension # is enabled, so we call it to highlight the code if self.codehilite_conf and self.codehilite_conf['use_pygments'] and config.get('use_pygments', True): local_config = self.codehilite_conf.copy() local_config.update(config) - # Combine classes with cssclass. Ensure cssclass is at end - # as pygments appends a suffix under certain circumstances. + # Combine classes with `cssclass`. Ensure `cssclass` is at end + # as Pygments appends a suffix under certain circumstances. # Ignore ID as Pygments does not offer an option to set it. if classes: local_config['css_class'] = '{} {}'.format( @@ -128,9 +128,9 @@ class FencedBlockPreprocessor(Preprocessor): if id: id_attr = f' id="{_escape_attrib_html(id)}"' if self.use_attr_list and config and not config.get('use_pygments', False): - # Only assign key/value pairs to code element if attr_list ext is enabled, key/value pairs - # were defined on the code block, and the `use_pygments` key was not set to True. The - # `use_pygments` key could be either set to False or not defined. It is omitted from output. + # Only assign key/value pairs to code element if `attr_list` extension is enabled, key/value + # pairs were defined on the code block, and the `use_pygments` key was not set to `True`. The + # `use_pygments` key could be either set to `False` or not defined. It is omitted from output. kv_pairs = ''.join( f' {k}="{_escape_attrib_html(v)}"' for k, v in config.items() if k != 'use_pygments' ) diff --git a/markdown/extensions/footnotes.py b/markdown/extensions/footnotes.py index 8a2e3c5..41074c0 100644 --- a/markdown/extensions/footnotes.py +++ b/markdown/extensions/footnotes.py @@ -74,20 +74,20 @@ class FootnoteExtension(Extension): md.registerExtension(self) self.parser = md.parser self.md = md - # Insert a blockprocessor before ReferencePreprocessor + # Insert a `blockprocessor` before `ReferencePreprocessor` md.parser.blockprocessors.register(FootnoteBlockProcessor(self), 'footnote', 17) - # Insert an inline pattern before ImageReferencePattern + # Insert an inline pattern before `ImageReferencePattern` FOOTNOTE_RE = r'\[\^([^\]]*)\]' # blah blah [^1] blah md.inlinePatterns.register(FootnoteInlineProcessor(FOOTNOTE_RE, self), 'footnote', 175) # Insert a tree-processor that would actually add the footnote div - # This must be before all other treeprocessors (i.e., inline and - # codehilite) so they can run on the the contents of the div. + # This must be before all other tree-processors (i.e., `inline` and + # `codehilite`) so they can run on the the contents of the div. md.treeprocessors.register(FootnoteTreeprocessor(self), 'footnote', 50) # Insert a tree-processor that will run after inline is done. # In this tree-processor we want to check our duplicate footnote tracker - # And add additional backrefs to the footnote pointing back to the + # And add additional `backrefs` to the footnote pointing back to the # duplicated references. md.treeprocessors.register(FootnotePostTreeprocessor(self), 'footnote-duplicate', 15) @@ -163,7 +163,7 @@ class FootnoteExtension(Extension): return self.unique_ref('fnref{}{}'.format(self.get_separator(), id), found) def makeFootnotesDiv(self, root): - """ Return div of footnotes as et Element. """ + """ Return `div` of footnotes as `etree` Element. """ if not list(self.footnotes.keys()): return None @@ -180,9 +180,9 @@ class FootnoteExtension(Extension): for index, id in enumerate(self.footnotes.keys(), start=1): li = etree.SubElement(ol, "li") li.set("id", self.makeFootnoteId(id)) - # Parse footnote with surrogate parent as li cannot be used. - # List block handlers have special logic to deal with li. - # When we are done parsing, we will copy everything over to li. + # Parse footnote with surrogate parent as `li` cannot be used. + # List block handlers have special logic to deal with `li`. + # When we are done parsing, we will copy everything over to `li`. self.parser.parseChunk(surrogate_parent, self.footnotes[id]) for el in list(surrogate_parent): li.append(el) @@ -296,7 +296,7 @@ class FootnoteBlockProcessor(BlockProcessor): class FootnoteInlineProcessor(InlineProcessor): - """ InlinePattern for footnote markers in a document's body text. """ + """ `InlinePattern` for footnote markers in a document's body text. """ def __init__(self, pattern, footnotes): super().__init__(pattern) @@ -325,7 +325,7 @@ class FootnotePostTreeprocessor(Treeprocessor): self.footnotes = footnotes def add_duplicates(self, li, duplicates): - """ Adjust current li and add the duplicates: fnref2, fnref3, etc. """ + """ Adjust current `li` and add the duplicates: `fnref2`, `fnref3`, etc. """ for link in li.iter('a'): # Find the link that needs to be duplicated. if link.attrib.get('class', '') == 'footnote-backref': @@ -407,5 +407,5 @@ class FootnotePostprocessor(Postprocessor): def makeExtension(**kwargs): # pragma: no cover - """ Return an instance of the FootnoteExtension """ + """ Return an instance of the `FootnoteExtension` """ return FootnoteExtension(**kwargs) diff --git a/markdown/extensions/legacy_attrs.py b/markdown/extensions/legacy_attrs.py index 445aba1..6e05e76 100644 --- a/markdown/extensions/legacy_attrs.py +++ b/markdown/extensions/legacy_attrs.py @@ -26,8 +26,8 @@ An extension to Python Markdown which implements legacy attributes. Prior to Python-Markdown version 3.0, the Markdown class had an `enable_attributes` keyword which was on by default and provided for attributes to be defined for elements using the format `{@key=value}`. This extension is provided as a replacement for -backward compatibility. New documents should be authored using attr_lists. However, -numerious documents exist which have been using the old attribute format for many +backward compatibility. New documents should be authored using `attr_lists`. However, +numerous documents exist which have been using the old attribute format for many years. This extension can be used to continue to render those documents correctly. """ diff --git a/markdown/extensions/legacy_em.py b/markdown/extensions/legacy_em.py index 360988b..bc147a6 100644 --- a/markdown/extensions/legacy_em.py +++ b/markdown/extensions/legacy_em.py @@ -45,5 +45,5 @@ class LegacyEmExtension(Extension): def makeExtension(**kwargs): # pragma: no cover - """ Return an instance of the LegacyEmExtension """ + """ Return an instance of the `LegacyEmExtension` """ return LegacyEmExtension(**kwargs) diff --git a/markdown/extensions/md_in_html.py b/markdown/extensions/md_in_html.py index ec7dcba..92afecf 100644 --- a/markdown/extensions/md_in_html.py +++ b/markdown/extensions/md_in_html.py @@ -25,7 +25,8 @@ import xml.etree.ElementTree as etree class HTMLExtractorExtra(HTMLExtractor): """ - Override HTMLExtractor and create etree Elements for any elements which should have content parsed as Markdown. + Override `HTMLExtractor` and create `etree` `Elements` for any elements which should have content parsed as + Markdown. """ def __init__(self, md, *args, **kwargs): @@ -56,17 +57,17 @@ class HTMLExtractorExtra(HTMLExtractor): super().close() # Handle any unclosed tags. if self.mdstack: - # Close the outermost parent. handle_endtag will close all unclosed children. + # Close the outermost parent. `handle_endtag` will close all unclosed children. self.handle_endtag(self.mdstack[0]) def get_element(self): - """ Return element from treebuilder and reset treebuilder for later use. """ + """ Return element from `treebuilder` and reset `treebuilder` for later use. """ element = self.treebuilder.close() self.treebuilder = etree.TreeBuilder() return element def get_state(self, tag, attrs): - """ Return state from tag and `markdown` attr. One of 'block', 'span', or 'off'. """ + """ Return state from tag and `markdown` attribute. One of 'block', 'span', or 'off'. """ md_attr = attrs.get('markdown', '0') if md_attr == 'markdown': # `` is the same as ``. @@ -100,7 +101,7 @@ class HTMLExtractorExtra(HTMLExtractor): return if tag in self.block_level_tags and (self.at_line_start() or self.intail): - # Valueless attr (ex: ``) results in `[('checked', None)]`. + # Valueless attribute (ex: ``) results in `[('checked', None)]`. # Convert to `{'checked': 'checked'}`. attrs = {key: value if value is not None else key for key, value in attrs} state = self.get_state(tag, attrs) @@ -157,7 +158,7 @@ class HTMLExtractorExtra(HTMLExtractor): # Check if element has a tail if not blank_line_re.match( self.rawdata[self.line_offset + self.offset + len(self.get_endtag_text(tag)):]): - # More content exists after endtag. + # More content exists after `endtag`. self.intail = True else: # Treat orphan closing tag as a span level tag. @@ -209,8 +210,8 @@ class HTMLExtractorExtra(HTMLExtractor): def parse_pi(self, i): if self.at_line_start() or self.intail or self.mdstack: - # The same override exists in HTMLExtractor without the check - # for mdstack. Therefore, use HTMLExtractor's parent instead. + # The same override exists in `HTMLExtractor` without the check + # for `mdstack`. Therefore, use parent of `HTMLExtractor` instead. return super(HTMLExtractor, self).parse_pi(i) # This is not the beginning of a raw block so treat as plain data # and avoid consuming any tags which may follow (see #1066). @@ -219,8 +220,8 @@ class HTMLExtractorExtra(HTMLExtractor): def parse_html_declaration(self, i): if self.at_line_start() or self.intail or self.mdstack: - # The same override exists in HTMLExtractor without the check - # for mdstack. Therefore, use HTMLExtractor's parent instead. + # The same override exists in `HTMLExtractor` without the check + # for `mdstack`. Therefore, use parent of `HTMLExtractor` instead. return super(HTMLExtractor, self).parse_html_declaration(i) # This is not the beginning of a raw block so treat as plain data # and avoid consuming any tags which may follow (see #1066). @@ -240,19 +241,19 @@ class HtmlBlockPreprocessor(Preprocessor): class MarkdownInHtmlProcessor(BlockProcessor): - """Process Markdown Inside HTML Blocks which have been stored in the HtmlStash.""" + """Process Markdown Inside HTML Blocks which have been stored in the `HtmlStash`.""" def test(self, parent, block): - # ALways return True. `run` will return `False` it not a valid match. + # Always return True. `run` will return `False` it not a valid match. return True def parse_element_content(self, element): """ - Recursively parse the text content of an etree Element as Markdown. + Recursively parse the text content of an `etree` Element as Markdown. Any block level elements generated from the Markdown will be inserted as children of the element in place of the text content. All `markdown` attributes are removed. For any elements in which Markdown parsing has - been disabled, the text content of it and its chidlren are wrapped in an `AtomicString`. + been disabled, the text content of it and its children are wrapped in an `AtomicString`. """ md_attr = element.attrib.pop('markdown', 'off') @@ -301,7 +302,7 @@ class MarkdownInHtmlProcessor(BlockProcessor): element.insert(0, child) elif md_attr == 'span': - # Span level parsing will be handled by inlineprocessors. + # Span level parsing will be handled by inline processors. # Walk children here to remove any `markdown` attributes. for child in list(element): self.parse_element_content(child) @@ -329,7 +330,7 @@ class MarkdownInHtmlProcessor(BlockProcessor): # Cleanup stash. Replace element with empty string to avoid confusing postprocessor. self.parser.md.htmlStash.rawHtmlBlocks.pop(index) self.parser.md.htmlStash.rawHtmlBlocks.insert(index, '') - # Confirm the match to the blockparser. + # Confirm the match to the `blockparser`. return True # No match found. return False @@ -337,7 +338,7 @@ class MarkdownInHtmlProcessor(BlockProcessor): class MarkdownInHTMLPostprocessor(RawHtmlPostprocessor): def stash_to_string(self, text): - """ Override default to handle any etree elements still in the stash. """ + """ Override default to handle any `etree` elements still in the stash. """ if isinstance(text, etree.Element): return self.md.serializer(text) else: @@ -352,7 +353,7 @@ class MarkdownInHtmlExtension(Extension): # Replace raw HTML preprocessor md.preprocessors.register(HtmlBlockPreprocessor(md), 'html_block', 20) - # Add blockprocessor which handles the placeholders for etree elements + # Add `blockprocessor` which handles the placeholders for `etree` elements md.parser.blockprocessors.register( MarkdownInHtmlProcessor(md.parser), 'markdown_block', 105 ) diff --git a/markdown/extensions/meta.py b/markdown/extensions/meta.py index 10dee11..8a93863 100644 --- a/markdown/extensions/meta.py +++ b/markdown/extensions/meta.py @@ -33,7 +33,7 @@ class MetaExtension (Extension): """ Meta-Data extension for Python-Markdown. """ def extendMarkdown(self, md): - """ Add MetaPreprocessor to Markdown instance. """ + """ Add `MetaPreprocessor` to Markdown instance. """ md.registerExtension(self) self.md = md md.preprocessors.register(MetaPreprocessor(md), 'meta', 27) diff --git a/markdown/extensions/nl2br.py b/markdown/extensions/nl2br.py index 6c7491b..23d5603 100644 --- a/markdown/extensions/nl2br.py +++ b/markdown/extensions/nl2br.py @@ -1,5 +1,5 @@ """ -NL2BR Extension +`NL2BR` Extension =============== A Python-Markdown extension to treat newlines as hard breaks; like @@ -8,7 +8,7 @@ GitHub-flavored Markdown does. See for documentation. -Oringinal code Copyright 2011 [Brian Neal](https://deathofagremmie.com/) +Original code Copyright 2011 [Brian Neal](https://deathofagremmie.com/) All changes Copyright 2011-2014 The Python Markdown Project diff --git a/markdown/extensions/smarty.py b/markdown/extensions/smarty.py index c4bfd58..15e5784 100644 --- a/markdown/extensions/smarty.py +++ b/markdown/extensions/smarty.py @@ -48,9 +48,9 @@ SmartyPants license: of this software, even if advised of the possibility of such damage. -smartypants.py license: +`smartypants.py` license: - smartypants.py is a derivative work of SmartyPants. + `smartypants.py` is a derivative work of SmartyPants. Copyright (c) 2004, 2007 Chad Miller Redistribution and use in source and binary forms, with or without @@ -95,7 +95,7 @@ openingQuotesBase = ( r'(\s' # a whitespace char r'| ' # or a non-breaking space entity r'|--' # or dashes - r'|–|—' # or unicode + r'|–|—' # or Unicode r'|&[mn]dash;' # or named dash entities r'|–|—' # or decimal entities r')' @@ -242,7 +242,7 @@ class SmartyExtension(Extension): self.educateQuotes(md) if configs['smart_angled_quotes']: self.educateAngledQuotes(md) - # Override HTML_RE from inlinepatterns.py so that it does not + # Override `HTML_RE` from `inlinepatterns.py` so that it does not # process tags with duplicate closing quotes. md.inlinePatterns.register(HtmlInlineProcessor(HTML_STRICT_RE, md), 'html', 90) if configs['smart_dashes']: diff --git a/markdown/extensions/tables.py b/markdown/extensions/tables.py index c8b1024..a72103f 100644 --- a/markdown/extensions/tables.py +++ b/markdown/extensions/tables.py @@ -225,7 +225,7 @@ class TableExtension(Extension): super().__init__(**kwargs) def extendMarkdown(self, md): - """ Add an instance of TableProcessor to BlockParser. """ + """ Add an instance of `TableProcessor` to `BlockParser`. """ if '|' not in md.ESCAPED_CHARS: md.ESCAPED_CHARS.append('|') processor = TableProcessor(md.parser, self.getConfigs()) diff --git a/markdown/extensions/toc.py b/markdown/extensions/toc.py index 1ded18d..9927b99 100644 --- a/markdown/extensions/toc.py +++ b/markdown/extensions/toc.py @@ -5,7 +5,7 @@ Table of Contents Extension for Python-Markdown See for documentation. -Oringinal code Copyright 2008 [Jack Miller](https://codezen.org/) +Original code Copyright 2008 [Jack Miller](https://codezen.org/) All changes Copyright 2008-2014 The Python Markdown Project @@ -26,7 +26,7 @@ import xml.etree.ElementTree as etree def slugify(value, separator, unicode=False): """ Slugify a string, to make it URL friendly. """ if not unicode: - # Replace Extended Latin characters with ASCII, i.e. žlutý → zluty + # Replace Extended Latin characters with ASCII, i.e. `žlutý` => `zluty` value = unicodedata.normalize('NFKD', value) value = value.encode('ascii', 'ignore').decode('ascii') value = re.sub(r'[^\w\s-]', '', value).strip().lower() @@ -179,7 +179,7 @@ class TocTreeprocessor(Treeprocessor): ''' Iterator wrapper to get allowed parent and child all at once. ''' # We do not allow the marker inside a header as that - # would causes an enless loop of placing a new TOC + # would causes an endless loop of placing a new TOC # inside previously generated TOC. for child in node: if not self.header_rgx.match(child.tag) and child.tag not in ['pre', 'code']: @@ -194,13 +194,13 @@ class TocTreeprocessor(Treeprocessor): continue # To keep the output from screwing up the - # validation by putting a
    inside of a

    - # we actually replace the

    in its entirety. + # validation by putting a `

    ` inside of a `

    ` + # we actually replace the `

    ` in its entirety. - # The

    element may contain more than a single text content - # (nl2br can introduce a
    ). In this situation, c.text returns + # The `

    ` element may contain more than a single text content + # (`nl2br` can introduce a `
    `). In this situation, `c.text` returns # the very first content, ignore children contents or tail content. - # len(c) == 0 is here to ensure there is only text in the

    . + # `len(c) == 0` is here to ensure there is only text in the `

    `. if c.text and c.text.strip() == self.marker and len(c) == 0: for i in range(len(p)): if p[i] == c: @@ -214,7 +214,7 @@ class TocTreeprocessor(Treeprocessor): level = 6 elem.tag = 'h%d' % level - def add_anchor(self, c, elem_id): # @ReservedAssignment + def add_anchor(self, c, elem_id): anchor = etree.Element("a") anchor.text = c.text anchor.attrib["href"] = "#" + elem_id @@ -368,11 +368,6 @@ class TocExtension(Extension): self.md = md self.reset() tocext = self.TreeProcessorClass(md, self.getConfigs()) - # Headerid ext is set to '>prettify'. With this set to '_end', - # it should always come after headerid ext (and honor ids assigned - # by the header id extension) if both are used. Same goes for - # attr_list extension. This must come last because we don't want - # to redefine ids after toc is created. But we do want toc prettified. md.treeprocessors.register(tocext, 'toc', 5) def reset(self): diff --git a/markdown/extensions/wikilinks.py b/markdown/extensions/wikilinks.py index cddee7a..d32d912 100644 --- a/markdown/extensions/wikilinks.py +++ b/markdown/extensions/wikilinks.py @@ -22,7 +22,7 @@ import re def build_url(label, base, end): - """ Build a url from the label, a base, and an end. """ + """ Build a URL from the label, a base, and an end. """ clean_label = re.sub(r'([ ]+_)|(_[ ]+)|([ ]+)', '_', label) return '{}{}{}'.format(base, clean_label, end) @@ -69,7 +69,7 @@ class WikiLinksInlineProcessor(InlineProcessor): return a, m.start(0), m.end(0) def _getMeta(self): - """ Return meta data or config data. """ + """ Return meta data or `config` data. """ base_url = self.config['base_url'] end_url = self.config['end_url'] html_class = self.config['html_class'] diff --git a/markdown/htmlparser.py b/markdown/htmlparser.py index 3512d1a..78ac958 100644 --- a/markdown/htmlparser.py +++ b/markdown/htmlparser.py @@ -31,15 +31,15 @@ htmlparser = importlib.util.module_from_spec(spec) spec.loader.exec_module(htmlparser) sys.modules['htmlparser'] = htmlparser -# Monkeypatch HTMLParser to only accept `?>` to close Processing Instructions. +# Monkeypatch `HTMLParser` to only accept `?>` to close Processing Instructions. htmlparser.piclose = re.compile(r'\?>') -# Monkeypatch HTMLParser to only recognize entity references with a closing semicolon. +# Monkeypatch `HTMLParser` to only recognize entity references with a closing semicolon. htmlparser.entityref = re.compile(r'&([a-zA-Z][-.a-zA-Z0-9]*);') -# Monkeypatch HTMLParser to no longer support partial entities. We are always feeding a complete block, -# so the 'incomplete' functionality is unnecessary. As the entityref regex is run right before incomplete, +# Monkeypatch `HTMLParser` to no longer support partial entities. We are always feeding a complete block, +# so the 'incomplete' functionality is unnecessary. As the `entityref` regex is run right before incomplete, # and the two regex are the same, then incomplete will simply never match and we avoid the logic within. htmlparser.incomplete = htmlparser.entityref -# Monkeypatch HTMLParser to not accept a backtick in a tag name, attribute name, or bare value. +# Monkeypatch `HTMLParser` to not accept a backtick in a tag name, attribute name, or bare value. htmlparser.locatestarttagend_tolerant = re.compile(r""" <[a-zA-Z][^`\t\n\r\f />\x00]* # tag name <= added backtick here (?:[\s/]* # optional whitespace before attribute name @@ -84,7 +84,7 @@ class HTMLExtractor(htmlparser.HTMLParser): """Reset this instance. Loses all unprocessed data.""" self.inraw = False self.intail = False - self.stack = [] # When inraw==True, stack contains a list of tags + self.stack = [] # When `inraw==True`, stack contains a list of tags self._cache = [] self.cleandoc = [] super().reset() @@ -106,13 +106,13 @@ class HTMLExtractor(htmlparser.HTMLParser): @property def line_offset(self): - """Returns char index in self.rawdata for the start of the current line. """ + """Returns char index in `self.rawdata` for the start of the current line. """ if self.lineno > 1 and '\n' in self.rawdata: m = re.match(r'([^\n]*\n){{{}}}'.format(self.lineno-1), self.rawdata) if m: return m.end() else: # pragma: no cover - # Value of self.lineno must exceed total number of lines. + # Value of `self.lineno` must exceed total number of lines. # Find index of beginning of last line. return self.rawdata.rfind('\n') return 0 @@ -182,7 +182,7 @@ class HTMLExtractor(htmlparser.HTMLParser): # Preserve blank line and end of raw block. self._cache.append('\n') else: - # More content exists after endtag. + # More content exists after `endtag`. self.intail = True # Reset stack. self.inraw = False @@ -263,13 +263,13 @@ class HTMLExtractor(htmlparser.HTMLParser): return i + 2 # The rest has been copied from base class in standard lib to address #1036. - # As __startag_text is private, all references to it must be in this subclass. - # The last few lines of parse_starttag are reversed so that handle_starttag - # can override cdata_mode in certain situations (in a code span). + # As `__startag_text` is private, all references to it must be in this subclass. + # The last few lines of `parse_starttag` are reversed so that `handle_starttag` + # can override `cdata_mode` in certain situations (in a code span). __starttag_text = None def get_starttag_text(self): - """Return full source of start tag: '<...>'.""" + """Return full source of start tag: `<...>`.""" return self.__starttag_text def parse_starttag(self, i): # pragma: no cover @@ -280,7 +280,7 @@ class HTMLExtractor(htmlparser.HTMLParser): rawdata = self.rawdata self.__starttag_text = rawdata[i:endpos] - # Now parse the data between i+1 and j into a tag and attrs + # Now parse the data between `i+1` and `j` into a tag and `attrs` attrs = [] match = htmlparser.tagfind_tolerant.match(rawdata, i+1) assert match, 'unexpected call to parse_starttag()' @@ -313,10 +313,10 @@ class HTMLExtractor(htmlparser.HTMLParser): self.handle_data(rawdata[i:endpos]) return endpos if end.endswith('/>'): - # XHTML-style empty tag: + # XHTML-style empty tag: `` self.handle_startendtag(tag, attrs) else: - # *** set cdata_mode first so we can override it in handle_starttag (see #1036) *** + # *** set `cdata_mode` first so we can override it in `handle_starttag` (see #1036) *** if tag in self.CDATA_CONTENT_ELEMENTS: self.set_cdata_mode(tag) self.handle_starttag(tag, attrs) diff --git a/markdown/inlinepatterns.py b/markdown/inlinepatterns.py index 0bd129c..bb55c4b 100644 --- a/markdown/inlinepatterns.py +++ b/markdown/inlinepatterns.py @@ -36,11 +36,11 @@ but you can add additional patterns that don't. Also note that all the regular expressions used by inline must capture the whole block. For this reason, they all start with -'^(.*)' and end with '(.*)!'. In case with built-in expression -Pattern takes care of adding the "^(.*)" and "(.*)!". +`^(.*)` and end with `(.*)!`. In case with built-in expression +Pattern takes care of adding the `^(.*)` and `(.*)!`. Finally, the order in which regular expressions are applied is very -important - e.g. if we first replace http://.../ links with tags +important - e.g. if we first replace `http://.../` links with `` tags and _then_ try to replace inline html, we would end up with a mess. So, we apply the expressions in the following order: @@ -108,64 +108,64 @@ NOIMG = r'(?) or [text](url "title") +# `[text](url)` or `[text]()` or `[text](url "title")` LINK_RE = NOIMG + r'\[' -# ![alttxt](http://x.com/) or ![alttxt]() +# `![alttxt](http://x.com/)` or `![alttxt]()` IMAGE_LINK_RE = r'\!\[' -# [Google][3] +# `[Google][3]` REFERENCE_RE = LINK_RE -# ![alt text][2] +# `![alt text][2]` IMAGE_REFERENCE_RE = IMAGE_LINK_RE -# stand-alone * or _ +# stand-alone `*` or `_` NOT_STRONG_RE = r'((^|(?<=\s))(\*{1,3}|_{1,3})(?=\s|$))' -# +# `` AUTOLINK_RE = r'<((?:[Ff]|[Hh][Tt])[Tt][Pp][Ss]?://[^<>]*)>' -# +# `` AUTOMAIL_RE = r'<([^<> !]+@[^@<> ]+)>' -# <...> +# `<...>` HTML_RE = r'(<(\/?[a-zA-Z][^<>@ ]*( [^<>]*)?|!--(?:(?!).)*--)>)' -# "&" (decimal) or "&" (hex) or "&" (named) +# `&` (decimal) or `&` (hex) or `&` (named) ENTITY_RE = r'(&(?:\#[0-9]+|\#x[0-9a-fA-F]+|[a-zA-Z0-9]+);)' # two spaces at end of line @@ -245,7 +245,7 @@ class Pattern: # pragma: no cover if isinstance(value, str): return value else: - # An etree Element - return text content only + # An `etree` Element - return text content only return ''.join(value.itertext()) return util.INLINE_PLACEHOLDER_RE.sub(get_stash, text) @@ -270,7 +270,7 @@ class InlineProcessor(Pattern): self.pattern = pattern self.compiled_re = re.compile(pattern, re.DOTALL | re.UNICODE) - # Api for Markdown to pass safe_mode into instance + # API for Markdown to pass `safe_mode` into instance self.safe_mode = False self.md = md @@ -710,7 +710,7 @@ class LinkInlineProcessor(InlineProcessor): if c != ' ': last = c - # We have a scenario: [test](link"notitle) + # We have a scenario: `[test](link"notitle)` # When we enter a string, we stop tracking bracket resolution in the main counter, # but we do keep a backup counter up until we discover where we might resolve all brackets # if the title string fails to resolve. @@ -749,7 +749,7 @@ class LinkInlineProcessor(InlineProcessor): class ImageInlineProcessor(LinkInlineProcessor): - """ Return a img element from the given match. """ + """ Return a `img` element from the given match. """ def handleMatch(self, m, data): text, index, handled = self.getText(data, m.end(0)) @@ -786,7 +786,7 @@ class ReferenceInlineProcessor(LinkInlineProcessor): if not handled: return None, None, None - # Clean up linebreaks in id + # Clean up line breaks in id id = self.NEWLINE_CLEANUP_RE.sub(' ', id) if id not in self.md.references: # ignore undefined refs return None, m.start(0), end @@ -831,7 +831,7 @@ class ShortReferenceInlineProcessor(ReferenceInlineProcessor): class ImageReferenceInlineProcessor(ReferenceInlineProcessor): - """ Match to a stored reference and return img element. """ + """ Match to a stored reference and return `img` element. """ def makeTag(self, href, title, text): el = etree.Element("img") el.set("src", href) @@ -842,7 +842,7 @@ class ImageReferenceInlineProcessor(ReferenceInlineProcessor): class ShortImageReferenceInlineProcessor(ImageReferenceInlineProcessor): - """ Short form of inage reference: ![ref]. """ + """ Short form of image reference: `![ref]`. """ def evalId(self, data, index, text): """Evaluate the id from of [ref] """ @@ -850,7 +850,7 @@ class ShortImageReferenceInlineProcessor(ImageReferenceInlineProcessor): class AutolinkInlineProcessor(InlineProcessor): - """ Return a link Element given an autolink (``). """ + """ Return a link Element given an auto-link (``). """ def handleMatch(self, m, data): el = etree.Element("a") el.set('href', self.unescape(m.group(1))) @@ -860,7 +860,7 @@ class AutolinkInlineProcessor(InlineProcessor): class AutomailInlineProcessor(InlineProcessor): """ - Return a mailto link Element given an automail link (``). + Return a `mailto` link Element given an auto-mail link (``). """ def handleMatch(self, m, data): el = etree.Element('a') diff --git a/markdown/postprocessors.py b/markdown/postprocessors.py index 498f7e8..0e89d40 100644 --- a/markdown/postprocessors.py +++ b/markdown/postprocessors.py @@ -103,7 +103,7 @@ class RawHtmlPostprocessor(Postprocessor): m = self.BLOCK_LEVEL_REGEX.match(html) if m: if m.group(1)[0] in ('!', '?', '@', '%'): - # Comment, php etc... + # Comment, PHP etc... return True return self.md.is_block_level(m.group(1)) return False diff --git a/markdown/serializers.py b/markdown/serializers.py index 59bab18..912c677 100644 --- a/markdown/serializers.py +++ b/markdown/serializers.py @@ -1,6 +1,4 @@ -# markdown/searializers.py -# -# Add x/html serialization to Elementree +# Add x/html serialization to `Elementree` # Taken from ElementTree 1.3 preview with slight modifications # # Copyright (c) 1999-2007 by Fredrik Lundh. All rights reserved. @@ -128,7 +126,7 @@ def _serialize_html(write, elem, format): else: namespace_uri = None if isinstance(tag, QName): - # QNAME objects store their data as a string: `{uri}tag` + # `QNAME` objects store their data as a string: `{uri}tag` if tag.text[:1] == "{": namespace_uri, tag = tag.text[1:].split("}", 1) else: @@ -139,10 +137,10 @@ def _serialize_html(write, elem, format): items = sorted(items) # lexical order for k, v in items: if isinstance(k, QName): - # Assume a text only QName + # Assume a text only `QName` k = k.text if isinstance(v, QName): - # Assume a text only QName + # Assume a text only `QName` v = v.text else: v = _escape_attrib_html(v) diff --git a/markdown/test_tools.py b/markdown/test_tools.py index 2ce0e74..c4db6b2 100644 --- a/markdown/test_tools.py +++ b/markdown/test_tools.py @@ -35,7 +35,7 @@ __all__ = ['TestCase', 'LegacyTestCase', 'Kwargs'] class TestCase(unittest.TestCase): """ - A unittest.TestCase subclass with helpers for testing Markdown output. + A `unittest.TestCase` subclass with helpers for testing Markdown output. Define `default_kwargs` as a dict of keywords to pass to Markdown for each test. The defaults can be overridden on individual tests. @@ -43,13 +43,13 @@ class TestCase(unittest.TestCase): The `assertMarkdownRenders` method accepts the source text, the expected output, and any keywords to pass to Markdown. The `default_kwargs` are used except where overridden by `kwargs`. The output and expected output are passed - to `TestCase.assertMultiLineEqual`. An AssertionError is raised with a diff + to `TestCase.assertMultiLineEqual`. An `AssertionError` is raised with a diff if the actual output does not equal the expected output. The `dedent` method is available to dedent triple-quoted strings if necessary. - In all other respects, behaves as unittest.TestCase. + In all other respects, behaves as `unittest.TestCase`. """ default_kwargs = {} @@ -80,7 +80,7 @@ class TestCase(unittest.TestCase): """ # TODO: If/when actual output ends with a newline, then use: - # return textwrap.dedent(text.strip('/n')) + # return textwrap.dedent(text.strip('/n')) return textwrap.dedent(text).strip() @@ -121,7 +121,7 @@ class Kwargs(dict): def _normalize_whitespace(text): - """ Normalize whitespace for a string of html using tidylib. """ + """ Normalize whitespace for a string of html using `tidylib`. """ output, errors = tidylib.tidy_fragment(text, options={ 'drop_empty_paras': 0, 'fix_backslash': 0, @@ -195,15 +195,15 @@ class LegacyTestCase(unittest.TestCase, metaclass=LegacyTestMeta): text-based test files and define various behaviors/defaults for those tests. The following properties are supported: - location: A path to the directory of test files. An absolute path is preferred. - exclude: A list of tests to exclude. Each test name should comprise the filename + `location`: A path to the directory of test files. An absolute path is preferred. + `exclude`: A list of tests to exclude. Each test name should comprise the filename without an extension. - normalize: A boolean value indicating if the HTML should be normalized. + `normalize`: A boolean value indicating if the HTML should be normalized. Default: `False`. - input_ext: A string containing the file extension of input files. Default: `.txt`. - ouput_ext: A string containing the file extension of expected output files. + `input_ext`: A string containing the file extension of input files. Default: `.txt`. + `output_ext`: A string containing the file extension of expected output files. Default: `html`. - default_kwargs: A `Kwargs` instance which stores the default set of keyword + `default_kwargs`: A `Kwargs` instance which stores the default set of keyword arguments for all test files in the directory. In addition, properties can be defined for each individual set of test files within @@ -214,7 +214,7 @@ class LegacyTestCase(unittest.TestCase, metaclass=LegacyTestMeta): test file. The keyword arguments will "update" the `default_kwargs`. When the class instance is created, it will walk the given directory and create - a separate unitttest for each set of test files using the naming scheme: - `test_filename`. One unittest will be run for each set of input and output files. + a separate `Unitttest` for each set of test files using the naming scheme: + `test_filename`. One `Unittest` will be run for each set of input and output files. """ pass diff --git a/markdown/treeprocessors.py b/markdown/treeprocessors.py index e9f48ca..c779d4d 100644 --- a/markdown/treeprocessors.py +++ b/markdown/treeprocessors.py @@ -26,7 +26,7 @@ from . import inlinepatterns def build_treeprocessors(md, **kwargs): - """ Build the default treeprocessors for Markdown. """ + """ Build the default `treeprocessors` for Markdown. """ treeprocessors = util.Registry() treeprocessors.register(InlineProcessor(md), 'inline', 20) treeprocessors.register(PrettifyTreeprocessor(md), 'prettify', 10) @@ -43,28 +43,28 @@ def isString(s): class Treeprocessor(util.Processor): """ - Treeprocessors are run on the ElementTree object before serialization. + `Treeprocessor`s are run on the `ElementTree` object before serialization. - Each Treeprocessor implements a "run" method that takes a pointer to an - ElementTree, modifies it as necessary and returns an ElementTree + Each `Treeprocessor` implements a `run` method that takes a pointer to an + `ElementTree`, modifies it as necessary and returns an `ElementTree` object. - Treeprocessors must extend markdown.Treeprocessor. + `Treeprocessors` must extend `markdown.Treeprocessor`. """ def run(self, root): """ - Subclasses of Treeprocessor should implement a `run` method, which - takes a root ElementTree. This method can return another ElementTree - object, and the existing root ElementTree will be replaced, or it can - modify the current tree and return None. + Subclasses of `Treeprocessor` should implement a `run` method, which + takes a root `ElementTree`. This method can return another `ElementTree` + object, and the existing root `ElementTree `will be replaced, or it can + modify the current tree and return `None`. """ pass # pragma: no cover class InlineProcessor(Treeprocessor): """ - A Treeprocessor that traverses a tree, applying inline patterns. + A `Treeprocessor` that traverses a tree, applying inline patterns. """ def __init__(self, md): @@ -89,8 +89,8 @@ class InlineProcessor(Treeprocessor): Keyword arguments: - * data: string - * index: index, from which we start search + * `data`: string + * `index`: index, from which we start search Returns: placeholder id and string index, after the found placeholder. @@ -114,8 +114,8 @@ class InlineProcessor(Treeprocessor): Keyword arguments: - * data: A line of Markdown text - * patternIndex: The index of the inlinePattern to start with + * `data`: A line of Markdown text + * `patternIndex`: The index of the `inlinePattern` to start with Returns: String with placeholders. @@ -133,14 +133,14 @@ class InlineProcessor(Treeprocessor): def __processElementText(self, node, subnode, isText=True): """ - Process placeholders in Element.text or Element.tail - of Elements popped from self.stashed_nodes. + Process placeholders in `Element.text` or `Element.tail` + of Elements popped from `self.stashed_nodes`. Keywords arguments: - * node: parent node - * subnode: processing node - * isText: bool variable, True - it's text, False - it's tail + * `node`: parent node + * `subnode`: processing node + * `isText`: boolean variable, True - it's text, False - it's a tail Returns: None @@ -165,14 +165,14 @@ class InlineProcessor(Treeprocessor): def __processPlaceholders(self, data, parent, isText=True): """ - Process string with placeholders and generate ElementTree tree. + Process string with placeholders and generate `ElementTree` tree. Keyword arguments: - * data: string with placeholders instead of ElementTree elements. - * parent: Element, which contains processing inline data + * `data`: string with placeholders instead of `ElementTree` elements. + * `parent`: Element, which contains processing inline data - Returns: list with ElementTree elements with applied inline patterns. + Returns: list with `ElementTree` elements with applied inline patterns. """ def linkText(text): @@ -231,7 +231,7 @@ class InlineProcessor(Treeprocessor): else: text = data[strartIndex:] if isinstance(data, util.AtomicString): - # We don't want to loose the AtomicString + # We don't want to loose the `AtomicString` text = util.AtomicString(text) linkText(text) data = "" @@ -241,16 +241,16 @@ class InlineProcessor(Treeprocessor): def __applyPattern(self, pattern, data, patternIndex, startIndex=0): """ Check if the line fits the pattern, create the necessary - elements, add it to stashed_nodes. + elements, add it to `stashed_nodes`. Keyword arguments: - * data: the text to be processed - * pattern: the pattern to be checked - * patternIndex: index of current pattern - * startIndex: string index, from which we start searching + * `data`: the text to be processed + * `pattern`: the pattern to be checked + * `patternIndex`: index of current pattern + * `startIndex`: string index, from which we start searching - Returns: String with placeholders instead of ElementTree elements. + Returns: String with placeholders instead of `ElementTree` elements. """ new_style = isinstance(pattern, inlinepatterns.InlineProcessor) @@ -261,7 +261,7 @@ class InlineProcessor(Treeprocessor): if new_style: match = None - # Since handleMatch may reject our first match, + # Since `handleMatch` may reject our first match, # we iterate over the buffer looking for matches # until we can't find any more. for match in pattern.getCompiledRegExp().finditer(data, startIndex): @@ -325,19 +325,19 @@ class InlineProcessor(Treeprocessor): def run(self, tree, ancestors=None): """Apply inline patterns to a parsed Markdown tree. - Iterate over ElementTree, find elements with inline tag, apply inline + Iterate over `ElementTree`, find elements with inline tag, apply inline patterns and append newly created Elements to tree. If you don't want to process your data with inline patterns, instead of normal - string, use subclass AtomicString: + string, use subclass `AtomicString`: node.text = markdown.AtomicString("This will not be processed.") Arguments: - * tree: ElementTree object, representing Markdown tree. - * ancestors: List of parent tag names that precede the tree node (if needed). + * `tree`: `ElementTree` object, representing Markdown tree. + * `ancestors`: List of parent tag names that precede the tree node (if needed). - Returns: ElementTree object with applied inline patterns. + Returns: `ElementTree` object with applied inline patterns. """ self.stashed_nodes = {} @@ -395,10 +395,10 @@ class InlineProcessor(Treeprocessor): class PrettifyTreeprocessor(Treeprocessor): - """ Add linebreaks to the html document. """ + """ Add line breaks to the html document. """ def _prettifyETree(self, elem): - """ Recursively add linebreaks to ElementTree children. """ + """ Recursively add line breaks to `ElementTree` children. """ i = "\n" if self.md.is_block_level(elem.tag) and elem.tag not in ['code', 'pre']: @@ -412,11 +412,11 @@ class PrettifyTreeprocessor(Treeprocessor): elem.tail = i def run(self, root): - """ Add linebreaks to ElementTree root object. """ + """ Add line breaks to `ElementTree` root object. """ self._prettifyETree(root) - # Do
    's separately as they are often in the middle of - # inline content and missed by _prettifyETree. + # Do `
    `'s separately as they are often in the middle of + # inline content and missed by `_prettifyETree`. brs = root.iter('br') for br in brs: if not br.tail or not br.tail.strip(): diff --git a/markdown/util.py b/markdown/util.py index 9bda07e..09b8cf6 100644 --- a/markdown/util.py +++ b/markdown/util.py @@ -47,8 +47,8 @@ BLOCK_LEVEL_ELEMENTS = [ ] # Placeholders -STX = '\u0002' # Use STX ("Start of text") for start-of-placeholder -ETX = '\u0003' # Use ETX ("End of text") for end-of-placeholder +STX = '\u0002' # Use `STX` ("Start of text") for start-of-placeholder +ETX = '\u0003' # Use `ETX` ("End of text") for end-of-placeholder INLINE_PLACEHOLDER_PREFIX = STX+"klzzwxh:" INLINE_PLACEHOLDER = INLINE_PLACEHOLDER_PREFIX + "%s" + ETX INLINE_PLACEHOLDER_RE = re.compile(INLINE_PLACEHOLDER % r'([0-9]+)') @@ -82,7 +82,7 @@ AUXILIARY GLOBAL FUNCTIONS def get_installed_extensions(): if sys.version_info >= (3, 10): from importlib import metadata - else: # ' ) def testCommentPrettify(self): - """ Test that an ElementTree Comment is prettified properly. """ + """ Test that an `ElementTree` `Comment` is prettified properly. """ pretty = markdown.treeprocessors.PrettifyTreeprocessor(markdown.Markdown()) pretty.run(self.comment) self.assertEqual( @@ -450,7 +450,7 @@ class testElementTailTests(unittest.TestCase): self.pretty = markdown.treeprocessors.PrettifyTreeprocessor(markdown.Markdown()) def testBrTailNoNewline(self): - """ Test that last
    in tree has a new line tail """ + """ Test that last `
    ` in tree has a new line tail """ root = etree.Element('root') br = etree.SubElement(root, 'br') self.assertEqual(br.tail, None) @@ -459,7 +459,7 @@ class testElementTailTests(unittest.TestCase): class testElementPreCodeTests(unittest.TestCase): - """ Element PreCode Tests """ + """ Element `PreCode` Tests """ def setUp(self): md = markdown.Markdown() self.pretty = markdown.treeprocessors.PrettifyTreeprocessor(md) @@ -557,7 +557,7 @@ class testSerializers(unittest.TestCase): ) def testProsessingInstruction(self): - """ Test serialization of ProcessignInstruction. """ + """ Test serialization of `ProcessignInstruction`. """ pi = ProcessingInstruction('foo', text='<&"test\nescaping">') self.assertIs(pi.tag, ProcessingInstruction) self.assertEqual( @@ -566,7 +566,7 @@ class testSerializers(unittest.TestCase): ) def testQNameTag(self): - """ Test serialization of QName tag. """ + """ Test serialization of `QName` tag. """ div = etree.Element('div') qname = etree.QName('http://www.w3.org/1998/Math/MathML', 'math') math = etree.SubElement(div, qname) @@ -595,7 +595,7 @@ class testSerializers(unittest.TestCase): ) def testQNameAttribute(self): - """ Test serialization of QName attribute. """ + """ Test serialization of `QName` attribute. """ div = etree.Element('div') div.set(etree.QName('foo'), etree.QName('bar')) self.assertEqual( @@ -604,13 +604,13 @@ class testSerializers(unittest.TestCase): ) def testBadQNameTag(self): - """ Test serialization of QName with no tag. """ + """ Test serialization of `QName` with no tag. """ qname = etree.QName('http://www.w3.org/1998/Math/MathML') el = etree.Element(qname) self.assertRaises(ValueError, markdown.serializers.to_xhtml_string, el) def testQNameEscaping(self): - """ Test QName escaping. """ + """ Test `QName` escaping. """ qname = etree.QName('<&"test\nescaping">', 'div') el = etree.Element(qname) self.assertEqual( @@ -619,7 +619,7 @@ class testSerializers(unittest.TestCase): ) def testQNamePreEscaping(self): - """ Test QName that is already partially escaped. """ + """ Test `QName` that is already partially escaped. """ qname = etree.QName('<&"test escaping">', 'div') el = etree.Element(qname) self.assertEqual( @@ -628,9 +628,9 @@ class testSerializers(unittest.TestCase): ) def buildExtension(self): - """ Build an extension which registers fakeSerializer. """ + """ Build an extension which registers `fakeSerializer`. """ def fakeSerializer(elem): - # Ignore input and return hardcoded output + # Ignore input and return hard-coded output return '

    ' class registerFakeSerializer(markdown.extensions.Extension): @@ -661,7 +661,7 @@ class testSerializers(unittest.TestCase): class testAtomicString(unittest.TestCase): - """ Test that AtomicStrings are honored (not parsed). """ + """ Test that `AtomicStrings` are honored (not parsed). """ def setUp(self): md = markdown.Markdown() @@ -679,7 +679,7 @@ class testAtomicString(unittest.TestCase): ) def testSimpleAtomicString(self): - """ Test that a simple AtomicString is not parsed. """ + """ Test that a simple `AtomicString` is not parsed. """ tree = etree.Element('div') p = etree.SubElement(tree, 'p') p.text = markdown.util.AtomicString('some *text*') @@ -690,7 +690,7 @@ class testAtomicString(unittest.TestCase): ) def testNestedAtomicString(self): - """ Test that a nested AtomicString is not parsed. """ + """ Test that a nested `AtomicString` is not parsed. """ tree = etree.Element('div') p = etree.SubElement(tree, 'p') p.text = markdown.util.AtomicString('*some* ') @@ -815,7 +815,7 @@ class TestCliOptionParsing(unittest.TestCase): self.assertEqual(options, self.default_options) def create_config_file(self, config): - """ Helper to create temp config files. """ + """ Helper to create temporary configuration files. """ if not isinstance(config, str): # convert to string config = yaml.dump(config) @@ -894,7 +894,7 @@ class TestEscapeAppend(unittest.TestCase): class TestBlockAppend(unittest.TestCase): - """ Tests block kHTML append. """ + """ Tests block `kHTML` append. """ def testBlockAppend(self): """ Test that appended escapes are only in the current instance. """ diff --git a/tests/test_extensions.py b/tests/test_extensions.py index b19d10a..ad985c3 100644 --- a/tests/test_extensions.py +++ b/tests/test_extensions.py @@ -22,7 +22,7 @@ Python-Markdown Extension Regression Tests ========================================== A collection of regression tests to confirm that the included extensions -continue to work as advertised. This used to be accomplished by doctests. +continue to work as advertised. This used to be accomplished by `doctests`. """ import unittest @@ -77,7 +77,7 @@ class TestExtensionClass(unittest.TestCase): self.assertEqual(self.ext.getConfigs(), {'foo': 'baz', 'bar': 'baz'}) def testSetConfigWithBadKey(self): - # self.ext.setConfig('bad', 'baz) ==> KeyError + # `self.ext.setConfig('bad', 'baz)` => `KeyError` self.assertRaises(KeyError, self.ext.setConfig, 'bad', 'baz') def testConfigAsKwargsOnInit(self): @@ -115,7 +115,7 @@ class TestAbbr(unittest.TestCase): class TestMetaData(unittest.TestCase): - """ Test MetaData extension. """ + """ Test `MetaData` extension. """ def setUp(self): self.md = markdown.Markdown(extensions=['meta']) @@ -196,14 +196,14 @@ The body. This is paragraph one.''' class TestWikiLinks(unittest.TestCase): - """ Test Wikilinks Extension. """ + """ Test `Wikilinks` Extension. """ def setUp(self): self.md = markdown.Markdown(extensions=['wikilinks']) self.text = "Some text with a [[WikiLink]]." def testBasicWikilinks(self): - """ Test [[wikilinks]]. """ + """ Test `[[wikilinks]]`. """ self.assertEqual( self.md.convert(self.text), @@ -212,7 +212,7 @@ class TestWikiLinks(unittest.TestCase): ) def testWikilinkWhitespace(self): - """ Test whitespace in wikilinks. """ + """ Test whitespace in `wikilinks`. """ self.assertEqual( self.md.convert('[[ foo bar_baz ]]'), '

    foo bar_baz

    ' @@ -257,7 +257,7 @@ class TestWikiLinks(unittest.TestCase): ) def testWikilinksMetaData(self): - """ test MetaData with Wikilinks Extension. """ + """ test `MetaData` with `Wikilinks` Extension. """ text = """wiki_base_url: http://example.com/ wiki_end_url: .html @@ -271,7 +271,7 @@ Some text with a [[WikiLink]].""" 'WikiLink.

    ' ) - # MetaData should not carry over to next document: + # `MetaData` should not carry over to next document: self.assertEqual( md.convert("No [[MetaData]] here."), '

    No MetaData ' @@ -548,7 +548,7 @@ class TestTOC(TestCaseWithAssertStartsWith): ) def testWithAttrList(self): - """ Test TOC with attr_list Extension. """ + """ Test TOC with `attr_list` Extension. """ md = markdown.Markdown(extensions=['toc', 'attr_list']) text = ('# Header 1\n\n' '## Header 2 { #foo }\n\n' @@ -640,7 +640,7 @@ class TestSmarty(unittest.TestCase): 'ndash': '\u2013', 'mdash': '\u2014', 'ellipsis': '\u2026', - 'left-single-quote': '‚', # sb is not a typo! + 'left-single-quote': '‚', # `sb` is not a typo! 'right-single-quote': '‘', 'left-double-quote': '„', 'right-double-quote': '“', diff --git a/tests/test_legacy.py b/tests/test_legacy.py index 7b2c09a..30b6c18 100644 --- a/tests/test_legacy.py +++ b/tests/test_legacy.py @@ -46,24 +46,24 @@ class TestPhp(LegacyTestCase): Quotes in attributes: attributes get output in different order - Inline HTML (Span): Backtick in raw HTML attribute TODO: fixme + Inline HTML (Span): Backtick in raw HTML attribute TODO: fix me Backslash escapes: Weird whitespace issue in output - Ins & del: Our behavior follows markdown.pl I think PHP is wrong here + `Ins` & `del`: Our behavior follows `markdown.pl`. I think PHP is wrong here - Auto Links: TODO: fix raw HTML so is doesn't match as a


    . + Auto Links: TODO: fix raw HTML so is doesn't match as a `
    `. - Empty List Item: We match markdown.pl here. Maybe someday we'll support this + Empty List Item: We match `markdown.pl` here. Maybe someday we'll support this Headers: TODO: fix headers to not require blank line before - Mixed OLs and ULs: We match markdown.pl here. I think PHP is wrong here + Mixed `OL`s and `UL`s: We match `markdown.pl` here. I think PHP is wrong here Emphasis: We have various minor differences in combined & incorrect em markup. Maybe fix a few of them - but most aren't too important - Code block in a list item: We match markdown.pl - not sure how php gets that output?? + Code block in a list item: We match `markdown.pl` - not sure how PHP gets that output?? PHP-Specific Bugs: Not sure what to make of the escaping stuff here. Why is PHP not removing a backslash? @@ -87,14 +87,6 @@ class TestPhp(LegacyTestCase): ] -# class TestPhpExtra(LegacyTestCase): -# location = os.path.join(parent_test_dir, 'php/extra') -# normalize = True -# input_ext = '.text' -# output_ext = '.xhtml' -# default_kwargs = Kwargs(extensions=['extra']) - - class TestPl2004(LegacyTestCase): location = os.path.join(parent_test_dir, 'pl/Tests_2004') normalize = True @@ -110,11 +102,11 @@ class TestPl2007(LegacyTestCase): Code Blocks: some weird whitespace issue - Links, reference style: weird issue with nested brackets TODO: fixme + Links, reference style: weird issue with nested brackets TODO: fix me - Backslash escapes: backticks in raw html attributes TODO: fixme + Backslash escapes: backticks in raw html attributes TODO: fix me - Code Spans: more backticks in raw html attributes TODO: fixme + Code Spans: more backticks in raw html attributes TODO: fix me """ location = os.path.join(parent_test_dir, 'pl/Tests_2007') normalize = True diff --git a/tests/test_syntax/blocks/test_html_blocks.py b/tests/test_syntax/blocks/test_html_blocks.py index 9ec0668..8623b30 100644 --- a/tests/test_syntax/blocks/test_html_blocks.py +++ b/tests/test_syntax/blocks/test_html_blocks.py @@ -1611,7 +1611,7 @@ class TestHTMLBlocks(TestCase): def test_placeholder_in_source(self): # This should never occur, but third party extensions could create weird edge cases. md = markdown.Markdown() - # Ensure there is an htmlstash so relevant code (nested in `if replacements`) is run. + # Ensure there is an `htmlstash` so relevant code (nested in `if replacements`) is run. md.htmlStash.store('foo') # Run with a placeholder which is not in the stash placeholder = md.htmlStash.get_placeholder(md.htmlStash.html_counter + 1) diff --git a/tests/test_syntax/extensions/test_attr_list.py b/tests/test_syntax/extensions/test_attr_list.py index 6baaafb..f6a4fe6 100644 --- a/tests/test_syntax/extensions/test_attr_list.py +++ b/tests/test_syntax/extensions/test_attr_list.py @@ -26,7 +26,7 @@ class TestAttrList(TestCase): maxDiff = None - # TODO: Move the rest of the attr_list tests here. + # TODO: Move the rest of the `attr_list` tests here. def test_empty_list(self): self.assertMarkdownRenders( diff --git a/tests/test_syntax/extensions/test_code_hilite.py b/tests/test_syntax/extensions/test_code_hilite.py index 09dd523..0a41c4f 100644 --- a/tests/test_syntax/extensions/test_code_hilite.py +++ b/tests/test_syntax/extensions/test_code_hilite.py @@ -29,9 +29,9 @@ try: except ImportError: has_pygments = False -# The version required by the tests is the version specified and installed in the 'pygments' tox env. -# In any environment where the PYGMENTS_VERSION environment variable is either not defined or doesn't -# match the version of Pygments installed, all tests which rely in pygments will be skipped. +# The version required by the tests is the version specified and installed in the `pygments` tox environment. +# In any environment where the `PYGMENTS_VERSION` environment variable is either not defined or doesn't +# match the version of Pygments installed, all tests which rely in Pygments will be skipped. required_pygments_version = os.environ.get('PYGMENTS_VERSION', '') @@ -54,7 +54,7 @@ class TestCodeHiliteClass(TestCase): def test_codehilite_defaults(self): if has_pygments: - # Odd result as no lang given and a single comment is not enough for guessing. + # Odd result as no `lang` given and a single comment is not enough for guessing. expected = ( '
    # A Code Comment\n'
                     '
    ' @@ -98,7 +98,7 @@ class TestCodeHiliteClass(TestCase): def test_codehilite_set_lang(self): if has_pygments: - # Note an extra `` is added to end of code block when lang explicitly set. + # Note an extra `` is added to end of code block when `lang` explicitly set. # Compare with expected output for `test_guess_lang`. Not sure why this happens. expected = ( '
    <?php '
    @@ -122,7 +122,7 @@ class TestCodeHiliteClass(TestCase):
                     '
    ' ) else: - # Note that without pygments there is no way to check that the language name is bad. + # Note that without Pygments there is no way to check that the language name is bad. expected = ( '
    '
                     '<?php print("Hello World"); ?>\n'
    @@ -273,7 +273,7 @@ class TestCodeHiliteClass(TestCase):
                     '
    ' ) else: - # TODO: Implement linenostart for no-pygments. Will need to check what JS libs look for. + # TODO: Implement `linenostart` for no-Pygments. Will need to check what JavaScript libraries look for. expected = ( '
    plain text\n'
                     '
    ' @@ -374,7 +374,7 @@ class TestCodeHiliteExtension(TestCase): def testBasicCodeHilite(self): if has_pygments: - # Odd result as no lang given and a single comment is not enough for guessing. + # Odd result as no `lang` given and a single comment is not enough for guessing. expected = ( '
    # A Code Comment\n'
                     '
    ' @@ -645,7 +645,7 @@ class TestCodeHiliteExtension(TestCase): def testUnknownOption(self): if has_pygments: - # Odd result as no lang given and a single comment is not enough for guessing. + # Odd result as no `lang` given and a single comment is not enough for guessing. expected = ( '
    # A Code Comment\n'
                     '
    ' diff --git a/tests/test_syntax/extensions/test_fenced_code.py b/tests/test_syntax/extensions/test_fenced_code.py index be3c215..e24a177 100644 --- a/tests/test_syntax/extensions/test_fenced_code.py +++ b/tests/test_syntax/extensions/test_fenced_code.py @@ -31,9 +31,9 @@ try: except ImportError: has_pygments = False -# The version required by the tests is the version specified and installed in the 'pygments' tox env. -# In any environment where the PYGMENTS_VERSION environment variable is either not defined or doesn't -# match the version of Pygments installed, all tests which rely in pygments will be skipped. +# The version required by the tests is the version specified and installed in the `pygments` tox environment. +# In any environment where the `PYGMENTS_VERSION` environment variable is either not defined or doesn't +# match the version of Pygments installed, all tests which rely in Pygments will be skipped. required_pygments_version = os.environ.get('PYGMENTS_VERSION', '') diff --git a/tests/test_syntax/extensions/test_footnotes.py b/tests/test_syntax/extensions/test_footnotes.py index 9a6b32a..9fe786b 100644 --- a/tests/test_syntax/extensions/test_footnotes.py +++ b/tests/test_syntax/extensions/test_footnotes.py @@ -266,7 +266,7 @@ class TestFootnotes(TestCase): ) def test_backlink_text(self): - """Test backlink configuration.""" + """Test back-link configuration.""" self.assertMarkdownRenders( 'paragraph[^1]\n\n[^1]: A Footnote', @@ -302,7 +302,7 @@ class TestFootnotes(TestCase): ) def test_backlink_title(self): - """Test backlink title configuration without placeholder.""" + """Test back-link title configuration without placeholder.""" self.assertMarkdownRenders( 'paragraph[^1]\n\n[^1]: A Footnote', diff --git a/tests/test_syntax/extensions/test_md_in_html.py b/tests/test_syntax/extensions/test_md_in_html.py index 6c13f11..3de49b0 100644 --- a/tests/test_syntax/extensions/test_md_in_html.py +++ b/tests/test_syntax/extensions/test_md_in_html.py @@ -32,7 +32,7 @@ class TestMarkdownInHTMLPostProcessor(TestCase): def test_stash_to_string(self): # There should be no known cases where this actually happens so we need to - # forcefully pass an etree Element to the method to ensure proper behavior. + # forcefully pass an `etree` `Element` to the method to ensure proper behavior. element = Element('div') element.text = 'Foo bar.' md = Markdown(extensions=['md_in_html']) @@ -1208,7 +1208,7 @@ class TestMdInHTML(TestCase): def load_tests(loader, tests, pattern): - ''' Ensure TestHTMLBlocks doesn't get run twice by excluding it here. ''' + ''' Ensure `TestHTMLBlocks` doesn't get run twice by excluding it here. ''' suite = TestSuite() for test_class in [TestDefaultwMdInHTML, TestMdInHTML, TestMarkdownInHTMLPostProcessor]: tests = loader.loadTestsFromTestCase(test_class) diff --git a/tests/test_syntax/extensions/test_tables.py b/tests/test_syntax/extensions/test_tables.py index cd3fbe4..6a1a0d4 100644 --- a/tests/test_syntax/extensions/test_tables.py +++ b/tests/test_syntax/extensions/test_tables.py @@ -26,7 +26,7 @@ from markdown.extensions.tables import TableExtension class TestTableBlocks(TestCase): def test_empty_cells(self): - """Empty cells (nbsp).""" + """Empty cells (`nbsp`).""" text = """   | Second Header diff --git a/tox.ini b/tox.ini index 4689516..ca30175 100644 --- a/tox.ini +++ b/tox.ini @@ -26,11 +26,13 @@ commands = flake8 {toxinidir}/markdown {toxinidir}/tests skip_install = true [testenv:checkspelling] -allowlist_externals = {toxinidir}/checkspelling.sh deps = mkdocs mkdocs_nature -commands = {toxinidir}/checkspelling.sh + pyspelling +commands = + {envpython} -m mkdocs build --strict --config-file {toxinidir}/mkdocs.yml + {envpython} -m pyspelling --config {toxinidir}/.pyspelling.yml [testenv:checklinks] whitelist_externals = markdown-link-check -- cgit v1.2.1