• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"""
2Python Markdown
3
4A Python implementation of John Gruber's Markdown.
5
6Documentation: https://python-markdown.github.io/
7GitHub: https://github.com/Python-Markdown/markdown/
8PyPI: https://pypi.org/project/Markdown/
9
10Started by Manfred Stienstra (http://www.dwerg.net/).
11Maintained for a few years by Yuri Takhteyev (http://www.freewisdom.org).
12Currently maintained by Waylan Limberg (https://github.com/waylan),
13Dmitry Shachnev (https://github.com/mitya57) and Isaac Muse (https://github.com/facelessuser).
14
15Copyright 2007-2018 The Python Markdown Project (v. 1.7 and later)
16Copyright 2004, 2005, 2006 Yuri Takhteyev (v. 0.2-1.6b)
17Copyright 2004 Manfred Stienstra (the original version)
18
19License: BSD (see LICENSE.md for details).
20
21PRE-PROCESSORS
22=============================================================================
23
24Preprocessors work on source text before we start doing anything too
25complicated.
26"""
27
28from . import util
29from .htmlparser import HTMLExtractor
30import re
31
32
33def build_preprocessors(md, **kwargs):
34    """ Build the default set of preprocessors used by Markdown. """
35    preprocessors = util.Registry()
36    preprocessors.register(NormalizeWhitespace(md), 'normalize_whitespace', 30)
37    preprocessors.register(HtmlBlockPreprocessor(md), 'html_block', 20)
38    return preprocessors
39
40
41class Preprocessor(util.Processor):
42    """
43    Preprocessors are run after the text is broken into lines.
44
45    Each preprocessor implements a "run" method that takes a pointer to a
46    list of lines of the document, modifies it as necessary and returns
47    either the same pointer or a pointer to a new list.
48
49    Preprocessors must extend markdown.Preprocessor.
50
51    """
52    def run(self, lines):
53        """
54        Each subclass of Preprocessor should override the `run` method, which
55        takes the document as a list of strings split by newlines and returns
56        the (possibly modified) list of lines.
57
58        """
59        pass  # pragma: no cover
60
61
62class NormalizeWhitespace(Preprocessor):
63    """ Normalize whitespace for consistent parsing. """
64
65    def run(self, lines):
66        source = '\n'.join(lines)
67        source = source.replace(util.STX, "").replace(util.ETX, "")
68        source = source.replace("\r\n", "\n").replace("\r", "\n") + "\n\n"
69        source = source.expandtabs(self.md.tab_length)
70        source = re.sub(r'(?<=\n) +\n', '\n', source)
71        return source.split('\n')
72
73
74class HtmlBlockPreprocessor(Preprocessor):
75    """Remove html blocks from the text and store them for later retrieval."""
76
77    def run(self, lines):
78        source = '\n'.join(lines)
79        parser = HTMLExtractor(self.md)
80        parser.feed(source)
81        parser.close()
82        return ''.join(parser.cleandoc).split('\n')
83