diff --git a/404.html b/404.html old mode 100755 new mode 100644 index d3fdb47..bd7380e --- a/404.html +++ b/404.html @@ -11,9 +11,12 @@ - Python-Markdown 3.4.4 documentation + Python-Markdown 3.5 documentation + + + @@ -23,7 +26,7 @@

Navigation

@@ -64,14 +67,6 @@

This Page

  • Report a Bug
  • - - @@ -82,7 +77,7 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/assets/_mkdocstrings.css b/assets/_mkdocstrings.css new file mode 100644 index 0000000..049a254 --- /dev/null +++ b/assets/_mkdocstrings.css @@ -0,0 +1,64 @@ + +/* Avoid breaking parameter names, etc. in table cells. */ +.doc-contents td code { + word-break: normal !important; +} + +/* No line break before first paragraph of descriptions. */ +.doc-md-description, +.doc-md-description>p:first-child { + display: inline; +} + +/* Max width for docstring sections tables. */ +.doc .md-typeset__table, +.doc .md-typeset__table table { + display: table !important; + width: 100%; +} + +.doc .md-typeset__table tr { + display: table-row; +} + +/* Defaults in Spacy table style. */ +.doc-param-default { + float: right; +} + +/* Keep headings consistent. */ +h1.doc-heading, +h2.doc-heading, +h3.doc-heading, +h4.doc-heading, +h5.doc-heading, +h6.doc-heading { + font-weight: 400; + line-height: 1.5; + color: inherit; + text-transform: none; +} + +h1.doc-heading { + font-size: 1.6rem; +} + +h2.doc-heading { + font-size: 1.2rem; +} + +h3.doc-heading { + font-size: 1.15rem; +} + +h4.doc-heading { + font-size: 1.10rem; +} + +h5.doc-heading { + font-size: 1.05rem; +} + +h6.doc-heading { + font-size: 1rem; +} \ No newline at end of file diff --git a/authors/index.html b/authors/index.html old mode 100755 new mode 100644 index b705395..70347e4 --- a/authors/index.html +++ b/authors/index.html @@ -10,10 +10,13 @@ - - Authors — Python-Markdown 3.4.4 documentation + + Authors — Python-Markdown 3.5 documentation + + + @@ -23,19 +26,19 @@

    Navigation

    - - @@ -186,19 +170,19 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/change_log/index.html b/change_log/index.html old mode 100755 new mode 100644 index fd4ea33..3374163 --- a/change_log/index.html +++ b/change_log/index.html @@ -9,11 +9,14 @@ - - - Change Log — Python-Markdown 3.4.4 documentation + + + Change Log — Python-Markdown 3.5 documentation + + + @@ -23,21 +26,17 @@

    Navigation

    @@ -72,108 +57,10 @@

    Navigation

    Python-Markdown Change Log

    -

    July 25, 2023: version 3.4.4 (a bug-fix release).

    -
      -
    • Add a special case for initial 's to smarty extension (#1305).
    • -
    • Unescape any backslash escaped inline raw HTML (#1358).
    • -
    • Unescape backslash escaped TOC token names (#1360).
    • -
    -

    March 23, 2023: version 3.4.3 (a bug-fix release).

    -
      -
    • Restore console script (#1327).
    • -
    -

    March 22, 2023: version 3.4.2 (a bug-fix release).

    -
      -
    • Improve standalone * and _ parsing (#1300).
    • -
    • Consider <html> HTML tag a block-level element (#1309).
    • -
    • Officially support Python 3.11.
    • -
    • Switch from setup.py to pyproject.toml.
    • -
    -

    July 15, 2022: version 3.4.1 (a bug-fix release).

    -
      -
    • Fix an import issue with importlib.util (#1274).
    • -
    -

    July 15, 2022: version 3.4 (Notes).

    -

    May 5, 2022: version 3.3.7 (a bug-fix release).

    -
      -
    • Disallow square brackets in reference link ids (#1209).
    • -
    • Retain configured pygments_style after first code block (#1240).
    • -
    • Ensure fenced code attributes are properly escaped (#1247).
    • -
    -

    Nov 17, 2021: version 3.3.6 (a bug-fix release).

    - -

    Nov 16, 2021: version 3.3.5 (a bug-fix release).

    -
      -
    • Make the slugify_unicode function not remove diacritical marks (#1118).
    • -
    • Fix [toc] detection when used with nl2br extension (#1160).
    • -
    • Re-use compiled regex for block level checks (#1169).
    • -
    • Don’t process shebangs in fenced code blocks when using CodeHilite (#1156).
    • -
    • Improve email address validation for Automatic Links (#1165).
    • -
    • Ensure <summary> tags are parsed correctly (#1079).
    • -
    • Support Python 3.10 (#1124).
    • -
    -

    Feb 24, 2021: version 3.3.4 (a bug-fix release).

    -
      -
    • Properly parse unclosed tags in code spans (#1066).
    • -
    • Properly parse processing instructions in md_in_html (#1070).
    • -
    • Properly parse code spans in md_in_html (#1069).
    • -
    • Preserve text immediately before an admonition (#1092).
    • -
    • Simplified regex for HTML placeholders (#928) addressing (#932).
    • -
    • Ensure permalinks and anchorlinks are not restricted by toc_depth (#1107).
    • -
    • Fix corner cases with lists under admonitions (#1102).
    • -
    -

    Oct 25, 2020: version 3.3.3 (a bug-fix release).

    -
      -
    • Unify all block-level tags (#1047).
    • -
    • Fix issue where some empty elements would have text rendered as None when using md_in_html (#1049).
    • -
    • Avoid catastrophic backtracking in hr regex (#1055).
    • -
    • Fix hr HTML handling (#1053).
    • -
    -

    Oct 19, 2020: version 3.3.2 (a bug-fix release).

    -
      -
    • Properly parse inline HTML in md_in_html (#1040 & #1045).
    • -
    • Avoid crashing when md_in_html fails (#1040).
    • -
    -

    Oct 12, 2020: version 3.3.1 (a bug-fix release).

    -
      -
    • Correctly parse raw script and style tags (#1036).
    • -
    • Ensure consistent class handling by fenced_code and codehilite (#1032).
    • -
    -

    Oct 6, 2020: version 3.3 (Notes).

    -

    May 8, 2020: version 3.2.2 (a bug-fix release).

    -
      -
    • Add checklinks tox environment to ensure all links in documentation are good.
    • -
    • Refactor extension API documentation (#729).
    • -
    • Load entry_points (for extensions) only once using importlib.metadata.
    • -
    • Do not double escape entities in TOC.
    • -
    • Correctly report if an extension raises a TypeError (#939).
    • -
    • Raise a KeyError when attempting to delete a nonexistent key from the - extension registry (#939).
    • -
    • Remove import of packaging (or pkg_resources fallback) entirely.
    • -
    • Remove setuptools as a run-time dependency (install_required).
    • -
    -

    Feb 12, 2020: Released version 3.2.1 (a bug-fix release).

    -
      -
    • The name property in toc_tokens from the TOC extension now - escapes HTML special characters (<, >, and &).
    • -
    -

    Feb 7, 2020: Released version 3.2 (Notes).

    -

    May 20, 2019: Released version 3.1.1 (a bug-fix release).

    -
      -
    • Fixed import failure in setup.py when the source directory is not - on sys.path (#823).
    • -
    • Prefer public packaging module to pkg_resources’ private copy of - it (#825).
    • -
    -

    Mar 25, 2019: Released version 3.1 (Notes).

    -

    Sept 28, 2018: Released version 3.0.1 (a bug-fix release).

    -
      -
    • Brought back the version and version_info variables (#709).
    • -
    • Added support for hexadecimal HTML entities (#712).
    • -
    -

    Sept 21, 2018: Released version 3.0 (Notes).

    +
    +

    Note

    +

    This is an archive of the changelog prior to the release of version 3.0. See the current changelog for up-to-date details.

    +

    Jan 4, 2018: Released version 2.6.11 (a bug-fix release). Added a new BACKLINK-TITLE option to the footnote extension so that non-English users can provide a custom title to back links (see #610).

    @@ -335,16 +222,8 @@

    Table Of Contents

    -

    Previous topic

    -

    - Contributing to Python-Markdown -

    -

    Next topic

    -

    - Release Notes for v.3.4 -

    This Page

    @@ -353,14 +232,6 @@

    This Page

  • Edit on GitHub
  • - -
    @@ -371,21 +242,17 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/change_log/release-2.0/index.html b/change_log/release-2.0/index.html old mode 100755 new mode 100644 index 85f78c8..cf47083 --- a/change_log/release-2.0/index.html +++ b/change_log/release-2.0/index.html @@ -9,11 +9,14 @@ - - - Release Notes for v.2.0 — Python-Markdown 3.4.4 documentation + + + Release Notes for v2.0 — Python-Markdown 3.5 documentation + + + @@ -23,21 +26,17 @@

    Navigation

    @@ -145,16 +130,8 @@

    Table Of Contents

    -

    Previous topic

    -

    - Release Notes for v.2.1 -

    -

    Next topic

    -

    - Authors -

    This Page

    @@ -163,14 +140,6 @@

    This Page

  • Edit on GitHub
  • - - @@ -181,21 +150,17 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/change_log/release-2.1/index.html b/change_log/release-2.1/index.html old mode 100755 new mode 100644 index cb46c1b..4b51b20 --- a/change_log/release-2.1/index.html +++ b/change_log/release-2.1/index.html @@ -9,11 +9,14 @@ - - - Release Notes for v.2.1 — Python-Markdown 3.4.4 documentation + + + Release Notes for v2.1 — Python-Markdown 3.5 documentation + + + @@ -23,21 +26,17 @@

    Navigation

    @@ -200,16 +185,8 @@

    Table Of Contents

    -

    Previous topic

    -

    - Release Notes for v.2.2 -

    -

    Next topic

    -

    - Release Notes for v.2.0 -

    This Page

    @@ -218,14 +195,6 @@

    This Page

  • Edit on GitHub
  • - - @@ -236,21 +205,17 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/change_log/release-2.2/index.html b/change_log/release-2.2/index.html old mode 100755 new mode 100644 index 5919f35..a2bf52d --- a/change_log/release-2.2/index.html +++ b/change_log/release-2.2/index.html @@ -9,11 +9,14 @@ - - - Release Notes for v.2.2 — Python-Markdown 3.4.4 documentation + + + Release Notes for v2.2 — Python-Markdown 3.5 documentation + + + @@ -23,21 +26,17 @@

    Navigation

    @@ -149,16 +134,8 @@

    Table Of Contents

    -

    Previous topic

    -

    - Release Notes for v.2.3 -

    -

    Next topic

    -

    - Release Notes for v.2.1 -

    This Page

    @@ -167,14 +144,6 @@

    This Page

  • Edit on GitHub
  • - - @@ -185,21 +154,17 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/change_log/release-2.3/index.html b/change_log/release-2.3/index.html old mode 100755 new mode 100644 index 03de0d4..366a64c --- a/change_log/release-2.3/index.html +++ b/change_log/release-2.3/index.html @@ -9,11 +9,14 @@ - - - Release Notes for v.2.3 — Python-Markdown 3.4.4 documentation + + + Release Notes for v2.3 — Python-Markdown 3.5 documentation + + + @@ -23,21 +26,17 @@

    Navigation

    @@ -178,16 +163,8 @@

    Table Of Contents

    -

    Previous topic

    -

    - Release Notes for v.2.4 -

    -

    Next topic

    -

    - Release Notes for v.2.2 -

    This Page

    @@ -196,14 +173,6 @@

    This Page

  • Edit on GitHub
  • - - @@ -214,21 +183,17 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/change_log/release-2.4/index.html b/change_log/release-2.4/index.html old mode 100755 new mode 100644 index cfc761b..16b75ed --- a/change_log/release-2.4/index.html +++ b/change_log/release-2.4/index.html @@ -9,11 +9,14 @@ - - - Release Notes for v.2.4 — Python-Markdown 3.4.4 documentation + + + Release Notes for v2.4 — Python-Markdown 3.5 documentation + + + @@ -23,21 +26,17 @@

    Navigation

    @@ -116,12 +101,12 @@

    What’s New in Python-Markdown 2.4

    The code blocks now support emphasizing some of the code lines. To use this feature, specify hl_lines option after language name, for example (using the Fenced Code Extension):

    -
    ```.python hl_lines="1 3"
    +
    ```.python hl_lines="1 3"
     # This line will be emphasized.
    -# This one won't.
    +# This one won't.
     # This one will be also emphasized.
     ```
    -
    +

    Thanks to A. Jesse Jiryu Davis for implementing this feature.

    @@ -155,16 +140,8 @@

    Table Of Contents

    -

    Previous topic

    -

    - Release Notes for v.2.5 -

    -

    Next topic

    -

    - Release Notes for v.2.3 -

    This Page

    @@ -173,14 +150,6 @@

    This Page

  • Edit on GitHub
  • - - @@ -191,21 +160,17 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/change_log/release-2.5/index.html b/change_log/release-2.5/index.html old mode 100755 new mode 100644 index 3789e5f..bc2d21c --- a/change_log/release-2.5/index.html +++ b/change_log/release-2.5/index.html @@ -9,11 +9,14 @@ - - - Release Notes for v.2.5 — Python-Markdown 3.4.4 documentation + + + Release Notes for v2.5 — Python-Markdown 3.5 documentation + + + @@ -23,21 +26,17 @@

    Navigation

    @@ -96,26 +81,26 @@

    Backwards-incompatible ChangesBleach) after being converted to HTML by markdown.

    If your code previously looked like this:

    -
    html = markdown.markdown(text, same_mode=True)
    -
    +
    html = markdown.markdown(text, same_mode=True)
    +

    Then it is recommended that you change your code to read something like this:

    -
    import bleach
    -html = bleach.clean(markdown.markdown(text))
    -
    +
    import bleach
    +html = bleach.clean(markdown.markdown(text))
    +

    If you are not interested in sanitizing untrusted text, but simply desire to escape raw HTML, then that can be accomplished through an extension which removes HTML parsing:

    -
    from markdown.extensions import Extension
    +
    from markdown.extensions import Extension
     
    -class EscapeHtml(Extension):
    -    def extendMarkdown(self, md, md_globals):
    -        del md.preprocessors['html_block']
    -        del md.inlinePatterns['html']
    +class EscapeHtml(Extension):
    +    def extendMarkdown(self, md, md_globals):
    +        del md.preprocessors['html_block']
    +        del md.inlinePatterns['html']
     
    -html = markdown.markdown(text, extensions=[EscapeHtml()])
    -
    +html = markdown.markdown(text, extensions=[EscapeHtml()]) +

    As the HTML would not be parsed with the above Extension, then the serializer will escape the raw HTML, which is exactly what happens now when @@ -126,12 +111,12 @@

    Backwards-incompatible Changes
     html = markdown.markdown(text, ['extra'])
    -
    +
     html = markdown.markdown(text, ['extra'])
    +

    Then it is recommended that you change it to read something like this:

    -
    html = markdown.markdown(text, extensions=['extra'])
    -
    +
    html = markdown.markdown(text, extensions=['extra'])
    +

    markdown.markdown(text, extensions=['extra'])
    -

    +
    markdown.markdown(text, extensions=['extra'])
    +

    You should change your code to the following:

    -
    markdown.markdown(text, extensions=['markdown.extensions.extra'])
    -
    +
    markdown.markdown(text, extensions=['markdown.extensions.extra'])
    +

    The same applies to the command line:

    -
    $ python -m markdown -x markdown.extensions.extra input.txt
    -
    +
    $ python -m markdown -x markdown.extensions.extra input.txt
    +

    See the documentation for a full explanation of the current behavior.

    @@ -191,12 +176,12 @@

    What’s New in Python-Markdown 2.5 end of the name (which uses dot notation from PYTHONPATH) and be separated by a colon from the module.

    Therefore, if you were to import the class like this:

    -
    from path.to.module import SomeExtensionClass
    -
    +
    from path.to.module import SomeExtensionClass
    +

    Then the named extension would comprise this string:

    -
    "path.to.module:SomeExtensionClass"
    -
    +
    "path.to.module:SomeExtensionClass"
    +

    This allows multiple extensions to be implemented within the same module and still accessible when the user is not able to import the extension directly @@ -267,16 +252,8 @@

    Table Of Contents

    -

    Previous topic

    -

    - Release Notes for v.2.6 -

    -

    Next topic

    -

    - Release Notes for v.2.4 -

    This Page

    @@ -285,14 +262,6 @@

    This Page

  • Edit on GitHub
  • - - @@ -303,21 +272,17 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/change_log/release-2.6/index.html b/change_log/release-2.6/index.html old mode 100755 new mode 100644 index 4f6a93b..2c87d3e --- a/change_log/release-2.6/index.html +++ b/change_log/release-2.6/index.html @@ -9,11 +9,14 @@ - - - Release Notes for v.2.6 — Python-Markdown 3.4.4 documentation + + + Release Notes for v2.6 — Python-Markdown 3.5 documentation + + + @@ -23,21 +26,17 @@

    Navigation

    @@ -89,27 +74,27 @@

    safe_mode Deprecated
    html = markdown.markdown(text, safe_mode=True)
    -
    +
    html = markdown.markdown(text, safe_mode=True)
    +

    Then it is recommended that you change your code to read something like this:

    -
    import bleach
    -from bleach_whitelist import markdown_tags, markdown_attrs
    -html = bleach.clean(markdown.markdown(text), markdown_tags, markdown_attrs)
    -
    +
    import bleach
    +from bleach_whitelist import markdown_tags, markdown_attrs
    +html = bleach.clean(markdown.markdown(text), markdown_tags, markdown_attrs)
    +

    If you are not interested in sanitizing untrusted text, but simply desire to escape raw HTML, then that can be accomplished through an extension which removes HTML parsing:

    -
    from markdown.extensions import Extension
    +
    from markdown.extensions import Extension
     
    -class EscapeHtml(Extension):
    -    def extendMarkdown(self, md, md_globals):
    -        del md.preprocessors['html_block']
    -        del md.inlinePatterns['html']
    +class EscapeHtml(Extension):
    +    def extendMarkdown(self, md, md_globals):
    +        del md.preprocessors['html_block']
    +        del md.inlinePatterns['html']
     
    -html = markdown.markdown(text, extensions=[EscapeHtml()])
    -
    +html = markdown.markdown(text, extensions=[EscapeHtml()]) +

    As the HTML would not be parsed with the above Extension, then the serializer will escape the raw HTML, which is exactly what happens now when @@ -120,12 +105,12 @@

    DeprecationWarning in 2.6 and an error in the next release. Only keyword arguments should be used. For example, if your code previously looked like this:

    -
    html = markdown.markdown(text, [SomeExtension()])
    -
    +
    html = markdown.markdown(text, [SomeExtension()])
    +

    Then it is recommended that you change it to read something like this:

    -
    html = markdown.markdown(text, extensions=[SomeExtension()])
    -
    +
    html = markdown.markdown(text, extensions=[SomeExtension()])
    +

    Note

    @@ -143,27 +128,27 @@

    “Shortened” Extension DeprecationWarning in version 2.6 and an error in the next release. Ensure that you always use the full path to your extensions. For example, if you previously did the following:

    -
    markdown.markdown(text, extensions=['extra'])
    -
    +
    markdown.markdown(text, extensions=['extra'])
    +

    You should change your code to the following:

    -
    markdown.markdown(text, extensions=['markdown.extensions.extra'])
    -
    +
    markdown.markdown(text, extensions=['markdown.extensions.extra'])
    +

    The same applies to the command line:

    -
    python -m markdown -x markdown.extensions.extra input.txt
    -
    +
    python -m markdown -x markdown.extensions.extra input.txt
    +

    Similarly, if you have used a third party extension (for example mdx_math), previously you might have called it like this:

    -
    markdown.markdown(text, extensions=['math'])
    -
    +
    markdown.markdown(text, extensions=['math'])
    +

    As the "mdx" prefix will no longer be appended, you will need to change your code as follows (assuming the file mdx_math.py is installed at the root of your PYTHONPATH):

    -
    markdown.markdown(text, extensions=['mdx_math'])
    -
    +
    markdown.markdown(text, extensions=['mdx_math'])
    +

    Extension authors will want to update their documentation to reflect the new behavior.

    @@ -192,24 +177,24 @@

    The configs Keyword is D individual configuration option should be passed to the class as a keyword/value pair. For example. one might have previously initiated an extension subclass like this:

    -
    ext = SomeExtension(configs={'somekey': 'somevalue'})
    -
    +
    ext = SomeExtension(configs={'somekey': 'somevalue'})
    +

    That code should be updated to pass in the options directly:

    -
    ext = SomeExtension(somekey='somevalue')
    -
    +
    ext = SomeExtension(somekey='somevalue')
    +

    Extension authors will want to note that this affects the makeExtension function as well. Previously it was common for the function to be defined as follows:

    -
    def makeExtension(configs=None):
    -    return SomeExtension(configs=configs)
    -
    +
    def makeExtension(configs=None):
    +    return SomeExtension(configs=configs)
    +

    Extension authors will want to update their code to the following instead:

    -
    def makeExtension(**kwargs):
    -    return SomeExtension(**kwargs)
    -
    +
    def makeExtension(**kwargs):
    +    return SomeExtension(**kwargs)
    +

    Failing to do so will result in a DeprecationWarning and will raise an error in the next release. See the Extension API documentation for more @@ -218,18 +203,18 @@

    The configs Keyword is D __init__ method and implements its own configuration handling, then the above may not apply. However, it is recommended that the subclass still calls the parent __init__ method to handle configuration options like so:

    -
    class SomeExtension(markdown.extension.Extension):
    -    def __init__(**kwargs):
    -        # Do pre-config stuff here
    -        # Set config defaults
    -        self.config = {
    -            'option1' : ['value1', 'description1'],
    -            'option2' : ['value2', 'description2']
    -        }
    -        # Set user defined configs
    -        super(MyExtension, self).__init__(**kwargs)
    -        # Do post-config stuff here
    -
    +
    class SomeExtension(markdown.extension.Extension):
    +    def __init__(**kwargs):
    +        # Do pre-config stuff here
    +        # Set config defaults
    +        self.config = {
    +            'option1' : ['value1', 'description1'],
    +            'option2' : ['value2', 'description2']
    +        }
    +        # Set user defined configs
    +        super(MyExtension, self).__init__(**kwargs)
    +        # Do post-config stuff here
    +

    Note the call to super to get the benefits of configuration handling from the parent class. See the documentation for more information.

    @@ -371,16 +356,8 @@

    Table Of Contents

    -

    Previous topic

    -

    - Release Notes for v.3.0 -

    -

    Next topic

    -

    - Release Notes for v.2.5 -

    This Page

    @@ -389,14 +366,6 @@

    This Page

  • Edit on GitHub
  • - -
    @@ -407,21 +376,17 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/change_log/release-3.0/index.html b/change_log/release-3.0/index.html deleted file mode 100755 index 3927408..0000000 --- a/change_log/release-3.0/index.html +++ /dev/null @@ -1,431 +0,0 @@ - - - - - - - - - - - - - - Release Notes for v.3.0 — Python-Markdown 3.4.4 documentation - - - - - - - - - -
    -
    -
    -

    Python-Markdown 3.0 Release Notes

    -

    We are pleased to release Python-Markdown 3.0 which adds a few new features and -fixes various bugs and deprecates various old features. See the list of changes -below for details.

    -

    Python-Markdown version 3.0 supports Python versions 2.7, 3.4, 3.5, 3.6, 3.7, -PyPy and PyPy3.

    -

    Backwards-incompatible changes

    -

    enable_attributes keyword deprecated

    -

    The enable_attributes keyword is deprecated in version 3.0 and will be -ignored. Previously the keyword was True by default and enabled an -undocumented way to define attributes on document elements. The feature has been -removed from version 3.0. As most users did not use the undocumented feature, it -should not affect most users. For the few who did use the feature, it can be -enabled by using the Legacy Attributes -extension.

    -

    smart_emphasis keyword and smart_strong extension deprecated

    -

    The smart_emphasis keyword is deprecated in version 3.0 and will be ignored. -Previously the keyword was True by default and caused the parser to ignore -middle-word emphasis. Additionally, the optional smart_strong extension -provided the same behavior for strong emphasis. Both of those features are now -part of the default behavior, and the Legacy -Emphasis extension is available to disable that -behavior.

    -

    output_formats simplified to html and xhtml.

    -

    The output_formats keyword now only accepts two options: html and xhtml -Note that if (x)html1, (x)html4 or (x)html5 are passed in, the number is -stripped and ignored.

    -

    safe_mode and html_replacement_text keywords deprecated

    -

    Both safe_mode and the associated html_replacement_text keywords are -deprecated in version 3.0 and will be ignored. The so-called “safe mode” was -never actually “safe” which has resulted in many people having a false sense of -security when using it. As an alternative, the developers of Python-Markdown -recommend that any untrusted content be passed through an HTML sanitizer (like -Bleach) after being converted to HTML by markdown. In fact, Bleach Whitelist -provides a curated list of tags, attributes, and styles suitable for filtering -user-provided HTML using bleach.

    -

    If your code previously looked like this:

    -
    html = markdown.markdown(text, safe_mode=True)
    -
    - -

    Then it is recommended that you change your code to read something like this:

    -
    import bleach
    -from bleach_whitelist import markdown_tags, markdown_attrs
    -html = bleach.clean(markdown.markdown(text), markdown_tags, markdown_attrs)
    -
    - -

    If you are not interested in sanitizing untrusted text, but simply desire to -escape raw HTML, then that can be accomplished through an extension which -removes HTML parsing:

    -
    from markdown.extensions import Extension
    -
    -class EscapeHtml(Extension):
    -    def extendMarkdown(self, md):
    -        md.preprocessors.deregister('html_block')
    -        md.inlinePatterns.deregister('html')
    -
    -html = markdown.markdown(text, extensions=[EscapeHtml()])
    -
    - -

    As the HTML would not be parsed with the above Extension, then the serializer -will escape the raw HTML, which is exactly what happened in previous versions -with safe_mode="escape".

    -

    Positional arguments deprecated

    -

    Positional arguments on the markdown.Markdown() class are deprecated as are -all except the text argument on the markdown.markdown() wrapper function. -Using positional arguments will raise an error. Only keyword arguments should be -used. For example, if your code previously looked like this:

    -
    html = markdown.markdown(text, [SomeExtension()])
    -
    - -

    Then it is recommended that you change it to read something like this:

    -
    html = markdown.markdown(text, extensions=[SomeExtension()])
    -
    - -
    -

    Note

    -

    This change is being made as a result of deprecating "safe_mode" as the -safe_mode argument was one of the positional arguments. When that argument -is removed, the two arguments following it will no longer be at the correct -position. It is recommended that you always use keywords when they are -supported for this reason.

    -
    -

    Extension name behavior has changed

    -

    In previous versions of Python-Markdown, the built-in extensions received -special status and did not require the full path to be provided. Additionally, -third party extensions whose name started with "mdx_" received the same -special treatment. This is no longer the case.

    -

    Support has been added for extensions to define an entry -point. An entry point is a string name which -can be used to point to an Extension class. The built-in extensions now have -entry points which match the old short names. And any third-party extensions -which define entry points can now get the same behavior. See the documentation -for each specific extension to find the assigned name.

    -

    If an extension does not define an entry point, then the full path to the -extension must be used. See the documentation for -a full explanation of the current behavior.

    -

    Extension configuration as part of extension name deprecated

    -

    The previously documented method of appending the extension configuration -options as a string to the extension name is deprecated and will raise an error. -The extension_configs keyword should be -used instead. See the documentation for a -full explanation of the current behavior.

    -

    HeaderId extension deprecated

    -

    The HeaderId Extension is deprecated and will raise an error if specified. Use -the Table of Contents Extension instead, which offers -most of the features of the HeaderId Extension and more (support for meta data -is missing).

    -

    Extension authors who have been using the slugify and unique functions -defined in the HeaderId Extension should note that those functions are now -defined in the Table of Contents extension and should adjust their import -statements accordingly (from markdown.extensions.toc import slugify, unique).

    -

    Homegrown OrderedDict has been replaced with a purpose-built Registry

    -

    All processors and patterns now get “registered” to a -Registry. A backwards compatible shim is -included so that existing simple extensions should continue to work. -A DeprecationWarning will be raised for any code which calls the old API.

    -

    Markdown class instance references.

    -

    Previously, instances of the Markdown class were represented as any one of -md, md_instance, or markdown. This inconsistency made it difficult when -developing extensions, or just maintaining the existing code. Now, all instances -are consistently represented as md.

    -

    The old attributes on class instances still exist, but raise a -DeprecationWarning when accessed. Also on classes where the instance was -optional, the attribute always exists now and is simply None if no instance -was provided (previously the attribute would not exist).

    -

    markdown.util.isBlockLevel deprecated

    -

    The markdown.util.isBlockLevel function is deprecated and will raise a -DeprecationWarning. Instead, extensions should use the isBlockLevel method -of the Markdown class instance. Additionally, a list of block level elements -is defined in the block_level_elements attribute of the Markdown class which -extensions can access to alter the list of elements which are treated as block -level elements.

    -

    md_globals keyword deprecated from extension API

    -

    Previously, the extendMarkdown method of a markdown.extensions.Extension -subclasses accepted an md_globals keyword, which contained the value returned -by Python’s globals() built-in function. As all of the configuration is now -held within the Markdown class instance, access to the globals is no longer -necessary and any extensions which expect the keyword will raise a -DeprecationWarning. A future release will raise an error.

    -

    markdown.version and markdown.version_info deprecated

    -

    Historically, version numbers were acquired via the attributes -markdown.version and markdown.version_info. Moving forward, a more -standardized approach is being followed and versions are acquired via the -markdown.__version__ and markdown.__version_info__ attributes. The legacy -attributes are still available to allow distinguishing versions between the -legacy Markdown 2.0 series and the Markdown 3.0 series, but in the future the -legacy attributes will be removed.

    -

    Added new, more flexible InlineProcessor class

    -

    A new InlineProcessor class handles inline processing much better and allows -for more flexibility. The new InlineProcessor classes no longer utilize -unnecessary pretext and post-text captures. New class can accept the buffer that -is being worked on and manually process the text without regular expressions and -return new replacement bounds. This helps us to handle links in a better way and -handle nested brackets and logic that is too much for regular expression.

    -

    New features

    -

    The following new features have been included in the release:

    -
      -
    • -

      A new testing framework is included as a part of the - Markdown library, which can also be used by third party extensions.

      -
    • -
    • -

      A new toc_depth parameter has been added to the - Table of Contents Extension.

      -
    • -
    • -

      A new toc_tokens attribute has been added to the Markdown class by the - Table of Contents Extension, which contains the raw - tokens used to build the Table of Contents. Users can use this to build their - own custom Table of Contents rather than needing to parse the HTML available - on the toc attribute of the Markdown class.

      -
    • -
    • -

      When the Table of Contents Extension is used in - conjunction with the Attribute Lists Extension - and a data-toc-label attribute is defined on a header, the content of the - data-toc-label attribute is now used as the content of the Table of Contents - item for that header.

      -
    • -
    • -

      Additional CSS class names can be appended to - Admonitions.

      -
    • -
    - -
    -
    -
    - - -
    -
    - - - - - - - - \ No newline at end of file diff --git a/change_log/release-3.1/index.html b/change_log/release-3.1/index.html deleted file mode 100755 index 0c8556d..0000000 --- a/change_log/release-3.1/index.html +++ /dev/null @@ -1,243 +0,0 @@ - - - - - - - - - - - - - - Release Notes for v.3.1 — Python-Markdown 3.4.4 documentation - - - - - - - - - -
    -
    -
    -

    Python-Markdown 3.1 Release Notes

    -

    Python-Markdown version 3.1 supports Python versions 2.7, 3.5, 3.6, 3.7, -PyPy and PyPy3.

    -

    Backwards-incompatible changes

    -

    markdown.version and markdown.version_info deprecated

    -

    Historically, version numbers were acquired via the attributes -markdown.version and markdown.version_info. As of 3.0, a more standardized -approach is being followed and versions are acquired via the -markdown.__version__ and markdown.__version_info__ attributes. As of 3.1 -the legacy attributes will raise a DeprecationWarning if they are accessed. In -a future release the legacy attributes will be removed.

    -

    New features

    -

    The following new features have been included in the release:

    -
      -
    • -

      A Contributing Guide has been added (#732).

      -
    • -
    • -

      A new configuration option to set the footnote separator has been added. Also, - the rel and rev attributes have been removed from footnotes as they are - not valid in HTML5. The refs and backrefs classes already exist and - serve the same purpose (#723).

      -
    • -
    • -

      A new option for toc_depth to set not only the bottom section level, - but also the top section level. A string consisting of two digits - separated by a hyphen in between ("2-5"), defines the top (t) and the - bottom (b) (<ht>..<hb>). A single integer still defines the bottom - section level (<h1>..<hb>) only. (#787).

      -
    • -
    -

    Bug fixes

    -

    The following bug fixes are included in the 3.1 release:

    -
      -
    • Update CLI to support PyYAML 5.1.
    • -
    • Overlapping raw HTML matches no longer leave placeholders behind (#458).
    • -
    • Emphasis patterns now recognize newline characters as whitespace (#783).
    • -
    • Version format had been updated to be PEP 440 compliant (#736).
    • -
    • Block level elements are defined per instance, not as class attributes - (#731).
    • -
    • Double escaping of block code has been eliminated (#725).
    • -
    • Problems with newlines in references has been fixed (#742).
    • -
    • Escaped # are now handled in header syntax (#762).
    • -
    - -
    -
    -
    - - -
    -
    - - - - - - - - \ No newline at end of file diff --git a/change_log/release-3.2/index.html b/change_log/release-3.2/index.html deleted file mode 100755 index 8f6865b..0000000 --- a/change_log/release-3.2/index.html +++ /dev/null @@ -1,298 +0,0 @@ - - - - - - - - - - - - - - Release Notes for v.3.2 — Python-Markdown 3.4.4 documentation - - - - - - - - - -
    -
    -
    -

    Python-Markdown 3.2 Release Notes

    -

    Python-Markdown version 3.2 supports Python versions 3.5, 3.6, 3.7, 3.8, and -PyPy3.

    -

    Backwards-incompatible changes

    -

    Drop support for Python 2.7

    -

    Python 2.7 reaches end-of-life on 2020-01-01 and Python-Markdown 3.2 has dropped -support for it. Please upgrade to Python 3, or use Python-Markdown 3.1.

    -

    em and strong inline processor changes

    -

    In order to fix issue #792, em/strong inline processors were refactored. This -translated into removing many of the existing inline processors that handled this -logic:

    -
      -
    • em_strong
    • -
    • strong
    • -
    • emphasis
    • -
    • strong2
    • -
    • emphasis
    • -
    -

    These processors were replaced with two new ones:

    -
      -
    • em_strong
    • -
    • em_strong2
    • -
    -

    The legacy_em extension was also modified with new, -refactored logic and simply overrides the em_strong2 inline processor.

    -

    CodeHilite now always wraps with <code> tags

    -

    Before, the HTML generated by CodeHilite looked like: -- <pre><code>foo = 'bar'</code></pre> if you were not using Pygments. -- <pre>foo = 'bar'</pre> if you were using Pygments.

    -

    To make the cases more consistent (and adhere to many Markdown specifications and -HTML code block markup suggestions), CodeHilite will now always additionally wrap -code with <code> tags. See #862 for more details.

    -

    This change does not alter the Python-Markdown API, but users relying on the old -markup will find their output now changed.

    -

    Internally, this change relies on the Pygments 2.4, so you must be using at least -that version to see this effect. Users with earlier Pygments versions will -continue to see the old behavior.

    -

    markdown.util.etree deprecated

    -

    Previously, Python-Markdown was using either the xml.etree.cElementTree module -or the xml.etree.ElementTree module, based on their availability. In modern -Python versions, the former is a deprecated alias for the latter. Thus, the -compatibility layer is deprecated and extensions are advised to use -xml.etree.ElementTree directly. Importing markdown.util.etree will raise -a DeprecationWarning beginning in version 3.2 and may be removed in a future -release.

    -

    Therefore, extension developers are encouraged to replace -from markdown.util import etree with -import xml.etree.ElementTree as etree in their code.

    -

    New features

    -

    The following new features have been included in the release:

    -
      -
    • -

      Some new configuration options have been added to the toc - extension:

      -
        -
      • -

        The anchorlink_class and permalink_class options allow class(es) to be - assigned to the anchorlink and permalink respectively. This allows using - icon fonts from CSS for the links. Therefore, an empty string passed to - permalink now generates an empty permalink. Previously no permalink - would have been generated. (#776)

        -
      • -
      • -

        The permalink_title option allows the title attribute of a permalink to be - set to something other than the default English string Permanent link. (#877)

        -
      • -
      -
    • -
    • -

      Document thread safety (#812).

      -
    • -
    • -

      Markdown parsing in HTML has been exposed via a separate extension called - md_in_html.

      -
    • -
    • -

      Add support for Python 3.8.

      -
    • -
    -

    Bug fixes

    -

    The following bug fixes are included in the 3.2 release:

    -
      -
    • HTML tag placeholders are no longer included in .toc_tokens (#899).
    • -
    • Unescape backslash-escaped characters in TOC ids (#864).
    • -
    • Refactor bold and italic logic in order to solve complex nesting issues (#792).
    • -
    • Always wrap CodeHilite code in code tags (#862).
    • -
    - -
    -
    -
    - - -
    -
    - - - - - - - - \ No newline at end of file diff --git a/change_log/release-3.3/index.html b/change_log/release-3.3/index.html deleted file mode 100755 index a0d6336..0000000 --- a/change_log/release-3.3/index.html +++ /dev/null @@ -1,301 +0,0 @@ - - - - - - - - - - - - - - Release Notes for v.3.3 — Python-Markdown 3.4.4 documentation - - - - - - - - - -
    -
    -
    -

    Python-Markdown 3.3 Release Notes

    -

    Python-Markdown version 3.3 supports Python versions 3.6, 3.7, 3.8, 3.9 and PyPy3.

    -

    Backwards-incompatible changes

    -

    The prefix language- is now prepended to all language classes by default on code blocks.

    -

    The HTML5 spec recommends that the class defining the language of a code block be prefixed with language-. -Therefore, by default, both the fenced_code and codehilite extensions now prepend the prefix when code -highlighting is disabled.

    -

    If you have previously been including the prefix manually in your fenced code blocks, then you will not want a second -instance of the prefix. Similarly, if you are using a third party syntax highlighting tool which does not recognize -the prefix, or requires a different prefix, then you will want to redefine the prefix globally using the lang_prefix -configuration option of either the fenced_code or codehilite extensions.

    -

    For example, to configure fenced_code to not apply any prefix (the previous behavior), set the option to an empty string:

    -
    from markdown.extensions.fenced_code import FencedCodeExtension
    -
    -markdown.markdown(src, extensions=[FencedCodeExtension(lang_prefix='')])
    -
    - -
    -

    Note

    -

    When code highlighting is enabled, the output from Pygments is used unaltered. Currently, Pygments does not -provide an option to include the language class in the output, let alone prefix it. Therefore, any language prefix -is only applied when syntax highlighting is disabled.

    -
    -

    Attribute Lists are more strict (#898).

    -

    Empty curly braces are now completely ignored by the Attribute List extension. Previously, the extension would -recognize them as attribute lists and remove them from the document. Therefore, it is no longer necessary to backslash -escape a set of curly braces which are empty or only contain whitespace.

    -

    Despite not being documented, previously an attribute list could be defined anywhere within a table cell and get -applied to the cell (<td> element). Now the attribute list must be defined at the end of the cell content and must -be separated from the rest of the content by at least one space. This makes it easy to differentiate between attribute -lists defined on inline elements within a cell and the attribute list for the cell itself. It is also more consistent -with how attribute lists are defined on other types of elements.

    -

    The extension has also added support for defining attribute lists on table header cells (<th> elements) in the same -manner as data cells (<td> elements).

    -

    In addition, the documentation for the extensions received an overhaul. The features (#987) and limitations (#965) of the extension are now fully documented.

    -

    New features

    -

    The following new features have been included in the 3.3 release:

    -
      -
    • -

      All Pygments’ options are now available for syntax highlighting (#816).

      -
        -
      • The Codehilite extension now accepts any options - which Pygments supports as global configuration settings on the extension.
      • -
      • Fenced Code Blocks will accept any of the - same options on individual code blocks.
      • -
      • Any of the previously supported aliases to Pygments’ options continue to be - supported at this time. However, it is recommended that the Pygments option names - be used directly to ensure continued compatibility in the future.
      • -
      -
    • -
    • -

      Fenced Code Blocks now work with - Attribute Lists when syntax highlighting is disabled. - Any random HTML attribute can be defined and set on the <code> tag of fenced code - 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, which - alleviates various bugs and simplify maintenance of the code (#803, #830).

      -
    • -
    • -

      The Markdown in HTML extension has been rebuilt on the - new HTML Parser, which drastically simplifies it. Note that raw HTML elements with a - markdown attribute defined are now converted to ElementTree Elements and are rendered - by the serializer. Various bugs have been fixed (#803, #595, #780, and #1012).

      -
    • -
    • -

      Link reference parsing, abbreviation reference parsing and footnote reference parsing - has all been moved from preprocessors to blockprocessors, which allows them to be - nested within other block level elements. Specifically, this change was necessary to - maintain the current behavior in the rebuilt Markdown in HTML extension. A few random - edge-case bugs (see the included tests) were resolved in the process (#803).

      -
    • -
    • -

      An alternate function markdown.extensions.headerid.slugify_unicode has been included - with the Table of Contents extension which supports Unicode - characters in table of contents slugs. The old markdown.extensions.headerid.slugify - method which removes non-ASCII characters remains the default. Import and pass - markdown.extensions.headerid.slugify_unicode to the slugify configuration option - to use the new behavior.

      -
    • -
    • -

      Support was added for Python 3.9 and dropped for Python 3.5.

      -
    • -
    -

    Bug fixes

    -

    The following bug fixes are included in the 3.3 release:

    -
      -
    • Document how to pass configuration options to Extra (#1019).
    • -
    • Fix HR which follows strong em (#897).
    • -
    • Support short reference image links (#894).
    • -
    • Avoid a RecursionError from deeply nested blockquotes (#799).
    • -
    • Fix issues with complex emphasis (#979).
    • -
    • Fix unescaping of HTML characters <> in CodeHilite (#990).
    • -
    • Fix complex scenarios involving lists and admonitions (#1004).
    • -
    • Fix complex scenarios with nested ordered and unordered lists in a definition list (#918).
    • -
    - -
    -
    -
    - - -
    -
    - - - - - - - - \ No newline at end of file diff --git a/change_log/release-3.4/index.html b/change_log/release-3.4/index.html deleted file mode 100755 index 853b84e..0000000 --- a/change_log/release-3.4/index.html +++ /dev/null @@ -1,349 +0,0 @@ - - - - - - - - - - - - - - Release Notes for v.3.4 — Python-Markdown 3.4.4 documentation - - - - - - - - - -
    -
    -
    -

    Python-Markdown 3.4 Release Notes

    -

    Python-Markdown version 3.4 supports Python versions 3.7, 3.8, 3.9, 3.10 and -PyPy3.

    -

    Backwards-incompatible changes

    -

    The tables extension now uses a style attribute instead of an align attribute for alignment.

    -

    The HTML4 spec specifically deprecates the use of the align attribute -and it does not appear at all in the HTML5 spec. Therefore, by default, -the tables extension will now use the style attribute (setting just the -text-align property) in td and th blocks.

    -

    The former behavior is available by setting the use_align_attribute -configuration option to True when enabling the extension.

    -

    For example, to configure the old align behavior:

    -
    from markdown.extensions.tables import TableExtension
    -
    -markdown.markdown(src, extensions=[TableExtension(use_align_attribute=True)])
    -
    - -

    Backslash unescaping moved to Treeprocessor (#1131).

    -

    Unescaping backslash escapes has been moved to a Treeprocessor, which enables -proper HTML escaping during serialization. However, it is recognized that -various third-party extensions may be calling the old class at -postprocessors.UnescapePostprocessor. Therefore, the old class remains in the -code base, but has been deprecated and will be removed in a future release. The -new class treeprocessors.UnescapeTreeprocessor should be used instead.

    -

    Previously deprecated objects have been removed

    -

    Various objects were deprecated in version 3.0 and began raising deprecation -warnings (see the version 3.0 release notes for details). Any of those objects -which remained in version 3.3 have been removed from the code base in version 3.4 -and will now raise errors. The relevant objects are listed below.

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Deprecated ObjectReplacement Object
    markdown.versionmarkdown.__version__
    markdown.version_infomarkdown.__version_info__
    markdown.util.etreexml.etree.ElementTree
    markdown.util.string_typestr
    markdown.util.text_typestr
    markdown.util.int2strchr
    markdown.util.iterrangerange
    markdown.util.isBlockLevelmarkdown.Markdown().is_block_level
    markdown.util.Processor().markdownmarkdown.util.Processor().md
    markdown.util.Registry().__setitem__markdown.util.Registry().register
    markdown.util.Registry().__delitem__markdown.util.Registry().deregister
    markdown.util.Registry().addmarkdown.util.Registry().register
    -

    In addition, the md_globals parameter of -Markdown.extensions.Extension.extendMarkdown() is no longer recognized as a -valid parameter and will raise an error if provided.

    -

    New features

    -

    The following new features have been included in the 3.4 release:

    -
      -
    • -

      Some new configuration options have been added to the - footnotes extension (#1218):

      -
        -
      • -

        Small refactor of the BACKLINK_TITLE option; The use of format() - instead of “old” %d formatter allows one to specify text without the - need to have the number of the footnote in it (like footnotes on - Wikipedia for example). The modification is backward compatible so no - configuration change is required.

        -
      • -
      • -

        Addition of a new option SUPERSCRIPT_TEXT that allows one to specify a - custom placeholder for the footnote itself in the text. - Ex: [{}] will give <sup>[1]</sup>, ({}) will give <sup>(1)</sup>, - or by default, the current behavior: <sup>1</sup>.

        -
      • -
      -
    • -
    • -

      The Table of Contents extension now accepts a - toc_class parameter which can be used to set the CSS class(es) on the - <div> that contains the Table of Contents (#1224).

      -
    • -
    • -

      The CodeHilite extension now supports a pygments_formatter option that can - be set to a custom formatter class (#1187).

      -
        -
      • If pygments_formatter is set to a string (ex: 'html'), Pygments’ - default formatter by that name is used.
      • -
      • If pygments_formatter is set to a formatter class (or any callable - which returns a formatter instance), then an instance of that class is - used.
      • -
      -

      The formatter class is now passed an additional option, lang_str, to -denote the language of the code block (#1258). While Pygments’ built-in -formatters will ignore the option, a custom formatter assigned to the -pygments_formatter option can make use of the lang_str to include the -code block’s language in the output.

      -
    • -
    -

    Bug fixes

    -

    The following bug fixes are included in the 3.4 release:

    -
      -
    • Extension entry-points are only loaded if needed (#1216).
    • -
    • Added additional checks to the <pre><code> handling of - PrettifyTreeprocessor (#1261, #1263).
    • -
    • Fix XML deprecation warnings.
    • -
    - -
    -
    -
    - - -
    -
    - - - - - - - - \ No newline at end of file diff --git a/changelog/index.html b/changelog/index.html new file mode 100644 index 0000000..2705d01 --- /dev/null +++ b/changelog/index.html @@ -0,0 +1,939 @@ + + + + + + + + + + + + + + Changelog — Python-Markdown 3.5 documentation + + + + + + + + + + + + +
    +
    +
    +

    Python-Markdown Changelog

    +

    All notable changes to this project will be documented in this file.

    +

    The format is based on Keep a Changelog, +and this project adheres to Semantic Versioning. See the Contributing Guide for details.

    +

    [3.5] – 2023-10-06

    +

    Added

    + +

    A new boolean option permalink_leading controls the position of the permanent +link anchors generated with permalink. Setting permalink_leading to True +will cause the links to be inserted at the start of the header, before any other +header content. The default behavior for permalink is to append permanent +links to the header, placing them after all other header content.

    +

    Changed

    +
      +
    • Add support for cPython version 3.12 (and PyPy 3.10) and drop support for + Python version 3.7 (#1357).
    • +
    • Refactor changelog to use the format defined at https://keepachangelog.com/.
    • +
    • Update the list of empty HTML tags (#1353).
    • +
    • Add customizable TOC title class to TOC extension (#1293).
    • +
    • Add API documentation of the code base which is generated by + mkdocstrings (#1220).
    • +
    +

    Fixed

    +
      +
    • Fix a corner case in admonitions where if an indented code block was provided + as the first block, the output would be malformed (#1329).
    • +
    +

    [3.4.4] – 2023-07-25

    +

    Fixed

    +
      +
    • Add a special case for initial 's to smarty extension (#1305).
    • +
    • Unescape any backslash escaped inline raw HTML (#1358).
    • +
    • Unescape backslash escaped TOC token names (#1360).
    • +
    +

    [3.4.3] – 2023-03-23

    +

    Fixed

    +
      +
    • Restore console script (#1327).
    • +
    +

    [3.4.2] – 2023-03-22

    +

    Added

    +
      +
    • Officially support Python 3.11.
    • +
    +

    Fixed

    +
      +
    • Improve standalone * and _ parsing (#1300).
    • +
    • Consider <html> HTML tag a block-level element (#1309).
    • +
    +

    Infrastructure

    +
      +
    • Switch from setup.py to pyproject.toml.
    • +
    +

    [3.4.1] – 2022-07-15

    +
      +
    • Fix an import issue with importlib.util (#1274).
    • +
    +

    [3.4] – 2022-07-15

    +

    Changed

    +

    The tables extension now uses a style attribute instead of an align attribute for alignment.

    +

    The HTML4 spec +specifically deprecates the use of the align attribute and it does not appear +at all in the HTML5 +spec. +Therefore, by default, the tables extension will now use +the style attribute (setting just the text-align property) in td and th +blocks.

    +

    The former behavior is available by setting the use_align_attribute +configuration option to True when enabling the extension.

    +

    For example, to configure the old align behavior:

    +
    from markdown.extensions.tables import TableExtension
    +
    +markdown.markdown(src, extensions=[TableExtension(use_align_attribute=True)])
    +
    + +

    Backslash unescaping moved to Treeprocessor (#1131).

    +

    Unescaping backslash escapes has been moved to a Treeprocessor, which enables +proper HTML escaping during serialization. However, it is recognized that +various third-party extensions may be calling the old class at +postprocessors.UnescapePostprocessor. Therefore, the old class remains in the +code base, but has been deprecated and will be removed in a future release. The +new class treeprocessors.UnescapeTreeprocessor should be used instead.

    +

    Previously deprecated objects have been removed

    +

    Various objects were deprecated in version 3.0 and began raising deprecation +warnings (see the version 3.0 release notes for details). Any of those objects +which remained in version 3.3 have been removed from the code base in version 3.4 +and will now raise errors. The relevant objects are listed below.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Deprecated ObjectReplacement Object
    markdown.versionmarkdown.__version__
    markdown.version_infomarkdown.__version_info__
    markdown.util.etreexml.etree.ElementTree
    markdown.util.string_typestr
    markdown.util.text_typestr
    markdown.util.int2strchr
    markdown.util.iterrangerange
    markdown.util.isBlockLevelmarkdown.Markdown().is_block_level
    markdown.util.Processor().markdownmarkdown.util.Processor().md
    markdown.util.Registry().__setitem__markdown.util.Registry().register
    markdown.util.Registry().__delitem__markdown.util.Registry().deregister
    markdown.util.Registry().addmarkdown.util.Registry().register
    +

    In addition, the md_globals parameter of +Markdown.extensions.Extension.extendMarkdown() is no longer recognized as a +valid parameter and will raise an error if provided.

    +

    Added

    +
      +
    • +

      Some new configuration options have been added to the + footnotes extension (#1218):

      +
        +
      • +

        Small refactor of the BACKLINK_TITLE option; The use of format() + instead of “old” %d formatter allows one to specify text without the + need to have the number of the footnote in it (like footnotes on + Wikipedia for example). The modification is backward compatible so no + configuration change is required.

        +
      • +
      • +

        Addition of a new option SUPERSCRIPT_TEXT that allows one to specify a + custom placeholder for the footnote itself in the text. + Ex: [{}] will give <sup>[1]</sup>, ({}) will give <sup>(1)</sup>, + or by default, the current behavior: <sup>1</sup>.

        +
      • +
      +
    • +
    • +

      The Table of Contents extension now accepts a + toc_class parameter which can be used to set the CSS class(es) on the + <div> that contains the Table of Contents (#1224).

      +
    • +
    • +

      The CodeHilite extension now supports a pygments_formatter option that can + be set to a custom formatter class (#1187).

      +
        +
      • If pygments_formatter is set to a string (ex: 'html'), Pygments’ + default formatter by that name is used.
      • +
      • If pygments_formatter is set to a formatter class (or any callable + which returns a formatter instance), then an instance of that class is + used.
      • +
      +

      The formatter class is now passed an additional option, lang_str, to +denote the language of the code block (#1258). While Pygments’ built-in +formatters will ignore the option, a custom formatter assigned to the +pygments_formatter option can make use of the lang_str to include the +code block’s language in the output.

      +
    • +
    +

    Fixed

    +
      +
    • Extension entry-points are only loaded if needed (#1216).
    • +
    • Added additional checks to the <pre><code> handling of + PrettifyTreeprocessor (#1261, #1263).
    • +
    • Fix XML deprecation warnings.
    • +
    +

    [3.3.7] – 2022-05-05

    +

    Fixed

    +
      +
    • Disallow square brackets in reference link ids (#1209).
    • +
    • Retain configured pygments_style after first code block (#1240).
    • +
    • Ensure fenced code attributes are properly escaped (#1247).
    • +
    +

    [3.3.6] – 2021-11-17

    +

    Fixed

    + +

    [3.3.5] – 2021-11-16

    +

    Added

    +
      +
    • Support Python 3.10 (#1124).
    • +
    +

    Fixed

    +
      +
    • Make the slugify_unicode function not remove diacritical marks (#1118).
    • +
    • Fix [toc] detection when used with nl2br extension (#1160).
    • +
    • Re-use compiled regex for block level checks (#1169).
    • +
    • Don’t process shebangs in fenced code blocks when using CodeHilite (#1156).
    • +
    • Improve email address validation for Automatic Links (#1165).
    • +
    • Ensure <summary> tags are parsed correctly (#1079).
    • +
    +

    [3.3.4] – 2021-02-24

    +

    Fixed

    +
      +
    • Properly parse unclosed tags in code spans (#1066).
    • +
    • Properly parse processing instructions in md_in_html (#1070).
    • +
    • Properly parse code spans in md_in_html (#1069).
    • +
    • Preserve text immediately before an admonition (#1092).
    • +
    • Simplified regex for HTML placeholders (#928) addressing (#932).
    • +
    • Ensure permalinks and anchorlinks are not restricted by toc_depth (#1107).
    • +
    • Fix corner cases with lists under admonitions (#1102).
    • +
    +

    [3.3.3] – 2020-10-25

    +

    Fixed

    +
      +
    • Unify all block-level tags (#1047).
    • +
    • Fix issue where some empty elements would have text rendered as None when using md_in_html (#1049).
    • +
    • Avoid catastrophic backtracking in hr regex (#1055).
    • +
    • Fix hr HTML handling (#1053).
    • +
    +

    [3.3.2] – 2020-10-19

    +

    Fixed

    +
      +
    • Properly parse inline HTML in md_in_html (#1040 & #1045).
    • +
    • Avoid crashing when md_in_html fails (#1040).
    • +
    +

    [3.3.1] – 2020-10-12

    +

    Fixed

    +
      +
    • Correctly parse raw script and style tags (#1036).
    • +
    • Ensure consistent class handling by fenced_code and codehilite (#1032).
    • +
    +

    [3.3] – 2020-10-06

    +

    Changed

    +

    The prefix language- is now prepended to all language classes by default on code blocks.

    +

    The HTML5 +spec +recommends that the class defining the language of a code block be prefixed with +language-. Therefore, by default, both the +fenced_code and +codehilite extensions now prepend the prefix when +code highlighting is disabled.

    +

    If you have previously been including the prefix manually in your fenced code blocks, then you will not want a second +instance of the prefix. Similarly, if you are using a third party syntax highlighting tool which does not recognize +the prefix, or requires a different prefix, then you will want to redefine the prefix globally using the lang_prefix +configuration option of either the fenced_code or codehilite extensions.

    +

    For example, to configure fenced_code to not apply any prefix (the previous behavior), set the option to an empty string:

    +
    from markdown.extensions.fenced_code import FencedCodeExtension
    +
    +markdown.markdown(src, extensions=[FencedCodeExtension(lang_prefix='')])
    +
    + +
    +

    Note

    +

    When code highlighting is +enabled, +the output from Pygments is used unaltered. Currently, Pygments does not +provide an option to include the language class in the output, let alone +prefix it. Therefore, any language prefix is only applied when syntax +highlighting is disabled.

    +
    +

    Attribute Lists are more strict (#898).

    +

    Empty curly braces are now completely ignored by the Attribute List extension. Previously, the extension would +recognize them as attribute lists and remove them from the document. Therefore, it is no longer necessary to backslash +escape a set of curly braces which are empty or only contain whitespace.

    +

    Despite not being documented, previously an attribute list could be defined anywhere within a table cell and get +applied to the cell (<td> element). Now the attribute list must be defined at the end of the cell content and must +be separated from the rest of the content by at least one space. This makes it easy to differentiate between attribute +lists defined on inline elements within a cell and the attribute list for the cell itself. It is also more consistent +with how attribute lists are defined on other types of elements.

    +

    The extension has also added support for defining attribute lists on table header cells (<th> elements) in the same +manner as data cells (<td> elements).

    +

    In addition, the documentation for the extensions received an overhaul. The features (#987) and limitations (#965) of the extension are now fully documented.

    +

    Added

    +
      +
    • +

      All Pygments’ options are now available for syntax highlighting (#816).

      +
        +
      • The Codehilite extension now accepts any options + which Pygments supports as global configuration settings on the extension.
      • +
      • Fenced Code Blocks will accept any of the + same options on individual code blocks.
      • +
      • Any of the previously supported aliases to Pygments’ options continue to be + supported at this time. However, it is recommended that the Pygments option names + be used directly to ensure continued compatibility in the future.
      • +
      +
    • +
    • +

      Fenced Code Blocks now work with + Attribute Lists when syntax highlighting is disabled. + Any random HTML attribute can be defined and set on the <code> tag of fenced code + 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, which + alleviates various bugs and simplify maintenance of the code (#803, #830).

      +
    • +
    • +

      The Markdown in HTML extension has been rebuilt on the + new HTML Parser, which drastically simplifies it. Note that raw HTML elements with a + markdown attribute defined are now converted to ElementTree Elements and are rendered + by the serializer. Various bugs have been fixed (#803, #595, #780, and #1012).

      +
    • +
    • +

      Link reference parsing, abbreviation reference parsing and footnote reference parsing + has all been moved from preprocessors to blockprocessors, which allows them to be + nested within other block level elements. Specifically, this change was necessary to + maintain the current behavior in the rebuilt Markdown in HTML extension. A few random + edge-case bugs (see the included tests) were resolved in the process (#803).

      +
    • +
    • +

      An alternate function markdown.extensions.headerid.slugify_unicode has been included + with the Table of Contents extension which supports Unicode + characters in table of contents slugs. The old markdown.extensions.headerid.slugify + method which removes non-ASCII characters remains the default. Import and pass + markdown.extensions.headerid.slugify_unicode to the slugify configuration option + to use the new behavior.

      +
    • +
    • +

      Support was added for Python 3.9 and dropped for Python 3.5.

      +
    • +
    +

    Fixed

    +
      +
    • Document how to pass configuration options to Extra (#1019).
    • +
    • Fix HR which follows strong em (#897).
    • +
    • Support short reference image links (#894).
    • +
    • Avoid a RecursionError from deeply nested blockquotes (#799).
    • +
    • Fix issues with complex emphasis (#979).
    • +
    • Fix unescaping of HTML characters <> in CodeHilite (#990).
    • +
    • Fix complex scenarios involving lists and admonitions (#1004).
    • +
    • Fix complex scenarios with nested ordered and unordered lists in a definition list (#918).
    • +
    +

    [3.2.2] – 2020-05-08

    +

    Fixed

    +
      +
    • Add checklinks tox environment to ensure all links in documentation are good.
    • +
    • Refactor extension API documentation (#729).
    • +
    • Load entry_points (for extensions) only once using importlib.metadata.
    • +
    • Do not double escape entities in TOC.
    • +
    • Correctly report if an extension raises a TypeError (#939).
    • +
    • Raise a KeyError when attempting to delete a nonexistent key from the + extension registry (#939).
    • +
    • Remove import of packaging (or pkg_resources fallback) entirely.
    • +
    • Remove setuptools as a run-time dependency (install_required).
    • +
    +

    [3.2.1] – 2020-02-12

    +

    Fixed

    +
      +
    • The name property in toc_tokens from the TOC extension now + escapes HTML special characters (<, >, and &).
    • +
    +

    [3.2] – 2020-02-07

    +

    Changed

    +

    Drop support for Python 2.7

    +

    Python 2.7 reaches end-of-life on 2020-01-01 and Python-Markdown 3.2 has dropped +support for it. Please upgrade to Python 3, or use Python-Markdown 3.1.

    +

    em and strong inline processor changes

    +

    In order to fix issue #792, em/strong inline processors were refactored. This +translated into removing many of the existing inline processors that handled this +logic:

    +
      +
    • em_strong
    • +
    • strong
    • +
    • emphasis
    • +
    • strong2
    • +
    • emphasis
    • +
    +

    These processors were replaced with two new ones:

    +
      +
    • em_strong
    • +
    • em_strong2
    • +
    +

    The legacy_em extension was also modified with new, +refactored logic and simply overrides the em_strong2 inline processor.

    +

    CodeHilite now always wraps with <code> tags

    +

    Before, the HTML generated by CodeHilite looked like: +- <pre><code>foo = 'bar'</code></pre> if you were not using Pygments. +- <pre>foo = 'bar'</pre> if you were using Pygments.

    +

    To make the cases more consistent (and adhere to many Markdown specifications and +HTML code block markup suggestions), CodeHilite will now always additionally wrap +code with <code> tags. See #862 for more details.

    +

    This change does not alter the Python-Markdown API, but users relying on the old +markup will find their output now changed.

    +

    Internally, this change relies on the Pygments 2.4, so you must be using at least +that version to see this effect. Users with earlier Pygments versions will +continue to see the old behavior.

    +

    markdown.util.etree deprecated

    +

    Previously, Python-Markdown was using either the xml.etree.cElementTree module +or the xml.etree.ElementTree module, based on their availability. In modern +Python versions, the former is a deprecated alias for the latter. Thus, the +compatibility layer is deprecated and extensions are advised to use +xml.etree.ElementTree directly. Importing markdown.util.etree will raise +a DeprecationWarning beginning in version 3.2 and may be removed in a future +release.

    +

    Therefore, extension developers are encouraged to replace +from markdown.util import etree with +import xml.etree.ElementTree as etree in their code.

    +

    Added

    +
      +
    • +

      Some new configuration options have been added to the toc + extension:

      +
        +
      • +

        The anchorlink_class and permalink_class options allow class(es) to be + assigned to the anchorlink and permalink respectively. This allows using + icon fonts from CSS for the links. Therefore, an empty string passed to + permalink now generates an empty permalink. Previously no permalink + would have been generated. (#776)

        +
      • +
      • +

        The permalink_title option allows the title attribute of a permalink to be + set to something other than the default English string Permanent link. (#877)

        +
      • +
      +
    • +
    • +

      Document thread safety (#812).

      +
    • +
    • +

      Markdown parsing in HTML has been exposed via a separate extension called + md_in_html.

      +
    • +
    • +

      Add support for Python 3.8.

      +
    • +
    +

    Fixed

    +
      +
    • HTML tag placeholders are no longer included in .toc_tokens (#899).
    • +
    • Unescape backslash-escaped characters in TOC ids (#864).
    • +
    • Refactor bold and italic logic in order to solve complex nesting issues (#792).
    • +
    • Always wrap CodeHilite code in code tags (#862).
    • +
    +

    [3.1.1] – 2019-05-20

    +

    Fixed

    +
      +
    • Fixed import failure in setup.py when the source directory is not + on sys.path (#823).
    • +
    • Prefer public packaging module to pkg_resources’ private copy of + it (#825).
    • +
    +

    [3.1] – 2019-03-25

    +

    Changed

    +

    markdown.version and markdown.version_info deprecated

    +

    Historically, version numbers were acquired via the attributes +markdown.version and markdown.version_info. As of 3.0, a more standardized +approach is being followed and versions are acquired via the +markdown.__version__ and markdown.__version_info__ attributes. As of 3.1 +the legacy attributes will raise a DeprecationWarning if they are accessed. In +a future release the legacy attributes will be removed.

    +

    Added

    +
      +
    • +

      A Contributing Guide has been added (#732).

      +
    • +
    • +

      A new configuration option to set the footnote separator has been added. Also, + the rel and rev attributes have been removed from footnotes as they are + not valid in HTML5. The refs and backrefs classes already exist and + serve the same purpose (#723).

      +
    • +
    • +

      A new option for toc_depth to set not only the bottom section level, + but also the top section level. A string consisting of two digits + separated by a hyphen in between ("2-5"), defines the top (t) and the + bottom (b) (<ht>..<hb>). A single integer still defines the bottom + section level (<h1>..<hb>) only. (#787).

      +
    • +
    +

    Fixed

    +
      +
    • Update CLI to support PyYAML 5.1.
    • +
    • Overlapping raw HTML matches no longer leave placeholders behind (#458).
    • +
    • Emphasis patterns now recognize newline characters as whitespace (#783).
    • +
    • Version format had been updated to be PEP 440 compliant (#736).
    • +
    • Block level elements are defined per instance, not as class attributes + (#731).
    • +
    • Double escaping of block code has been eliminated (#725).
    • +
    • Problems with newlines in references has been fixed (#742).
    • +
    • Escaped # are now handled in header syntax (#762).
    • +
    +

    [3.0.1] – 2018-09-28

    +

    Fixed

    +
      +
    • Brought back the version and version_info variables (#709).
    • +
    • Added support for hexadecimal HTML entities (#712).
    • +
    +

    [3.0] – 2018-09-21

    +

    Changed

    +

    enable_attributes keyword deprecated

    +

    The enable_attributes keyword is deprecated in version 3.0 and will be +ignored. Previously the keyword was True by default and enabled an +undocumented way to define attributes on document elements. The feature has been +removed from version 3.0. As most users did not use the undocumented feature, it +should not affect most users. For the few who did use the feature, it can be +enabled by using the Legacy Attributes +extension.

    +

    smart_emphasis keyword and smart_strong extension deprecated

    +

    The smart_emphasis keyword is deprecated in version 3.0 and will be ignored. +Previously the keyword was True by default and caused the parser to ignore +middle-word emphasis. Additionally, the optional smart_strong extension +provided the same behavior for strong emphasis. Both of those features are now +part of the default behavior, and the Legacy +Emphasis extension is available to disable that +behavior.

    +

    output_formats simplified to html and xhtml.

    +

    The output_formats keyword now only accepts two options: html and xhtml +Note that if (x)html1, (x)html4 or (x)html5 are passed in, the number is +stripped and ignored.

    +

    safe_mode and html_replacement_text keywords deprecated

    +

    Both safe_mode and the associated html_replacement_text keywords are +deprecated in version 3.0 and will be ignored. The so-called “safe mode” was +never actually “safe” which has resulted in many people having a false sense of +security when using it. As an alternative, the developers of Python-Markdown +recommend that any untrusted content be passed through an HTML sanitizer (like +Bleach) after being converted to HTML by +markdown. In fact, Bleach +Whitelist provides a curated list +of tags, attributes, and styles suitable for filtering user-provided HTML using +bleach.

    +

    If your code previously looked like this:

    +
    html = markdown.markdown(text, safe_mode=True)
    +
    + +

    Then it is recommended that you change your code to read something like this:

    +
    import bleach
    +from bleach_whitelist import markdown_tags, markdown_attrs
    +html = bleach.clean(markdown.markdown(text), markdown_tags, markdown_attrs)
    +
    + +

    If you are not interested in sanitizing untrusted text, but simply desire to +escape raw HTML, then that can be accomplished through an extension which +removes HTML parsing:

    +
    from markdown.extensions import Extension
    +
    +class EscapeHtml(Extension):
    +    def extendMarkdown(self, md):
    +        md.preprocessors.deregister('html_block')
    +        md.inlinePatterns.deregister('html')
    +
    +html = markdown.markdown(text, extensions=[EscapeHtml()])
    +
    + +

    As the HTML would not be parsed with the above Extension, then the serializer +will escape the raw HTML, which is exactly what happened in previous versions +with safe_mode="escape".

    +

    Positional arguments deprecated

    +

    Positional arguments on the markdown.Markdown() class are deprecated as are +all except the text argument on the markdown.markdown() wrapper function. +Using positional arguments will raise an error. Only keyword arguments should be +used. For example, if your code previously looked like this:

    +
    html = markdown.markdown(text, [SomeExtension()])
    +
    + +

    Then it is recommended that you change it to read something like this:

    +
    html = markdown.markdown(text, extensions=[SomeExtension()])
    +
    + +
    +

    Note

    +

    This change is being made as a result of deprecating "safe_mode" as the +safe_mode argument was one of the positional arguments. When that argument +is removed, the two arguments following it will no longer be at the correct +position. It is recommended that you always use keywords when they are +supported for this reason.

    +
    +

    Extension name behavior has changed

    +

    In previous versions of Python-Markdown, the built-in extensions received +special status and did not require the full path to be provided. Additionally, +third party extensions whose name started with "mdx_" received the same +special treatment. This is no longer the case.

    +

    Support has been added for extensions to define an entry +point. An entry point is a string name which +can be used to point to an Extension class. The built-in extensions now have +entry points which match the old short names. And any third-party extensions +which define entry points can now get the same behavior. See the documentation +for each specific extension to find the assigned name.

    +

    If an extension does not define an entry point, then the full path to the +extension must be used. See the documentation for +a full explanation of the current behavior.

    +

    Extension configuration as part of extension name deprecated

    +

    The previously documented method of appending the extension configuration +options as a string to the extension name is deprecated and will raise an error. +The extension_configs keyword should be +used instead. See the documentation for a +full explanation of the current behavior.

    +

    HeaderId extension deprecated

    +

    The HeaderId Extension is deprecated and will raise an error if specified. Use +the Table of Contents Extension instead, which offers +most of the features of the HeaderId Extension and more (support for meta data +is missing).

    +

    Extension authors who have been using the slugify and unique functions +defined in the HeaderId Extension should note that those functions are now +defined in the Table of Contents extension and should adjust their import +statements accordingly (from markdown.extensions.toc import slugify, unique).

    +

    Homegrown OrderedDict has been replaced with a purpose-built Registry

    +

    All processors and patterns now get “registered” to a +Registry. A backwards compatible shim is +included so that existing simple extensions should continue to work. +A DeprecationWarning will be raised for any code which calls the old API.

    +

    Markdown class instance references.

    +

    Previously, instances of the Markdown class were represented as any one of +md, md_instance, or markdown. This inconsistency made it difficult when +developing extensions, or just maintaining the existing code. Now, all instances +are consistently represented as md.

    +

    The old attributes on class instances still exist, but raise a +DeprecationWarning when accessed. Also on classes where the instance was +optional, the attribute always exists now and is simply None if no instance +was provided (previously the attribute would not exist).

    +

    markdown.util.isBlockLevel deprecated

    +

    The markdown.util.isBlockLevel function is deprecated and will raise a +DeprecationWarning. Instead, extensions should use the isBlockLevel method +of the Markdown class instance. Additionally, a list of block level elements +is defined in the block_level_elements attribute of the Markdown class which +extensions can access to alter the list of elements which are treated as block +level elements.

    +

    md_globals keyword deprecated from extension API

    +

    Previously, the extendMarkdown method of a markdown.extensions.Extension +subclasses accepted an md_globals keyword, which contained the value returned +by Python’s globals() built-in function. As all of the configuration is now +held within the Markdown class instance, access to the globals is no longer +necessary and any extensions which expect the keyword will raise a +DeprecationWarning. A future release will raise an error.

    +

    markdown.version and markdown.version_info deprecated

    +

    Historically, version numbers were acquired via the attributes +markdown.version and markdown.version_info. Moving forward, a more +standardized approach is being followed and versions are acquired via the +markdown.__version__ and markdown.__version_info__ attributes. The legacy +attributes are still available to allow distinguishing versions between the +legacy Markdown 2.0 series and the Markdown 3.0 series, but in the future the +legacy attributes will be removed.

    +

    Added new, more flexible InlineProcessor class

    +

    A new InlineProcessor class handles inline processing much better and allows +for more flexibility. The new InlineProcessor classes no longer utilize +unnecessary pretext and post-text captures. New class can accept the buffer that +is being worked on and manually process the text without regular expressions and +return new replacement bounds. This helps us to handle links in a better way and +handle nested brackets and logic that is too much for regular expression.

    +

    Added

    +
      +
    • +

      A new testing framework is included as a part of the + Markdown library, which can also be used by third party extensions.

      +
    • +
    • +

      A new toc_depth parameter has been added to the + Table of Contents Extension.

      +
    • +
    • +

      A new toc_tokens attribute has been added to the Markdown class by the + Table of Contents Extension, which contains the raw + tokens used to build the Table of Contents. Users can use this to build their + own custom Table of Contents rather than needing to parse the HTML available + on the toc attribute of the Markdown class.

      +
    • +
    • +

      When the Table of Contents Extension is used in + conjunction with the Attribute Lists Extension + and a data-toc-label attribute is defined on a header, the content of the + data-toc-label attribute is now used as the content of the Table of Contents + item for that header.

      +
    • +
    • +

      Additional CSS class names can be appended to + Admonitions.

      +
    • +
    +

    Previous Releases

    +

    For information on prior releases, see their changelogs:

    + + +
    +
    +
    + + +
    +
    + + + + + + + \ No newline at end of file diff --git a/cli/index.html b/cli/index.html old mode 100755 new mode 100644 index 1f01d59..ba6ef10 --- a/cli/index.html +++ b/cli/index.html @@ -11,9 +11,12 @@ - Command Line — Python-Markdown 3.4.4 documentation + Command Line — Python-Markdown 3.5 documentation + + + @@ -23,7 +26,7 @@

    Navigation

    @@ -82,22 +74,22 @@

    Navigation

    Python-Markdown’s command line script takes advantage of Python’s -m flag. Therefore, assuming the python executable is on your system path, use the following format:

    -
    python -m markdown [options] [args]
    -
    +
    python -m markdown [options] [args]
    +

    That will run the module as a script with the options and arguments provided.

    At its most basic usage, one would simply pass in a file name as the only argument:

    -
    python -m markdown input_file.txt
    -
    +
    python -m markdown input_file.txt
    +

    Piping input and output (on STDIN and STDOUT) is fully supported as well. For example:

    -
    echo "Some **Markdown** text." | python -m markdown > output.html
    -
    +
    echo "Some **Markdown** text." | python -m markdown > output.html
    +

    Use the --help option for a list all available options and arguments:

    -
    python -m markdown --help
    -
    +
    python -m markdown --help
    +

    If you don’t want to call the python executable directly (using the -m flag), follow the instructions below to use a wrapper script:

    @@ -153,16 +145,16 @@

    Setup&

    Usage

    To use markdown_py from the command line, run it as

    -
    markdown_py input_file.txt
    -
    +
    markdown_py input_file.txt
    +

    or

    -
    markdown_py input_file.txt > output_file.html
    -
    +
    markdown_py input_file.txt > output_file.html
    +

    For a complete list of options, run

    -
    markdown_py --help
    -
    +
    markdown_py --help
    +

    Using Extensions

    To load a Python-Markdown extension from the command line use the -x @@ -172,42 +164,42 @@

    Using Extensions
    python -m markdown -x myext input.txt
    -
    +
    python -m markdown -x myext input.txt
    +

    And to load an extension with Python’s dot notation:

    -
    python -m markdown -x path.to.module:MyExtClass input.txt
    -
    +
    python -m markdown -x path.to.module:MyExtClass input.txt
    +

    To load multiple extensions, specify an -x option for each extension:

    -
    python -m markdown -x myext -x path.to.module:MyExtClass input.txt
    -
    +
    python -m markdown -x myext -x path.to.module:MyExtClass input.txt
    +

    If the extension supports configuration options (see the documentation for the extension you are using to determine what settings it supports, if any), you can pass them in as well:

    -
    python -m markdown -x myext -c config.yml input.txt
    -
    +
    python -m markdown -x myext -c config.yml input.txt
    +

    The -c (or --extension_configs) option accepts a file name. The file must be in either the YAML or JSON format and contain YAML or JSON data that would map to a Python Dictionary in the format required by the extension_configs keyword of the markdown.Markdown class. Therefore, the file config.yaml referenced in the above example might look like this:

    -
    myext:
    -    option1: 'value1'
    -    option2: True
    -
    +
    myext:
    +    option1: 'value1'
    +    option2: True
    +

    Similarly, a JSON configuration file might look like this:

    -
    {
    -  "myext":
    -  {
    -    "option1": "value1",
    -    "option2": "value2"
    -  }
    -}
    -
    +
    {
    +  "myext":
    +  {
    +    "option1": "value1",
    +    "option2": "value2"
    +  }
    +}
    +

    Note that while the --extension_configs option does specify the myext extension, you still need to load the extension with the -x option, @@ -263,14 +255,6 @@

    This Page

  • Edit on GitHub
  • - - @@ -281,7 +265,7 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/contributing/index.html b/contributing/index.html old mode 100755 new mode 100644 index 563fd32..3165bac --- a/contributing/index.html +++ b/contributing/index.html @@ -9,11 +9,14 @@ - - - Contributing to Python-Markdown — Python-Markdown 3.4.4 documentation + + + Contributing to Python-Markdown — Python-Markdown 3.5 documentation + + + @@ -23,21 +26,21 @@

    Navigation

    @@ -145,7 +137,7 @@

    Pull Requests

    Before being accepted, each pull request must include the applicable code, new tests of all new features, updated tests for any changed features, documentation -updates, and an appropriate update to the release notes. All changes must follow +updates, and an appropriate update to the changelog. All changes must follow the applicable style guides. Failure to meet any one of the requirements is likely to delay any serious consideration of your pull request and may even cause it to be closed. Of course, if you are in the early stages of development, @@ -183,23 +175,23 @@

    Code Style Guide
    my_list = [
    -    1, 2, 3,
    -    4, 5, 6,
    -]
    -result = some_function_that_takes_arguments(
    -    'a', 'b', 'c',
    -    'd', 'e', 'f',
    -)
    -
    +
    my_list = [
    +    1, 2, 3,
    +    4, 5, 6,
    +]
    +result = some_function_that_takes_arguments(
    +    'a', 'b', 'c',
    +    'd', 'e', 'f',
    +)
    +

    When the conditional part of an if-statement is long enough to require that it be written across multiple lines, extra indentation should be included on the conditional continuation line.

    -
    if (this_is_one_thing
    -        and that_is_another_thing):
    -    do_something()
    -
    +
    if (this_is_one_thing
    +        and that_is_another_thing):
    +    do_something()
    +

    Documentation Style Guide

    Documentation should be in American English. The tone of the documentation @@ -217,31 +209,31 @@

    Documentation Style GuideHeaders

    Headers should use the hash style. For example:

    -
    ## Some important topic
    -
    +
    ## Some important topic
    +

    The underline style should not be used. Don’t do this:

    -
    Some important topic
    -====================
    -
    +
    Some important topic
    +====================
    +

    Links should always use the reference style, with the referenced hyperlinks kept at the end of the document.

    -
    Here is a link to [some other thing][other-thing].
    +
    Here is a link to [some other thing][other-thing].
     
     More text...
     
    -[other-thing]: http://example.com/other/thing
    -
    +[other-thing]: http://example.com/other/thing +

    This style helps keep the documentation source consistent and readable.

    If you are linking to another document within Python-Markdown’s documentation, you should use a relative link, and link to the .md suffix. If applicable, it is preferred that the link includes a hash fragment pointing to the specific section of the page. For example:

    -
    [authentication]: reference.md#Markdown
    -
    +
    [authentication]: reference.md#Markdown
    +

    Linking in this style ensures that the links work when browsing the documentation on GitHub. If your Markdown editor makes links clickable, they @@ -250,41 +242,39 @@

    Release Notes

    +

    Changelog

    Any commit/pull request which changes the behavior of the Markdown library in -any way must include an entry in the release notes. If a change only alters the -documentation or tooling for the project, then an entry in the release notes is -not necessary. The release notes can be found at docs/change_log.

    -

    Each release must have an entry in docs/change_log/index.md which follows the -format of the existing entries. A MAJOR release (X.0.0) and a MINOR release -(X.X.0) should only include a single line in docs/change_log/index.md which -links to a full document outlining all changes included in the release. -However, a PATCH release (X.X.X) should include a list of single line entries -summarizing each change directly in the file docs/change_log/index.md (see -Versions for an explanation of MAJOR, MINOR, and PATCH releases). -The description of each change should include a reference to the relevant -GitHub issue in the format #123 (where 123 is the issue number).

    -

    Prior to a version being released, the text *under development* should be -used as a placeholder for the release date. That text will be replaced with the -release date as part of the release process.

    -

    If a change is the first since the last release, then the appropriate entries -and/or files may need to be created and included in a pull request. A pull -request should not alter an entry for an existing version which has already -been released, unless it is editing an error in the release notes for that -version, or is otherwise expressly deemed appropriate by the project +any way must include an entry in the changelog. If a change only alters the +documentation or tooling for the project, then an entry in the changelog is +not necessary. The current changelog can be found at docs/changelog.md.

    +

    The current changelog follows the format defined at +keepachangelog.com. The description of +each change should include a reference to the relevant GitHub issue in the +format #123 (where 123 is the issue number).

    +

    Edits to the changelog should generally add entries to the [unreleased] +version at the top of the log. A pull request should not alter an entry for a +previously released version, unless it is editing an error in the notes for +that version, or is otherwise expressly deemed appropriate by the project maintainers.

    +

    The current changelog should only document the changes for one MAJOR release and +its various MINOR and PATCH releases (see Versions for an +explanation of MAJOR, MINOR, and PATCH releases). Older versions from previous +series of releases can be found in the archive at docs/change_log/ and may +follow a different format. Note that the archived changelogs are not in the site +navigation and are only linked from the Previous +Releases section of the current changelog.

    Commit Message Style Guide

    Use the present tense (“Add feature” not “Added feature”).

    Use the imperative mood (“Move item to…” not “Moves item to…”).

    Limit the first line to 72 characters or less.

    Reference issues and pull requests liberally after the first line. Include a summary of the changes/additions made without replicating the content of the -documentation or release notes. This is where an explanation of the choices made +documentation or changelog. This is where an explanation of the choices made should be found. References to issues and pull requests should only provide the context in which a choice was made. However, the commit should be able to stand on its own.

    @@ -297,8 +287,8 @@

    Development Environment, which isolates any experimental code from the general system. To create a virtual environment, use the following command from the root of the local working copy of your GitHub fork:

    -
    virtualenv venv
    -
    +
    virtualenv venv
    +

    That creates a virtual environment which is contained in the venv directory within your local working copy. Note that the repository is configured so that @@ -306,53 +296,53 @@

    Development Environment

    On Posix systems (Linux, BSD, MacOS, etc.), use the following command to activate the environment:

    -
    source venv/bin/activate
    -
    +
    source venv/bin/activate
    +

    On Windows, use this command instead:

    -
    venv/Scripts/activate
    -
    +
    venv/Scripts/activate
    +

    See the User Guide for more information on using virtual environments.

    To be able to run the Markdown library directly while working on it, install the working copy into the environment in Development Mode after activating the virtual environment for the first time:

    -
    pip install -e .
    -
    +
    pip install -e .
    +

    Now any saved changes will immediately be available within the virtual environment.

    You can run the command line script with the following command:

    -
    python -m markdown
    -
    +
    python -m markdown
    +

    Before building the documentation for the first time, you will need to install some optional dependencies with the command:

    -
    pip install -e .[docs]
    -
    +
    pip install -e .[docs]
    +

    To build the documentation and serve it locally on a development server, run:

    -
    mkdocs serve
    -
    +
    mkdocs serve
    +

    Then point your browser at http://127.0.0.1:8000/. For a complete list of options available, view MkDocs’ help with the command:

    -
    mkdocs --help
    -
    +
    mkdocs --help
    +

    Before running tests for the first time, you will need to install some optional dependencies with the command:

    -
    pip install -e .[testing]
    -
    +
    pip install -e .[testing]
    +

    And you can directly run the tests with:

    -
    python -m unittest discover tests
    -
    +
    python -m unittest discover tests
    +

    To get a coverage report after running the tests, use these commands instead:

    -
    coverage run --source=markdown -m unittest discover tests
    +
    coverage run --source=markdown -m unittest discover tests
     coverage report --show-missing
    -
    +

    Versions

    -

    Python-Markdown follows Semantic Versioning and uses the +

    Python-Markdown follows Semantic Versioning and uses the MAJOR.MINOR.PATCH[.dev#|a#|b#|rc#] format for identifying releases. The status of the master branch should always be identified in the __version_info__ tuple defined in markdown/__meta__.py. The contents of that tuple will automatically be converted into a normalized version which -conforms to PEP 440. An invalid __version_info__ tuple will raise an error, -preventing the library from running and the package from building.

    +conforms to PEP 440. Each time the version is changed, the continuous +integration server will run a test to ensure that the current version is in a +valid normalized format.

    Version Status

    A MAJOR version is in development status when the MINOR version is 0, the PATCH version is 0, and the version includes a dev segment.

    @@ -416,7 +407,7 @@

    Version WorkflowSemantic Versioning.

    +pursuant to Semantic Versioning.

    A separate commit to the master branch should be made to bump up the MAJOR and/or MINOR version and set development status. Only then will any pull requests implementing new features or backward incompatible changes be accepted.

    @@ -437,8 +428,8 @@

    Release Processmarkdown/__meta__.py.

    @@ -449,8 +440,8 @@

    Release Process
    Bump version to X.X.X
    -
    +
    Bump version to X.X.X
    +
  • @@ -473,9 +464,9 @@

    Release ProcessPython-Markdown/Python-Markdown.github.io repositories are in sibling directories named markdown and Python-Markdown.github.io respectively.

    -
    cd Python-Markdown.github.io
    +
    cd Python-Markdown.github.io
     mkdocs gh-deploy --config-file ../markdown/mkdocs.yml --remote-branch master
    -
    +

  • @@ -714,7 +705,7 @@

    Table Of Contents

  • - Release Notes + Changelog
  • @@ -774,13 +765,13 @@

    Table Of Contents

    Previous topic

    - Test Tools + test_tools

    Next topic

    - Change Log + Changelog

    @@ -790,14 +781,6 @@

    This Page

  • Edit on GitHub
  • - - @@ -808,21 +791,21 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/custom.css b/custom.css new file mode 100644 index 0000000..901060e --- /dev/null +++ b/custom.css @@ -0,0 +1,5 @@ +div.body h4, div.body h5, div.body h6 { + background-color: transparent; + padding-left: 0; + font-weight: bold; +} diff --git a/extensions/abbreviations/index.html b/extensions/abbreviations/index.html old mode 100755 new mode 100644 index 91078aa..864671d --- a/extensions/abbreviations/index.html +++ b/extensions/abbreviations/index.html @@ -11,9 +11,12 @@ - Abbreviations — Python-Markdown 3.4.4 documentation + Abbreviations — Python-Markdown 3.5 documentation + + + @@ -23,7 +26,7 @@

    Navigation

    - - @@ -184,7 +168,7 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/extensions/admonition/index.html b/extensions/admonition/index.html old mode 100755 new mode 100644 index 1e7f0c7..09cb973 --- a/extensions/admonition/index.html +++ b/extensions/admonition/index.html @@ -11,9 +11,12 @@ - Admonition — Python-Markdown 3.4.4 documentation + Admonition — Python-Markdown 3.5 documentation + + + @@ -23,7 +26,7 @@

    Navigation

    - - @@ -234,7 +218,7 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/extensions/api/index.html b/extensions/api/index.html old mode 100755 new mode 100644 index f4026c5..9dd1fd2 --- a/extensions/api/index.html +++ b/extensions/api/index.html @@ -11,9 +11,12 @@ - Extension API — Python-Markdown 3.4.4 documentation + Extension API — Python-Markdown 3.5 documentation + + + @@ -23,7 +26,7 @@

    Navigation

    @@ -97,20 +89,20 @@

    Preprocessors

    Example

    This simple example removes any lines with ‘NO RENDER’ before processing:

    -
    from markdown.preprocessors import Preprocessor
    -import re
    +
    from markdown.preprocessors import Preprocessor
    +import re
     
    -class NoRender(Preprocessor):
    -    """ Skip any line with words 'NO RENDER' in it. """
    -    def run(self, lines):
    -        new_lines = []
    -        for line in lines:
    -            m = re.search("NO RENDER", line)
    -            if not m:
    -                # any line without NO RENDER is passed through
    -                new_lines.append(line)
    -        return new_lines
    -
    +class NoRender(Preprocessor): + """ Skip any line with words 'NO RENDER' in it. """ + def run(self, lines): + new_lines = [] + for line in lines: + m = re.search("NO RENDER", line) + if not m: + # any line without NO RENDER is passed through + new_lines.append(line) + return new_lines +

    Usages

    Some preprocessors in the Markdown source tree include:

    @@ -204,42 +196,42 @@

    Example
    def test_block_processor():
    -    class BoxBlockProcessor(BlockProcessor):
    -        RE_FENCE_START = r'^ *!{3,} *\n' # start line, e.g., `   !!!! `
    -        RE_FENCE_END = r'\n *!{3,}\s*$'  # last non-blank line, e.g, '!!!\n  \n\n'
    +
    def test_block_processor():
    +    class BoxBlockProcessor(BlockProcessor):
    +        RE_FENCE_START = r'^ *!{3,} *\n' # start line, e.g., `   !!!! `
    +        RE_FENCE_END = r'\n *!{3,}\s*$'  # last non-blank line, e.g, '!!!\n  \n\n'
     
    -        def test(self, parent, block):
    -            return re.match(self.RE_FENCE_START, block)
    +        def test(self, parent, block):
    +            return re.match(self.RE_FENCE_START, block)
     
    -        def run(self, parent, blocks):
    -            original_block = blocks[0]
    -            blocks[0] = re.sub(self.RE_FENCE_START, '', blocks[0])
    +        def run(self, parent, blocks):
    +            original_block = blocks[0]
    +            blocks[0] = re.sub(self.RE_FENCE_START, '', blocks[0])
     
    -            # Find block with ending fence
    -            for block_num, block in enumerate(blocks):
    -                if re.search(self.RE_FENCE_END, block):
    -                    # remove fence
    -                    blocks[block_num] = re.sub(self.RE_FENCE_END, '', block)
    -                    # render fenced area inside a new div
    -                    e = etree.SubElement(parent, 'div')
    -                    e.set('style', 'display: inline-block; border: 1px solid red;')
    -                    self.parser.parseBlocks(e, blocks[0:block_num + 1])
    -                    # remove used blocks
    -                    for i in range(0, block_num + 1):
    -                        blocks.pop(0)
    -                    return True  # or could have had no return statement
    -            # No closing marker!  Restore and do nothing
    -            blocks[0] = original_block
    -            return False  # equivalent to our test() routine returning False
    +            # Find block with ending fence
    +            for block_num, block in enumerate(blocks):
    +                if re.search(self.RE_FENCE_END, block):
    +                    # remove fence
    +                    blocks[block_num] = re.sub(self.RE_FENCE_END, '', block)
    +                    # render fenced area inside a new div
    +                    e = etree.SubElement(parent, 'div')
    +                    e.set('style', 'display: inline-block; border: 1px solid red;')
    +                    self.parser.parseBlocks(e, blocks[0:block_num + 1])
    +                    # remove used blocks
    +                    for i in range(0, block_num + 1):
    +                        blocks.pop(0)
    +                    return True  # or could have had no return statement
    +            # No closing marker!  Restore and do nothing
    +            blocks[0] = original_block
    +            return False  # equivalent to our test() routine returning False
     
    -    class BoxExtension(Extension):
    -        def extendMarkdown(self, md):
    -            md.parser.blockprocessors.register(BoxBlockProcessor(md.parser), 'box', 175)
    -
    + class BoxExtension(Extension): + def extendMarkdown(self, md): + md.parser.blockprocessors.register(BoxBlockProcessor(md.parser), 'box', 175) +

    Start with this example input:

    -
    A regular paragraph of text.
    +
    A regular paragraph of text.
     
     !!!!!
     First paragraph of wrapped text.
    @@ -248,7 +240,7 @@ 

    ExampleTree processorsWorking with the ElementTree below.

    Example

    A pseudo example:

    -
    from markdown.treeprocessors import Treeprocessor
    +
    from markdown.treeprocessors import Treeprocessor
     
    -class MyTreeprocessor(Treeprocessor):
    -    def run(self, root):
    -        root.text = 'modified content'
    -        # No return statement is same as `return None`
    -
    +class MyTreeprocessor(Treeprocessor): + def run(self, root): + root.text = 'modified content' + # No return statement is same as `return None` +

    Usages

    The core InlineProcessor class is a tree processor. It walks the tree, matches patterns, and splits and creates @@ -399,29 +391,29 @@

    Convenience ClassesExample

    This example changes --strike-- to <del>strike</del>.

    -
    from markdown.inlinepatterns import InlineProcessor
    -from markdown.extensions import Extension
    -import xml.etree.ElementTree as etree
    +
    from markdown.inlinepatterns import InlineProcessor
    +from markdown.extensions import Extension
    +import xml.etree.ElementTree as etree
     
     
    -class DelInlineProcessor(InlineProcessor):
    -    def handleMatch(self, m, data):
    -        el = etree.Element('del')
    -        el.text = m.group(1)
    -        return el, m.start(0), m.end(0)
    +class DelInlineProcessor(InlineProcessor):
    +    def handleMatch(self, m, data):
    +        el = etree.Element('del')
    +        el.text = m.group(1)
    +        return el, m.start(0), m.end(0)
     
    -class DelExtension(Extension):
    -    def extendMarkdown(self, md):
    -        DEL_PATTERN = r'--(.*?)--'  # like --del--
    -        md.inlinePatterns.register(DelInlineProcessor(DEL_PATTERN, md), 'del', 175)
    -
    +class DelExtension(Extension): + def extendMarkdown(self, md): + DEL_PATTERN = r'--(.*?)--' # like --del-- + md.inlinePatterns.register(DelInlineProcessor(DEL_PATTERN, md), 'del', 175) +

    Use this input example:

    -
    First line of the block.
    +
    First line of the block.
     This is --strike one--.
     This is --strike two--.
     End of the block.
    -
    +

    The example output might display as follows:

    +class DelExtension(Extension): + def extendMarkdown(self, md): + md.inlinePatterns.register(SimpleTagInlineProcessor(r'()--(.*?)--', 'del'), 'del', 175) +
    Usages

    Here are some convenience functions and other examples:

    @@ -544,23 +536,23 @@

    Inline Patterns
    from markdown.inlinepatterns import Pattern
    -import xml.etree.ElementTree as etree
    +
    from markdown.inlinepatterns import Pattern
    +import xml.etree.ElementTree as etree
     
    -class EmphasisPattern(Pattern):
    -    def handleMatch(self, m):
    -        el = etree.Element('em')
    -        el.text = m.group(2)
    -        return el
    -

    +class EmphasisPattern(Pattern): + def handleMatch(self, m): + el = etree.Element('em') + el.text = m.group(2) + return el +

    As discussed in Integrating Your Code Into Markdown, an instance of this class will need to be provided to Markdown. That instance would be created like so:

    -
    # an oversimplified regex
    -MYPATTERN = r'\*([^*]+)\*'
    -# pass in pattern and create instance
    -emphasis = EmphasisPattern(MYPATTERN)
    -
    +
    # an oversimplified regex
    +MYPATTERN = r'\*([^*]+)\*'
    +# pass in pattern and create instance
    +emphasis = EmphasisPattern(MYPATTERN)
    +

    Postprocessors

    Postprocessors munge the document after the ElementTree has been serialized into a string. Postprocessors should be @@ -571,14 +563,14 @@

    PostprocessorsExample

    Here is a simple example that changes the output to one big page showing the raw html.

    -
    from markdown.postprocessors import Postprocessor
    -import re
    +
    from markdown.postprocessors import Postprocessor
    +import re
     
    -class ShowActualHtmlPostprocesor(Postprocessor):
    -    """ Wrap entire output in <pre> tags as a diagnostic. """
    -    def run(self, text):
    -        return '<pre>\n' + re.sub('<', '&lt;', text) + '</pre>\n'
    -
    +class ShowActualHtmlPostprocesor(Postprocessor): + """ Wrap entire output in <pre> tags as a diagnostic. """ + def run(self, text): + return '<pre>\n' + re.sub('<', '&lt;', text) + '</pre>\n' +

    Usages

    Some postprocessors in the Markdown source tree include:

    @@ -618,36 +610,36 @@

    Working with the ElementTree

    First, import the ElementTree module:

    -
    import xml.etree.ElementTree as etree
    -
    +
    import xml.etree.ElementTree as etree
    +

    Sometimes you may want text inserted into an element to be parsed by [Inline Patterns][]. In such a situation, simply insert the text as you normally would and the text will be automatically run through the Inline Patterns. However, if you do not want some text to be parsed by Inline Patterns, then insert the text as an AtomicString.

    -
    from markdown.util import AtomicString
    -some_element.text = AtomicString(some_text)
    -
    +
    from markdown.util import AtomicString
    +some_element.text = AtomicString(some_text)
    +

    Here’s a basic example which creates an HTML table (note that the contents of the second cell (td2) will be run through Inline Patterns latter):

    -
    table = etree.Element("table")
    -table.set("cellpadding", "2")                      # Set cellpadding to 2
    -tr = etree.SubElement(table, "tr")                 # Add child tr to table
    -td1 = etree.SubElement(tr, "td")                   # Add child td1 to tr
    -td1.text = markdown.util.AtomicString("Cell content") # Add plain text content
    -td2 = etree.SubElement(tr, "td")                   # Add second td to tr
    -td2.text = "*text* with **inline** formatting."    # Add markup text
    -table.tail = "Text after table"                    # Add text after table
    -
    +
    table = etree.Element("table")
    +table.set("cellpadding", "2")                      # Set cellpadding to 2
    +tr = etree.SubElement(table, "tr")                 # Add child tr to table
    +td1 = etree.SubElement(tr, "td")                   # Add child td1 to tr
    +td1.text = markdown.util.AtomicString("Cell content") # Add plain text content
    +td2 = etree.SubElement(tr, "td")                   # Add second td to tr
    +td2.text = "*text* with **inline** formatting."    # Add markup text
    +table.tail = "Text after table"                    # Add text after table
    +

    You can also manipulate an existing tree. Consider the following example which adds a class attribute to <a> elements:

    -
    def set_link_class(self, element):
    -    for child in element:
    -        if child.tag == "a":
    -              child.set("class", "myclass") #set the class attribute
    -        set_link_class(child) # run recursively on children
    -
    +
    def set_link_class(self, element):
    +    for child in element:
    +        if child.tag == "a":
    +              child.set("class", "myclass") #set the class attribute
    +        set_link_class(child) # run recursively on children
    +

    For more information about working with ElementTree see the ElementTree Documentation.

    @@ -659,10 +651,10 @@

    Working with Raw HTML
    html = "<p>This is some <em>raw</em> HTML data</p>"
    -el = etree.Element("div")
    -el.text = self.md.htmlStash.store(html)
    -
    +
    html = "<p>This is some <em>raw</em> HTML data</p>"
    +el = etree.Element("div")
    +el.text = self.md.htmlStash.store(html)
    +

    For the global htmlStash instance to be available from a processor, the markdown.Markdown instance must be passed to the processor from extendMarkdown and will be available as self.md.htmlStash.

    @@ -714,32 +706,32 @@

    extendMarkdown
    from markdown.extensions import Extension
    +
    from markdown.extensions import Extension
     
    -class MyExtension(Extension):
    -    def extendMarkdown(self, md):
    -        # Register instance of 'mypattern' with a priority of 175
    -        md.inlinePatterns.register(MyPattern(md), 'mypattern', 175)
    -
    +class MyExtension(Extension): + def extendMarkdown(self, md): + # Register instance of 'mypattern' with a priority of 175 + md.inlinePatterns.register(MyPattern(md), 'mypattern', 175) +

    registerExtension

    Some extensions may need to have their state reset between multiple runs of the markdown.Markdown class. For example, consider the following use of the Footnotes extension:

    -
    md = markdown.Markdown(extensions=['footnotes'])
    -html1 = md.convert(text_with_footnote)
    -md.reset()
    -html2 = md.convert(text_without_footnote)
    -
    +
    md = markdown.Markdown(extensions=['footnotes'])
    +html1 = md.convert(text_with_footnote)
    +md.reset()
    +html2 = md.convert(text_without_footnote)
    +

    Without calling reset, the footnote definitions from the first document will be inserted into the second document as they are still stored within the class instance. Therefore the Extension class needs to define a reset method that will reset the state of the extension (i.e.: self.footnotes = {}). However, as many extensions do not have a need for reset, reset is only called on extensions that are registered.

    To register an extension, call md.registerExtension from within your extendMarkdown method:

    -
    def extendMarkdown(self, md):
    -    md.registerExtension(self)
    -    # insert processors and patterns here
    -
    +
    def extendMarkdown(self, md):
    +    md.registerExtension(self)
    +    # insert processors and patterns here
    +

    Then, each time reset is called on the markdown.Markdown instance, the reset method of each registered extension will be called as well. You should also note that reset will be called on each registered extension after it is @@ -747,19 +739,19 @@

    registerExtensionConfiguration Settings

    If an extension uses any parameters that the user may want to change, those parameters should be stored in self.config of your markdown.extensions.Extension class in the following format:

    -
    class MyExtension(markdown.extensions.Extension):
    -    def __init__(self, **kwargs):
    -        self.config = {
    -            'option1' : ['value1', 'description1'],
    -            'option2' : ['value2', 'description2']
    -        }
    -        super(MyExtension, self).__init__(**kwargs)
    -
    +
    class MyExtension(markdown.extensions.Extension):
    +    def __init__(self, **kwargs):
    +        self.config = {
    +            'option1' : ['value1', 'description1'],
    +            'option2' : ['value2', 'description2']
    +        }
    +        super(MyExtension, self).__init__(**kwargs)
    +

    When implemented this way the configuration parameters can be over-ridden at run time (thus the call to super). For example:

    -
    markdown.Markdown(extensions=[MyExtension(option1='other value')])
    -
    +
    markdown.Markdown(extensions=[MyExtension(option1='other value')])
    +

    Note that if a keyword is passed in that is not already defined in self.config, then a KeyError is raised.

    The markdown.extensions.Extension class and its subclasses have the following methods available to assist in working @@ -794,10 +786,10 @@

    Naming an Extensionlibrary reference an instance of an extension can be passed directly to markdown.Markdown. In fact, this is the preferred way to use third-party extensions.

    For example:

    -
    import markdown
    -from path.to.module import MyExtension
    -md = markdown.Markdown(extensions=[MyExtension(option='value')])
    -
    +
    import markdown
    +from path.to.module import MyExtension
    +md = markdown.Markdown(extensions=[MyExtension(option='value')])
    +

    However, Markdown also accepts “named” third party extensions for those occasions when it is impractical to import an extension directly (from the command line or from within templates). A “name” can either be a registered entry @@ -806,20 +798,20 @@

    Entry PointEntry points are defined in a Python package’s setup.py script. The script must use setuptools to support entry points. Python-Markdown extensions must be assigned to the markdown.extensions group. An entry point definition might look like this:

    -
    from setuptools import setup
    +
    from setuptools import setup
     
    -setup(
    -    # ...
    -    entry_points={
    -        'markdown.extensions': ['myextension = path.to.module:MyExtension']
    -    }
    -)
    -
    +setup( + # ... + entry_points={ + 'markdown.extensions': ['myextension = path.to.module:MyExtension'] + } +) +

    After a user installs your extension using the above script, they could then call the extension using the myextension string name like this:

    -
    markdown.markdown(text, extensions=['myextension'])
    -
    +
    markdown.markdown(text, extensions=['myextension'])
    +

    Note that if two or more entry points within the same group are assigned the same name, Python-Markdown will only ever use the first one found and ignore all others. Therefore, be sure to give your extension a unique name.

    @@ -830,12 +822,12 @@

    Dot Notation

    Therefore, if you were to import the class like this:

    -
    from path.to.module import MyExtension
    -
    +
    from path.to.module import MyExtension
    +

    Then the extension can be loaded as follows:

    -
    markdown.markdown(text, extensions=['path.to.module:MyExtension'])
    -
    +
    markdown.markdown(text, extensions=['path.to.module:MyExtension'])
    +

    You do not need to do anything special to support this feature. As long as your extension class is able to be imported, a user can include it with the above syntax.

    @@ -844,12 +836,12 @@

    Dot NotationmakeExtension that accepts **kwargs and returns an extension instance.

    For example:

    -
    class MyExtension(markdown.extensions.Extension)
    -    # Define extension here...
    +
    class MyExtension(markdown.extensions.Extension)
    +    # Define extension here...
     
    -def makeExtension(**kwargs):
    -    return MyExtension(**kwargs)
    -
    +def makeExtension(**kwargs): + return MyExtension(**kwargs) +

    When markdown.Markdown is passed the “name” of your extension as a dot notation string that does not include a class (for example path.to.module), it will import the module and call the makeExtension function to initiate your @@ -865,30 +857,30 @@

    Registries
    registry = Registry()
    -registry.register(SomeItem(), 'itemname', 20)
    -# Get the item by index
    -item = registry[0]
    -# Get the item by name
    -item = registry['itemname']
    -
    +
    registry = Registry()
    +registry.register(SomeItem(), 'itemname', 20)
    +# Get the item by index
    +item = registry[0]
    +# Get the item by name
    +item = registry['itemname']
    +

    When checking that the registry contains an item, you may use either the string-based “name”, or a reference to the actual item. For example:

    -
    someitem = SomeItem()
    -registry.register(someitem, 'itemname', 20)
    -# Contains the name
    -assert 'itemname' in registry
    -# Contains the item instance
    -assert someitem in registry
    -
    +
    someitem = SomeItem()
    +registry.register(someitem, 'itemname', 20)
    +# Contains the name
    +assert 'itemname' in registry
    +# Contains the item instance
    +assert someitem in registry
    +

    markdown.util.Registry has the following methods:

    Registry.register(self, item, name, priority)

    Add an item to the registry with the given name and priority.

    -

    Parameters:

    +

    Arguments:

    • item: The item being registered.
    • name: A string used to reference the item.
    • @@ -1100,14 +1092,6 @@

      This Page

    • Edit on GitHub
    - - @@ -1118,7 +1102,7 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/extensions/attr_list/index.html b/extensions/attr_list/index.html old mode 100755 new mode 100644 index eb1b741..59da3d5 --- a/extensions/attr_list/index.html +++ b/extensions/attr_list/index.html @@ -11,9 +11,12 @@ - Attribute Lists — Python-Markdown 3.4.4 documentation + Attribute Lists — Python-Markdown 3.5 documentation + + + @@ -23,7 +26,7 @@

    Navigation

    • - +
    • index @@ -37,7 +40,7 @@

      Navigation

    • icon
    • @@ -69,17 +72,6 @@

      Navigation

      - - - - - - - - - - - @@ -101,8 +93,8 @@

      Syntaxweb archive).

      The List

      An example attribute list might look like this:

      -
      {: #someid .someclass somekey='some value' }
      -
      +
      {: #someid .someclass somekey='some value' }
      +

      A word which starts with a hash (#) will set the id of an element.

      A word which starts with a dot (.) will be added to the list of classes @@ -110,26 +102,26 @@

      The List
      {: #id1 .class1 id=id2 class="class2 class3" .class4 }
      -
      +
      {: #id1 .class1 id=id2 class="class2 class3" .class4 }
      +

      The above example would result in the following attributes being defined:

      -
      id="id2" class="class2 class3 class4"
      -
      +
      id="id2" class="class2 class3 class4"
      +

      HTML includes support for some attributes to be a single term, like checked, for example. Therefore, the attribute list {: checked } would result in checked if the output format is html or checked="checked" if the output format is xhtml.

      Curly braces can be backslash escaped to avoid being identified as an attribute list.

      -
      \{ not an attribute list }
      -
      +
      \{ not an attribute list }
      +

      Opening and closing curly braces which are empty or only contain whitespace are ignored whether they are escaped or not. Additionally, any attribute lists which are not located in the specific locations documented below are ignored.

      The colon after the opening brace is optional, but is supported to maintain consistency with other implementations. Therefore, the following is also a valid attribute list:

      -
      { #someid .someclass somekey='some value' }
      -
      +
      { #someid .someclass somekey='some value' }
      +

      In addition, the spaces after the opening brace and before the closing brace are optional. They are recommended as they improve readability, but they are not required.

      @@ -140,25 +132,25 @@

      The ListBlock Level

      To define attributes for a block level element, the attribute list should be defined on the last line of the block by itself.

      -
      This is a paragraph.
      +
      This is a paragraph.
       {: #an_id .a_class }
      -
      +

      The above results in the following output:

      -
      <p id="an_id" class="a_class">This is a paragraph.</p>
      -
      +
      <p id="an_id" class="a_class">This is a paragraph.</p>
      +

      An exception is headers, as they are only ever allowed on one line.

      -
      A setext style header {: #setext}
      +
      A setext style header {: #setext}
       =================================
       
       ### A hash style header ### {: #hash }
      -
      +

      The above results in the following output:

      -
      <h1 id="setext">A setext style header</h1>
      -<h3 id="hash">A hash style header</h3>
      -
      +
      <h1 id="setext">A setext style header</h1>
      +<h3 id="hash">A hash style header</h3>
      +

      See Also

      @@ -168,38 +160,38 @@

      Block LevelInline

      To define attributes on inline elements, the attribute list should be defined immediately after the inline element with no white space.

      -
      [link](http://example.com){: class="foo bar" title="Some title!" }
      -
      +
      [link](http://example.com){: class="foo bar" title="Some title!" }
      +

      The above results in the following output:

      -
      <p><a href="http://example.com" class="foo bar" title="Some title!">link</a></p>
      -
      +
      <p><a href="http://example.com" class="foo bar" title="Some title!">link</a></p>
      +

      If the tables extension is enabled, attribute lists can be defined on table cells. To differentiate attributes for an inline element from attributes for the containing cell, the attribute list must be separated from the content by at least one space and be defined at the end of the cell content. As table cells can only ever be on a single line, the attribute list must remain on the same line as the content of the cell.

      -
      | set on td    | set on em   |
      +
      | set on td    | set on em   |
       |--------------|-------------|
       | *a* { .foo } | *b*{ .foo } |
      -
      +

      The above example results in the following output:

      -
      <table>
      -  <thead>
      -    <tr>
      -      <th>set on td</th>
      -      <th>set on em</th>
      -    </tr>
      -  </thead>
      -  <tbody>
      -    <tr>
      -      <td class="foo"><em>a</em></td>
      -      <td><em class="foo">b</em></td>
      -    </tr>
      -  </tbody>
      -</table>
      -
      +
      <table>
      +  <thead>
      +    <tr>
      +      <th>set on td</th>
      +      <th>set on em</th>
      +    </tr>
      +  </thead>
      +  <tbody>
      +    <tr>
      +      <td class="foo"><em>a</em></td>
      +      <td><em class="foo">b</em></td>
      +    </tr>
      +  </tbody>
      +</table>
      +

      Note that in the first column, the attribute list is preceded by a space; therefore, it is assigned to the table cell (<td> element). However, in the second column, the attribute list is not preceded by a space; therefore, it is @@ -237,8 +229,8 @@

      Usage& name of the extension.

      This extension does not accept any special configuration options.

      A trivial example:

      -
      markdown.markdown(some_text, extensions=['attr_list'])
      -
      +
      markdown.markdown(some_text, extensions=['attr_list'])
      +

      @@ -303,14 +295,6 @@

      This Page

    • Edit on GitHub
    - - @@ -321,7 +305,7 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/extensions/code_hilite/index.html b/extensions/code_hilite/index.html old mode 100755 new mode 100644 index f65ad85..750073e --- a/extensions/code_hilite/index.html +++ b/extensions/code_hilite/index.html @@ -11,9 +11,12 @@ - CodeHilite — Python-Markdown 3.4.4 documentation + CodeHilite — Python-Markdown 3.5 documentation + + + @@ -23,7 +26,7 @@

    Navigation

    A trivial example:

    -
    markdown.markdown(some_text, extensions=['codehilite'])
    -
    +
    markdown.markdown(some_text, extensions=['codehilite'])
    +

    To keep the code block’s language in the Pygments generated HTML output, one can provide a custom Pygments formatter that takes the lang_str option. For example,

    -
    from pygments.formatters import HtmlFormatter
    -from markdown.extensions.codehilite import CodeHiliteExtension
    +
    from pygments.formatters import HtmlFormatter
    +from markdown.extensions.codehilite import CodeHiliteExtension
     
     
    -class CustomHtmlFormatter(HtmlFormatter):
    -    def __init__(self, lang_str='', **options):
    -        super().__init__(**options)
    -        # lang_str has the value {lang_prefix}{lang}
    -        # specified by the CodeHilite's options
    -        self.lang_str = lang_str
    +class CustomHtmlFormatter(HtmlFormatter):
    +    def __init__(self, lang_str='', **options):
    +        super().__init__(**options)
    +        # lang_str has the value {lang_prefix}{lang}
    +        # specified by the CodeHilite's options
    +        self.lang_str = lang_str
     
    -    def _wrap_code(self, source):
    -        yield 0, f'<code class="{self.lang_str}">'
    -        yield from source
    -        yield 0, '</code>'
    +    def _wrap_code(self, source):
    +        yield 0, f'<code class="{self.lang_str}">'
    +        yield from source
    +        yield 0, '</code>'
     
     
    -some_text = '''\
    -    :::python
    -    print('hellow world')
    -'''
    +some_text = '''\
    +    :::python
    +    print('hellow world')
    +'''
     
    -markdown.markdown(
    -    some_text,
    -    extensions=[CodeHiliteExtension(pygments_formatter=CustomHtmlFormatter)],
    -)
    -
    +markdown.markdown( + some_text, + extensions=[CodeHiliteExtension(pygments_formatter=CustomHtmlFormatter)], +) +

    The formatter above will output the following HTML structure for a code block:

    -
    <div class="codehilite">
    -    <pre>
    -        <code class="language-python">
    +
    <div class="codehilite">
    +    <pre>
    +        <code class="language-python">
             ...
    -        </code>
    -    </pre>
    -</div>
    -
    + </code> + </pre> +</div> + @@ -422,14 +413,6 @@

    This Page

  • Edit on GitHub
  • - - @@ -440,7 +423,7 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/extensions/definition_lists/index.html b/extensions/definition_lists/index.html old mode 100755 new mode 100644 index 800c864..0935d21 --- a/extensions/definition_lists/index.html +++ b/extensions/definition_lists/index.html @@ -11,9 +11,12 @@ - Definition Lists — Python-Markdown 3.4.4 documentation + Definition Lists — Python-Markdown 3.5 documentation + + + @@ -23,7 +26,7 @@

    Navigation

    • - +
    • index @@ -37,7 +40,7 @@

      Navigation

    • icon
    • @@ -69,17 +72,6 @@

      Navigation

      - - - - - - - - - - - @@ -101,32 +93,32 @@

      SyntaxPHP Markdown Extra.

      Thus, the following text (taken from the above referenced PHP documentation):

      -
      Apple
      +
      Apple
       :   Pomaceous fruit of plants of the genus Malus in
           the family Rosaceae.
       
       Orange
       :   The fruit of an evergreen tree of the genus Citrus.
      -
      +

      will be rendered as:

      -
      <dl>
      -<dt>Apple</dt>
      -<dd>Pomaceous fruit of plants of the genus Malus in
      -the family Rosaceae.</dd>
      +
      <dl>
      +<dt>Apple</dt>
      +<dd>Pomaceous fruit of plants of the genus Malus in
      +the family Rosaceae.</dd>
       
      -<dt>Orange</dt>
      -<dd>The fruit of an evergreen tree of the genus Citrus.</dd>
      -</dl>
      -
      +<dt>Orange</dt> +<dd>The fruit of an evergreen tree of the genus Citrus.</dd> +</dl> +

      Usage

      See Extensions for general extension usage. Use def_list as the name of the extension.

      This extension does not accept any special configuration options.

      A trivial example:

      -
      markdown.markdown(some_text, extensions=['def_list'])
      -
      +
      markdown.markdown(some_text, extensions=['def_list'])
      +
      @@ -173,14 +165,6 @@

      This Page

    • Edit on GitHub
    - - @@ -191,7 +175,7 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/extensions/extra/index.html b/extensions/extra/index.html old mode 100755 new mode 100644 index 3d4ad9d..5030343 --- a/extensions/extra/index.html +++ b/extensions/extra/index.html @@ -11,9 +11,12 @@ - Extra — Python-Markdown 3.4.4 documentation + Extra — Python-Markdown 3.5 documentation + + + @@ -23,7 +26,7 @@

    Navigation

    • - +
    • index @@ -37,7 +40,7 @@

      Navigation

    • icon
    • @@ -69,17 +72,6 @@

      Navigation

      - - - - - - - - - - - @@ -110,29 +102,29 @@

      SummaryUsage

      From the Python interpreter:

      -
      >>> import markdown
      ->>> html = markdown.markdown(text, extensions=['extra'])
      -
      +
      >>> import markdown
      +>>> html = markdown.markdown(text, extensions=['extra'])
      +

      To pass configuration options to the extensions included with Extra, they must be passed to Extra, with the underlying extension identified as well. In that way Extra will have access to the options and can pass them on to the appropriate underlying extension.

      -
      config = {
      -    'extra': {
      -        'footnotes': {
      -            'UNIQUE_IDS': True
      -        },
      -        'fenced_code': {
      -            'lang_prefix': 'lang-'
      -        }
      -    },
      -    'toc': {
      -        'permalink': True
      -    }
      -}
      +
      config = {
      +    'extra': {
      +        'footnotes': {
      +            'UNIQUE_IDS': True
      +        },
      +        'fenced_code': {
      +            'lang_prefix': 'lang-'
      +        }
      +    },
      +    'toc': {
      +        'permalink': True
      +    }
      +}
       
      -html = markdown.markdown(text, extensions=['extra', 'toc'], extension_configs=config)
      -
      +html = markdown.markdown(text, extensions=['extra', 'toc'], extension_configs=config) +

      Note that in the above example, footnotes and fenced_code are both nested under the extra key as those extensions are included with Extra. However, the toc extension is not included with extra and therefore its @@ -183,14 +175,6 @@

      This Page

    • Edit on GitHub
    - - @@ -201,7 +185,7 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/extensions/fenced_code_blocks/index.html b/extensions/fenced_code_blocks/index.html old mode 100755 new mode 100644 index f636a1c..9672338 --- a/extensions/fenced_code_blocks/index.html +++ b/extensions/fenced_code_blocks/index.html @@ -11,9 +11,12 @@ - Fenced Code Blocks — Python-Markdown 3.4.4 documentation + Fenced Code Blocks — Python-Markdown 3.5 documentation + + + @@ -23,7 +26,7 @@

    Navigation

    A trivial example:

    -
    markdown.markdown(some_text, extensions=['fenced_code'])
    -
    +
    markdown.markdown(some_text, extensions=['fenced_code'])
    +
    @@ -363,14 +355,6 @@

    This Page

  • Edit on GitHub
  • - - @@ -381,7 +365,7 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/extensions/footnotes/index.html b/extensions/footnotes/index.html old mode 100755 new mode 100644 index 1b4eaa4..7ac4bb3 --- a/extensions/footnotes/index.html +++ b/extensions/footnotes/index.html @@ -11,9 +11,12 @@ - Footnotes — Python-Markdown 3.4.4 documentation + Footnotes — Python-Markdown 3.5 documentation + + + @@ -23,7 +26,7 @@

    Navigation

    A trivial example:

    -
    markdown.markdown(some_text, extensions=['footnotes'])
    -
    +
    markdown.markdown(some_text, extensions=['footnotes'])
    +

    Resetting Instance State

    Footnote definitions are stored within the markdown.Markdown class instance between @@ -193,11 +185,11 @@

    Resetting Instance State

    An example of calling reset:

    -
    md = markdown.Markdown(extensions=['footnotes'])
    -html1 = md.convert(text_with_footnote)
    -md.reset()
    -html2 = md.convert(text_without_footnote)
    -
    +
    md = markdown.Markdown(extensions=['footnotes'])
    +html1 = md.convert(text_with_footnote)
    +md.reset()
    +html2 = md.convert(text_without_footnote)
    +
    @@ -248,14 +240,6 @@

    This Page

  • Edit on GitHub
  • - - @@ -266,7 +250,7 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/extensions/index.html b/extensions/index.html old mode 100755 new mode 100644 index b39dcfc..a9ca629 --- a/extensions/index.html +++ b/extensions/index.html @@ -11,9 +11,12 @@ - Extensions — Python-Markdown 3.4.4 documentation + Extensions — Python-Markdown 3.5 documentation + + + @@ -23,7 +26,7 @@

    Navigation

    @@ -76,13 +68,13 @@

    Navigation

    to change and/or extend the behavior of the parser without having to edit the actual source files.

    To use an extension, pass it to markdown with the extensions keyword.

    -
    markdown.markdown(some_text, extensions=[MyExtClass(), 'myext', 'path.to.my.ext:MyExtClass'])
    -
    +
    markdown.markdown(some_text, extensions=[MyExtClass(), 'myext', 'path.to.my.ext:MyExtClass'])
    +

    See the Library Reference for more details.

    From the command line, specify an extension with the -x option.

    -
    python -m markdown -x myext -x path.to.module:MyExtClass input.txt > output.html
    -
    +
    python -m markdown -x myext -x path.to.module:MyExtClass input.txt > output.html
    +

    See the Command Line docs or use the --help option for more details.

    @@ -245,14 +237,6 @@

    This Page

  • Edit on GitHub
  • - - @@ -263,7 +247,7 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/extensions/legacy_attrs/index.html b/extensions/legacy_attrs/index.html old mode 100755 new mode 100644 index 89591b5..c90115d --- a/extensions/legacy_attrs/index.html +++ b/extensions/legacy_attrs/index.html @@ -11,9 +11,12 @@ - Legacy Attributes — Python-Markdown 3.4.4 documentation + Legacy Attributes — Python-Markdown 3.5 documentation + + + @@ -23,7 +26,7 @@

    Navigation

    • - +
    • index @@ -37,7 +40,7 @@

      Navigation

    • icon
    • @@ -69,17 +72,6 @@

      Navigation

      - - - - - - - - - - - @@ -103,38 +95,38 @@

      SummarySyntax

      Attributes are defined by including the following within the element you wish to assign the attributes to:

      -
      {@key=value}
      -
      +
      {@key=value}
      +

      For example, to define a class to a paragraph:

      -
      A paragraph with the attribute defined {@class=foo}anywhere within.
      -
      +
      A paragraph with the attribute defined {@class=foo}anywhere within.
      +

      Which results in the following output:

      -
      <p class="foo">A paragraph with the attribute defined anywhere within.</p>
      -
      +
      <p class="foo">A paragraph with the attribute defined anywhere within.</p>
      +

      The same applies for inline elements:

      -
      Some *emphasized{@id=bar}* text.
      -
      +
      Some *emphasized{@id=bar}* text.
      +
      -
      <p>Some <em id="bar">emphasized</em> text.</p>
      -
      +
      <p>Some <em id="bar">emphasized</em> text.</p>
      +

      You can also define attributes in images:

      -
      ![Alt text{@id=baz}](path/to/image.jpg)
      -
      +
      ![Alt text{@id=baz}](path/to/image.jpg)
      +
      -
      <p><img alt="Alt text" id="baz" src="path/to/image.jpg" /></p>
      -
      +
      <p><img alt="Alt text" id="baz" src="path/to/image.jpg" /></p>
      +

      Usage

      See Extensions for general extension usage. Use legacy_attrs as the name of the extension.

      This extension does not accept any special configuration options.

      A trivial example:

      -
      markdown.markdown(some_text, extensions=['legacy_attrs'])
      -
      +
      markdown.markdown(some_text, extensions=['legacy_attrs'])
      +
      @@ -181,14 +173,6 @@

      This Page

    • Edit on GitHub
    - - @@ -199,7 +183,7 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/extensions/legacy_em/index.html b/extensions/legacy_em/index.html old mode 100755 new mode 100644 index 7d54de8..3ba8cbb --- a/extensions/legacy_em/index.html +++ b/extensions/legacy_em/index.html @@ -11,9 +11,12 @@ - Legacy Emphasis — Python-Markdown 3.4.4 documentation + Legacy Emphasis — Python-Markdown 3.5 documentation + + + @@ -23,7 +26,7 @@

    Navigation

    - - @@ -171,7 +155,7 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/extensions/md_in_html/index.html b/extensions/md_in_html/index.html old mode 100755 new mode 100644 index 5f02b05..793b93c --- a/extensions/md_in_html/index.html +++ b/extensions/md_in_html/index.html @@ -11,9 +11,12 @@ - Markdown in HTML — Python-Markdown 3.4.4 documentation + Markdown in HTML — Python-Markdown 3.5 documentation + + + @@ -23,7 +26,7 @@

    Navigation

    @@ -114,30 +106,30 @@

    markdown="1" { iframe, main, map, menu, nav, noscript, object, ol, output, progress, section, table, tbody, tfoot, thead, tr, ul and video.

    For example, the following:

    -
    <div markdown="1">
    +
    <div markdown="1">
     This is a *Markdown* Paragraph.
    -</div>
    -
    +</div> +

    … is rendered as:

    -
    <div>
    -<p>This is a <em>Markdown</em> Paragraph.</p>
    -</div>
    -
    +
    <div>
    +<p>This is a <em>Markdown</em> Paragraph.</p>
    +</div>
    +

    The following tags have the span behavior by default: address, dd, dt, h[1-6], legend, li, p, td, and th.

    For example, the following:

    -
    <p markdown="1">
    +
    <p markdown="1">
     This is not a *Markdown* Paragraph.
    -</p>
    -
    +</p> +

    … is rendered as:

    -
    <p>
    -This is not a <em>Markdown</em> Paragraph.
    -</p>
    -
    +
    <p>
    +This is not a <em>Markdown</em> Paragraph.
    +</p>
    +

    markdown="block"

    When the markdown attribute is set to "block", then the parser will force the block behavior on the contents of @@ -145,7 +137,7 @@

    markdown="block"The content of a block element is parsed into block-level content. In other words, the text is rendered as paragraphs, headers, lists, blockquotes, etc. Any inline syntax within those elements is processed as well.

    For example, the following:

    -
    +</section> +

    … is rendered as:

    -
    <section>
    -<h1>A header.</h1>
    -<p>A <em>Markdown</em> paragraph.</p>
    -<ul>
    -<li>A list item.</li>
    -<li>A second list item.</li>
    -</ul>
    -</section>
    -
    +
    <section>
    +<h1>A header.</h1>
    +<p>A <em>Markdown</em> paragraph.</p>
    +<ul>
    +<li>A list item.</li>
    +<li>A second list item.</li>
    +</ul>
    +</section>
    +
    +</article> +

    … is rendered as:

    -
    <article id="my-article">
    -<h1>Article Title</h1>
    -<p>A Markdown paragraph.</p>
    -<section id="section-1">
    -<h2>Section 1 Title</h2>
    -<p>Custom raw **HTML** which gets ignored.</p>
    -</section>
    -<section id="section-2">
    -<h2>Section 2 Title</h2>
    -<p><strong>Markdown</strong> content.</p>
    -</section>
    -</article>
    -
    +
    <article id="my-article">
    +<h1>Article Title</h1>
    +<p>A Markdown paragraph.</p>
    +<section id="section-1">
    +<h2>Section 1 Title</h2>
    +<p>Custom raw **HTML** which gets ignored.</p>
    +</section>
    +<section id="section-2">
    +<h2>Section 2 Title</h2>
    +<p><strong>Markdown</strong> content.</p>
    +</section>
    +</article>
    +

    When the value of an element’s markdown attribute is more permissive that its parent, then the parent’s stricter behavior is enforced. For example, a block element nested within a span element will be parsed using the span @@ -244,20 +236,20 @@

    NestingTag Normalization

    While the default behavior is for Markdown to not alter raw HTML, as this extension is parsing the content of raw HTML elements, it will do some normalization of the tags of block-level elements. For example, the following raw HTML:

    -
    <div markdown="1">
    -<p markdown="1">A Markdown paragraph with *no* closing tag.
    -<p>A raw paragraph with *no* closing tag.
    -</div>
    -
    +
    <div markdown="1">
    +<p markdown="1">A Markdown paragraph with *no* closing tag.
    +<p>A raw paragraph with *no* closing tag.
    +</div>
    +

    … is rendered as:

    -
    <div>
    -<p>A Markdown paragraph with <em>no</em> closing tag.
    -</p>
    -<p>A raw paragraph with *no* closing tag.
    -</p>
    -</div>
    -
    +
    <div>
    +<p>A Markdown paragraph with <em>no</em> closing tag.
    +</p>
    +<p>A raw paragraph with *no* closing tag.
    +</p>
    +</div>
    +

    Notice that the parser properly recognizes that an unclosed <p> tag ends when another <p> tag begins or when the parent element ends. In both cases, a closing </p> was added to the end of the element, regardless of whether a @@ -273,9 +265,9 @@

    Tag NormalizationUsage

    From the Python interpreter:

    -
    >>> import markdown
    ->>> html = markdown.markdown(text, extensions=['md_in_html'])
    -
    +
    >>> import markdown
    +>>> html = markdown.markdown(text, extensions=['md_in_html'])
    +
    @@ -348,14 +340,6 @@

    This Page

  • Edit on GitHub
  • - - @@ -366,7 +350,7 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/extensions/meta_data/index.html b/extensions/meta_data/index.html old mode 100755 new mode 100644 index 6138c64..ab5d705 --- a/extensions/meta_data/index.html +++ b/extensions/meta_data/index.html @@ -11,9 +11,12 @@ - Meta-Data — Python-Markdown 3.4.4 documentation + Meta-Data — Python-Markdown 3.5 documentation + + + @@ -23,7 +26,7 @@

    Navigation

    • - +
    • index @@ -37,7 +40,7 @@

      Navigation

    • icon
    • @@ -71,17 +74,6 @@

      Navigation

      - - - - - - - - - - - @@ -103,7 +95,7 @@

      SummarySyntax

      Meta-data consists of a series of keywords and values defined at the beginning of a markdown document like this:

      -
      Title:   My Document
      +
      Title:   My Document
       Summary: A brief description of my document.
       Authors: Waylan Limberg
                John Doe
      @@ -112,7 +104,7 @@ 

      SyntaxUsage&

      See Extensions for general extension usage. Use meta as the name of the extension.

      A trivial example:

      -
      markdown.markdown(some_text, extensions=['meta'])
      -
      +
      markdown.markdown(some_text, extensions=['meta'])
      +

      Accessing the Meta-Data

      The meta-data is made available as a python Dict in the Meta attribute of an instance of the Markdown class. For example, using the above document:

      -
      >>> md = markdown.Markdown(extensions = ['meta'])
      ->>> html = md.convert(text)
      ->>> # Meta-data has been stripped from output
      ->>> print html
      -<p>This is the first paragraph of the document.</p>
      +
      >>> md = markdown.Markdown(extensions = ['meta'])
      +>>> html = md.convert(text)
      +>>> # Meta-data has been stripped from output
      +>>> print html
      +<p>This is the first paragraph of the document.</p>
       
      ->>> # View meta-data
      ->>> print md.Meta
      -{
      -'title' : ['My Document'],
      -'summary' : ['A brief description of my document.'],
      -'authors' : ['Waylan Limberg', 'John Doe'],
      -'date' : ['October 2, 2007'],
      -'blank-value' : [''],
      -'base_url' : ['http://example.com']
      -}
      -
      +>>> # View meta-data +>>> print md.Meta +{ +'title' : ['My Document'], +'summary' : ['A brief description of my document.'], +'authors' : ['Waylan Limberg', 'John Doe'], +'date' : ['October 2, 2007'], +'blank-value' : [''], +'base_url' : ['http://example.com'] +} +

      Note that the keys are all lowercase and the values consist of a list of strings where each item is one line for that key. This way, one could preserve @@ -230,14 +222,6 @@

      This Page

    • Edit on GitHub
    - - @@ -248,7 +232,7 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/extensions/nl2br/index.html b/extensions/nl2br/index.html old mode 100755 new mode 100644 index fc8c37e..33b3dd3 --- a/extensions/nl2br/index.html +++ b/extensions/nl2br/index.html @@ -11,9 +11,12 @@ - New Line to Break — Python-Markdown 3.4.4 documentation + New Line to Break — Python-Markdown 3.5 documentation + + + @@ -23,7 +26,7 @@

    Navigation

    • - +
    • index @@ -37,7 +40,7 @@

      Navigation

    • icon
    • @@ -72,17 +75,6 @@

      Navigation

      - - - - - - - - - - - @@ -97,24 +89,24 @@

      SummaryGitHub flavored Markdown do.

      Example

      -
      >>> import markdown
      ->>> text = """
      -... Line 1
      -... Line 2
      -... """
      ->>> html = markdown.markdown(text, extensions=['nl2br'])
      ->>> print html
      -<p>Line 1<br />
      -Line 2</p>
      -
      +
      >>> import markdown
      +>>> text = """
      +... Line 1
      +... Line 2
      +... """
      +>>> html = markdown.markdown(text, extensions=['nl2br'])
      +>>> print html
      +<p>Line 1<br />
      +Line 2</p>
      +

      Usage

      See Extensions for general extension usage. Use nl2br as the name of the extension.

      This extension does not accept any special configuration options.

      A trivial example:

      -
      markdown.markdown(some_text, extensions=['nl2br'])
      -
      +
      markdown.markdown(some_text, extensions=['nl2br'])
      +
      @@ -161,14 +153,6 @@

      This Page

    • Edit on GitHub
    - - @@ -179,7 +163,7 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/extensions/sane_lists/index.html b/extensions/sane_lists/index.html old mode 100755 new mode 100644 index 44539b7..e928068 --- a/extensions/sane_lists/index.html +++ b/extensions/sane_lists/index.html @@ -11,9 +11,12 @@ - Sane Lists — Python-Markdown 3.4.4 documentation + Sane Lists — Python-Markdown 3.5 documentation + + + @@ -23,7 +26,7 @@

    Navigation

    @@ -101,62 +93,62 @@

    Syntax
    1. Ordered item 1
    -2. Ordered item 2
    +
    1. Ordered item 1
    +2. Ordered item 2
     
    -* Unordered item 1
    -* Unordered item 2
    -
    +* Unordered item 1 +* Unordered item 2 +

    will result in the following output:

    -
    <ol>
    -  <li>Ordered item 1</li>
    -  <li>Ordered item 2</li>
    -</ol>
    +
    <ol>
    +  <li>Ordered item 1</li>
    +  <li>Ordered item 2</li>
    +</ol>
     
    -<ul>
    -  <li>Unordered item 1</li>
    -  <li>Unordered item 2</li>
    -</ul>
    -
    +<ul> + <li>Unordered item 1</li> + <li>Unordered item 2</li> +</ul> +

    Whereas the default Markdown behavior would be to generate an unordered list.

    Note that, unlike the default Markdown behavior, if a blank line is not included between list items, the different list type is ignored completely. This corresponds to the behavior of paragraphs. For example:

    -
    A Paragraph.
    -* Not a list item.
    +
    A Paragraph.
    +* Not a list item.
     
    -1. Ordered list item.
    -* Not a separate list item.
    -
    +1. Ordered list item. +* Not a separate list item. +

    With this extension the above will result in the following output:

    -
    <p>A Paragraph.
    -* Not a list item.</p>
    +
    <p>A Paragraph.
    +* Not a list item.</p>
     
    -<ol>
    -  <li>Ordered list item.
    -  * Not a separate list item.</li>
    -</ol>
    -
    +<ol> + <li>Ordered list item. + * Not a separate list item.</li> +</ol> +

    Sane lists also recognize the number used in ordered lists. Given the following list:

    -
    4. Apples
    -5. Oranges
    -6. Pears
    -
    +
    4. Apples
    +5. Oranges
    +6. Pears
    +

    By default markdown will ignore the fact that the first line started with item number “4” and the HTML list will start with a number “1”. This extension will result in the following HTML output:

    -
    <ol start="4">
    -  <li>Apples</li>
    -  <li>Oranges</li>
    -  <li>Pears</li>
    -</ol>
    -
    +
    <ol start="4">
    +  <li>Apples</li>
    +  <li>Oranges</li>
    +  <li>Pears</li>
    +</ol>
    +

    In all other ways, Sane Lists should behave as normal Markdown lists.

    Usage

    @@ -164,8 +156,8 @@

    Usage& name of the extension.

    This extension does not accept any special configuration options.

    A trivial example:

    -
    markdown.markdown(some_text, extensions=['sane_lists'])
    -
    +
    markdown.markdown(some_text, extensions=['sane_lists'])
    +
    @@ -212,14 +204,6 @@

    This Page

  • Edit on GitHub
  • - - @@ -230,7 +214,7 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/extensions/smarty/index.html b/extensions/smarty/index.html old mode 100755 new mode 100644 index cb85358..64218c6 --- a/extensions/smarty/index.html +++ b/extensions/smarty/index.html @@ -11,9 +11,12 @@ - SmartyPants — Python-Markdown 3.4.4 documentation + SmartyPants — Python-Markdown 3.5 documentation + + + @@ -23,7 +26,7 @@

    Navigation

    @@ -149,17 +141,17 @@

    Summary
    extension_configs = {
    -    'smarty': {
    -        'substitutions': {
    -            'left-single-quote': '&sbquo;', # sb is not a typo!
    -            'right-single-quote': '&lsquo;',
    -            'left-double-quote': '&bdquo;',
    -            'right-double-quote': '&ldquo;'
    -        }
    -    }
    -}
    -
    +
    extension_configs = {
    +    'smarty': {
    +        'substitutions': {
    +            'left-single-quote': '&sbquo;', # sb is not a typo!
    +            'right-single-quote': '&lsquo;',
    +            'left-double-quote': '&bdquo;',
    +            'right-double-quote': '&ldquo;'
    +        }
    +    }
    +}
    +
    - - @@ -284,7 +268,7 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/extensions/tables/index.html b/extensions/tables/index.html old mode 100755 new mode 100644 index 85b2965..79e5b3b --- a/extensions/tables/index.html +++ b/extensions/tables/index.html @@ -11,9 +11,12 @@ - Tables — Python-Markdown 3.4.4 documentation + Tables — Python-Markdown 3.5 documentation + + + @@ -23,7 +26,7 @@

    Navigation

    @@ -99,32 +91,32 @@

    SummarySyntax

    Tables are defined using the syntax established in PHP Markdown Extra.

    Thus, the following text (taken from the above referenced PHP documentation):

    -
    First Header  | Second Header
    +
    First Header  | Second Header
     ------------- | -------------
     Content Cell  | Content Cell
     Content Cell  | Content Cell
    -
    +

    will be rendered as:

    -
    <table>
    -  <thead>
    -    <tr>
    -      <th>First Header</th>
    -      <th>Second Header</th>
    -    </tr>
    -  </thead>
    -  <tbody>
    -    <tr>
    -      <td>Content Cell</td>
    -      <td>Content Cell</td>
    -    </tr>
    -    <tr>
    -      <td>Content Cell</td>
    -      <td>Content Cell</td>
    -    </tr>
    -  </tbody>
    -</table>
    -
    +
    <table>
    +  <thead>
    +    <tr>
    +      <th>First Header</th>
    +      <th>Second Header</th>
    +    </tr>
    +  </thead>
    +  <tbody>
    +    <tr>
    +      <td>Content Cell</td>
    +      <td>Content Cell</td>
    +    </tr>
    +    <tr>
    +      <td>Content Cell</td>
    +      <td>Content Cell</td>
    +    </tr>
    +  </tbody>
    +</table>
    +

    See Also

    @@ -143,17 +135,17 @@

    Usage&

    A trivial example:

    -
    markdown.markdown(some_text, extensions=['tables'])
    -
    +
    markdown.markdown(some_text, extensions=['tables'])
    +

    Examples

    For an example, let us suppose that alignment should be controlled by the legacy align attribute.

    -
    >>> from markdown.extensions.tables import TableExtension
    ->>> html = markdown.markdown(text,
    -...                 extensions=[TableExtension(use_align_attribute=True)]
    -... )
    -
    +
    >>> from markdown.extensions.tables import TableExtension
    +>>> html = markdown.markdown(text,
    +...                 extensions=[TableExtension(use_align_attribute=True)]
    +... )
    +

    @@ -206,14 +198,6 @@

    This Page

  • Edit on GitHub
  • - - @@ -224,7 +208,7 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/extensions/toc/index.html b/extensions/toc/index.html old mode 100755 new mode 100644 index 9001eea..1791f7e --- a/extensions/toc/index.html +++ b/extensions/toc/index.html @@ -11,9 +11,12 @@ - Table of Contents — Python-Markdown 3.4.4 documentation + Table of Contents — Python-Markdown 3.5 documentation + + + @@ -23,7 +26,7 @@

    Navigation

    @@ -101,63 +93,63 @@

    Syntax
    #Header
    -#Header
    -#Header
    -
    +
    #Header
    +#Header
    +#Header
    +

    Results in:

    -
    <h1 id="header">Header</h1>
    -<h1 id="header_1">Header</h1>
    -<h1 id="header_2">Header</h1>
    -
    +
    <h1 id="header">Header</h1>
    +<h1 id="header_1">Header</h1>
    +<h1 id="header_2">Header</h1>
    +

    Place a marker in the document where you would like the Table of Contents to appear. Then, a nested list of all the headers in the document will replace the marker. The marker defaults to [TOC] so the following document:

    -
    [TOC]
    +
    [TOC]
     
    -# Header 1
    +# Header 1
     
    -## Header 2
    -
    +## Header 2 +

    would generate the following output:

    -
    <div class="toc">
    -  <ul>
    -    <li><a href="#header-1">Header 1</a></li>
    -      <ul>
    -        <li><a href="#header-2">Header 2</a></li>
    -      </ul>
    -  </ul>
    -</div>
    -<h1 id="header-1">Header 1</h1>
    -<h2 id="header-2">Header 2</h2>
    -
    +
    <div class="toc">
    +  <ul>
    +    <li><a href="#header-1">Header 1</a></li>
    +      <ul>
    +        <li><a href="#header-2">Header 2</a></li>
    +      </ul>
    +  </ul>
    +</div>
    +<h1 id="header-1">Header 1</h1>
    +<h2 id="header-2">Header 2</h2>
    +

    Regardless of whether a marker is found in the document (or disabled), the Table of Contents is available as an attribute (toc) on the Markdown class. This allows one to insert the Table of Contents elsewhere in their page template. For example:

    -
    >>> md = markdown.Markdown(extensions=['toc'])
    ->>> html = md.convert(text)
    ->>> page = render_some_template(context={'body': html, 'toc': md.toc})
    -
    +
    >>> md = markdown.Markdown(extensions=['toc'])
    +>>> html = md.convert(text)
    +>>> page = render_some_template(context={'body': html, 'toc': md.toc})
    +

    The toc_tokens attribute is also available on the Markdown class and contains a nested list of dict objects. For example, the above document would result in the following object at md.toc_tokens:

    -
    [
    -    {
    -        'level': 1,
    -        'id': 'header-1',
    -        'name': 'Header 1',
    -        'children': [
    -            {'level': 2, 'id': 'header-2', 'name': 'Header 2', 'children':[]}
    -        ]
    -    }
    -]
    -
    +
    [
    +    {
    +        'level': 1,
    +        'id': 'header-1',
    +        'name': 'Header 1',
    +        'children': [
    +            {'level': 2, 'id': 'header-2', 'name': 'Header 2', 'children':[]}
    +        ]
    +    }
    +]
    +

    Note that the level refers to the hn level. In other words, <h1> is level 1 and <h2> is level 2, etc. Be aware that improperly nested levels in the @@ -169,25 +161,25 @@

    Custom Labelsdata-toc-label attribute is defined on the header, then the contents of that attribute will be used as the text label for the item in the Table of Contents. For example, the following Markdown:

    -
    [TOC]
    +
    [TOC]
     
    -# Functions
    +# Functions
     
    -## `markdown.markdown(text [, **kwargs])` { #markdown data-toc-label='markdown.markdown' }
    -
    +## `markdown.markdown(text [, **kwargs])` { #markdown data-toc-label='markdown.markdown' } +

    would generate the following output:

    -
    <div class="toc">
    -  <ul>
    -    <li><a href="#functions">Functions</a></li>
    -      <ul>
    -        <li><a href="#markdown">markdown.markdown</a></li>
    -      </ul>
    -  </ul>
    -</div>
    -<h1 id="functions">Functions</h1>
    -<h2 id="markdown"><code>markdown.markdown(text [, **kwargs])</code></h2>
    -
    +
    <div class="toc">
    +  <ul>
    +    <li><a href="#functions">Functions</a></li>
    +      <ul>
    +        <li><a href="#markdown">markdown.markdown</a></li>
    +      </ul>
    +  </ul>
    +</div>
    +<h1 id="functions">Functions</h1>
    +<h2 id="markdown"><code>markdown.markdown(text [, **kwargs])</code></h2>
    +

    Notice that the text in the Table of Contents is much cleaner and easier to read in the context of a Table of Contents. The data-toc-label is not included in @@ -213,6 +205,10 @@

    Usage& Title to insert in the Table of Contents’ <div>. Defaults to None.

  • +

    title_class: + CSS class used for the title contained in the Table of Contents. Defaults to toctitle.

    +
  • +
  • toc_class: CSS class(es) used for the <div> containing the Table of Contents. Defaults to toc.

  • @@ -241,21 +237,30 @@

    Usage& Title attribute of the permanent link. Defaults to Permanent link.

  • +

    permalink_leading: + Set to True if the extension should generate leading permanent links. + Default is False.

    +

    Leading permanent links are placed at the start of the header tag, +before any header content. The default permalink behavior (when +permalink_leading is unset or set to False) creates trailing +permanent links, which are placed at the end of the header content.

    +
  • +
  • baselevel: Base level for headers. Defaults to 1.

    The baselevel setting allows the header levels to be automatically adjusted to fit within the hierarchy of your HTML templates. For example, suppose the Markdown text for a page should not contain any headers higher than level 3 (<h3>). The following will accomplish that:

    -
    >>>  text = '''
    -... #Some Header
    -... ## Next Level'''
    ->>> from markdown.extensions.toc import TocExtension
    ->>> html = markdown.markdown(text, extensions=[TocExtension(baselevel=3)])
    ->>> print html
    -<h3 id="some_header">Some Header</h3>
    -<h4 id="next_level">Next Level</h4>'
    -
    +
    >>>  text = '''
    +... #Some Header
    +... ## Next Level'''
    +>>> from markdown.extensions.toc import TocExtension
    +>>> html = markdown.markdown(text, extensions=[TocExtension(baselevel=3)])
    +>>> print html
    +<h3 id="some_header">Some Header</h3>
    +<h4 id="next_level">Next Level</h4>'
    +
  • @@ -292,8 +297,8 @@

    Usage&

  • A trivial example:

    -
    markdown.markdown(some_text, extensions=['toc'])
    -
    +
    markdown.markdown(some_text, extensions=['toc'])
    +
    @@ -346,14 +351,6 @@

    This Page

  • Edit on GitHub
  • - - @@ -364,7 +361,7 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/extensions/wikilinks/index.html b/extensions/wikilinks/index.html old mode 100755 new mode 100644 index 2f0af53..0c0420b --- a/extensions/wikilinks/index.html +++ b/extensions/wikilinks/index.html @@ -11,9 +11,12 @@ - WikiLinks — Python-Markdown 3.4.4 documentation + WikiLinks — Python-Markdown 3.5 documentation + + + @@ -23,7 +26,7 @@

    Navigation

    @@ -100,12 +92,12 @@

    SummarySyntax

    A [[bracketed]] word is any combination of upper or lower case letters, number, dashes, underscores and spaces surrounded by double brackets. Therefore

    -
    [[Bracketed]]
    -
    +
    [[Bracketed]]
    +

    would produce the following HTML:

    -
    <a href="/Bracketed/" class="wikilink">Bracketed</a>
    -
    +
    <a href="/Bracketed/" class="wikilink">Bracketed</a>
    +

    Note that WikiLinks are automatically assigned class="wikilink" making it easy to style WikiLinks differently from other links on a page if one so @@ -113,12 +105,12 @@

    Syntax
    [[Wiki Link]]
    -
    +
    [[Wiki Link]]
    +

    becomes

    -
    <a href="/Wiki_Link/" class="wikilink">Wiki Link</a>
    -
    +
    <a href="/Wiki_Link/" class="wikilink">Wiki Link</a>
    +

    Usage

    See Extensions for general extension usage. Use wikilinks as the @@ -147,43 +139,43 @@

    Usage&

    A trivial example:

    -
    markdown.markdown(some_text, extensions=['wikilinks'])
    -
    +
    markdown.markdown(some_text, extensions=['wikilinks'])
    +

    Examples

    For an example, let us suppose links should always point to the sub-directory /wiki/ and end with .html

    -
    >>> from markdown.extensions.wikilinks import WikiLinkExtension
    ->>> html = markdown.markdown(text,
    -...     extensions=[WikiLinkExtension(base_url='/wiki/', end_url='.html')]
    -... )
    -
    +
    >>> from markdown.extensions.wikilinks import WikiLinkExtension
    +>>> html = markdown.markdown(text,
    +...     extensions=[WikiLinkExtension(base_url='/wiki/', end_url='.html')]
    +... )
    +

    The above would result in the following link for [[WikiLink]].

    -
    <a href="/wiki/WikiLink.html" class="wikilink">WikiLink</a>
    -
    +
    <a href="/wiki/WikiLink.html" class="wikilink">WikiLink</a>
    +

    If you want to do more that just alter the base and/or end of the URL, you could also pass in a callable which must accept three arguments (label, base, and end). The callable must return the URL in it’s entirety.

    -
    >>> def my_url_builder(label, base, end):
    -...    # do stuff
    -...    return url
    -...
    ->>> html = markdown.markdown(text,
    -...     extensions=[WikiLinkExtension(build_url=my_url_builder)],
    -... )
    -
    +
    >>> def my_url_builder(label, base, end):
    +...    # do stuff
    +...    return url
    +...
    +>>> html = markdown.markdown(text,
    +...     extensions=[WikiLinkExtension(build_url=my_url_builder)],
    +... )
    +

    The option is also provided to change or remove the class attribute.

    -
    >>> html = markdown.markdown(text,
    -...     extensions=[WikiLinkExtension(html_class='myclass')]
    -... )
    -
    +
    >>> html = markdown.markdown(text,
    +...     extensions=[WikiLinkExtension(html_class='myclass')]
    +... )
    +

    Would cause all WikiLinks to be assigned to the class myclass.

    -
    <a href="/WikiLink/" class="myclass">WikiLink</a>
    -
    +
    <a href="/WikiLink/" class="myclass">WikiLink</a>
    +

    Using with Meta-Data extension

    The WikiLink extension also supports the Meta-Data extension. @@ -197,16 +189,16 @@

    Using with Meta-Data extension
  • Edit on GitHub
  • - - @@ -281,7 +265,7 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/favicon.ico b/favicon.ico old mode 100755 new mode 100644 diff --git a/index.html b/index.html old mode 100755 new mode 100644 index 4de274c..817a00e --- a/index.html +++ b/index.html @@ -11,9 +11,12 @@ - Python-Markdown — Python-Markdown 3.4.4 documentation + Python-Markdown — Python-Markdown 3.5 documentation + + + @@ -23,7 +26,7 @@

    Navigation

    @@ -197,14 +200,6 @@

    This Page

  • Edit on GitHub
  • - - @@ -215,7 +210,7 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/install/index.html b/install/index.html old mode 100755 new mode 100644 index 3d6643b..da96d58 --- a/install/index.html +++ b/install/index.html @@ -11,9 +11,12 @@ - Installation — Python-Markdown 3.4.4 documentation + Installation — Python-Markdown 3.5 documentation + + + @@ -23,7 +26,7 @@

    Navigation

    @@ -75,8 +67,8 @@

    Navigation

    The Easy Way

    The easiest way to install Python-Markdown is simply to type the following command from the command line:

    -
    pip install markdown
    -
    +
    pip install markdown
    +

    That’s it! You’re ready to use Python-Markdown. Enjoy!

    For more detailed instructions on installing Python packages, see the @@ -87,8 +79,8 @@

    Using the Git Repository
    pip install git+https://github.com/Python-Markdown/markdown.git
    -
    +
    pip install git+https://github.com/Python-Markdown/markdown.git
    +
    @@ -131,14 +123,6 @@

    This Page

  • Edit on GitHub
  • - - @@ -149,7 +133,7 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/mkdocstrings.css b/mkdocstrings.css new file mode 100644 index 0000000..efc62f4 --- /dev/null +++ b/mkdocstrings.css @@ -0,0 +1,105 @@ +/* Indentation. */ +div.doc-contents:not(.first) { + padding-left: 25px; +} + +/* Mark external links as such. */ +a.external::after, +a.autorefs-external::after { + /* https://primer.style/octicons/arrow-up-right-24 */ + mask-image: url('data:image/svg+xml,'); + -webkit-mask-image: url('data:image/svg+xml,'); + content: ' '; + + display: inline-block; + vertical-align: middle; + position: relative; + + height: 1em; + width: 1em; + background-color: #005b81; +} + +a.external:hover::after, +a.autorefs-external:hover::after { + background-color: #e32e00; +} + +/* Customize custom links. */ +a.autorefs code { + background-color: #ecf0f3; + font-weight: normal; + color: #005B81; +} + +a.autorefs:hover code { + color: #E32E00; +} + +/* Customize labels. */ +.doc-label { + border-radius: 15px; + padding: 2px 8px; + background-color: #f2f2f3; + text-wrap: nowrap; +} + +.doc-label code { + color: #444; +} + +.doc-label-deprecated { + background-color: #ffe4e4; + border: 1px solid #f66; +} + +/* No shadows in any code. */ + +code { + text-shadow: none; +} + +/* Code spans in tables. */ + +table code { + background-color: transparent !important; +} + +/* Style source links */ +a.doc-source-link { + position: relative; + float: right; + border: 1px #005B81 solid; + margin: 0 5px; + padding: 0 5px; + font-weight: normal; + text-shadow: none; + background-color: #f2f2f3; + font-size: 1rem; +} + +a.doc-source-link:hover { + text-decoration: none; + border-color: #E32E00; +} + +/* Customize symbol names. */ +code.doc-symbol-attribute::after { + content: "Attr"; +} + +code.doc-symbol-function::after { + content: "Func"; +} + +code.doc-symbol-method::after { + content: "Method"; +} + +code.doc-symbol-class::after { + content: "Class"; +} + +code.doc-symbol-module::after { + content: "Module"; +} diff --git a/objects.inv b/objects.inv new file mode 100644 index 0000000..a20537d Binary files /dev/null and b/objects.inv differ diff --git a/py.png b/py.png old mode 100755 new mode 100644 diff --git a/reference/SUMMARY/index.html b/reference/SUMMARY/index.html new file mode 100644 index 0000000..f992c6b --- /dev/null +++ b/reference/SUMMARY/index.html @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + SUMMARY — Python-Markdown 3.5 documentation + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/reference/index.html b/reference/index.html old mode 100755 new mode 100644 index 21e6a27..12f415c --- a/reference/index.html +++ b/reference/index.html @@ -11,9 +11,12 @@ - Library Reference — Python-Markdown 3.4.4 documentation + Library Reference — Python-Markdown 3.5 documentation + + + @@ -23,7 +26,7 @@

    Navigation

    @@ -76,9 +68,9 @@

    Navigation

    used by various projects to convert Markdown syntax into HTML.

    The Basics

    To use markdown as a module:

    -
    import markdown
    -html = markdown.markdown(your_text_string)
    -
    +
    import markdown
    +html = markdown.markdown(your_text_string)
    +

    The Details

    Python-Markdown provides two public functions (markdown.markdown @@ -100,15 +92,15 @@

    markdown.markdown(text [, **kwargs])Python-Markdown expects a Unicode string as input (some simple ASCII binary strings may work only by coincidence) and returns output as a Unicode string. Do not pass binary strings to it! If your input is encoded, (e.g. as UTF-8), it is your responsibility to decode it. For example:

    -
    with open("some_file.txt", "r", encoding="utf-8") as input_file:
    -    text = input_file.read()
    -html = markdown.markdown(text)
    -
    +
    with open("some_file.txt", "r", encoding="utf-8") as input_file:
    +    text = input_file.read()
    +html = markdown.markdown(text)
    +

    If you want to write the output to disk, you must encode it yourself:

    -
    with open("some_file.html", "w", encoding="utf-8", errors="xmlcharrefreplace") as output_file:
    -    output_file.write(html)
    -
    +
    with open("some_file.html", "w", encoding="utf-8", errors="xmlcharrefreplace") as output_file:
    +    output_file.write(html)
    +

    @@ -122,8 +114,8 @@

    markdown.markdown(text [, **kwargs])

    The list of extensions may contain instances of extensions and/or strings of extension names.

    -
    extensions=[MyExtClass(), 'myext', 'path.to.my.ext:MyExtClass']
    -
    +
    extensions=[MyExtClass(), 'myext', 'path.to.my.ext:MyExtClass']
    +

    Note

    @@ -135,12 +127,12 @@

    markdown.markdown(text [, **kwargs])markdown.extensions.Extension and any configuration options should be defined when initiating the class instance rather than using the extension_configs keyword. For example:

    -
    from markdown.extensions import Extension
    -class MyExtClass(Extension):
    -    # define your extension here...
    +
    from markdown.extensions import Extension
    +class MyExtClass(Extension):
    +    # define your extension here...
     
    -markdown.markdown(text, extensions=[MyExtClass(option='value')])
    -
    +markdown.markdown(text, extensions=[MyExtClass(option='value')]) +

    If an extension name is provided as a string, the string must either be the registered entry point of any installed extension or the importable path @@ -150,8 +142,8 @@

    markdown.markdown(text [, **kwargs])myext assigned to it and the extension is properly installed, then do the following:

    -
    markdown.markdown(text, extensions=['myext'])
    -
    +
    markdown.markdown(text, extensions=['myext'])
    +

    If an extension does not have a registered entry point, Python’s dot notation may be used instead. The extension must be installed as a @@ -159,12 +151,12 @@

    markdown.markdown(text [, **kwargs])

    Therefore, if you were to import the class like this:

    -
    from path.to.module import MyExtClass
    -
    +
    from path.to.module import MyExtClass
    +

    Then load the extension as follows:

    -
    markdown.markdown(text, extensions=['path.to.module:MyExtClass'])
    -
    +
    markdown.markdown(text, extensions=['path.to.module:MyExtClass'])
    +

    If only one extension is defined within a module and the module includes a makeExtension function which returns an instance of the extension, then @@ -193,16 +185,16 @@

    markdown.markdown(text [, **kwargs])extensions keyword for details.

    The dictionary of configuration settings must be in the following format:

    -
    extension_configs = {
    -    'extension_name_1': {
    -        'option_1': 'value_1',
    -        'option_2': 'value_2'
    -    },
    -    'extension_name_2': {
    -        'option_1': 'value_1'
    -    }
    -}
    -
    +
    extension_configs = {
    +    'extension_name_1': {
    +        'option_1': 'value_1',
    +        'option_2': 'value_2'
    +    },
    +    'extension_name_2': {
    +        'option_1': 'value_1'
    +    }
    +}
    +

    When specifying the extension name, be sure to use the exact same string as is used in the extensions keyword to load the @@ -284,21 +276,21 @@

    Markdown.convert(source)markdown.markdown function.

    You should also use this method if you want to process multiple strings without creating a new instance of the class for each string.

    -
    md = markdown.Markdown()
    -html1 = md.convert(text1)
    -html2 = md.convert(text2)
    -
    +
    md = markdown.Markdown()
    +html1 = md.convert(text1)
    +html2 = md.convert(text2)
    +

    Depending on which options and/or extensions are being used, the parser may need its state reset between each call to convert.

    -
    html1 = md.convert(text1)
    -md.reset()
    -html2 = md.convert(text2)
    -
    +
    html1 = md.convert(text1)
    +md.reset()
    +html2 = md.convert(text2)
    +

    To make this easier, you can also chain calls to reset together:

    -
    html3 = md.reset().convert(text3)
    -
    +
    html3 = md.reset().convert(text3)
    +

    Markdown.convertFile(**kwargs)

    The arguments of this method are identical to the arguments of the same @@ -374,14 +366,6 @@

    This Page

  • Edit on GitHub
  • - - @@ -392,7 +376,7 @@

    Quick search

    Navigation

    - \ No newline at end of file diff --git a/reference/markdown/blockparser/index.html b/reference/markdown/blockparser/index.html new file mode 100644 index 0000000..8eee0f7 --- /dev/null +++ b/reference/markdown/blockparser/index.html @@ -0,0 +1,635 @@ + + + + + + + + + + + + + + blockparser — Python-Markdown 3.5 documentation + + + + + + + + + + + + +
    +
    +
    +
    + + + + +

    + markdown.blockparser + + +

    + +
    + +

    The block 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 +as they need to alter how Markdown blocks are parsed.

    + + + +
    + + + + + + + + + + + + + + + +
    + + + + +

    + markdown.blockparser.State + + +

    + + +
    +

    + Bases: list

    + + +

    Track the current and nested state of the parser.

    +

    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 +the list.

    +

    Therefore, each time a state is set for a nested block, that state must be +reset when we back out of that level of nesting or the state could be +corrupted.

    +

    While all the methods of a list object are available, only the three +defined below need be used.

    + + + + +
    + + + + + + + + +
    + + + + +

    + markdown.blockparser.State.set(state: Any) + +

    + + +
    + +

    Set a new state.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockparser.State.reset() + +

    + + +
    + +

    Step back one step in nested state.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockparser.State.isstate(state: Any) -> bool + +

    + + +
    + +

    Test that top (current) level is of given state.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.blockparser.BlockParser(md: Markdown) + +

    + + +
    + + +

    Parse Markdown blocks into an ElementTree object.

    +

    A wrapper class that stitches the various BlockProcessors together, +looping through them and creating an ElementTree object.

    + + + + +

    Parameters:

    +
      +
    • + md + (Markdown) + – +
      +

      A Markdown instance.

      +
      +
    • +
    + + + +

    Attributes:

    +
      +
    • + BlockParser.md + (Markdown) + – +
      +

      A Markdown instance.

      +
      +
    • +
    • + BlockParser.state + (State) + – +
      +

      Tracks the nesting level of current location in document being parsed.

      +
      +
    • +
    • + BlockParser.blockprocessors + (Registry) + – +
      +

      A collection of +blockprocessors.

      +
      +
    • +
    + + + + +
    + + + + + + + + +
    + + + + +

    + markdown.blockparser.BlockParser.parseDocument(lines: Sequence[str]) -> etree.ElementTree + +

    + + +
    + +

    Parse a Markdown document into an ElementTree.

    +

    Given a list of lines, an ElementTree object (not just a parent +Element) is created and the root element is passed to the parser +as the parent. The ElementTree object is returned.

    +

    This should only be called on an entire document, not pieces.

    + + + +

    Parameters:

    +
      +
    • + lines + (Sequence[str]) + – +
      +

      A list of lines (strings).

      +
      +
    • +
    + + + +

    Returns:

    +
      +
    • + ElementTree + – +
      +

      An element tree.

      +
      +
    • +
    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockparser.BlockParser.parseChunk(parent: etree.Element, text: str) + +

    + + +
    + +

    Parse a chunk of Markdown text and attach to given etree node.

    +

    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. +Nothing is returned.

    + + + +

    Parameters:

    +
      +
    • + parent + (Element) + – +
      +

      The parent element.

      +
      +
    • +
    • + text + (str) + – +
      +

      The text to parse.

      +
      +
    • +
    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockparser.BlockParser.parseBlocks(parent: etree.Element, blocks: Sequence[str]) + +

    + + +
    + +

    Process blocks of Markdown text and attach to given etree node.

    +

    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 +parse a nested block.

    + + + +

    Parameters:

    +
      +
    • + parent + (Element) + – +
      +

      The parent element.

      +
      +
    • +
    • + blocks + (Sequence[str]) + – +
      +

      The blocks of text to parse.

      +
      +
    • +
    + +
    + +
    + + + + +
    + +
    + +
    + + + + +
    + +
    + +
    + +
    +
    +
    + + +
    +
    + + + + + + + \ No newline at end of file diff --git a/reference/markdown/blockprocessors/index.html b/reference/markdown/blockprocessors/index.html new file mode 100644 index 0000000..4c3a7f8 --- /dev/null +++ b/reference/markdown/blockprocessors/index.html @@ -0,0 +1,2521 @@ + + + + + + + + + + + + + + blockprocessors — Python-Markdown 3.5 documentation + + + + + + + + + + + + +
    +
    +
    +
    + + + + +

    + markdown.blockprocessors + + +

    + +
    + +

    A block processor parses blocks of text and adds new elements to the ElementTree. Blocks of text, +separated from other text by blank lines, may have a different syntax and produce a differently +structured tree than other Markdown. Block processors excel at handling code formatting, equation +layouts, tables, etc.

    + + + +
    + + + + + + + + + + + + + + + + + + + + +
    + + + + +

    + markdown.blockprocessors.build_block_parser(md: Markdown, **kwargs: Any) -> BlockParser + +

    + + +
    + +

    Build the default block parser used by Markdown.

    +

    Return a BlockParser instance which contains the following collection of classes with their assigned names and priorities.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Class InstanceNamePriority
    EmptyBlockProcessorempty100
    ListIndentProcessorindent90
    CodeBlockProcessorcode80
    HashHeaderProcessorhashheader70
    SetextHeaderProcessorsetextheader60
    HRProcessorhr50
    OListProcessorolist40
    UListProcessorulist30
    BlockQuoteProcessorquote20
    ReferenceProcessorreference15
    ParagraphProcessorparagraph10
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.blockprocessors.BlockProcessor(parser: BlockParser) + +

    + + +
    + + +

    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 +whether the current block should be processed by this processor. If the +test passes, the parser will call the processors run method.

    + + + +

    Attributes:

    +
      +
    • + BlockProcessor.parser + (BlockParser) + – +
      +

      The BlockParser instance this is attached to.

      +
      +
    • +
    • + BlockProcessor.tab_length + (int) + – +
      +

      The tab length set on the Markdown instance.

      +
      +
    • +
    + + + + +
    + + + + + + + + +
    + + + + +

    + markdown.blockprocessors.BlockProcessor.lastChild(parent: etree.Element) -> etree.Element | None + +

    + + +
    + +

    Return the last child of an etree element.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockprocessors.BlockProcessor.detab(text: str, length: int = None) -> str + +

    + + +
    + +

    Remove a tab from the front of each line of the given text.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockprocessors.BlockProcessor.looseDetab(text: str, level: int = 1) -> str + +

    + + +
    + +

    Remove a tab from front of lines but allowing dedented lines.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockprocessors.BlockProcessor.test(parent: etree.Element, block: list[str]) -> bool + +

    + + +
    + +

    Test for block type. Must be overridden by subclasses.

    +

    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 +actual method of testing is left to the needs of that particular +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.

    + + + +

    Other Parameters:

    +
      +
    • + parent + (Element) + – +
      +

      An etree element which will be the parent of the block.

      +
      +
    • +
    • + block + (list[str]) + – +
      +

      A block of text from the source which has been split at blank lines.

      +
      +
    • +
    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockprocessors.BlockProcessor.run(parent: etree.Element, blocks: list[str]) -> bool | None + +

    + + +
    + +

    Run processor. Must be overridden by subclasses.

    +

    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.

    +

    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 +to the parent, and should remove (pop) or add (insert) items to +the list of blocks.

    +

    If False is returned, this will have the same effect as returning False +from the test method.

    + + + +

    Other Parameters:

    +
      +
    • + parent + (Element) + – +
      +

      An etree element which is the parent of the current block.

      +
      +
    • +
    • + blocks + (list[str]) + – +
      +

      A list of all remaining blocks of the document.

      +
      +
    • +
    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.blockprocessors.ListIndentProcessor(*args) + +

    + + +
    +

    + Bases: BlockProcessor

    + + +

    Process children of list items.

    +

    Example

    +
    * a list item
    +    process this part
    +
    +    or this part
    +
    + + + + +
    + + + + + + + + +
    + + + + +

    + markdown.blockprocessors.ListIndentProcessor.lastChild(parent: etree.Element) -> etree.Element | None + +

    + + +
    + +

    Return the last child of an etree element.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockprocessors.ListIndentProcessor.detab(text: str, length: int = None) -> str + +

    + + +
    + +

    Remove a tab from the front of each line of the given text.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockprocessors.ListIndentProcessor.looseDetab(text: str, level: int = 1) -> str + +

    + + +
    + +

    Remove a tab from front of lines but allowing dedented lines.

    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.blockprocessors.ListIndentProcessor.ITEM_TYPES = ['li'] + + + class-attribute + instance-attribute + + +

    + + +
    + +

    List of tags used for list items.

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.blockprocessors.ListIndentProcessor.LIST_TYPES = ['ul', 'ol'] + + + class-attribute + instance-attribute + + +

    + + +
    + +

    Types of lists this processor can operate on.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockprocessors.ListIndentProcessor.create_item(parent: etree.Element, block: str) + +

    + + +
    + +

    Create a new li and parse the block with it as the parent.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockprocessors.ListIndentProcessor.get_level(parent: etree.Element, block: str) -> tuple[int, etree.Element] + +

    + + +
    + +

    Get level of indentation based on list level.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.blockprocessors.CodeBlockProcessor(parser: BlockParser) + +

    + + +
    +

    + Bases: BlockProcessor

    + + +

    Process code blocks.

    + + + + +
    + + + + + + + + +
    + + + + +

    + markdown.blockprocessors.CodeBlockProcessor.lastChild(parent: etree.Element) -> etree.Element | None + +

    + + +
    + +

    Return the last child of an etree element.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockprocessors.CodeBlockProcessor.detab(text: str, length: int = None) -> str + +

    + + +
    + +

    Remove a tab from the front of each line of the given text.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockprocessors.CodeBlockProcessor.looseDetab(text: str, level: int = 1) -> str + +

    + + +
    + +

    Remove a tab from front of lines but allowing dedented lines.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.blockprocessors.BlockQuoteProcessor(parser: BlockParser) + +

    + + +
    +

    + Bases: BlockProcessor

    + + +

    Process blockquotes.

    + + + + +
    + + + + + + + + +
    + + + + +

    + markdown.blockprocessors.BlockQuoteProcessor.lastChild(parent: etree.Element) -> etree.Element | None + +

    + + +
    + +

    Return the last child of an etree element.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockprocessors.BlockQuoteProcessor.detab(text: str, length: int = None) -> str + +

    + + +
    + +

    Remove a tab from the front of each line of the given text.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockprocessors.BlockQuoteProcessor.looseDetab(text: str, level: int = 1) -> str + +

    + + +
    + +

    Remove a tab from front of lines but allowing dedented lines.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockprocessors.BlockQuoteProcessor.clean(line: str) -> str + +

    + + +
    + +

    Remove > from beginning of a line.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.blockprocessors.OListProcessor(parser) + +

    + + +
    +

    + Bases: BlockProcessor

    + + +

    Process ordered list blocks.

    + + + + +
    + + + + + + + + +
    + + + + +

    + markdown.blockprocessors.OListProcessor.lastChild(parent: etree.Element) -> etree.Element | None + +

    + + +
    + +

    Return the last child of an etree element.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockprocessors.OListProcessor.detab(text: str, length: int = None) -> str + +

    + + +
    + +

    Remove a tab from the front of each line of the given text.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockprocessors.OListProcessor.looseDetab(text: str, level: int = 1) -> str + +

    + + +
    + +

    Remove a tab from front of lines but allowing dedented lines.

    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.blockprocessors.OListProcessor.TAG: str = 'ol' + + + class-attribute + instance-attribute + + +

    + + +
    + +

    The tag used for the the wrapping element.

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.blockprocessors.OListProcessor.STARTSWITH: int = '1' + + + class-attribute + instance-attribute + + +

    + + +
    + +

    The integer (as a string ) with which the list starts. For example, if a list is initialized as +3. Item, then the ol tag will be assigned an HTML attribute of starts="3". Default: "1".

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.blockprocessors.OListProcessor.LAZY_OL: bool = True + + + class-attribute + instance-attribute + + +

    + + +
    + +

    Ignore STARTSWITH if True.

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.blockprocessors.OListProcessor.SIBLING_TAGS: list[str] = ['ol', 'ul'] + + + class-attribute + instance-attribute + + +

    + + +
    + +

    Markdown does not require the type of a new list item match the previous list item type. +This is the list of types which can be mixed.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockprocessors.OListProcessor.get_items(block: str) -> list[str] + +

    + + +
    + +

    Break a block into list items.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.blockprocessors.UListProcessor(parser) + +

    + + +
    +

    + Bases: OListProcessor

    + + +

    Process unordered list blocks.

    + + + + +
    + + + + + + + + +
    + + + + +

    + markdown.blockprocessors.UListProcessor.lastChild(parent: etree.Element) -> etree.Element | None + +

    + + +
    + +

    Return the last child of an etree element.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockprocessors.UListProcessor.detab(text: str, length: int = None) -> str + +

    + + +
    + +

    Remove a tab from the front of each line of the given text.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockprocessors.UListProcessor.looseDetab(text: str, level: int = 1) -> str + +

    + + +
    + +

    Remove a tab from front of lines but allowing dedented lines.

    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.blockprocessors.UListProcessor.STARTSWITH: int = '1' + + + class-attribute + instance-attribute + + +

    + + +
    + +

    The integer (as a string ) with which the list starts. For example, if a list is initialized as +3. Item, then the ol tag will be assigned an HTML attribute of starts="3". Default: "1".

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.blockprocessors.UListProcessor.LAZY_OL: bool = True + + + class-attribute + instance-attribute + + +

    + + +
    + +

    Ignore STARTSWITH if True.

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.blockprocessors.UListProcessor.SIBLING_TAGS: list[str] = ['ol', 'ul'] + + + class-attribute + instance-attribute + + +

    + + +
    + +

    Markdown does not require the type of a new list item match the previous list item type. +This is the list of types which can be mixed.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockprocessors.UListProcessor.get_items(block: str) -> list[str] + +

    + + +
    + +

    Break a block into list items.

    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.blockprocessors.UListProcessor.TAG: str = 'ul' + + + class-attribute + instance-attribute + + +

    + + +
    + +

    The tag used for the the wrapping element.

    +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.blockprocessors.HashHeaderProcessor(parser: BlockParser) + +

    + + +
    +

    + Bases: BlockProcessor

    + + +

    Process Hash Headers.

    + + + + +
    + + + + + + + + +
    + + + + +

    + markdown.blockprocessors.HashHeaderProcessor.lastChild(parent: etree.Element) -> etree.Element | None + +

    + + +
    + +

    Return the last child of an etree element.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockprocessors.HashHeaderProcessor.detab(text: str, length: int = None) -> str + +

    + + +
    + +

    Remove a tab from the front of each line of the given text.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockprocessors.HashHeaderProcessor.looseDetab(text: str, level: int = 1) -> str + +

    + + +
    + +

    Remove a tab from front of lines but allowing dedented lines.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.blockprocessors.SetextHeaderProcessor(parser: BlockParser) + +

    + + +
    +

    + Bases: BlockProcessor

    + + +

    Process Setext-style Headers.

    + + + + +
    + + + + + + + + +
    + + + + +

    + markdown.blockprocessors.SetextHeaderProcessor.lastChild(parent: etree.Element) -> etree.Element | None + +

    + + +
    + +

    Return the last child of an etree element.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockprocessors.SetextHeaderProcessor.detab(text: str, length: int = None) -> str + +

    + + +
    + +

    Remove a tab from the front of each line of the given text.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockprocessors.SetextHeaderProcessor.looseDetab(text: str, level: int = 1) -> str + +

    + + +
    + +

    Remove a tab from front of lines but allowing dedented lines.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.blockprocessors.HRProcessor(parser: BlockParser) + +

    + + +
    +

    + Bases: BlockProcessor

    + + +

    Process Horizontal Rules.

    + + + + +
    + + + + + + + + +
    + + + + +

    + markdown.blockprocessors.HRProcessor.lastChild(parent: etree.Element) -> etree.Element | None + +

    + + +
    + +

    Return the last child of an etree element.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockprocessors.HRProcessor.detab(text: str, length: int = None) -> str + +

    + + +
    + +

    Remove a tab from the front of each line of the given text.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockprocessors.HRProcessor.looseDetab(text: str, level: int = 1) -> str + +

    + + +
    + +

    Remove a tab from front of lines but allowing dedented lines.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.blockprocessors.EmptyBlockProcessor(parser: BlockParser) + +

    + + +
    +

    + Bases: BlockProcessor

    + + +

    Process blocks that are empty or start with an empty line.

    + + + + +
    + + + + + + + + +
    + + + + +

    + markdown.blockprocessors.EmptyBlockProcessor.lastChild(parent: etree.Element) -> etree.Element | None + +

    + + +
    + +

    Return the last child of an etree element.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockprocessors.EmptyBlockProcessor.detab(text: str, length: int = None) -> str + +

    + + +
    + +

    Remove a tab from the front of each line of the given text.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockprocessors.EmptyBlockProcessor.looseDetab(text: str, level: int = 1) -> str + +

    + + +
    + +

    Remove a tab from front of lines but allowing dedented lines.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.blockprocessors.ReferenceProcessor(parser: BlockParser) + +

    + + +
    +

    + Bases: BlockProcessor

    + + +

    Process link references.

    + + + + +
    + + + + + + + + +
    + + + + +

    + markdown.blockprocessors.ReferenceProcessor.lastChild(parent: etree.Element) -> etree.Element | None + +

    + + +
    + +

    Return the last child of an etree element.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockprocessors.ReferenceProcessor.detab(text: str, length: int = None) -> str + +

    + + +
    + +

    Remove a tab from the front of each line of the given text.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockprocessors.ReferenceProcessor.looseDetab(text: str, level: int = 1) -> str + +

    + + +
    + +

    Remove a tab from front of lines but allowing dedented lines.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.blockprocessors.ParagraphProcessor(parser: BlockParser) + +

    + + +
    +

    + Bases: BlockProcessor

    + + +

    Process Paragraph blocks.

    + + + + +
    + + + + + + + + +
    + + + + +

    + markdown.blockprocessors.ParagraphProcessor.lastChild(parent: etree.Element) -> etree.Element | None + +

    + + +
    + +

    Return the last child of an etree element.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockprocessors.ParagraphProcessor.detab(text: str, length: int = None) -> str + +

    + + +
    + +

    Remove a tab from the front of each line of the given text.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.blockprocessors.ParagraphProcessor.looseDetab(text: str, level: int = 1) -> str + +

    + + +
    + +

    Remove a tab from front of lines but allowing dedented lines.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + +
    + +
    + +
    + +
    +
    +
    + + +
    +
    + + + + + + + \ No newline at end of file diff --git a/reference/markdown/htmlparser/index.html b/reference/markdown/htmlparser/index.html new file mode 100644 index 0000000..6cc2bea --- /dev/null +++ b/reference/markdown/htmlparser/index.html @@ -0,0 +1,471 @@ + + + + + + + + + + + + + + htmlparser — Python-Markdown 3.5 documentation + + + + + + + + + + + + +
    +
    +
    +
    + + + + +

    + markdown.htmlparser + + +

    + +
    + +

    This module imports a copy of html.parser.HTMLParser and modifies it heavily through monkey-patches. +A copy is imported rather than the module being directly imported as this ensures that the user can import +and use the unmodified library for their own needs.

    + + + +
    + + + + + + + +
    + + + + +

    + markdown.htmlparser.HTMLExtractor(md, *args, **kwargs) + +

    + + +
    +

    + Bases: HTMLParser

    + + +

    Extract raw HTML from text.

    +

    The raw HTML is stored in the htmlStash of the +Markdown instance passed to md and the remaining text +is stored in cleandoc as a list of strings.

    + + + + +
    + + + + + + + + +
    + + + + +

    + markdown.htmlparser.HTMLExtractor.reset() + +

    + + +
    + +

    Reset this instance. Loses all unprocessed data.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.htmlparser.HTMLExtractor.close() + +

    + + +
    + +

    Handle any buffered data.

    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.htmlparser.HTMLExtractor.line_offset: int + + + property + + +

    + + +
    + +

    Returns char index in self.rawdata for the start of the current line.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.htmlparser.HTMLExtractor.at_line_start() -> bool + +

    + + +
    + +

    Returns True if current position is at start of line.

    +

    Allows for up to three blank spaces at start of line.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.htmlparser.HTMLExtractor.get_endtag_text(tag: str) -> str + +

    + + +
    + +

    Returns the text of the end tag.

    +

    If it fails to extract the actual text from the raw data, it builds a closing tag with tag.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.htmlparser.HTMLExtractor.handle_empty_tag(data: str, is_block: bool) + +

    + + +
    + +

    Handle empty tags (<data>).

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.htmlparser.HTMLExtractor.get_starttag_text() -> str + +

    + + +
    + +

    Return full source of start tag: <...>.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + +
    + +
    + +
    + +
    +
    +
    + + +
    +
    + + + + + + + \ No newline at end of file diff --git a/reference/markdown/index.html b/reference/markdown/index.html new file mode 100644 index 0000000..04ded56 --- /dev/null +++ b/reference/markdown/index.html @@ -0,0 +1,1254 @@ + + + + + + + + + + + + + + markdown — Python-Markdown 3.5 documentation + + + + + + + + + + + + +
    +
    +
    +
    + + + + +

    + markdown + + +

    + +
    + +

    Python-Markdown provides two public functions (markdown.markdown and markdown.markdownFromFile) +both of which wrap the public class markdown.Markdown. All submodules support these public functions +and class and/or provide extension support.

    + + + +

    Modules:

    +
      +
    • + core + – +
      +

      Core functionality.

      +
      +
    • +
    • + preprocessors + – +
      +

      Pre-processors.

      +
      +
    • +
    • + blockparser + – +
      +

      Core Markdown block parser.

      +
      +
    • +
    • + blockprocessors + – +
      +

      Block processors.

      +
      +
    • +
    • + treeprocessors + – +
      +

      Tree processors.

      +
      +
    • +
    • + inlinepatterns + – +
      +

      Inline patterns.

      +
      +
    • +
    • + postprocessors + – +
      +

      Post-processors.

      +
      +
    • +
    • + serializers + – +
      +

      Serializers.

      +
      +
    • +
    • + util + – +
      +

      Utility functions.

      +
      +
    • +
    • + htmlparser + – +
      +

      HTML parser.

      +
      +
    • +
    • + test_tools + – +
      +

      Testing utilities.

      +
      +
    • +
    • + extensions + – +
      +

      Markdown extensions.

      +
      +
    • +
    + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + +

    + markdown.Markdown(**kwargs) + +

    + + +
    + + +

    A parser which converts Markdown to HTML.

    + + + +

    Attributes:

    +
      +
    • + Markdown.tab_length + (int) + – +
      +

      The number of spaces which correspond to a single tab. Default: 4.

      +
      +
    • +
    • + Markdown.ESCAPED_CHARS + (list[str]) + – +
      +

      List of characters which get the backslash escape treatment.

      +
      +
    • +
    • + Markdown.block_level_elements + (list[str]) + – +
      +

      List of HTML tags which get treated as block-level elements. +See markdown.util.BLOCK_LEVEL_ELEMENTS for the full list of elements.

      +
      +
    • +
    • + Markdown.registeredExtensions + (list[Extension]) + – +
      +

      List of extensions which have called +registerExtension during setup.

      +
      +
    • +
    • + Markdown.doc_tag + (str) + – +
      +

      Element used to wrap document. Default: div.

      +
      +
    • +
    • + Markdown.stripTopLevelTags + (bool) + – +
      +

      Indicates whether the doc_tag should be removed. Default: ‘True’.

      +
      +
    • +
    • + Markdown.references + (dict[str, tuple[str, str]]) + – +
      +

      A mapping of link references found in a parsed document + where the key is the reference name and the value is a tuple of the URL and title.

      +
      +
    • +
    • + Markdown.htmlStash + (HtmlStash) + – +
      +

      The instance of the HtmlStash used by an instance of this class.

      +
      +
    • +
    • + Markdown.output_formats + (dict[str, Callable[Element]]) + – +
      +

      A mapping of known output + formats by name and their respective serializers. Each serializer must be a callable which accepts an +Element and returns a str.

      +
      +
    • +
    • + Markdown.output_format + (str) + – +
      +

      The output format set by +set_output_format.

      +
      +
    • +
    • + Markdown.serializer + (Callable[Element]) + – +
      +

      The serializer set by +set_output_format.

      +
      +
    • +
    • + Markdown.preprocessors + (Registry) + – +
      +

      A collection of preprocessors.

      +
      +
    • +
    • + Markdown.parser + (BlockParser) + – +
      +

      A collection of blockprocessors.

      +
      +
    • +
    • + Markdown.inlinePatterns + (Registry) + – +
      +

      A collection of inlinepatterns.

      +
      +
    • +
    • + Markdown.treeprocessors + (Registry) + – +
      +

      A collection of treeprocessors.

      +
      +
    • +
    • + Markdown.postprocessors + (Registry) + – +
      +

      A collection of postprocessors.

      +
      +
    • +
    + + + + +

    Other Parameters:

    +
      +
    • + extensions + (list[Extension | str]) + – +
      +

      A list of extensions.

      +

      If an item is an instance of a subclass of [markdown.extensions.Extension][markdown.extensions.Extension], +the instance will be used as-is. If an item is of type str, it is passed +to build_extension with its corresponding +extension_configs and the returned instance of [markdown.extensions.Extension][markdown.extensions.Extension] +is used.

      +
      +
    • +
    • + extension_configs + (dict[str, dict[str, Any]]) + – +
      +

      Configuration settings for extensions.

      +
      +
    • +
    • + output_format + (str) + – +
      +

      Format of output. Supported formats are:

      +
        +
      • xhtml: Outputs XHTML style tags. Default.
      • +
      • html: Outputs HTML style tags.
      • +
      +
      +
    • +
    • + tab_length + (int) + – +
      +

      Length of tabs in the source. Default: 4

      +
      +
    • +
    + + + + +
    + + + + + + + +
    + + + + +

    + markdown.Markdown.output_formats: dict[str, Callable[Element]] = {'html': to_html_string, 'xhtml': to_xhtml_string} + + + class-attribute + instance-attribute + + +

    + + +
    + +

    A mapping of known output formats by name and their respective serializers. Each serializer must be a +callable which accepts an Element and returns a str.

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.Markdown.ESCAPED_CHARS: list[str] = ['\\', '`', '*', '_', '{', '}', '[', ']', '(', ')', '>', '#', '+', '-', '.', '!'] + + + instance-attribute + + +

    + + +
    + +

    List of characters which get the backslash escape treatment.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.Markdown.build_parser() -> Markdown + +

    + + +
    + +

    Build the parser from the various parts.

    +

    Assigns a value to each of the following attributes on the class instance:

    + +

    This method could be redefined in a subclass to build a custom parser which is made up of a different +combination of processors and patterns.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.Markdown.registerExtensions(extensions: list[Extension | str], configs: dict[str, dict[str, Any]]) -> Markdown + +

    + + +
    + +

    Load a list of extensions into an instance of the Markdown class.

    + + + +

    Parameters:

    +
      +
    • + extensions + (list[Extension | str]) + – +
      +

      A list of extensions.

      +

      If an item is an instance of a subclass of [markdown.extensions.Extension][markdown.extensions.Extension], +the instance will be used as-is. If an item is of type str, it is passed +to build_extension with its corresponding configs and the +returned instance of [markdown.extensions.Extension][markdown.extensions.Extension] is used.

      +
      +
    • +
    • + configs + (dict[str, dict[str, Any]]) + – +
      +

      Configuration settings for extensions.

      +
      +
    • +
    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.Markdown.build_extension(ext_name: str, configs: dict[str, Any]) -> Extension + +

    + + +
    + +

    Build extension from a string name, then return an instance using the given configs.

    + + + +

    Parameters:

    +
      +
    • + ext_name + (str) + – +
      +

      Name of extension as a string.

      +
      +
    • +
    • + configs + (dict[str, Any]) + – +
      +

      Configuration settings for extension.

      +
      +
    • +
    + + + +

    Returns:

    +
      +
    • + Extension + – +
      +

      An instance of the extension with the given configuration settings.

      +
      +
    • +
    +

    First attempt to load an entry point. The string name must be registered as an entry point in the +markdown.extensions group which points to a subclass of the [markdown.extensions.Extension][markdown.extensions.Extension] class. +If multiple distributions have registered the same name, the first one found is returned.

    +

    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 [markdown.extensions.Extension][markdown.extensions.Extension] instance returned by that function.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.Markdown.registerExtension(extension: Extension) -> Markdown + +

    + + +
    + +

    Register an extension as having a resettable state.

    + + + +

    Parameters:

    +
      +
    • + extension + (Extension) + – +
      +

      An instance of the extension to register.

      +
      +
    • +
    +

    This should get called once by an extension during setup. A “registered” extension’s +reset method is called by Markdown.reset(). Not all extensions have or need a +resettable state, and so it should not be assumed that all extensions are “registered.”

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.Markdown.reset() -> Markdown + +

    + + +
    + +

    Resets all state variables to prepare the parser instance for new input.

    +

    Called once upon creation of a class instance. Should be called manually between calls +to Markdown.convert.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.Markdown.set_output_format(format: str) -> Markdown + +

    + + +
    + +

    Set the output format for the class instance.

    + + + +

    Parameters:

    +
      +
    • + format + (str) + – +
      +

      Must be a known value in Markdown.output_formats.

      +
      +
    • +
    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.Markdown.is_block_level(tag: Any) -> bool + +

    + + +
    + +

    Check if the given tag is a block level HTML tag.

    +

    Returns True for any string listed in Markdown.block_level_elements. A tag which is +not a string always returns False.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.Markdown.convert(source: str) -> str + +

    + + +
    + +

    Convert a Markdown string to a string in the specified output format.

    + + + +

    Parameters:

    +
      +
    • + source + (str) + – +
      +

      Markdown formatted text as Unicode or ASCII string.

      +
      +
    • +
    + + + +

    Returns:

    +
      +
    • + str + – +
      +

      A string in the specified output format.

      +
      +
    • +
    +

    Markdown parsing takes place in five steps:

    +
      +
    1. A bunch of preprocessors munge the input text.
    2. +
    3. A BlockParser parses the high-level structural elements of the + pre-processed text into an ElementTree object.
    4. +
    5. A bunch of treeprocessors are run against the + ElementTree object. One such treeprocessor + (markdown.treeprocessors.InlineProcessor) runs inlinepatterns + against the ElementTree object, parsing inline markup.
    6. +
    7. Some postprocessors are run against the text after the + ElementTree object has been serialized into text.
    8. +
    9. The output is returned as a string.
    10. +
    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.Markdown.convertFile(input: str | TextIO | None = None, output: str | TextIO | None = None, encoding: str | None = None) -> Markdown + +

    + + +
    + +

    Converts a Markdown file and returns the HTML as a Unicode string.

    +

    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 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.)

    + + + +

    Parameters:

    +
      +
    • + input + (str | TextIO | None, default: + None +) + – +
      +

      File object or path. Reads from stdin if None.

      +
      +
    • +
    • + output + (str | TextIO | None, default: + None +) + – +
      +

      File object or path. Writes to stdout if None.

      +
      +
    • +
    • + encoding + (str | None, default: + None +) + – +
      +

      Encoding of input and output files. Defaults to utf-8.

      +
      +
    • +
    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.markdown(text: str, **kwargs: Any) -> str + +

    + + +
    + +

    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 +necessary extensions and runs the parser on the given text.

    + + + +

    Parameters:

    +
      +
    • + text + (str) + – +
      +

      Markdown formatted text as Unicode or ASCII string.

      +
      +
    • +
    + + + +

    Other Parameters:

    +
      +
    • + **kwargs + (Any) + – +
      +

      Any arguments accepted by the Markdown class.

      +
      +
    • +
    + + + +

    Returns:

    +
      +
    • + str + – +
      +

      A string in the specified output format.

      +
      +
    • +
    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.markdownFromFile(**kwargs: Any) + +

    + + +
    + +

    Read Markdown text from a file and write output 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.

    + + + +

    Other Parameters:

    +
      +
    • + input + (str | TextIO) + – +
      +

      A file name or readable object.

      +
      +
    • +
    • + output + (str | TextIO) + – +
      +

      A file name or writable object.

      +
      +
    • +
    • + encoding + (str) + – +
      +

      Encoding of input and output.

      +
      +
    • +
    • + **kwargs + (Any) + – +
      +

      Any arguments accepted by the Markdown class.

      +
      +
    • +
    + +
    + +
    + + + + + + + + +
    + +
    + +
    + +
    +
    +
    + + +
    +
    + + + + + + + \ No newline at end of file diff --git a/reference/markdown/inlinepatterns/index.html b/reference/markdown/inlinepatterns/index.html new file mode 100644 index 0000000..1ea3983 --- /dev/null +++ b/reference/markdown/inlinepatterns/index.html @@ -0,0 +1,7447 @@ + + + + + + + + + + + + + + inlinepatterns — Python-Markdown 3.5 documentation + + + + + + + + + + + + +
    +
    +
    +
    + + + + +

    + markdown.inlinepatterns + + +

    + +
    + +

    In version 3.0, a new, more flexible inline processor was added, markdown.inlinepatterns.InlineProcessor. The +original inline patterns, which inherit from markdown.inlinepatterns.Pattern or one of its children are still +supported, though users are encouraged to migrate.

    +

    The new InlineProcessor provides two major enhancements to Patterns:

    +
      +
    1. +

      Inline Processors no longer need to match the entire block, so regular expressions no longer need to start with + r'^(.*?)' and end with r'(.*?)%'. This runs faster. The returned Match object will only contain + what is explicitly matched in the pattern, and extension pattern groups now start with m.group(1).

      +
    2. +
    3. +

      The handleMatch method now takes an additional input called data, which is the entire block under analysis, + not just what is matched with the specified pattern. The method now returns the element and the indexes relative + to data that the return element is replacing (usually m.start(0) and m.end(0)). If the boundaries are + returned as None, it is assumed that the match did not take place, and nothing will be altered in data.

      +

      This allows handling of more complex constructs than regular expressions can handle, e.g., matching nested +brackets, and explicit control of the span “consumed” by the processor.

      +
    4. +
    + + + +
    + + + + + + + + + + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.build_inlinepatterns(md: Markdown, **kwargs: Any) -> util.Registry + +

    + + +
    + +

    Build the default set of inline patterns for Markdown.

    +

    The order in which processors and/or patterns are applied is very important - e.g. if we first replace +http://.../ links with <a> tags and then try to replace inline HTML, we would end up with a mess. So, we +apply the expressions in the following order:

    +
      +
    • +

      backticks and escaped characters have to be handled before everything else so that we can preempt any markdown + patterns by escaping them;

      +
    • +
    • +

      then we handle the various types of links (auto-links must be handled before inline HTML);

      +
    • +
    • +

      then we handle inline HTML. At this point we will simply replace all inline HTML strings with a placeholder + and add the actual HTML to a stash;

      +
    • +
    • +

      finally we apply strong, emphasis, etc.

      +
    • +
    +

    Return a Registry instance which contains the following collection of classes with their assigned names and priorities.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Class InstanceNamePriority
    BacktickInlineProcessor(BACKTICK_RE)backtick190
    EscapeInlineProcessor(ESCAPE_RE)escape180
    ReferenceInlineProcessor(REFERENCE_RE)reference170
    LinkInlineProcessor(LINK_RE)link160
    ImageInlineProcessor(IMAGE_LINK_RE)image_link150
    ImageReferenceInlineProcessor(IMAGE_REFERENCE_RE)image_reference140
    ShortReferenceInlineProcessor(REFERENCE_RE)short_reference130
    ShortImageReferenceInlineProcessor(IMAGE_REFERENCE_RE)short_image_ref125
    AutolinkInlineProcessor(AUTOLINK_RE)autolink120
    AutomailInlineProcessor(AUTOMAIL_RE)automail110
    SubstituteTagInlineProcessor(LINE_BREAK_RE)linebreak100
    HtmlInlineProcessor(HTML_RE)html90
    HtmlInlineProcessor(ENTITY_RE)entity80
    SimpleTextInlineProcessor(NOT_STRONG_RE)not_strong70
    AsteriskProcessor("\*")em_strong60
    UnderscoreProcessor("_")em_strong250
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.NOIMG = '(?<!\\!)' + + + module-attribute + + +

    + + +
    + +

    Match not an image. Partial regular expression which matches if not preceded by !.

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.BACKTICK_RE = '(?:(?<!\\\\)((?:\\\\{2})+)(?=`+)|(?<!\\\\)(`+)(.+?)(?<!`)\\2(?!`))' + + + module-attribute + + +

    + + +
    + +

    Match backtick quoted string (`e=f()` or ``e=f("`")``).

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ESCAPE_RE = '\\\\(.)' + + + module-attribute + + +

    + + +
    + +

    Match a backslash escaped character (\< or \*).

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.EMPHASIS_RE = '(\\*)([^\\*]+)\\1' + + + module-attribute + + +

    + + +
    + +

    Match emphasis with an asterisk (*emphasis*).

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.STRONG_RE = '(\\*{2})(.+?)\\1' + + + module-attribute + + +

    + + +
    + +

    Match strong with an asterisk (**strong**).

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SMART_STRONG_RE = '(?<!\\w)(_{2})(?!_)(.+?)(?<!_)\\1(?!\\w)' + + + module-attribute + + +

    + + +
    + +

    Match strong with underscore while ignoring middle word underscores (__smart__strong__).

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SMART_EMPHASIS_RE = '(?<!\\w)(_)(?!_)(.+?)(?<!_)\\1(?!\\w)' + + + module-attribute + + +

    + + +
    + +

    Match emphasis with underscore while ignoring middle word underscores (_smart_emphasis_).

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SMART_STRONG_EM_RE = '(?<!\\w)(\\_)\\1(?!\\1)(.+?)(?<!\\w)\\1(?!\\1)(.+?)\\1{3}(?!\\w)' + + + module-attribute + + +

    + + +
    + +

    Match strong emphasis with underscores (__strong _em__).

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.EM_STRONG_RE = '(\\*)\\1{2}(.+?)\\1(.*?)\\1{2}' + + + module-attribute + + +

    + + +
    + +

    Match emphasis strong with asterisk (***strongem*** or ***em*strong**).

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.EM_STRONG2_RE = '(_)\\1{2}(.+?)\\1(.*?)\\1{2}' + + + module-attribute + + +

    + + +
    + +

    Match emphasis strong with underscores (___emstrong___ or ___em_strong__).

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.STRONG_EM_RE = '(\\*)\\1{2}(.+?)\\1{2}(.*?)\\1' + + + module-attribute + + +

    + + +
    + +

    Match strong emphasis with asterisk (***strong**em*).

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.STRONG_EM2_RE = '(_)\\1{2}(.+?)\\1{2}(.*?)\\1' + + + module-attribute + + +

    + + +
    + +

    Match strong emphasis with underscores (___strong__em_).

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.STRONG_EM3_RE = '(\\*)\\1(?!\\1)([^*]+?)\\1(?!\\1)(.+?)\\1{3}' + + + module-attribute + + +

    + + +
    + +

    Match strong emphasis with asterisk (**strong*em***).

    +
    + +
    + + + + + + +
    + + + + + + + +
    + +

    Match start of in-line link ([text](url) or [text](<url>) or [text](url "title")).

    +
    + +
    + + + + + + +
    + + + + + + + +
    + +

    Match start of in-line image link (![alttxt](url) or ![alttxt](<url>)).

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.REFERENCE_RE = LINK_RE + + + module-attribute + + +

    + + +
    + +

    Match start of reference link ([Label][3]).

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.IMAGE_REFERENCE_RE = IMAGE_LINK_RE + + + module-attribute + + +

    + + +
    + +

    Match start of image reference (![alt text][2]).

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.NOT_STRONG_RE = '((^|(?<=\\s))(\\*{1,3}|_{1,3})(?=\\s|$))' + + + module-attribute + + +

    + + +
    + +

    Match a stand-alone * or _.

    +
    + +
    + + + + + + +
    + + + + + + + +
    + +

    Match an automatic link (<http://www.example.com>).

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.AUTOMAIL_RE = '<([^<> !]+@[^@<> ]+)>' + + + module-attribute + + +

    + + +
    + +

    Match an automatic email link (<me@example.com>).

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.HTML_RE = '(<(\\/?[a-zA-Z][^<>@ ]*( [^<>]*)?|!--(?:(?!<!--|-->).)*--)>)' + + + module-attribute + + +

    + + +
    + +

    Match an HTML tag (<...>).

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ENTITY_RE = '(&(?:\\#[0-9]+|\\#x[0-9a-fA-F]+|[a-zA-Z0-9]+);)' + + + module-attribute + + +

    + + +
    + +

    Match an HTML entity (&#38; (decimal) or &#x26; (hex) or &amp; (named)).

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.LINE_BREAK_RE = ' \\n' + + + module-attribute + + +

    + + +
    + +

    Match two spaces at end of line.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.dequote(string: str) -> str + +

    + + +
    + +

    Remove quotes from around a string.

    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.EmStrongItem + + +

    + + +
    +

    + Bases: namedtuple('EmStrongItem', ['pattern', 'builder', 'tags'])

    + + +

    Emphasis/strong pattern item.

    + + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.Pattern(pattern: str, md: Markdown | None = None) + +

    + + +
    + + +

    Base class that inline patterns subclass.

    +

    Inline patterns are handled by means of Pattern subclasses, one per regular expression. +Each pattern object uses a single regular expression and must support the following methods: +getCompiledRegExp and +handleMatch.

    +

    All the regular expressions used by Pattern subclasses must capture the whole block. For this +reason, they all start with ^(.*) and end with (.*)!. When passing a regular expression on +class initialization, the ^(.*) and (.*)! are added automatically and the regular expression +is pre-compiled.

    +

    It is strongly suggested that the newer style markdown.inlinepatterns.InlineProcessor that +use a more efficient and flexible search approach be used instead. However, the older style +Pattern remains for backward compatibility with many existing third-party extensions.

    + + + + +

    Parameters:

    +
      +
    • + pattern + (str) + – +
      +

      A regular expression that matches a pattern.

      +
      +
    • +
    • + md + (Markdown | None, default: + None +) + – +
      +

      An optional pointer to the instance of markdown.Markdown and is available as +self.md on the class instance.

      +
      +
    • +
    + + + + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.Pattern.ANCESTOR_EXCLUDES = tuple() + + + class-attribute + instance-attribute + + +

    + + +
    + +

    A collection of elements which are undesirable ancestors. The processor will be skipped if it +would cause the content to be a descendant of one of the listed tag names.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.Pattern.getCompiledRegExp() -> re.Pattern + +

    + + +
    + +

    Return a compiled regular expression.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.Pattern.handleMatch(m: Match) -> etree.Element + +

    + + +
    + +

    Return a ElementTree element from the given match.

    +

    Subclasses should override this method.

    + + + +

    Parameters:

    +
      +
    • + m + (Match) + – +
      +

      A match object containing a match of the pattern.

      +
      +
    • +
    +

    Returns: An ElementTree Element object.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.Pattern.type() -> str + +

    + + +
    + +

    Return class name, to define pattern type

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.Pattern.unescape(text: str) -> str + +

    + + +
    + +

    Return unescaped text given text with an inline placeholder.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.InlineProcessor(pattern: str, md: Markdown | None = None) + +

    + + +
    +

    + Bases: Pattern

    + + +

    Base class that inline processors subclass.

    +

    This is the newer style inline processor that uses a more +efficient and flexible search approach.

    + + + + +

    Parameters:

    +
      +
    • + pattern + (str) + – +
      +

      A regular expression that matches a pattern.

      +
      +
    • +
    • + md + (Markdown | None, default: + None +) + – +
      +

      An optional pointer to the instance of markdown.Markdown and is available as +self.md on the class instance.

      +
      +
    • +
    + + + + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.InlineProcessor.ANCESTOR_EXCLUDES = tuple() + + + class-attribute + instance-attribute + + +

    + + +
    + +

    A collection of elements which are undesirable ancestors. The processor will be skipped if it +would cause the content to be a descendant of one of the listed tag names.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.InlineProcessor.getCompiledRegExp() -> re.Pattern + +

    + + +
    + +

    Return a compiled regular expression.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.InlineProcessor.type() -> str + +

    + + +
    + +

    Return class name, to define pattern type

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.InlineProcessor.unescape(text: str) -> str + +

    + + +
    + +

    Return unescaped text given text with an inline placeholder.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.InlineProcessor.handleMatch(m: Match, data: str) -> tuple[etree.Element | str | None, int | None, int | None] + +

    + + +
    + +

    Return a ElementTree element from the given match and the +start and end index of the matched text.

    +

    If start and/or end are returned as None, it will be +assumed that the processor did not find a valid region of text.

    +

    Subclasses should override this method.

    + + + +

    Parameters:

    +
      +
    • + m + (Match) + – +
      +

      A re match object containing a match of the pattern.

      +
      +
    • +
    • + data + (str) + – +
      +

      The buffer currently under analysis.

      +
      +
    • +
    + + + +

    Returns:

    +
      +
    • +el ( Element | str | None +) – +
      +

      The ElementTree element, text or None.

      +
      +
    • +
    • +start ( int | None +) – +
      +

      The start of the region that has been matched or None.

      +
      +
    • +
    • +end ( int | None +) – +
      +

      The end of the region that has been matched or None.

      +
      +
    • +
    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SimpleTextPattern(pattern: str, md: Markdown | None = None) + +

    + + +
    +

    + Bases: Pattern

    + + +

    Return a simple text of group(2) of a Pattern.

    + + + + +

    Parameters:

    +
      +
    • + pattern + (str) + – +
      +

      A regular expression that matches a pattern.

      +
      +
    • +
    • + md + (Markdown | None, default: + None +) + – +
      +

      An optional pointer to the instance of markdown.Markdown and is available as +self.md on the class instance.

      +
      +
    • +
    + + + + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SimpleTextPattern.ANCESTOR_EXCLUDES = tuple() + + + class-attribute + instance-attribute + + +

    + + +
    + +

    A collection of elements which are undesirable ancestors. The processor will be skipped if it +would cause the content to be a descendant of one of the listed tag names.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SimpleTextPattern.getCompiledRegExp() -> re.Pattern + +

    + + +
    + +

    Return a compiled regular expression.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SimpleTextPattern.type() -> str + +

    + + +
    + +

    Return class name, to define pattern type

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SimpleTextPattern.unescape(text: str) -> str + +

    + + +
    + +

    Return unescaped text given text with an inline placeholder.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SimpleTextPattern.handleMatch(m: Match) -> str + +

    + + +
    + +

    Return string content of group(2) of a matching pattern.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SimpleTextInlineProcessor(pattern: str, md: Markdown | None = None) + +

    + + +
    +

    + Bases: InlineProcessor

    + + +

    Return a simple text of group(1) of a Pattern.

    + + + + +

    Parameters:

    +
      +
    • + pattern + (str) + – +
      +

      A regular expression that matches a pattern.

      +
      +
    • +
    • + md + (Markdown | None, default: + None +) + – +
      +

      An optional pointer to the instance of markdown.Markdown and is available as +self.md on the class instance.

      +
      +
    • +
    + + + + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SimpleTextInlineProcessor.ANCESTOR_EXCLUDES = tuple() + + + class-attribute + instance-attribute + + +

    + + +
    + +

    A collection of elements which are undesirable ancestors. The processor will be skipped if it +would cause the content to be a descendant of one of the listed tag names.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SimpleTextInlineProcessor.getCompiledRegExp() -> re.Pattern + +

    + + +
    + +

    Return a compiled regular expression.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SimpleTextInlineProcessor.type() -> str + +

    + + +
    + +

    Return class name, to define pattern type

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SimpleTextInlineProcessor.unescape(text: str) -> str + +

    + + +
    + +

    Return unescaped text given text with an inline placeholder.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SimpleTextInlineProcessor.handleMatch(m: Match, data: str) -> tuple[str, int, int] + +

    + + +
    + +

    Return string content of group(1) of a matching pattern.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.EscapeInlineProcessor(pattern: str, md: Markdown | None = None) + +

    + + +
    +

    + Bases: InlineProcessor

    + + +

    Return an escaped character.

    + + + + +

    Parameters:

    +
      +
    • + pattern + (str) + – +
      +

      A regular expression that matches a pattern.

      +
      +
    • +
    • + md + (Markdown | None, default: + None +) + – +
      +

      An optional pointer to the instance of markdown.Markdown and is available as +self.md on the class instance.

      +
      +
    • +
    + + + + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.EscapeInlineProcessor.ANCESTOR_EXCLUDES = tuple() + + + class-attribute + instance-attribute + + +

    + + +
    + +

    A collection of elements which are undesirable ancestors. The processor will be skipped if it +would cause the content to be a descendant of one of the listed tag names.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.EscapeInlineProcessor.getCompiledRegExp() -> re.Pattern + +

    + + +
    + +

    Return a compiled regular expression.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.EscapeInlineProcessor.type() -> str + +

    + + +
    + +

    Return class name, to define pattern type

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.EscapeInlineProcessor.unescape(text: str) -> str + +

    + + +
    + +

    Return unescaped text given text with an inline placeholder.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.EscapeInlineProcessor.handleMatch(m: Match, data: str) -> tuple[str | None, int, int] + +

    + + +
    + +

    If the character matched by group(1) of a pattern is in ESCAPED_CHARS +then return the integer representing the character’s Unicode code point (as returned by ord) wrapped +in util.STX and util.ETX.

    +

    If the matched character is not in ESCAPED_CHARS, then return None.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SimpleTagPattern(pattern: str, tag: str) + +

    + + +
    +

    + Bases: Pattern

    + + +

    Return element of type tag with a text attribute of group(3) +of a Pattern.

    + + + + +

    Parameters:

    +
      +
    • + pattern + (str) + – +
      +

      A regular expression that matches a pattern.

      +
      +
    • +
    • + tag + (str) + – +
      +

      Tag of element.

      +
      +
    • +
    + + + + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SimpleTagPattern.ANCESTOR_EXCLUDES = tuple() + + + class-attribute + instance-attribute + + +

    + + +
    + +

    A collection of elements which are undesirable ancestors. The processor will be skipped if it +would cause the content to be a descendant of one of the listed tag names.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SimpleTagPattern.getCompiledRegExp() -> re.Pattern + +

    + + +
    + +

    Return a compiled regular expression.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SimpleTagPattern.type() -> str + +

    + + +
    + +

    Return class name, to define pattern type

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SimpleTagPattern.unescape(text: str) -> str + +

    + + +
    + +

    Return unescaped text given text with an inline placeholder.

    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SimpleTagPattern.tag = tag + + + instance-attribute + + +

    + + +
    + +

    The tag of the rendered element.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SimpleTagPattern.handleMatch(m: Match) -> etree.Element + +

    + + +
    + +

    Return Element of type tag with the string in group(3) of a +matching pattern as the Element’s text.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SimpleTagInlineProcessor(pattern: str, tag: str) + +

    + + +
    +

    + Bases: InlineProcessor

    + + +

    Return element of type tag with a text attribute of group(2) +of a Pattern.

    + + + + +

    Parameters:

    +
      +
    • + pattern + (str) + – +
      +

      A regular expression that matches a pattern.

      +
      +
    • +
    • + tag + (str) + – +
      +

      Tag of element.

      +
      +
    • +
    + + + + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SimpleTagInlineProcessor.ANCESTOR_EXCLUDES = tuple() + + + class-attribute + instance-attribute + + +

    + + +
    + +

    A collection of elements which are undesirable ancestors. The processor will be skipped if it +would cause the content to be a descendant of one of the listed tag names.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SimpleTagInlineProcessor.getCompiledRegExp() -> re.Pattern + +

    + + +
    + +

    Return a compiled regular expression.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SimpleTagInlineProcessor.type() -> str + +

    + + +
    + +

    Return class name, to define pattern type

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SimpleTagInlineProcessor.unescape(text: str) -> str + +

    + + +
    + +

    Return unescaped text given text with an inline placeholder.

    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SimpleTagInlineProcessor.tag = tag + + + instance-attribute + + +

    + + +
    + +

    The tag of the rendered element.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SimpleTagInlineProcessor.handleMatch(m: Match, data: str) -> tuple[etree.Element, int, int] + +

    + + +
    + +

    Return Element of type tag with the string in group(2) of a +matching pattern as the Element’s text.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SubstituteTagPattern(pattern: str, tag: str) + +

    + + +
    +

    + Bases: SimpleTagPattern

    + + +

    Return an element of type tag with no children.

    + + + + +

    Parameters:

    +
      +
    • + pattern + (str) + – +
      +

      A regular expression that matches a pattern.

      +
      +
    • +
    • + tag + (str) + – +
      +

      Tag of element.

      +
      +
    • +
    + + + + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SubstituteTagPattern.ANCESTOR_EXCLUDES = tuple() + + + class-attribute + instance-attribute + + +

    + + +
    + +

    A collection of elements which are undesirable ancestors. The processor will be skipped if it +would cause the content to be a descendant of one of the listed tag names.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SubstituteTagPattern.getCompiledRegExp() -> re.Pattern + +

    + + +
    + +

    Return a compiled regular expression.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SubstituteTagPattern.type() -> str + +

    + + +
    + +

    Return class name, to define pattern type

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SubstituteTagPattern.unescape(text: str) -> str + +

    + + +
    + +

    Return unescaped text given text with an inline placeholder.

    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SubstituteTagPattern.tag = tag + + + instance-attribute + + +

    + + +
    + +

    The tag of the rendered element.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SubstituteTagPattern.handleMatch(m: Match) -> etree.Element + +

    + + +
    + +

    Return empty Element of type tag.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SubstituteTagInlineProcessor(pattern: str, tag: str) + +

    + + +
    +

    + Bases: SimpleTagInlineProcessor

    + + +

    Return an element of type tag with no children.

    + + + + +

    Parameters:

    +
      +
    • + pattern + (str) + – +
      +

      A regular expression that matches a pattern.

      +
      +
    • +
    • + tag + (str) + – +
      +

      Tag of element.

      +
      +
    • +
    + + + + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SubstituteTagInlineProcessor.ANCESTOR_EXCLUDES = tuple() + + + class-attribute + instance-attribute + + +

    + + +
    + +

    A collection of elements which are undesirable ancestors. The processor will be skipped if it +would cause the content to be a descendant of one of the listed tag names.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SubstituteTagInlineProcessor.getCompiledRegExp() -> re.Pattern + +

    + + +
    + +

    Return a compiled regular expression.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SubstituteTagInlineProcessor.type() -> str + +

    + + +
    + +

    Return class name, to define pattern type

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SubstituteTagInlineProcessor.unescape(text: str) -> str + +

    + + +
    + +

    Return unescaped text given text with an inline placeholder.

    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SubstituteTagInlineProcessor.tag = tag + + + instance-attribute + + +

    + + +
    + +

    The tag of the rendered element.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.SubstituteTagInlineProcessor.handleMatch(m: Match, data: str) -> tuple[etree.Element, int, int] + +

    + + +
    + +

    Return empty Element of type tag.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.BacktickInlineProcessor(pattern) + +

    + + +
    +

    + Bases: InlineProcessor

    + + +

    Return a <code> element containing the escaped matching text.

    + + + + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.BacktickInlineProcessor.ANCESTOR_EXCLUDES = tuple() + + + class-attribute + instance-attribute + + +

    + + +
    + +

    A collection of elements which are undesirable ancestors. The processor will be skipped if it +would cause the content to be a descendant of one of the listed tag names.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.BacktickInlineProcessor.getCompiledRegExp() -> re.Pattern + +

    + + +
    + +

    Return a compiled regular expression.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.BacktickInlineProcessor.type() -> str + +

    + + +
    + +

    Return class name, to define pattern type

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.BacktickInlineProcessor.unescape(text: str) -> str + +

    + + +
    + +

    Return unescaped text given text with an inline placeholder.

    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.BacktickInlineProcessor.tag = 'code' + + + instance-attribute + + +

    + + +
    + +

    The tag of the rendered element.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.BacktickInlineProcessor.handleMatch(m: Match, data: str) -> tuple[etree.Element | str, int, int] + +

    + + +
    + +

    If the match contains group(3) of a pattern, then return a code +Element which contains HTML escaped text (with +code_escape) as an AtomicString.

    +

    If the match does not contain group(3) then return the text of group(1) backslash escaped.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.DoubleTagPattern(pattern: str, tag: str) + +

    + + +
    +

    + Bases: SimpleTagPattern

    + + +

    Return a ElementTree element nested in tag2 nested in tag1.

    +

    Useful for strong emphasis etc.

    + + + + +

    Parameters:

    +
      +
    • + pattern + (str) + – +
      +

      A regular expression that matches a pattern.

      +
      +
    • +
    • + tag + (str) + – +
      +

      Tag of element.

      +
      +
    • +
    + + + + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.DoubleTagPattern.ANCESTOR_EXCLUDES = tuple() + + + class-attribute + instance-attribute + + +

    + + +
    + +

    A collection of elements which are undesirable ancestors. The processor will be skipped if it +would cause the content to be a descendant of one of the listed tag names.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.DoubleTagPattern.getCompiledRegExp() -> re.Pattern + +

    + + +
    + +

    Return a compiled regular expression.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.DoubleTagPattern.type() -> str + +

    + + +
    + +

    Return class name, to define pattern type

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.DoubleTagPattern.unescape(text: str) -> str + +

    + + +
    + +

    Return unescaped text given text with an inline placeholder.

    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.DoubleTagPattern.tag = tag + + + instance-attribute + + +

    + + +
    + +

    The tag of the rendered element.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.DoubleTagPattern.handleMatch(m: Match) -> etree.Element + +

    + + +
    + +

    Return Element in following format: +<tag1><tag2>group(3)</tag2>group(4)</tag2> where group(4) is optional.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.DoubleTagInlineProcessor(pattern: str, tag: str) + +

    + + +
    +

    + Bases: SimpleTagInlineProcessor

    + + +

    Return a ElementTree element nested in tag2 nested in tag1.

    +

    Useful for strong emphasis etc.

    + + + + +

    Parameters:

    +
      +
    • + pattern + (str) + – +
      +

      A regular expression that matches a pattern.

      +
      +
    • +
    • + tag + (str) + – +
      +

      Tag of element.

      +
      +
    • +
    + + + + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.DoubleTagInlineProcessor.ANCESTOR_EXCLUDES = tuple() + + + class-attribute + instance-attribute + + +

    + + +
    + +

    A collection of elements which are undesirable ancestors. The processor will be skipped if it +would cause the content to be a descendant of one of the listed tag names.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.DoubleTagInlineProcessor.getCompiledRegExp() -> re.Pattern + +

    + + +
    + +

    Return a compiled regular expression.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.DoubleTagInlineProcessor.type() -> str + +

    + + +
    + +

    Return class name, to define pattern type

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.DoubleTagInlineProcessor.unescape(text: str) -> str + +

    + + +
    + +

    Return unescaped text given text with an inline placeholder.

    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.DoubleTagInlineProcessor.tag = tag + + + instance-attribute + + +

    + + +
    + +

    The tag of the rendered element.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.DoubleTagInlineProcessor.handleMatch(m: Match, data: str) -> tuple[etree.Element, int, int] + +

    + + +
    + +

    Return Element in following format: +<tag1><tag2>group(2)</tag2>group(3)</tag2> where group(3) is optional.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.HtmlInlineProcessor(pattern: str, md: Markdown | None = None) + +

    + + +
    +

    + Bases: InlineProcessor

    + + +

    Store raw inline html and return a placeholder.

    + + + + +

    Parameters:

    +
      +
    • + pattern + (str) + – +
      +

      A regular expression that matches a pattern.

      +
      +
    • +
    • + md + (Markdown | None, default: + None +) + – +
      +

      An optional pointer to the instance of markdown.Markdown and is available as +self.md on the class instance.

      +
      +
    • +
    + + + + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.HtmlInlineProcessor.ANCESTOR_EXCLUDES = tuple() + + + class-attribute + instance-attribute + + +

    + + +
    + +

    A collection of elements which are undesirable ancestors. The processor will be skipped if it +would cause the content to be a descendant of one of the listed tag names.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.HtmlInlineProcessor.getCompiledRegExp() -> re.Pattern + +

    + + +
    + +

    Return a compiled regular expression.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.HtmlInlineProcessor.type() -> str + +

    + + +
    + +

    Return class name, to define pattern type

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.HtmlInlineProcessor.handleMatch(m: Match, data: str) -> tuple[str, int, int] + +

    + + +
    + +

    Store the text of group(1) of a pattern and return a placeholder string.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.HtmlInlineProcessor.unescape(text) + +

    + + +
    + +

    Return unescaped text given text with an inline placeholder.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.HtmlInlineProcessor.backslash_unescape(text) + +

    + + +
    + +

    Return text with backslash escapes undone (backslashes are restored).

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.AsteriskProcessor(pattern: str, md: Markdown | None = None) + +

    + + +
    +

    + Bases: InlineProcessor

    + + +

    Emphasis processor for handling strong and em matches inside asterisks.

    + + + + +

    Parameters:

    +
      +
    • + pattern + (str) + – +
      +

      A regular expression that matches a pattern.

      +
      +
    • +
    • + md + (Markdown | None, default: + None +) + – +
      +

      An optional pointer to the instance of markdown.Markdown and is available as +self.md on the class instance.

      +
      +
    • +
    + + + + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.AsteriskProcessor.ANCESTOR_EXCLUDES = tuple() + + + class-attribute + instance-attribute + + +

    + + +
    + +

    A collection of elements which are undesirable ancestors. The processor will be skipped if it +would cause the content to be a descendant of one of the listed tag names.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.AsteriskProcessor.getCompiledRegExp() -> re.Pattern + +

    + + +
    + +

    Return a compiled regular expression.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.AsteriskProcessor.type() -> str + +

    + + +
    + +

    Return class name, to define pattern type

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.AsteriskProcessor.unescape(text: str) -> str + +

    + + +
    + +

    Return unescaped text given text with an inline placeholder.

    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.AsteriskProcessor.PATTERNS = [EmStrongItem(re.compile(EM_STRONG_RE, re.DOTALL | re.UNICODE), 'double', 'strong,em'), EmStrongItem(re.compile(STRONG_EM_RE, re.DOTALL | re.UNICODE), 'double', 'em,strong'), EmStrongItem(re.compile(STRONG_EM3_RE, re.DOTALL | re.UNICODE), 'double2', 'strong,em'), EmStrongItem(re.compile(STRONG_RE, re.DOTALL | re.UNICODE), 'single', 'strong'), EmStrongItem(re.compile(EMPHASIS_RE, re.DOTALL | re.UNICODE), 'single', 'em')] + + + class-attribute + instance-attribute + + +

    + + +
    + +

    The various strong and emphasis patterns handled by this processor.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.AsteriskProcessor.build_single(m, tag, idx) + +

    + + +
    + +

    Return single tag.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.AsteriskProcessor.build_double(m, tags, idx) + +

    + + +
    + +

    Return double tag.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.AsteriskProcessor.build_double2(m, tags, idx) + +

    + + +
    + +

    Return double tags (variant 2): <strong>text <em>text</em></strong>.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.AsteriskProcessor.parse_sub_patterns(data, parent, last, idx) + +

    + + +
    + +

    Parses sub patterns.

    +

    data (str): + text to evaluate.

    +

    parent (etree.Element): + Parent to attach text and sub elements to.

    +

    last (etree.Element): + Last appended child to parent. Can also be None if parent has no children.

    +

    idx (int): + Current pattern index that was used to evaluate the parent.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.AsteriskProcessor.build_element(m, builder, tags, index) + +

    + + +
    + +

    Element builder.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.AsteriskProcessor.handleMatch(m: Match, data: str) -> tuple[etree.Element, int, int] + +

    + + +
    + +

    Parse patterns.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.UnderscoreProcessor(pattern: str, md: Markdown | None = None) + +

    + + +
    +

    + Bases: AsteriskProcessor

    + + +

    Emphasis processor for handling strong and em matches inside underscores.

    + + + + +

    Parameters:

    +
      +
    • + pattern + (str) + – +
      +

      A regular expression that matches a pattern.

      +
      +
    • +
    • + md + (Markdown | None, default: + None +) + – +
      +

      An optional pointer to the instance of markdown.Markdown and is available as +self.md on the class instance.

      +
      +
    • +
    + + + + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.UnderscoreProcessor.ANCESTOR_EXCLUDES = tuple() + + + class-attribute + instance-attribute + + +

    + + +
    + +

    A collection of elements which are undesirable ancestors. The processor will be skipped if it +would cause the content to be a descendant of one of the listed tag names.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.UnderscoreProcessor.getCompiledRegExp() -> re.Pattern + +

    + + +
    + +

    Return a compiled regular expression.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.UnderscoreProcessor.handleMatch(m: Match, data: str) -> tuple[etree.Element, int, int] + +

    + + +
    + +

    Parse patterns.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.UnderscoreProcessor.type() -> str + +

    + + +
    + +

    Return class name, to define pattern type

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.UnderscoreProcessor.unescape(text: str) -> str + +

    + + +
    + +

    Return unescaped text given text with an inline placeholder.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.UnderscoreProcessor.build_single(m, tag, idx) + +

    + + +
    + +

    Return single tag.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.UnderscoreProcessor.build_double(m, tags, idx) + +

    + + +
    + +

    Return double tag.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.UnderscoreProcessor.build_double2(m, tags, idx) + +

    + + +
    + +

    Return double tags (variant 2): <strong>text <em>text</em></strong>.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.UnderscoreProcessor.parse_sub_patterns(data, parent, last, idx) + +

    + + +
    + +

    Parses sub patterns.

    +

    data (str): + text to evaluate.

    +

    parent (etree.Element): + Parent to attach text and sub elements to.

    +

    last (etree.Element): + Last appended child to parent. Can also be None if parent has no children.

    +

    idx (int): + Current pattern index that was used to evaluate the parent.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.UnderscoreProcessor.build_element(m, builder, tags, index) + +

    + + +
    + +

    Element builder.

    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.UnderscoreProcessor.PATTERNS = [EmStrongItem(re.compile(EM_STRONG2_RE, re.DOTALL | re.UNICODE), 'double', 'strong,em'), EmStrongItem(re.compile(STRONG_EM2_RE, re.DOTALL | re.UNICODE), 'double', 'em,strong'), EmStrongItem(re.compile(SMART_STRONG_EM_RE, re.DOTALL | re.UNICODE), 'double2', 'strong,em'), EmStrongItem(re.compile(SMART_STRONG_RE, re.DOTALL | re.UNICODE), 'single', 'strong'), EmStrongItem(re.compile(SMART_EMPHASIS_RE, re.DOTALL | re.UNICODE), 'single', 'em')] + + + class-attribute + instance-attribute + + +

    + + +
    + +

    The various strong and emphasis patterns handled by this processor.

    +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.LinkInlineProcessor(pattern: str, md: Markdown | None = None) + +

    + + +
    +

    + Bases: InlineProcessor

    + + +

    Return a link element from the given match.

    + + + + +

    Parameters:

    +
      +
    • + pattern + (str) + – +
      +

      A regular expression that matches a pattern.

      +
      +
    • +
    • + md + (Markdown | None, default: + None +) + – +
      +

      An optional pointer to the instance of markdown.Markdown and is available as +self.md on the class instance.

      +
      +
    • +
    + + + + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.LinkInlineProcessor.ANCESTOR_EXCLUDES = tuple() + + + class-attribute + instance-attribute + + +

    + + +
    + +

    A collection of elements which are undesirable ancestors. The processor will be skipped if it +would cause the content to be a descendant of one of the listed tag names.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.LinkInlineProcessor.getCompiledRegExp() -> re.Pattern + +

    + + +
    + +

    Return a compiled regular expression.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.LinkInlineProcessor.type() -> str + +

    + + +
    + +

    Return class name, to define pattern type

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.LinkInlineProcessor.unescape(text: str) -> str + +

    + + +
    + +

    Return unescaped text given text with an inline placeholder.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.LinkInlineProcessor.handleMatch(m: Match, data: str) -> tuple[etree.Element | None, int | None, int | None] + +

    + + +
    + +

    Return an a Element or (None, None, None).

    + +
    + +
    + + + + + + + +
    + + + + + + + +
    + +

    Parse data between () of [Text]() allowing recursive ().

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.LinkInlineProcessor.getText(data, index) + +

    + + +
    + +

    Parse the content between [] of the start of an image or link +resolving nested square brackets.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ImageInlineProcessor(pattern: str, md: Markdown | None = None) + +

    + + +
    +

    + Bases: LinkInlineProcessor

    + + +

    Return a img element from the given match.

    + + + + +

    Parameters:

    +
      +
    • + pattern + (str) + – +
      +

      A regular expression that matches a pattern.

      +
      +
    • +
    • + md + (Markdown | None, default: + None +) + – +
      +

      An optional pointer to the instance of markdown.Markdown and is available as +self.md on the class instance.

      +
      +
    • +
    + + + + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ImageInlineProcessor.ANCESTOR_EXCLUDES = tuple() + + + class-attribute + instance-attribute + + +

    + + +
    + +

    A collection of elements which are undesirable ancestors. The processor will be skipped if it +would cause the content to be a descendant of one of the listed tag names.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ImageInlineProcessor.getCompiledRegExp() -> re.Pattern + +

    + + +
    + +

    Return a compiled regular expression.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ImageInlineProcessor.type() -> str + +

    + + +
    + +

    Return class name, to define pattern type

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ImageInlineProcessor.unescape(text: str) -> str + +

    + + +
    + +

    Return unescaped text given text with an inline placeholder.

    + +
    + +
    + + + + + + + +
    + + + + + + + +
    + +

    Parse data between () of [Text]() allowing recursive ().

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ImageInlineProcessor.getText(data, index) + +

    + + +
    + +

    Parse the content between [] of the start of an image or link +resolving nested square brackets.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ImageInlineProcessor.handleMatch(m: Match, data: str) -> tuple[etree.Element | None, int | None, int | None] + +

    + + +
    + +

    Return an img Element or (None, None, None).

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ReferenceInlineProcessor(pattern: str, md: Markdown | None = None) + +

    + + +
    +

    + Bases: LinkInlineProcessor

    + + +

    Match to a stored reference and return link element.

    + + + + +

    Parameters:

    +
      +
    • + pattern + (str) + – +
      +

      A regular expression that matches a pattern.

      +
      +
    • +
    • + md + (Markdown | None, default: + None +) + – +
      +

      An optional pointer to the instance of markdown.Markdown and is available as +self.md on the class instance.

      +
      +
    • +
    + + + + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ReferenceInlineProcessor.ANCESTOR_EXCLUDES = tuple() + + + class-attribute + instance-attribute + + +

    + + +
    + +

    A collection of elements which are undesirable ancestors. The processor will be skipped if it +would cause the content to be a descendant of one of the listed tag names.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ReferenceInlineProcessor.getCompiledRegExp() -> re.Pattern + +

    + + +
    + +

    Return a compiled regular expression.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ReferenceInlineProcessor.type() -> str + +

    + + +
    + +

    Return class name, to define pattern type

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ReferenceInlineProcessor.unescape(text: str) -> str + +

    + + +
    + +

    Return unescaped text given text with an inline placeholder.

    + +
    + +
    + + + + + + + +
    + + + + + + + +
    + +

    Parse data between () of [Text]() allowing recursive ().

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ReferenceInlineProcessor.getText(data, index) + +

    + + +
    + +

    Parse the content between [] of the start of an image or link +resolving nested square brackets.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ReferenceInlineProcessor.handleMatch(m: Match, data: str) -> tuple[etree.Element | None, int | None, int | None] + +

    + + +
    + +

    Return Element returned by makeTag method or (None, None, None).

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ReferenceInlineProcessor.evalId(data, index, text) + +

    + + +
    + +

    Evaluate the id portion of [ref][id].

    +

    If [ref][] use [ref].

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ReferenceInlineProcessor.makeTag(href: str, title: str, text: str) -> etree.Element + +

    + + +
    + +

    Return an a Element.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ShortReferenceInlineProcessor(pattern: str, md: Markdown | None = None) + +

    + + +
    +

    + Bases: ReferenceInlineProcessor

    + + +

    Short form of reference: [google].

    + + + + +

    Parameters:

    +
      +
    • + pattern + (str) + – +
      +

      A regular expression that matches a pattern.

      +
      +
    • +
    • + md + (Markdown | None, default: + None +) + – +
      +

      An optional pointer to the instance of markdown.Markdown and is available as +self.md on the class instance.

      +
      +
    • +
    + + + + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ShortReferenceInlineProcessor.ANCESTOR_EXCLUDES = tuple() + + + class-attribute + instance-attribute + + +

    + + +
    + +

    A collection of elements which are undesirable ancestors. The processor will be skipped if it +would cause the content to be a descendant of one of the listed tag names.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ShortReferenceInlineProcessor.getCompiledRegExp() -> re.Pattern + +

    + + +
    + +

    Return a compiled regular expression.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ShortReferenceInlineProcessor.handleMatch(m: Match, data: str) -> tuple[etree.Element | None, int | None, int | None] + +

    + + +
    + +

    Return Element returned by makeTag method or (None, None, None).

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ShortReferenceInlineProcessor.type() -> str + +

    + + +
    + +

    Return class name, to define pattern type

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ShortReferenceInlineProcessor.unescape(text: str) -> str + +

    + + +
    + +

    Return unescaped text given text with an inline placeholder.

    + +
    + +
    + + + + + + + +
    + + + + + + + +
    + +

    Parse data between () of [Text]() allowing recursive ().

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ShortReferenceInlineProcessor.getText(data, index) + +

    + + +
    + +

    Parse the content between [] of the start of an image or link +resolving nested square brackets.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ShortReferenceInlineProcessor.makeTag(href: str, title: str, text: str) -> etree.Element + +

    + + +
    + +

    Return an a Element.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ShortReferenceInlineProcessor.evalId(data, index, text) + +

    + + +
    + +

    Evaluate the id of [ref].

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ImageReferenceInlineProcessor(pattern: str, md: Markdown | None = None) + +

    + + +
    +

    + Bases: ReferenceInlineProcessor

    + + +

    Match to a stored reference and return img element.

    + + + + +

    Parameters:

    +
      +
    • + pattern + (str) + – +
      +

      A regular expression that matches a pattern.

      +
      +
    • +
    • + md + (Markdown | None, default: + None +) + – +
      +

      An optional pointer to the instance of markdown.Markdown and is available as +self.md on the class instance.

      +
      +
    • +
    + + + + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ImageReferenceInlineProcessor.ANCESTOR_EXCLUDES = tuple() + + + class-attribute + instance-attribute + + +

    + + +
    + +

    A collection of elements which are undesirable ancestors. The processor will be skipped if it +would cause the content to be a descendant of one of the listed tag names.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ImageReferenceInlineProcessor.getCompiledRegExp() -> re.Pattern + +

    + + +
    + +

    Return a compiled regular expression.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ImageReferenceInlineProcessor.handleMatch(m: Match, data: str) -> tuple[etree.Element | None, int | None, int | None] + +

    + + +
    + +

    Return Element returned by makeTag method or (None, None, None).

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ImageReferenceInlineProcessor.type() -> str + +

    + + +
    + +

    Return class name, to define pattern type

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ImageReferenceInlineProcessor.unescape(text: str) -> str + +

    + + +
    + +

    Return unescaped text given text with an inline placeholder.

    + +
    + +
    + + + + + + + +
    + + + + + + + +
    + +

    Parse data between () of [Text]() allowing recursive ().

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ImageReferenceInlineProcessor.getText(data, index) + +

    + + +
    + +

    Parse the content between [] of the start of an image or link +resolving nested square brackets.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ImageReferenceInlineProcessor.evalId(data, index, text) + +

    + + +
    + +

    Evaluate the id portion of [ref][id].

    +

    If [ref][] use [ref].

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ImageReferenceInlineProcessor.makeTag(href: str, title: str, text: str) -> etree.Element + +

    + + +
    + +

    Return an img Element.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ShortImageReferenceInlineProcessor(pattern: str, md: Markdown | None = None) + +

    + + +
    +

    + Bases: ImageReferenceInlineProcessor

    + + +

    Short form of image reference: ![ref].

    + + + + +

    Parameters:

    +
      +
    • + pattern + (str) + – +
      +

      A regular expression that matches a pattern.

      +
      +
    • +
    • + md + (Markdown | None, default: + None +) + – +
      +

      An optional pointer to the instance of markdown.Markdown and is available as +self.md on the class instance.

      +
      +
    • +
    + + + + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ShortImageReferenceInlineProcessor.ANCESTOR_EXCLUDES = tuple() + + + class-attribute + instance-attribute + + +

    + + +
    + +

    A collection of elements which are undesirable ancestors. The processor will be skipped if it +would cause the content to be a descendant of one of the listed tag names.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ShortImageReferenceInlineProcessor.getCompiledRegExp() -> re.Pattern + +

    + + +
    + +

    Return a compiled regular expression.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ShortImageReferenceInlineProcessor.handleMatch(m: Match, data: str) -> tuple[etree.Element | None, int | None, int | None] + +

    + + +
    + +

    Return Element returned by makeTag method or (None, None, None).

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ShortImageReferenceInlineProcessor.type() -> str + +

    + + +
    + +

    Return class name, to define pattern type

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ShortImageReferenceInlineProcessor.unescape(text: str) -> str + +

    + + +
    + +

    Return unescaped text given text with an inline placeholder.

    + +
    + +
    + + + + + + + +
    + + + + + + + +
    + +

    Parse data between () of [Text]() allowing recursive ().

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ShortImageReferenceInlineProcessor.getText(data, index) + +

    + + +
    + +

    Parse the content between [] of the start of an image or link +resolving nested square brackets.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ShortImageReferenceInlineProcessor.makeTag(href: str, title: str, text: str) -> etree.Element + +

    + + +
    + +

    Return an img Element.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.ShortImageReferenceInlineProcessor.evalId(data, index, text) + +

    + + +
    + +

    Evaluate the id of [ref].

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.AutolinkInlineProcessor(pattern: str, md: Markdown | None = None) + +

    + + +
    +

    + Bases: InlineProcessor

    + + +

    Return a link Element given an auto-link (<http://example/com>).

    + + + + +

    Parameters:

    +
      +
    • + pattern + (str) + – +
      +

      A regular expression that matches a pattern.

      +
      +
    • +
    • + md + (Markdown | None, default: + None +) + – +
      +

      An optional pointer to the instance of markdown.Markdown and is available as +self.md on the class instance.

      +
      +
    • +
    + + + + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.AutolinkInlineProcessor.ANCESTOR_EXCLUDES = tuple() + + + class-attribute + instance-attribute + + +

    + + +
    + +

    A collection of elements which are undesirable ancestors. The processor will be skipped if it +would cause the content to be a descendant of one of the listed tag names.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.AutolinkInlineProcessor.getCompiledRegExp() -> re.Pattern + +

    + + +
    + +

    Return a compiled regular expression.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.AutolinkInlineProcessor.type() -> str + +

    + + +
    + +

    Return class name, to define pattern type

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.AutolinkInlineProcessor.unescape(text: str) -> str + +

    + + +
    + +

    Return unescaped text given text with an inline placeholder.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.AutolinkInlineProcessor.handleMatch(m: Match, data: str) -> tuple[etree.Element, int, int] + +

    + + +
    + +

    Return an a Element of group(1).

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.inlinepatterns.AutomailInlineProcessor(pattern: str, md: Markdown | None = None) + +

    + + +
    +

    + Bases: InlineProcessor

    + + +

    Return a mailto link Element given an auto-mail link (<foo@example.com>).

    + + + + +

    Parameters:

    +
      +
    • + pattern + (str) + – +
      +

      A regular expression that matches a pattern.

      +
      +
    • +
    • + md + (Markdown | None, default: + None +) + – +
      +

      An optional pointer to the instance of markdown.Markdown and is available as +self.md on the class instance.

      +
      +
    • +
    + + + + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.AutomailInlineProcessor.ANCESTOR_EXCLUDES = tuple() + + + class-attribute + instance-attribute + + +

    + + +
    + +

    A collection of elements which are undesirable ancestors. The processor will be skipped if it +would cause the content to be a descendant of one of the listed tag names.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.AutomailInlineProcessor.getCompiledRegExp() -> re.Pattern + +

    + + +
    + +

    Return a compiled regular expression.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.AutomailInlineProcessor.type() -> str + +

    + + +
    + +

    Return class name, to define pattern type

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.AutomailInlineProcessor.unescape(text: str) -> str + +

    + + +
    + +

    Return unescaped text given text with an inline placeholder.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.inlinepatterns.AutomailInlineProcessor.handleMatch(m: Match, data: str) -> tuple[etree.Element, int, int] + +

    + + +
    + +

    Return an Element containing a mailto link of group(1).

    + +
    + +
    + + + + +
    + +
    + +
    + + + + +
    + +
    + +
    + +
    +
    +
    + + +
    +
    + + + + + + + \ No newline at end of file diff --git a/reference/markdown/postprocessors/index.html b/reference/markdown/postprocessors/index.html new file mode 100644 index 0000000..fc10350 --- /dev/null +++ b/reference/markdown/postprocessors/index.html @@ -0,0 +1,578 @@ + + + + + + + + + + + + + + postprocessors — Python-Markdown 3.5 documentation + + + + + + + + + + + + +
    +
    +
    +
    + + + + +

    + markdown.postprocessors + + +

    + +
    + +

    Post-processors run on the text of the entire document after is has been serialized into a string. +Postprocessors should be used to work with the text just before output. Usually, they are used add +back sections that were extracted in a preprocessor, fix up outgoing encodings, or wrap the whole +document.

    + + + +
    + + + + + + + + + + + + + + + + +
    + + + + +

    + markdown.postprocessors.build_postprocessors(md: Markdown, **kwargs: Any) -> util.Registry + +

    + + +
    + +

    Build the default postprocessors for Markdown.

    +

    Return a Registry instance which contains the following collection of classes with their assigned names and priorities.

    + + + + + + + + + + + + + + + + + + + + +
    Class InstanceNamePriority
    RawHtmlPostprocessorraw_html30
    AndSubstitutePostprocessoramp_substitute20
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.postprocessors.Postprocessor(md: Markdown = None) + +

    + + +
    +

    + Bases: Processor

    + + +

    Postprocessors are run after the ElementTree it converted back into text.

    +

    Each Postprocessor implements a run method that takes a pointer to a +text string, modifies it as necessary and returns a text string.

    +

    Postprocessors must extend Postprocessor.

    + + + + +
    + + + + + + + + +
    + + + + +

    + markdown.postprocessors.Postprocessor.run(text: str) -> str + +

    + + +
    + +

    Subclasses of Postprocessor should implement a run method, which +takes the html document as a single text string and returns a +(possibly modified) string.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.postprocessors.RawHtmlPostprocessor(md: Markdown = None) + +

    + + +
    +

    + Bases: Postprocessor

    + + +

    Restore raw html to the document.

    + + + + +
    + + + + + + + + +
    + + + + +

    + markdown.postprocessors.RawHtmlPostprocessor.run(text: str) + +

    + + +
    + +

    Iterate over html stash and restore html.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.postprocessors.RawHtmlPostprocessor.isblocklevel(html: str) -> bool + +

    + + +
    + +

    Check is block of HTML is block-level.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.postprocessors.RawHtmlPostprocessor.stash_to_string(text: str) -> str + +

    + + +
    + +

    Convert a stashed object to a string.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.postprocessors.AndSubstitutePostprocessor(md: Markdown = None) + +

    + + +
    +

    + Bases: Postprocessor

    + + +

    Restore valid entities

    + + + + +
    + + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.postprocessors.UnescapePostprocessor(md: Markdown = None) + + + deprecated + + +

    + + +
    +

    + Bases: Postprocessor

    + + + +
    + Deprecated +

    This class is deprecated and will be removed in the future; use UnescapeTreeprocessor instead.

    +

    Restore escaped chars.

    + + + + +
    + + + + + +
    + +
    + +
    + + + + +
    + +
    + +
    + +
    +
    +
    + + +
    +
    + + + + + + + \ No newline at end of file diff --git a/reference/markdown/preprocessors/index.html b/reference/markdown/preprocessors/index.html new file mode 100644 index 0000000..febd073 --- /dev/null +++ b/reference/markdown/preprocessors/index.html @@ -0,0 +1,445 @@ + + + + + + + + + + + + + + preprocessors — Python-Markdown 3.5 documentation + + + + + + + + + + + + +
    +
    +
    +
    + + + + +

    + markdown.preprocessors + + +

    + +
    + +

    Preprocessors work on source text before it is broken down into its individual parts. +This is an excellent place to clean up bad characters or to extract portions for later +processing that the parser may otherwise choke on.

    + + + +
    + + + + + + + + + + + + + + + + + + + + +
    + + + + +

    + markdown.preprocessors.build_preprocessors(md: Markdown, **kwargs: Any) -> util.Registry + +

    + + +
    + +

    Build and return the default set of preprocessors used by Markdown.

    +

    Return a Registry instance which contains the following collection of classes with their assigned names and priorities.

    + + + + + + + + + + + + + + + + + + + + +
    Class InstanceNamePriority
    NormalizeWhitespacenormalize_whitespace30
    HtmlBlockPreprocessorhtml_block20
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.preprocessors.Preprocessor(md: Markdown = None) + +

    + + +
    +

    + Bases: Processor

    + + +

    Preprocessors are run after the text is broken into lines.

    +

    Each preprocessor implements a run method that takes a pointer to a +list of lines of the document, modifies it as necessary and returns +either the same pointer or a pointer to a new list.

    +

    Preprocessors must extend Preprocessor.

    + + + + +
    + + + + + + + + +
    + + + + +

    + markdown.preprocessors.Preprocessor.run(lines: list[str]) -> list[str] + +

    + + +
    + +

    Each subclass of Preprocessor should override the run method, which +takes the document as a list of strings split by newlines and returns +the (possibly modified) list of lines.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.preprocessors.NormalizeWhitespace(md: Markdown = None) + +

    + + +
    +

    + Bases: Preprocessor

    + + +

    Normalize whitespace for consistent parsing.

    + + + + +
    + + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.preprocessors.HtmlBlockPreprocessor(md: Markdown = None) + +

    + + +
    +

    + Bases: Preprocessor

    + + +

    Remove html blocks from the text and store them for later retrieval.

    +

    The raw HTML is stored in the htmlStash of the +Markdown instance.

    + + + + +
    + + + + + +
    + +
    + +
    + + + + +
    + +
    + +
    + +
    +
    +
    + + +
    +
    + + + + + + + \ No newline at end of file diff --git a/reference/markdown/serializers/index.html b/reference/markdown/serializers/index.html new file mode 100644 index 0000000..1a0b0b3 --- /dev/null +++ b/reference/markdown/serializers/index.html @@ -0,0 +1,279 @@ + + + + + + + + + + + + + + serializers — Python-Markdown 3.5 documentation + + + + + + + + + + + + +
    +
    +
    +
    + + + + +

    + markdown.serializers + + +

    + +
    + +

    Python-Markdown provides two serializers which render ElementTree.Element +objects to a string of HTML. Both functions wrap the same underlying code with only a few minor +differences as outlined below:

    +
      +
    1. Empty (self-closing) tags are rendered as <tag> for HTML and as <tag /> for XHTML.
    2. +
    3. Boolean attributes are rendered as attrname for HTML and as attrname="attrname" for XHTML.
    4. +
    + + + +
    + + + + + + + + +
    + + + + +

    + markdown.serializers.to_html_string(element: Element) -> str + +

    + + +
    + +

    Serialize element and its children to a string of HTML5.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.serializers.to_xhtml_string(element: Element) -> str + +

    + + +
    + +

    Serialize element and its children to a string of XHTML.

    + +
    + +
    + + + + +
    + +
    + +
    + +
    +
    +
    + + +
    +
    + + + + + + + \ No newline at end of file diff --git a/reference/markdown/test_tools/index.html b/reference/markdown/test_tools/index.html new file mode 100644 index 0000000..7935eae --- /dev/null +++ b/reference/markdown/test_tools/index.html @@ -0,0 +1,558 @@ + + + + + + + + + + + + + + test_tools — Python-Markdown 3.5 documentation + + + + + + + + + + + + +
    +
    +
    +
    + + + + +

    + markdown.test_tools + + +

    + +
    + +

    A collection of tools for testing the Markdown code base and extensions.

    + + + +
    + + + + + + + + + + + + + + + + + + + +
    + + + + +

    + markdown.test_tools.TestCase + + +

    + + +
    +

    + Bases: TestCase

    + + +

    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.

    +

    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 +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.

    + + + + +
    + + + + + + + +
    + + + + +

    + markdown.test_tools.TestCase.default_kwargs: dict[str, Any] = {} + + + class-attribute + instance-attribute + + +

    + + +
    + +

    Default options to pass to Markdown for each test.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.test_tools.TestCase.assertMarkdownRenders(source, expected, expected_attrs=None, **kwargs) + +

    + + +
    + +

    Test that source Markdown text renders to expected output with given keywords.

    +

    expected_attrs accepts a dict. Each key should be the name of an attribute +on the Markdown instance and the value should be the expected value after +the source text is parsed by Markdown. After the expected output is tested, +the expected value for each attribute is compared against the actual +attribute of the Markdown instance using TestCase.assertEqual.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.test_tools.TestCase.dedent(text) + +

    + + +
    + +

    Dedent text.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.test_tools.recursionlimit(limit) + +

    + + +
    + + +

    A context manager which temporarily modifies the Python recursion limit.

    +

    The testing framework, coverage, etc. may add an arbitrary number of levels to the depth. To maintain consistency +in the tests, the current stack depth is determined when called, then added to the provided limit.

    +

    Example usage:

    +
    with recursionlimit(20):
    +    # test code here
    +
    + +

    See https://stackoverflow.com/a/50120316/866026.

    + + + + +
    + + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.test_tools.Kwargs + + +

    + + +
    +

    + Bases: dict

    + + +

    A dict like class for holding keyword arguments.

    + + +
    + +
    + + + + + + +
    + + + + +

    + markdown.test_tools.LegacyTestCase + + +

    + + +
    +

    + Bases: TestCase

    + + +

    A unittest.TestCase subclass for running Markdown’s legacy file-based tests.

    +

    A subclass should define various properties which point to a directory of +text-based test files and define various behaviors/defaults for those tests. +The following properties are supported:

    + + + +

    Attributes:

    +
      +
    • + location + (str) + – +
      +

      A path to the directory of test files. An absolute path is preferred.

      +
      +
    • +
    • + exclude + (list[str]) + – +
      +

      A list of tests to exclude. Each test name should comprise the filename +without an extension.

      +
      +
    • +
    • + normalize + (bool) + – +
      +

      A boolean value indicating if the HTML should be normalized. Default: False.

      +
      +
    • +
    • + input_ext + (str) + – +
      +

      A string containing the file extension of input files. Default: .txt.

      +
      +
    • +
    • + output_ext + (str) + – +
      +

      A string containing the file extension of expected output files. Default: html.

      +
      +
    • +
    • + default_kwargs + (Kwargs[str, Any]) + – +
      +

      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 +the directory. The property should be given the name of the file without the file +extension. Any spaces and dashes in the filename should be replaced with +underscores. The value of the property should be a Kwargs instance which +contains the keyword arguments that should be passed to Markdown for that +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.

    + + +
    + +
    + + + + +
    + +
    + +
    + +
    +
    +
    + + +
    +
    + + + + + + + \ No newline at end of file diff --git a/reference/markdown/treeprocessors/index.html b/reference/markdown/treeprocessors/index.html new file mode 100644 index 0000000..ad7953a --- /dev/null +++ b/reference/markdown/treeprocessors/index.html @@ -0,0 +1,655 @@ + + + + + + + + + + + + + + treeprocessors — Python-Markdown 3.5 documentation + + + + + + + + + + + + +
    +
    +
    +
    + + + + +

    + markdown.treeprocessors + + +

    + +
    + +

    Tree processors manipulate the tree created by block processors. They can even create an entirely +new ElementTree object. This is an excellent place for creating summaries, adding collected +references, or last minute adjustments.

    + + + +
    + + + + + + + + + + + + + + + + + + + + +
    + + + + +

    + markdown.treeprocessors.build_treeprocessors(md: Markdown, **kwargs: Any) -> util.Registry + +

    + + +
    + +

    Build the default treeprocessors for Markdown.

    +

    Return a Registry instance which contains the following collection of classes with their assigned names and priorities.

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    Class InstanceNamePriority
    InlineProcessorinline20
    PrettifyTreeprocessorprettify10
    UnescapeTreeprocessorunescape0
    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.treeprocessors.isString(s: Any) -> bool + +

    + + +
    + +

    Return True if object is a string but not an AtomicString.

    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.treeprocessors.Treeprocessor(md: Markdown = None) + +

    + + +
    +

    + Bases: Processor

    + + +

    Treeprocessors are run on the ElementTree object before serialization.

    +

    Each Treeprocessor implements a run method that takes a pointer to an +Element and modifies it as necessary.

    +

    Treeprocessors must extend markdown.Treeprocessor.

    + + + + +
    + + + + + + + + +
    + + + + +

    + markdown.treeprocessors.Treeprocessor.run(root: etree.Element) -> etree.Element | None + +

    + + +
    + +

    Subclasses of Treeprocessor should implement a run method, which +takes a root Element. This method can return another Element +object, and the existing root Element will be replaced, or it can +modify the current tree and return None.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.treeprocessors.InlineProcessor(md) + +

    + + +
    +

    + Bases: Treeprocessor

    + + +

    A Treeprocessor that traverses a tree, applying inline patterns.

    + + + + +
    + + + + + + + + +
    + + + + +

    + markdown.treeprocessors.InlineProcessor.run(tree: etree.Element, ancestors: Sequence[str] | None = None) -> etree.Element + +

    + + +
    + +

    Apply inline patterns to a parsed Markdown tree.

    +

    Iterate over Element, find elements with inline tag, apply inline +patterns and append newly created Elements to tree. To avoid further +processing of string with inline patterns, instead of normal string, +use subclass AtomicString:

    +
    node.text = markdown.util.AtomicString("This will not be processed.")
    +
    + + + +

    Parameters:

    +
      +
    • + tree + (Element) + – +
      +

      Element object, representing Markdown tree.

      +
      +
    • +
    • + ancestors + (Sequence[str] | None, default: + None +) + – +
      +

      List of parent tag names that precede the tree node (if needed).

      +
      +
    • +
    + + + +

    Returns:

    +
      +
    • + Element + – +
      +

      An element tree object with applied inline patterns.

      +
      +
    • +
    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.treeprocessors.PrettifyTreeprocessor(md: Markdown = None) + +

    + + +
    +

    + Bases: Treeprocessor

    + + +

    Add line breaks to the html document.

    + + + + +
    + + + + + + + + +
    + + + + +

    + markdown.treeprocessors.PrettifyTreeprocessor.run(root: etree.Element) -> None + +

    + + +
    + +

    Add line breaks to Element object and its children.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.treeprocessors.UnescapeTreeprocessor(md: Markdown = None) + +

    + + +
    +

    + Bases: Treeprocessor

    + + +

    Restore escaped chars

    + + + + +
    + + + + + + + + +
    + + + + +

    + markdown.treeprocessors.UnescapeTreeprocessor.run(root) + +

    + + +
    + +

    Loop over all elements and unescape all text.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + +
    + +
    + +
    + +
    +
    +
    + + +
    +
    + + + + + + + \ No newline at end of file diff --git a/reference/markdown/util/index.html b/reference/markdown/util/index.html new file mode 100644 index 0000000..c2299bf --- /dev/null +++ b/reference/markdown/util/index.html @@ -0,0 +1,1146 @@ + + + + + + + + + + + + + + util — Python-Markdown 3.5 documentation + + + + + + + + + + + + +
    +
    +
    +
    + + + + +

    + markdown.util + + +

    + +
    + +

    This module contains various contacts, classes and functions which get referenced and used +throughout the code base.

    + + + +
    + + + + + + + + + + + +
    + + + + +

    + markdown.util.BLOCK_LEVEL_ELEMENTS: list[str] = ['address', 'article', 'aside', 'blockquote', 'details', 'div', 'dl', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hgroup', 'hr', 'main', 'menu', 'nav', 'ol', 'p', 'pre', 'section', 'table', 'ul', 'canvas', 'colgroup', 'dd', 'body', 'dt', 'group', 'html', 'iframe', 'li', 'legend', 'math', 'map', 'noscript', 'output', 'object', 'option', 'progress', 'script', 'style', 'summary', 'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'tr', 'video'] + + + module-attribute + + +

    + + +
    + +

    List of HTML tags which get treated as block-level elements. Same as the block_level_elements +attribute of the Markdown class. Generally one should use the +attribute on the class. This remains for compatibility with older extensions.

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.util.STX = '\x02' + + + module-attribute + + +

    + + +
    + +

    “Start of Text” marker for placeholder templates.

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.util.ETX = '\x03' + + + module-attribute + + +

    + + +
    + +

    “End of Text” marker for placeholder templates.

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.util.INLINE_PLACEHOLDER_PREFIX = STX + 'klzzwxh:' + + + module-attribute + + +

    + + +
    + +

    Prefix for inline placeholder template.

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.util.INLINE_PLACEHOLDER = INLINE_PLACEHOLDER_PREFIX + '%s' + ETX + + + module-attribute + + +

    + + +
    + +

    Placeholder template for stashed inline text.

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.util.INLINE_PLACEHOLDER_RE = re.compile(INLINE_PLACEHOLDER % '([0-9]+)') + + + module-attribute + + +

    + + +
    + +

    Regular Expression which matches inline placeholders.

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.util.AMP_SUBSTITUTE = STX + 'amp' + ETX + + + module-attribute + + +

    + + +
    + +

    Placeholder template for HTML entities.

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.util.HTML_PLACEHOLDER = STX + 'wzxhzdk:%s' + ETX + + + module-attribute + + +

    + + +
    + +

    Placeholder template for raw HTML.

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.util.HTML_PLACEHOLDER_RE = re.compile(HTML_PLACEHOLDER % '([0-9]+)') + + + module-attribute + + +

    + + +
    + +

    Regular expression which matches HTML placeholders.

    +
    + +
    + + + + + + +
    + + + + +

    + markdown.util.TAG_PLACEHOLDER = STX + 'hzzhzkh:%s' + ETX + + + module-attribute + + +

    + + +
    + +

    Placeholder template for tags.

    +
    + +
    + + + + + + + +
    + + + + +

    + markdown.util.get_installed_extensions() + + + cached + + +

    + + +
    + +

    Return all entry_points in the markdown.extensions group.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.util.deprecated(message, stacklevel=2) + +

    + + +
    + +

    Raise a DeprecationWarning when wrapped function/method is called.

    +

    Usage:

    +
    @deprecated("This method will be removed in version X; use Y instead.")
    +def some_method():
    +    pass
    +
    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.util.parseBoolValue(value: str, fail_on_errors: bool = True, preserve_none: bool = False) -> bool | None + +

    + + +
    + +

    Parses a string representing a boolean value. If parsing was successful, +returns True or False. If preserve_none=True, returns True, False, +or None. If parsing was not successful, raises ValueError, or, if +fail_on_errors=False, returns None.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.util.code_escape(text: str) -> str + +

    + + +
    + +

    HTML escape a string of code.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.util.nearing_recursion_limit() + +

    + + +
    + +

    Return true if current stack depth is within 100 of maximum limit.

    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.util.AtomicString + + +

    + + +
    +

    + Bases: str

    + + +

    A string which should not be further processed.

    + + +
    + +
    + + + + + + +
    + + + + +

    + markdown.util.Processor(md: Markdown = None) + +

    + + +
    + + +

    The base class for all processors.

    + + + +

    Attributes:

    +
      +
    • + Processor.md + – +
      +

      The Markdown instance passed in an initialization.

      +
      +
    • +
    + + + +

    Parameters:

    +
      +
    • + md + (Markdown, default: + None +) + – +
      +

      The Markdown instance this processor is a part of.

      +
      +
    • +
    + + + + +
    + + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.util.HtmlStash() + +

    + + +
    + + +

    This class is used for stashing HTML objects that we extract +in the beginning and replace with place-holders.

    + + + + +
    + + + + + + + + +
    + + + + +

    + markdown.util.HtmlStash.store(html: str) -> str + +

    + + +
    + +

    Saves an HTML segment for later reinsertion. Returns a +placeholder string that needs to be inserted into the +document.

    + + + +

    Other Parameters:

    +
      +
    • + html + (str) + – +
      +

      An html segment.

      +
      +
    • +
    + + + +

    Returns:

    +
      +
    • + str + – +
      +

      A placeholder string.

      +
      +
    • +
    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.util.HtmlStash.reset() + +

    + + +
    + +

    Clear the stash.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.util.HtmlStash.store_tag(tag, attrs, left_index, right_index) -> str + +

    + + +
    + +

    Store tag data and return a placeholder.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + + + +
    + + + + +

    + markdown.util.Registry() + +

    + + +
    + + +

    A priority sorted registry.

    +

    A Registry instance provides two public methods to alter the data of the +registry: register and deregister. Use register to add items and +deregister to remove items. See each method for specifics.

    +

    When registering an item, a “name” and a “priority” must be provided. All +items are automatically sorted by “priority” from highest to lowest. The +“name” is used to remove (“deregister”) and get items.

    +

    A Registry instance it like a list (which maintains order) when reading +data. You may iterate over the items, get an item and get a count (length) +of all items. You may also check that the registry contains an item.

    +

    When getting an item you may use either the index of the item or the +string-based “name”. For example:

    +
    registry = Registry()
    +registry.register(SomeItem(), 'itemname', 20)
    +# Get the item by index
    +item = registry[0]
    +# Get the item by name
    +item = registry['itemname']
    +
    + +

    When checking that the registry contains an item, you may use either the +string-based “name”, or a reference to the actual item. For example:

    +
    someitem = SomeItem()
    +registry.register(someitem, 'itemname', 20)
    +# Contains the name
    +assert 'itemname' in registry
    +# Contains the item instance
    +assert someitem in registry
    +
    + +

    The method get_index_for_name is also available to obtain the index of +an item using that item’s assigned “name”.

    + + + + +
    + + + + + + + + +
    + + + + +

    + markdown.util.Registry.get_index_for_name(name) -> int + +

    + + +
    + +

    Return the index of the given name.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.util.Registry.register(item: Any, name: str, priority: int) + +

    + + +
    + +

    Add an item to the registry with the given name and priority.

    + + + +

    Parameters:

    +
      +
    • + item + (Any) + – +
      +

      The item being registered.

      +
      +
    • +
    • + name + (str) + – +
      +

      A string used to reference the item.

      +
      +
    • +
    • + priority + (int) + – +
      +

      An integer or float used to sort against all items.

      +
      +
    • +
    +

    If an item is registered with a “name” which already exists, the +existing item is replaced with the new item. Treat carefully as the +old item is lost with no way to recover it. The new item will be +sorted according to its priority and will not retain the position +of the old item.

    + +
    + +
    + + + + + + + +
    + + + + +

    + markdown.util.Registry.deregister(name, strict=True) + +

    + + +
    + +

    Remove an item from the registry.

    +

    Set strict=False to fail silently. Otherwise a ValueError is raised for an unknown name.

    + +
    + +
    + + + + +
    + +
    + +
    + + + + +
    + +
    + +
    + +
    +
    +
    + + +
    +
    + + + + + + + \ No newline at end of file diff --git a/search.html b/search.html deleted file mode 100755 index b035c85..0000000 --- a/search.html +++ /dev/null @@ -1,122 +0,0 @@ - - - - - - - - - - - - - - Search — Python-Markdown 3.4.4 documentation - - - - - - - - - -
    -
    -
    -
    -

    Search

    -
    - -

    - Please activate JavaScript to enable the search - functionality. -

    -
    -

    - From here you can search these documents. Enter your search - words into the box below. -

    -
    - -
    - -
    - -
    - -
    -
    -
    - - -
    -
    - - - - - - - - \ No newline at end of file diff --git a/search/lunr.js b/search/lunr.js deleted file mode 100755 index c353765..0000000 --- a/search/lunr.js +++ /dev/null @@ -1,3475 +0,0 @@ -/** - * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.8 - * Copyright (C) 2019 Oliver Nightingale - * @license MIT - */ - -;(function(){ - -/** - * A convenience function for configuring and constructing - * a new lunr Index. - * - * A lunr.Builder instance is created and the pipeline setup - * with a trimmer, stop word filter and stemmer. - * - * This builder object is yielded to the configuration function - * that is passed as a parameter, allowing the list of fields - * and other builder parameters to be customised. - * - * All documents _must_ be added within the passed config function. - * - * @example - * var idx = lunr(function () { - * this.field('title') - * this.field('body') - * this.ref('id') - * - * documents.forEach(function (doc) { - * this.add(doc) - * }, this) - * }) - * - * @see {@link lunr.Builder} - * @see {@link lunr.Pipeline} - * @see {@link lunr.trimmer} - * @see {@link lunr.stopWordFilter} - * @see {@link lunr.stemmer} - * @namespace {function} lunr - */ -var lunr = function (config) { - var builder = new lunr.Builder - - builder.pipeline.add( - lunr.trimmer, - lunr.stopWordFilter, - lunr.stemmer - ) - - builder.searchPipeline.add( - lunr.stemmer - ) - - config.call(builder, builder) - return builder.build() -} - -lunr.version = "2.3.8" -/*! - * lunr.utils - * Copyright (C) 2019 Oliver Nightingale - */ - -/** - * A namespace containing utils for the rest of the lunr library - * @namespace lunr.utils - */ -lunr.utils = {} - -/** - * Print a warning message to the console. - * - * @param {String} message The message to be printed. - * @memberOf lunr.utils - * @function - */ -lunr.utils.warn = (function (global) { - /* eslint-disable no-console */ - return function (message) { - if (global.console && console.warn) { - console.warn(message) - } - } - /* eslint-enable no-console */ -})(this) - -/** - * Convert an object to a string. - * - * In the case of `null` and `undefined` the function returns - * the empty string, in all other cases the result of calling - * `toString` on the passed object is returned. - * - * @param {Any} obj The object to convert to a string. - * @return {String} string representation of the passed object. - * @memberOf lunr.utils - */ -lunr.utils.asString = function (obj) { - if (obj === void 0 || obj === null) { - return "" - } else { - return obj.toString() - } -} - -/** - * Clones an object. - * - * Will create a copy of an existing object such that any mutations - * on the copy cannot affect the original. - * - * Only shallow objects are supported, passing a nested object to this - * function will cause a TypeError. - * - * Objects with primitives, and arrays of primitives are supported. - * - * @param {Object} obj The object to clone. - * @return {Object} a clone of the passed object. - * @throws {TypeError} when a nested object is passed. - * @memberOf Utils - */ -lunr.utils.clone = function (obj) { - if (obj === null || obj === undefined) { - return obj - } - - var clone = Object.create(null), - keys = Object.keys(obj) - - for (var i = 0; i < keys.length; i++) { - var key = keys[i], - val = obj[key] - - if (Array.isArray(val)) { - clone[key] = val.slice() - continue - } - - if (typeof val === 'string' || - typeof val === 'number' || - typeof val === 'boolean') { - clone[key] = val - continue - } - - throw new TypeError("clone is not deep and does not support nested objects") - } - - return clone -} -lunr.FieldRef = function (docRef, fieldName, stringValue) { - this.docRef = docRef - this.fieldName = fieldName - this._stringValue = stringValue -} - -lunr.FieldRef.joiner = "/" - -lunr.FieldRef.fromString = function (s) { - var n = s.indexOf(lunr.FieldRef.joiner) - - if (n === -1) { - throw "malformed field ref string" - } - - var fieldRef = s.slice(0, n), - docRef = s.slice(n + 1) - - return new lunr.FieldRef (docRef, fieldRef, s) -} - -lunr.FieldRef.prototype.toString = function () { - if (this._stringValue == undefined) { - this._stringValue = this.fieldName + lunr.FieldRef.joiner + this.docRef - } - - return this._stringValue -} -/*! - * lunr.Set - * Copyright (C) 2019 Oliver Nightingale - */ - -/** - * A lunr set. - * - * @constructor - */ -lunr.Set = function (elements) { - this.elements = Object.create(null) - - if (elements) { - this.length = elements.length - - for (var i = 0; i < this.length; i++) { - this.elements[elements[i]] = true - } - } else { - this.length = 0 - } -} - -/** - * A complete set that contains all elements. - * - * @static - * @readonly - * @type {lunr.Set} - */ -lunr.Set.complete = { - intersect: function (other) { - return other - }, - - union: function (other) { - return other - }, - - contains: function () { - return true - } -} - -/** - * An empty set that contains no elements. - * - * @static - * @readonly - * @type {lunr.Set} - */ -lunr.Set.empty = { - intersect: function () { - return this - }, - - union: function (other) { - return other - }, - - contains: function () { - return false - } -} - -/** - * Returns true if this set contains the specified object. - * - * @param {object} object - Object whose presence in this set is to be tested. - * @returns {boolean} - True if this set contains the specified object. - */ -lunr.Set.prototype.contains = function (object) { - return !!this.elements[object] -} - -/** - * Returns a new set containing only the elements that are present in both - * this set and the specified set. - * - * @param {lunr.Set} other - set to intersect with this set. - * @returns {lunr.Set} a new set that is the intersection of this and the specified set. - */ - -lunr.Set.prototype.intersect = function (other) { - var a, b, elements, intersection = [] - - if (other === lunr.Set.complete) { - return this - } - - if (other === lunr.Set.empty) { - return other - } - - if (this.length < other.length) { - a = this - b = other - } else { - a = other - b = this - } - - elements = Object.keys(a.elements) - - for (var i = 0; i < elements.length; i++) { - var element = elements[i] - if (element in b.elements) { - intersection.push(element) - } - } - - return new lunr.Set (intersection) -} - -/** - * Returns a new set combining the elements of this and the specified set. - * - * @param {lunr.Set} other - set to union with this set. - * @return {lunr.Set} a new set that is the union of this and the specified set. - */ - -lunr.Set.prototype.union = function (other) { - if (other === lunr.Set.complete) { - return lunr.Set.complete - } - - if (other === lunr.Set.empty) { - return this - } - - return new lunr.Set(Object.keys(this.elements).concat(Object.keys(other.elements))) -} -/** - * A function to calculate the inverse document frequency for - * a posting. This is shared between the builder and the index - * - * @private - * @param {object} posting - The posting for a given term - * @param {number} documentCount - The total number of documents. - */ -lunr.idf = function (posting, documentCount) { - var documentsWithTerm = 0 - - for (var fieldName in posting) { - if (fieldName == '_index') continue // Ignore the term index, its not a field - documentsWithTerm += Object.keys(posting[fieldName]).length - } - - var x = (documentCount - documentsWithTerm + 0.5) / (documentsWithTerm + 0.5) - - return Math.log(1 + Math.abs(x)) -} - -/** - * A token wraps a string representation of a token - * as it is passed through the text processing pipeline. - * - * @constructor - * @param {string} [str=''] - The string token being wrapped. - * @param {object} [metadata={}] - Metadata associated with this token. - */ -lunr.Token = function (str, metadata) { - this.str = str || "" - this.metadata = metadata || {} -} - -/** - * Returns the token string that is being wrapped by this object. - * - * @returns {string} - */ -lunr.Token.prototype.toString = function () { - return this.str -} - -/** - * A token update function is used when updating or optionally - * when cloning a token. - * - * @callback lunr.Token~updateFunction - * @param {string} str - The string representation of the token. - * @param {Object} metadata - All metadata associated with this token. - */ - -/** - * Applies the given function to the wrapped string token. - * - * @example - * token.update(function (str, metadata) { - * return str.toUpperCase() - * }) - * - * @param {lunr.Token~updateFunction} fn - A function to apply to the token string. - * @returns {lunr.Token} - */ -lunr.Token.prototype.update = function (fn) { - this.str = fn(this.str, this.metadata) - return this -} - -/** - * Creates a clone of this token. Optionally a function can be - * applied to the cloned token. - * - * @param {lunr.Token~updateFunction} [fn] - An optional function to apply to the cloned token. - * @returns {lunr.Token} - */ -lunr.Token.prototype.clone = function (fn) { - fn = fn || function (s) { return s } - return new lunr.Token (fn(this.str, this.metadata), this.metadata) -} -/*! - * lunr.tokenizer - * Copyright (C) 2019 Oliver Nightingale - */ - -/** - * A function for splitting a string into tokens ready to be inserted into - * the search index. Uses `lunr.tokenizer.separator` to split strings, change - * the value of this property to change how strings are split into tokens. - * - * This tokenizer will convert its parameter to a string by calling `toString` and - * then will split this string on the character in `lunr.tokenizer.separator`. - * Arrays will have their elements converted to strings and wrapped in a lunr.Token. - * - * Optional metadata can be passed to the tokenizer, this metadata will be cloned and - * added as metadata to every token that is created from the object to be tokenized. - * - * @static - * @param {?(string|object|object[])} obj - The object to convert into tokens - * @param {?object} metadata - Optional metadata to associate with every token - * @returns {lunr.Token[]} - * @see {@link lunr.Pipeline} - */ -lunr.tokenizer = function (obj, metadata) { - if (obj == null || obj == undefined) { - return [] - } - - if (Array.isArray(obj)) { - return obj.map(function (t) { - return new lunr.Token( - lunr.utils.asString(t).toLowerCase(), - lunr.utils.clone(metadata) - ) - }) - } - - var str = obj.toString().toLowerCase(), - len = str.length, - tokens = [] - - for (var sliceEnd = 0, sliceStart = 0; sliceEnd <= len; sliceEnd++) { - var char = str.charAt(sliceEnd), - sliceLength = sliceEnd - sliceStart - - if ((char.match(lunr.tokenizer.separator) || sliceEnd == len)) { - - if (sliceLength > 0) { - var tokenMetadata = lunr.utils.clone(metadata) || {} - tokenMetadata["position"] = [sliceStart, sliceLength] - tokenMetadata["index"] = tokens.length - - tokens.push( - new lunr.Token ( - str.slice(sliceStart, sliceEnd), - tokenMetadata - ) - ) - } - - sliceStart = sliceEnd + 1 - } - - } - - return tokens -} - -/** - * The separator used to split a string into tokens. Override this property to change the behaviour of - * `lunr.tokenizer` behaviour when tokenizing strings. By default this splits on whitespace and hyphens. - * - * @static - * @see lunr.tokenizer - */ -lunr.tokenizer.separator = /[\s\-]+/ -/*! - * lunr.Pipeline - * Copyright (C) 2019 Oliver Nightingale - */ - -/** - * lunr.Pipelines maintain an ordered list of functions to be applied to all - * tokens in documents entering the search index and queries being ran against - * the index. - * - * An instance of lunr.Index created with the lunr shortcut will contain a - * pipeline with a stop word filter and an English language stemmer. Extra - * functions can be added before or after either of these functions or these - * default functions can be removed. - * - * When run the pipeline will call each function in turn, passing a token, the - * index of that token in the original list of all tokens and finally a list of - * all the original tokens. - * - * The output of functions in the pipeline will be passed to the next function - * in the pipeline. To exclude a token from entering the index the function - * should return undefined, the rest of the pipeline will not be called with - * this token. - * - * For serialisation of pipelines to work, all functions used in an instance of - * a pipeline should be registered with lunr.Pipeline. Registered functions can - * then be loaded. If trying to load a serialised pipeline that uses functions - * that are not registered an error will be thrown. - * - * If not planning on serialising the pipeline then registering pipeline functions - * is not necessary. - * - * @constructor - */ -lunr.Pipeline = function () { - this._stack = [] -} - -lunr.Pipeline.registeredFunctions = Object.create(null) - -/** - * A pipeline function maps lunr.Token to lunr.Token. A lunr.Token contains the token - * string as well as all known metadata. A pipeline function can mutate the token string - * or mutate (or add) metadata for a given token. - * - * A pipeline function can indicate that the passed token should be discarded by returning - * null, undefined or an empty string. This token will not be passed to any downstream pipeline - * functions and will not be added to the index. - * - * Multiple tokens can be returned by returning an array of tokens. Each token will be passed - * to any downstream pipeline functions and all will returned tokens will be added to the index. - * - * Any number of pipeline functions may be chained together using a lunr.Pipeline. - * - * @interface lunr.PipelineFunction - * @param {lunr.Token} token - A token from the document being processed. - * @param {number} i - The index of this token in the complete list of tokens for this document/field. - * @param {lunr.Token[]} tokens - All tokens for this document/field. - * @returns {(?lunr.Token|lunr.Token[])} - */ - -/** - * Register a function with the pipeline. - * - * Functions that are used in the pipeline should be registered if the pipeline - * needs to be serialised, or a serialised pipeline needs to be loaded. - * - * Registering a function does not add it to a pipeline, functions must still be - * added to instances of the pipeline for them to be used when running a pipeline. - * - * @param {lunr.PipelineFunction} fn - The function to check for. - * @param {String} label - The label to register this function with - */ -lunr.Pipeline.registerFunction = function (fn, label) { - if (label in this.registeredFunctions) { - lunr.utils.warn('Overwriting existing registered function: ' + label) - } - - fn.label = label - lunr.Pipeline.registeredFunctions[fn.label] = fn -} - -/** - * Warns if the function is not registered as a Pipeline function. - * - * @param {lunr.PipelineFunction} fn - The function to check for. - * @private - */ -lunr.Pipeline.warnIfFunctionNotRegistered = function (fn) { - var isRegistered = fn.label && (fn.label in this.registeredFunctions) - - if (!isRegistered) { - lunr.utils.warn('Function is not registered with pipeline. This may cause problems when serialising the index.\n', fn) - } -} - -/** - * Loads a previously serialised pipeline. - * - * All functions to be loaded must already be registered with lunr.Pipeline. - * If any function from the serialised data has not been registered then an - * error will be thrown. - * - * @param {Object} serialised - The serialised pipeline to load. - * @returns {lunr.Pipeline} - */ -lunr.Pipeline.load = function (serialised) { - var pipeline = new lunr.Pipeline - - serialised.forEach(function (fnName) { - var fn = lunr.Pipeline.registeredFunctions[fnName] - - if (fn) { - pipeline.add(fn) - } else { - throw new Error('Cannot load unregistered function: ' + fnName) - } - }) - - return pipeline -} - -/** - * Adds new functions to the end of the pipeline. - * - * Logs a warning if the function has not been registered. - * - * @param {lunr.PipelineFunction[]} functions - Any number of functions to add to the pipeline. - */ -lunr.Pipeline.prototype.add = function () { - var fns = Array.prototype.slice.call(arguments) - - fns.forEach(function (fn) { - lunr.Pipeline.warnIfFunctionNotRegistered(fn) - this._stack.push(fn) - }, this) -} - -/** - * Adds a single function after a function that already exists in the - * pipeline. - * - * Logs a warning if the function has not been registered. - * - * @param {lunr.PipelineFunction} existingFn - A function that already exists in the pipeline. - * @param {lunr.PipelineFunction} newFn - The new function to add to the pipeline. - */ -lunr.Pipeline.prototype.after = function (existingFn, newFn) { - lunr.Pipeline.warnIfFunctionNotRegistered(newFn) - - var pos = this._stack.indexOf(existingFn) - if (pos == -1) { - throw new Error('Cannot find existingFn') - } - - pos = pos + 1 - this._stack.splice(pos, 0, newFn) -} - -/** - * Adds a single function before a function that already exists in the - * pipeline. - * - * Logs a warning if the function has not been registered. - * - * @param {lunr.PipelineFunction} existingFn - A function that already exists in the pipeline. - * @param {lunr.PipelineFunction} newFn - The new function to add to the pipeline. - */ -lunr.Pipeline.prototype.before = function (existingFn, newFn) { - lunr.Pipeline.warnIfFunctionNotRegistered(newFn) - - var pos = this._stack.indexOf(existingFn) - if (pos == -1) { - throw new Error('Cannot find existingFn') - } - - this._stack.splice(pos, 0, newFn) -} - -/** - * Removes a function from the pipeline. - * - * @param {lunr.PipelineFunction} fn The function to remove from the pipeline. - */ -lunr.Pipeline.prototype.remove = function (fn) { - var pos = this._stack.indexOf(fn) - if (pos == -1) { - return - } - - this._stack.splice(pos, 1) -} - -/** - * Runs the current list of functions that make up the pipeline against the - * passed tokens. - * - * @param {Array} tokens The tokens to run through the pipeline. - * @returns {Array} - */ -lunr.Pipeline.prototype.run = function (tokens) { - var stackLength = this._stack.length - - for (var i = 0; i < stackLength; i++) { - var fn = this._stack[i] - var memo = [] - - for (var j = 0; j < tokens.length; j++) { - var result = fn(tokens[j], j, tokens) - - if (result === null || result === void 0 || result === '') continue - - if (Array.isArray(result)) { - for (var k = 0; k < result.length; k++) { - memo.push(result[k]) - } - } else { - memo.push(result) - } - } - - tokens = memo - } - - return tokens -} - -/** - * Convenience method for passing a string through a pipeline and getting - * strings out. This method takes care of wrapping the passed string in a - * token and mapping the resulting tokens back to strings. - * - * @param {string} str - The string to pass through the pipeline. - * @param {?object} metadata - Optional metadata to associate with the token - * passed to the pipeline. - * @returns {string[]} - */ -lunr.Pipeline.prototype.runString = function (str, metadata) { - var token = new lunr.Token (str, metadata) - - return this.run([token]).map(function (t) { - return t.toString() - }) -} - -/** - * Resets the pipeline by removing any existing processors. - * - */ -lunr.Pipeline.prototype.reset = function () { - this._stack = [] -} - -/** - * Returns a representation of the pipeline ready for serialisation. - * - * Logs a warning if the function has not been registered. - * - * @returns {Array} - */ -lunr.Pipeline.prototype.toJSON = function () { - return this._stack.map(function (fn) { - lunr.Pipeline.warnIfFunctionNotRegistered(fn) - - return fn.label - }) -} -/*! - * lunr.Vector - * Copyright (C) 2019 Oliver Nightingale - */ - -/** - * A vector is used to construct the vector space of documents and queries. These - * vectors support operations to determine the similarity between two documents or - * a document and a query. - * - * Normally no parameters are required for initializing a vector, but in the case of - * loading a previously dumped vector the raw elements can be provided to the constructor. - * - * For performance reasons vectors are implemented with a flat array, where an elements - * index is immediately followed by its value. E.g. [index, value, index, value]. This - * allows the underlying array to be as sparse as possible and still offer decent - * performance when being used for vector calculations. - * - * @constructor - * @param {Number[]} [elements] - The flat list of element index and element value pairs. - */ -lunr.Vector = function (elements) { - this._magnitude = 0 - this.elements = elements || [] -} - - -/** - * Calculates the position within the vector to insert a given index. - * - * This is used internally by insert and upsert. If there are duplicate indexes then - * the position is returned as if the value for that index were to be updated, but it - * is the callers responsibility to check whether there is a duplicate at that index - * - * @param {Number} insertIdx - The index at which the element should be inserted. - * @returns {Number} - */ -lunr.Vector.prototype.positionForIndex = function (index) { - // For an empty vector the tuple can be inserted at the beginning - if (this.elements.length == 0) { - return 0 - } - - var start = 0, - end = this.elements.length / 2, - sliceLength = end - start, - pivotPoint = Math.floor(sliceLength / 2), - pivotIndex = this.elements[pivotPoint * 2] - - while (sliceLength > 1) { - if (pivotIndex < index) { - start = pivotPoint - } - - if (pivotIndex > index) { - end = pivotPoint - } - - if (pivotIndex == index) { - break - } - - sliceLength = end - start - pivotPoint = start + Math.floor(sliceLength / 2) - pivotIndex = this.elements[pivotPoint * 2] - } - - if (pivotIndex == index) { - return pivotPoint * 2 - } - - if (pivotIndex > index) { - return pivotPoint * 2 - } - - if (pivotIndex < index) { - return (pivotPoint + 1) * 2 - } -} - -/** - * Inserts an element at an index within the vector. - * - * Does not allow duplicates, will throw an error if there is already an entry - * for this index. - * - * @param {Number} insertIdx - The index at which the element should be inserted. - * @param {Number} val - The value to be inserted into the vector. - */ -lunr.Vector.prototype.insert = function (insertIdx, val) { - this.upsert(insertIdx, val, function () { - throw "duplicate index" - }) -} - -/** - * Inserts or updates an existing index within the vector. - * - * @param {Number} insertIdx - The index at which the element should be inserted. - * @param {Number} val - The value to be inserted into the vector. - * @param {function} fn - A function that is called for updates, the existing value and the - * requested value are passed as arguments - */ -lunr.Vector.prototype.upsert = function (insertIdx, val, fn) { - this._magnitude = 0 - var position = this.positionForIndex(insertIdx) - - if (this.elements[position] == insertIdx) { - this.elements[position + 1] = fn(this.elements[position + 1], val) - } else { - this.elements.splice(position, 0, insertIdx, val) - } -} - -/** - * Calculates the magnitude of this vector. - * - * @returns {Number} - */ -lunr.Vector.prototype.magnitude = function () { - if (this._magnitude) return this._magnitude - - var sumOfSquares = 0, - elementsLength = this.elements.length - - for (var i = 1; i < elementsLength; i += 2) { - var val = this.elements[i] - sumOfSquares += val * val - } - - return this._magnitude = Math.sqrt(sumOfSquares) -} - -/** - * Calculates the dot product of this vector and another vector. - * - * @param {lunr.Vector} otherVector - The vector to compute the dot product with. - * @returns {Number} - */ -lunr.Vector.prototype.dot = function (otherVector) { - var dotProduct = 0, - a = this.elements, b = otherVector.elements, - aLen = a.length, bLen = b.length, - aVal = 0, bVal = 0, - i = 0, j = 0 - - while (i < aLen && j < bLen) { - aVal = a[i], bVal = b[j] - if (aVal < bVal) { - i += 2 - } else if (aVal > bVal) { - j += 2 - } else if (aVal == bVal) { - dotProduct += a[i + 1] * b[j + 1] - i += 2 - j += 2 - } - } - - return dotProduct -} - -/** - * Calculates the similarity between this vector and another vector. - * - * @param {lunr.Vector} otherVector - The other vector to calculate the - * similarity with. - * @returns {Number} - */ -lunr.Vector.prototype.similarity = function (otherVector) { - return this.dot(otherVector) / this.magnitude() || 0 -} - -/** - * Converts the vector to an array of the elements within the vector. - * - * @returns {Number[]} - */ -lunr.Vector.prototype.toArray = function () { - var output = new Array (this.elements.length / 2) - - for (var i = 1, j = 0; i < this.elements.length; i += 2, j++) { - output[j] = this.elements[i] - } - - return output -} - -/** - * A JSON serializable representation of the vector. - * - * @returns {Number[]} - */ -lunr.Vector.prototype.toJSON = function () { - return this.elements -} -/* eslint-disable */ -/*! - * lunr.stemmer - * Copyright (C) 2019 Oliver Nightingale - * Includes code from - http://tartarus.org/~martin/PorterStemmer/js.txt - */ - -/** - * lunr.stemmer is an english language stemmer, this is a JavaScript - * implementation of the PorterStemmer taken from http://tartarus.org/~martin - * - * @static - * @implements {lunr.PipelineFunction} - * @param {lunr.Token} token - The string to stem - * @returns {lunr.Token} - * @see {@link lunr.Pipeline} - * @function - */ -lunr.stemmer = (function(){ - var step2list = { - "ational" : "ate", - "tional" : "tion", - "enci" : "ence", - "anci" : "ance", - "izer" : "ize", - "bli" : "ble", - "alli" : "al", - "entli" : "ent", - "eli" : "e", - "ousli" : "ous", - "ization" : "ize", - "ation" : "ate", - "ator" : "ate", - "alism" : "al", - "iveness" : "ive", - "fulness" : "ful", - "ousness" : "ous", - "aliti" : "al", - "iviti" : "ive", - "biliti" : "ble", - "logi" : "log" - }, - - step3list = { - "icate" : "ic", - "ative" : "", - "alize" : "al", - "iciti" : "ic", - "ical" : "ic", - "ful" : "", - "ness" : "" - }, - - c = "[^aeiou]", // consonant - v = "[aeiouy]", // vowel - C = c + "[^aeiouy]*", // consonant sequence - V = v + "[aeiou]*", // vowel sequence - - mgr0 = "^(" + C + ")?" + V + C, // [C]VC... is m>0 - meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$", // [C]VC[V] is m=1 - mgr1 = "^(" + C + ")?" + V + C + V + C, // [C]VCVC... is m>1 - s_v = "^(" + C + ")?" + v; // vowel in stem - - var re_mgr0 = new RegExp(mgr0); - var re_mgr1 = new RegExp(mgr1); - var re_meq1 = new RegExp(meq1); - var re_s_v = new RegExp(s_v); - - var re_1a = /^(.+?)(ss|i)es$/; - var re2_1a = /^(.+?)([^s])s$/; - var re_1b = /^(.+?)eed$/; - var re2_1b = /^(.+?)(ed|ing)$/; - var re_1b_2 = /.$/; - var re2_1b_2 = /(at|bl|iz)$/; - var re3_1b_2 = new RegExp("([^aeiouylsz])\\1$"); - var re4_1b_2 = new RegExp("^" + C + v + "[^aeiouwxy]$"); - - var re_1c = /^(.+?[^aeiou])y$/; - var re_2 = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; - - var re_3 = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; - - var re_4 = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; - var re2_4 = /^(.+?)(s|t)(ion)$/; - - var re_5 = /^(.+?)e$/; - var re_5_1 = /ll$/; - var re3_5 = new RegExp("^" + C + v + "[^aeiouwxy]$"); - - var porterStemmer = function porterStemmer(w) { - var stem, - suffix, - firstch, - re, - re2, - re3, - re4; - - if (w.length < 3) { return w; } - - firstch = w.substr(0,1); - if (firstch == "y") { - w = firstch.toUpperCase() + w.substr(1); - } - - // Step 1a - re = re_1a - re2 = re2_1a; - - if (re.test(w)) { w = w.replace(re,"$1$2"); } - else if (re2.test(w)) { w = w.replace(re2,"$1$2"); } - - // Step 1b - re = re_1b; - re2 = re2_1b; - if (re.test(w)) { - var fp = re.exec(w); - re = re_mgr0; - if (re.test(fp[1])) { - re = re_1b_2; - w = w.replace(re,""); - } - } else if (re2.test(w)) { - var fp = re2.exec(w); - stem = fp[1]; - re2 = re_s_v; - if (re2.test(stem)) { - w = stem; - re2 = re2_1b_2; - re3 = re3_1b_2; - re4 = re4_1b_2; - if (re2.test(w)) { w = w + "e"; } - else if (re3.test(w)) { re = re_1b_2; w = w.replace(re,""); } - else if (re4.test(w)) { w = w + "e"; } - } - } - - // Step 1c - replace suffix y or Y by i if preceded by a non-vowel which is not the first letter of the word (so cry -> cri, by -> by, say -> say) - re = re_1c; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - w = stem + "i"; - } - - // Step 2 - re = re_2; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - suffix = fp[2]; - re = re_mgr0; - if (re.test(stem)) { - w = stem + step2list[suffix]; - } - } - - // Step 3 - re = re_3; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - suffix = fp[2]; - re = re_mgr0; - if (re.test(stem)) { - w = stem + step3list[suffix]; - } - } - - // Step 4 - re = re_4; - re2 = re2_4; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - re = re_mgr1; - if (re.test(stem)) { - w = stem; - } - } else if (re2.test(w)) { - var fp = re2.exec(w); - stem = fp[1] + fp[2]; - re2 = re_mgr1; - if (re2.test(stem)) { - w = stem; - } - } - - // Step 5 - re = re_5; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - re = re_mgr1; - re2 = re_meq1; - re3 = re3_5; - if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) { - w = stem; - } - } - - re = re_5_1; - re2 = re_mgr1; - if (re.test(w) && re2.test(w)) { - re = re_1b_2; - w = w.replace(re,""); - } - - // and turn initial Y back to y - - if (firstch == "y") { - w = firstch.toLowerCase() + w.substr(1); - } - - return w; - }; - - return function (token) { - return token.update(porterStemmer); - } -})(); - -lunr.Pipeline.registerFunction(lunr.stemmer, 'stemmer') -/*! - * lunr.stopWordFilter - * Copyright (C) 2019 Oliver Nightingale - */ - -/** - * lunr.generateStopWordFilter builds a stopWordFilter function from the provided - * list of stop words. - * - * The built in lunr.stopWordFilter is built using this generator and can be used - * to generate custom stopWordFilters for applications or non English languages. - * - * @function - * @param {Array} token The token to pass through the filter - * @returns {lunr.PipelineFunction} - * @see lunr.Pipeline - * @see lunr.stopWordFilter - */ -lunr.generateStopWordFilter = function (stopWords) { - var words = stopWords.reduce(function (memo, stopWord) { - memo[stopWord] = stopWord - return memo - }, {}) - - return function (token) { - if (token && words[token.toString()] !== token.toString()) return token - } -} - -/** - * lunr.stopWordFilter is an English language stop word list filter, any words - * contained in the list will not be passed through the filter. - * - * This is intended to be used in the Pipeline. If the token does not pass the - * filter then undefined will be returned. - * - * @function - * @implements {lunr.PipelineFunction} - * @params {lunr.Token} token - A token to check for being a stop word. - * @returns {lunr.Token} - * @see {@link lunr.Pipeline} - */ -lunr.stopWordFilter = lunr.generateStopWordFilter([ - 'a', - 'able', - 'about', - 'across', - 'after', - 'all', - 'almost', - 'also', - 'am', - 'among', - 'an', - 'and', - 'any', - 'are', - 'as', - 'at', - 'be', - 'because', - 'been', - 'but', - 'by', - 'can', - 'cannot', - 'could', - 'dear', - 'did', - 'do', - 'does', - 'either', - 'else', - 'ever', - 'every', - 'for', - 'from', - 'get', - 'got', - 'had', - 'has', - 'have', - 'he', - 'her', - 'hers', - 'him', - 'his', - 'how', - 'however', - 'i', - 'if', - 'in', - 'into', - 'is', - 'it', - 'its', - 'just', - 'least', - 'let', - 'like', - 'likely', - 'may', - 'me', - 'might', - 'most', - 'must', - 'my', - 'neither', - 'no', - 'nor', - 'not', - 'of', - 'off', - 'often', - 'on', - 'only', - 'or', - 'other', - 'our', - 'own', - 'rather', - 'said', - 'say', - 'says', - 'she', - 'should', - 'since', - 'so', - 'some', - 'than', - 'that', - 'the', - 'their', - 'them', - 'then', - 'there', - 'these', - 'they', - 'this', - 'tis', - 'to', - 'too', - 'twas', - 'us', - 'wants', - 'was', - 'we', - 'were', - 'what', - 'when', - 'where', - 'which', - 'while', - 'who', - 'whom', - 'why', - 'will', - 'with', - 'would', - 'yet', - 'you', - 'your' -]) - -lunr.Pipeline.registerFunction(lunr.stopWordFilter, 'stopWordFilter') -/*! - * lunr.trimmer - * Copyright (C) 2019 Oliver Nightingale - */ - -/** - * lunr.trimmer is a pipeline function for trimming non word - * characters from the beginning and end of tokens before they - * enter the index. - * - * This implementation may not work correctly for non latin - * characters and should either be removed or adapted for use - * with languages with non-latin characters. - * - * @static - * @implements {lunr.PipelineFunction} - * @param {lunr.Token} token The token to pass through the filter - * @returns {lunr.Token} - * @see lunr.Pipeline - */ -lunr.trimmer = function (token) { - return token.update(function (s) { - return s.replace(/^\W+/, '').replace(/\W+$/, '') - }) -} - -lunr.Pipeline.registerFunction(lunr.trimmer, 'trimmer') -/*! - * lunr.TokenSet - * Copyright (C) 2019 Oliver Nightingale - */ - -/** - * A token set is used to store the unique list of all tokens - * within an index. Token sets are also used to represent an - * incoming query to the index, this query token set and index - * token set are then intersected to find which tokens to look - * up in the inverted index. - * - * A token set can hold multiple tokens, as in the case of the - * index token set, or it can hold a single token as in the - * case of a simple query token set. - * - * Additionally token sets are used to perform wildcard matching. - * Leading, contained and trailing wildcards are supported, and - * from this edit distance matching can also be provided. - * - * Token sets are implemented as a minimal finite state automata, - * where both common prefixes and suffixes are shared between tokens. - * This helps to reduce the space used for storing the token set. - * - * @constructor - */ -lunr.TokenSet = function () { - this.final = false - this.edges = {} - this.id = lunr.TokenSet._nextId - lunr.TokenSet._nextId += 1 -} - -/** - * Keeps track of the next, auto increment, identifier to assign - * to a new tokenSet. - * - * TokenSets require a unique identifier to be correctly minimised. - * - * @private - */ -lunr.TokenSet._nextId = 1 - -/** - * Creates a TokenSet instance from the given sorted array of words. - * - * @param {String[]} arr - A sorted array of strings to create the set from. - * @returns {lunr.TokenSet} - * @throws Will throw an error if the input array is not sorted. - */ -lunr.TokenSet.fromArray = function (arr) { - var builder = new lunr.TokenSet.Builder - - for (var i = 0, len = arr.length; i < len; i++) { - builder.insert(arr[i]) - } - - builder.finish() - return builder.root -} - -/** - * Creates a token set from a query clause. - * - * @private - * @param {Object} clause - A single clause from lunr.Query. - * @param {string} clause.term - The query clause term. - * @param {number} [clause.editDistance] - The optional edit distance for the term. - * @returns {lunr.TokenSet} - */ -lunr.TokenSet.fromClause = function (clause) { - if ('editDistance' in clause) { - return lunr.TokenSet.fromFuzzyString(clause.term, clause.editDistance) - } else { - return lunr.TokenSet.fromString(clause.term) - } -} - -/** - * Creates a token set representing a single string with a specified - * edit distance. - * - * Insertions, deletions, substitutions and transpositions are each - * treated as an edit distance of 1. - * - * Increasing the allowed edit distance will have a dramatic impact - * on the performance of both creating and intersecting these TokenSets. - * It is advised to keep the edit distance less than 3. - * - * @param {string} str - The string to create the token set from. - * @param {number} editDistance - The allowed edit distance to match. - * @returns {lunr.Vector} - */ -lunr.TokenSet.fromFuzzyString = function (str, editDistance) { - var root = new lunr.TokenSet - - var stack = [{ - node: root, - editsRemaining: editDistance, - str: str - }] - - while (stack.length) { - var frame = stack.pop() - - // no edit - if (frame.str.length > 0) { - var char = frame.str.charAt(0), - noEditNode - - if (char in frame.node.edges) { - noEditNode = frame.node.edges[char] - } else { - noEditNode = new lunr.TokenSet - frame.node.edges[char] = noEditNode - } - - if (frame.str.length == 1) { - noEditNode.final = true - } - - stack.push({ - node: noEditNode, - editsRemaining: frame.editsRemaining, - str: frame.str.slice(1) - }) - } - - if (frame.editsRemaining == 0) { - continue - } - - // insertion - if ("*" in frame.node.edges) { - var insertionNode = frame.node.edges["*"] - } else { - var insertionNode = new lunr.TokenSet - frame.node.edges["*"] = insertionNode - } - - if (frame.str.length == 0) { - insertionNode.final = true - } - - stack.push({ - node: insertionNode, - editsRemaining: frame.editsRemaining - 1, - str: frame.str - }) - - // deletion - // can only do a deletion if we have enough edits remaining - // and if there are characters left to delete in the string - if (frame.str.length > 1) { - stack.push({ - node: frame.node, - editsRemaining: frame.editsRemaining - 1, - str: frame.str.slice(1) - }) - } - - // deletion - // just removing the last character from the str - if (frame.str.length == 1) { - frame.node.final = true - } - - // substitution - // can only do a substitution if we have enough edits remaining - // and if there are characters left to substitute - if (frame.str.length >= 1) { - if ("*" in frame.node.edges) { - var substitutionNode = frame.node.edges["*"] - } else { - var substitutionNode = new lunr.TokenSet - frame.node.edges["*"] = substitutionNode - } - - if (frame.str.length == 1) { - substitutionNode.final = true - } - - stack.push({ - node: substitutionNode, - editsRemaining: frame.editsRemaining - 1, - str: frame.str.slice(1) - }) - } - - // transposition - // can only do a transposition if there are edits remaining - // and there are enough characters to transpose - if (frame.str.length > 1) { - var charA = frame.str.charAt(0), - charB = frame.str.charAt(1), - transposeNode - - if (charB in frame.node.edges) { - transposeNode = frame.node.edges[charB] - } else { - transposeNode = new lunr.TokenSet - frame.node.edges[charB] = transposeNode - } - - if (frame.str.length == 1) { - transposeNode.final = true - } - - stack.push({ - node: transposeNode, - editsRemaining: frame.editsRemaining - 1, - str: charA + frame.str.slice(2) - }) - } - } - - return root -} - -/** - * Creates a TokenSet from a string. - * - * The string may contain one or more wildcard characters (*) - * that will allow wildcard matching when intersecting with - * another TokenSet. - * - * @param {string} str - The string to create a TokenSet from. - * @returns {lunr.TokenSet} - */ -lunr.TokenSet.fromString = function (str) { - var node = new lunr.TokenSet, - root = node - - /* - * Iterates through all characters within the passed string - * appending a node for each character. - * - * When a wildcard character is found then a self - * referencing edge is introduced to continually match - * any number of any characters. - */ - for (var i = 0, len = str.length; i < len; i++) { - var char = str[i], - final = (i == len - 1) - - if (char == "*") { - node.edges[char] = node - node.final = final - - } else { - var next = new lunr.TokenSet - next.final = final - - node.edges[char] = next - node = next - } - } - - return root -} - -/** - * Converts this TokenSet into an array of strings - * contained within the TokenSet. - * - * This is not intended to be used on a TokenSet that - * contains wildcards, in these cases the results are - * undefined and are likely to cause an infinite loop. - * - * @returns {string[]} - */ -lunr.TokenSet.prototype.toArray = function () { - var words = [] - - var stack = [{ - prefix: "", - node: this - }] - - while (stack.length) { - var frame = stack.pop(), - edges = Object.keys(frame.node.edges), - len = edges.length - - if (frame.node.final) { - /* In Safari, at this point the prefix is sometimes corrupted, see: - * https://github.com/olivernn/lunr.js/issues/279 Calling any - * String.prototype method forces Safari to "cast" this string to what - * it's supposed to be, fixing the bug. */ - frame.prefix.charAt(0) - words.push(frame.prefix) - } - - for (var i = 0; i < len; i++) { - var edge = edges[i] - - stack.push({ - prefix: frame.prefix.concat(edge), - node: frame.node.edges[edge] - }) - } - } - - return words -} - -/** - * Generates a string representation of a TokenSet. - * - * This is intended to allow TokenSets to be used as keys - * in objects, largely to aid the construction and minimisation - * of a TokenSet. As such it is not designed to be a human - * friendly representation of the TokenSet. - * - * @returns {string} - */ -lunr.TokenSet.prototype.toString = function () { - // NOTE: Using Object.keys here as this.edges is very likely - // to enter 'hash-mode' with many keys being added - // - // avoiding a for-in loop here as it leads to the function - // being de-optimised (at least in V8). From some simple - // benchmarks the performance is comparable, but allowing - // V8 to optimize may mean easy performance wins in the future. - - if (this._str) { - return this._str - } - - var str = this.final ? '1' : '0', - labels = Object.keys(this.edges).sort(), - len = labels.length - - for (var i = 0; i < len; i++) { - var label = labels[i], - node = this.edges[label] - - str = str + label + node.id - } - - return str -} - -/** - * Returns a new TokenSet that is the intersection of - * this TokenSet and the passed TokenSet. - * - * This intersection will take into account any wildcards - * contained within the TokenSet. - * - * @param {lunr.TokenSet} b - An other TokenSet to intersect with. - * @returns {lunr.TokenSet} - */ -lunr.TokenSet.prototype.intersect = function (b) { - var output = new lunr.TokenSet, - frame = undefined - - var stack = [{ - qNode: b, - output: output, - node: this - }] - - while (stack.length) { - frame = stack.pop() - - // NOTE: As with the #toString method, we are using - // Object.keys and a for loop instead of a for-in loop - // as both of these objects enter 'hash' mode, causing - // the function to be de-optimised in V8 - var qEdges = Object.keys(frame.qNode.edges), - qLen = qEdges.length, - nEdges = Object.keys(frame.node.edges), - nLen = nEdges.length - - for (var q = 0; q < qLen; q++) { - var qEdge = qEdges[q] - - for (var n = 0; n < nLen; n++) { - var nEdge = nEdges[n] - - if (nEdge == qEdge || qEdge == '*') { - var node = frame.node.edges[nEdge], - qNode = frame.qNode.edges[qEdge], - final = node.final && qNode.final, - next = undefined - - if (nEdge in frame.output.edges) { - // an edge already exists for this character - // no need to create a new node, just set the finality - // bit unless this node is already final - next = frame.output.edges[nEdge] - next.final = next.final || final - - } else { - // no edge exists yet, must create one - // set the finality bit and insert it - // into the output - next = new lunr.TokenSet - next.final = final - frame.output.edges[nEdge] = next - } - - stack.push({ - qNode: qNode, - output: next, - node: node - }) - } - } - } - } - - return output -} -lunr.TokenSet.Builder = function () { - this.previousWord = "" - this.root = new lunr.TokenSet - this.uncheckedNodes = [] - this.minimizedNodes = {} -} - -lunr.TokenSet.Builder.prototype.insert = function (word) { - var node, - commonPrefix = 0 - - if (word < this.previousWord) { - throw new Error ("Out of order word insertion") - } - - for (var i = 0; i < word.length && i < this.previousWord.length; i++) { - if (word[i] != this.previousWord[i]) break - commonPrefix++ - } - - this.minimize(commonPrefix) - - if (this.uncheckedNodes.length == 0) { - node = this.root - } else { - node = this.uncheckedNodes[this.uncheckedNodes.length - 1].child - } - - for (var i = commonPrefix; i < word.length; i++) { - var nextNode = new lunr.TokenSet, - char = word[i] - - node.edges[char] = nextNode - - this.uncheckedNodes.push({ - parent: node, - char: char, - child: nextNode - }) - - node = nextNode - } - - node.final = true - this.previousWord = word -} - -lunr.TokenSet.Builder.prototype.finish = function () { - this.minimize(0) -} - -lunr.TokenSet.Builder.prototype.minimize = function (downTo) { - for (var i = this.uncheckedNodes.length - 1; i >= downTo; i--) { - var node = this.uncheckedNodes[i], - childKey = node.child.toString() - - if (childKey in this.minimizedNodes) { - node.parent.edges[node.char] = this.minimizedNodes[childKey] - } else { - // Cache the key for this node since - // we know it can't change anymore - node.child._str = childKey - - this.minimizedNodes[childKey] = node.child - } - - this.uncheckedNodes.pop() - } -} -/*! - * lunr.Index - * Copyright (C) 2019 Oliver Nightingale - */ - -/** - * An index contains the built index of all documents and provides a query interface - * to the index. - * - * Usually instances of lunr.Index will not be created using this constructor, instead - * lunr.Builder should be used to construct new indexes, or lunr.Index.load should be - * used to load previously built and serialized indexes. - * - * @constructor - * @param {Object} attrs - The attributes of the built search index. - * @param {Object} attrs.invertedIndex - An index of term/field to document reference. - * @param {Object} attrs.fieldVectors - Field vectors - * @param {lunr.TokenSet} attrs.tokenSet - An set of all corpus tokens. - * @param {string[]} attrs.fields - The names of indexed document fields. - * @param {lunr.Pipeline} attrs.pipeline - The pipeline to use for search terms. - */ -lunr.Index = function (attrs) { - this.invertedIndex = attrs.invertedIndex - this.fieldVectors = attrs.fieldVectors - this.tokenSet = attrs.tokenSet - this.fields = attrs.fields - this.pipeline = attrs.pipeline -} - -/** - * A result contains details of a document matching a search query. - * @typedef {Object} lunr.Index~Result - * @property {string} ref - The reference of the document this result represents. - * @property {number} score - A number between 0 and 1 representing how similar this document is to the query. - * @property {lunr.MatchData} matchData - Contains metadata about this match including which term(s) caused the match. - */ - -/** - * Although lunr provides the ability to create queries using lunr.Query, it also provides a simple - * query language which itself is parsed into an instance of lunr.Query. - * - * For programmatically building queries it is advised to directly use lunr.Query, the query language - * is best used for human entered text rather than program generated text. - * - * At its simplest queries can just be a single term, e.g. `hello`, multiple terms are also supported - * and will be combined with OR, e.g `hello world` will match documents that contain either 'hello' - * or 'world', though those that contain both will rank higher in the results. - * - * Wildcards can be included in terms to match one or more unspecified characters, these wildcards can - * be inserted anywhere within the term, and more than one wildcard can exist in a single term. Adding - * wildcards will increase the number of documents that will be found but can also have a negative - * impact on query performance, especially with wildcards at the beginning of a term. - * - * Terms can be restricted to specific fields, e.g. `title:hello`, only documents with the term - * hello in the title field will match this query. Using a field not present in the index will lead - * to an error being thrown. - * - * Modifiers can also be added to terms, lunr supports edit distance and boost modifiers on terms. A term - * boost will make documents matching that term score higher, e.g. `foo^5`. Edit distance is also supported - * to provide fuzzy matching, e.g. 'hello~2' will match documents with hello with an edit distance of 2. - * Avoid large values for edit distance to improve query performance. - * - * Each term also supports a presence modifier. By default a term's presence in document is optional, however - * this can be changed to either required or prohibited. For a term's presence to be required in a document the - * term should be prefixed with a '+', e.g. `+foo bar` is a search for documents that must contain 'foo' and - * optionally contain 'bar'. Conversely a leading '-' sets the terms presence to prohibited, i.e. it must not - * appear in a document, e.g. `-foo bar` is a search for documents that do not contain 'foo' but may contain 'bar'. - * - * To escape special characters the backslash character '\' can be used, this allows searches to include - * characters that would normally be considered modifiers, e.g. `foo\~2` will search for a term "foo~2" instead - * of attempting to apply a boost of 2 to the search term "foo". - * - * @typedef {string} lunr.Index~QueryString - * @example Simple single term query - * hello - * @example Multiple term query - * hello world - * @example term scoped to a field - * title:hello - * @example term with a boost of 10 - * hello^10 - * @example term with an edit distance of 2 - * hello~2 - * @example terms with presence modifiers - * -foo +bar baz - */ - -/** - * Performs a search against the index using lunr query syntax. - * - * Results will be returned sorted by their score, the most relevant results - * will be returned first. For details on how the score is calculated, please see - * the {@link https://lunrjs.com/guides/searching.html#scoring|guide}. - * - * For more programmatic querying use lunr.Index#query. - * - * @param {lunr.Index~QueryString} queryString - A string containing a lunr query. - * @throws {lunr.QueryParseError} If the passed query string cannot be parsed. - * @returns {lunr.Index~Result[]} - */ -lunr.Index.prototype.search = function (queryString) { - return this.query(function (query) { - var parser = new lunr.QueryParser(queryString, query) - parser.parse() - }) -} - -/** - * A query builder callback provides a query object to be used to express - * the query to perform on the index. - * - * @callback lunr.Index~queryBuilder - * @param {lunr.Query} query - The query object to build up. - * @this lunr.Query - */ - -/** - * Performs a query against the index using the yielded lunr.Query object. - * - * If performing programmatic queries against the index, this method is preferred - * over lunr.Index#search so as to avoid the additional query parsing overhead. - * - * A query object is yielded to the supplied function which should be used to - * express the query to be run against the index. - * - * Note that although this function takes a callback parameter it is _not_ an - * asynchronous operation, the callback is just yielded a query object to be - * customized. - * - * @param {lunr.Index~queryBuilder} fn - A function that is used to build the query. - * @returns {lunr.Index~Result[]} - */ -lunr.Index.prototype.query = function (fn) { - // for each query clause - // * process terms - // * expand terms from token set - // * find matching documents and metadata - // * get document vectors - // * score documents - - var query = new lunr.Query(this.fields), - matchingFields = Object.create(null), - queryVectors = Object.create(null), - termFieldCache = Object.create(null), - requiredMatches = Object.create(null), - prohibitedMatches = Object.create(null) - - /* - * To support field level boosts a query vector is created per - * field. An empty vector is eagerly created to support negated - * queries. - */ - for (var i = 0; i < this.fields.length; i++) { - queryVectors[this.fields[i]] = new lunr.Vector - } - - fn.call(query, query) - - for (var i = 0; i < query.clauses.length; i++) { - /* - * Unless the pipeline has been disabled for this term, which is - * the case for terms with wildcards, we need to pass the clause - * term through the search pipeline. A pipeline returns an array - * of processed terms. Pipeline functions may expand the passed - * term, which means we may end up performing multiple index lookups - * for a single query term. - */ - var clause = query.clauses[i], - terms = null, - clauseMatches = lunr.Set.complete - - if (clause.usePipeline) { - terms = this.pipeline.runString(clause.term, { - fields: clause.fields - }) - } else { - terms = [clause.term] - } - - for (var m = 0; m < terms.length; m++) { - var term = terms[m] - - /* - * Each term returned from the pipeline needs to use the same query - * clause object, e.g. the same boost and or edit distance. The - * simplest way to do this is to re-use the clause object but mutate - * its term property. - */ - clause.term = term - - /* - * From the term in the clause we create a token set which will then - * be used to intersect the indexes token set to get a list of terms - * to lookup in the inverted index - */ - var termTokenSet = lunr.TokenSet.fromClause(clause), - expandedTerms = this.tokenSet.intersect(termTokenSet).toArray() - - /* - * If a term marked as required does not exist in the tokenSet it is - * impossible for the search to return any matches. We set all the field - * scoped required matches set to empty and stop examining any further - * clauses. - */ - if (expandedTerms.length === 0 && clause.presence === lunr.Query.presence.REQUIRED) { - for (var k = 0; k < clause.fields.length; k++) { - var field = clause.fields[k] - requiredMatches[field] = lunr.Set.empty - } - - break - } - - for (var j = 0; j < expandedTerms.length; j++) { - /* - * For each term get the posting and termIndex, this is required for - * building the query vector. - */ - var expandedTerm = expandedTerms[j], - posting = this.invertedIndex[expandedTerm], - termIndex = posting._index - - for (var k = 0; k < clause.fields.length; k++) { - /* - * For each field that this query term is scoped by (by default - * all fields are in scope) we need to get all the document refs - * that have this term in that field. - * - * The posting is the entry in the invertedIndex for the matching - * term from above. - */ - var field = clause.fields[k], - fieldPosting = posting[field], - matchingDocumentRefs = Object.keys(fieldPosting), - termField = expandedTerm + "/" + field, - matchingDocumentsSet = new lunr.Set(matchingDocumentRefs) - - /* - * if the presence of this term is required ensure that the matching - * documents are added to the set of required matches for this clause. - * - */ - if (clause.presence == lunr.Query.presence.REQUIRED) { - clauseMatches = clauseMatches.union(matchingDocumentsSet) - - if (requiredMatches[field] === undefined) { - requiredMatches[field] = lunr.Set.complete - } - } - - /* - * if the presence of this term is prohibited ensure that the matching - * documents are added to the set of prohibited matches for this field, - * creating that set if it does not yet exist. - */ - if (clause.presence == lunr.Query.presence.PROHIBITED) { - if (prohibitedMatches[field] === undefined) { - prohibitedMatches[field] = lunr.Set.empty - } - - prohibitedMatches[field] = prohibitedMatches[field].union(matchingDocumentsSet) - - /* - * Prohibited matches should not be part of the query vector used for - * similarity scoring and no metadata should be extracted so we continue - * to the next field - */ - continue - } - - /* - * The query field vector is populated using the termIndex found for - * the term and a unit value with the appropriate boost applied. - * Using upsert because there could already be an entry in the vector - * for the term we are working with. In that case we just add the scores - * together. - */ - queryVectors[field].upsert(termIndex, clause.boost, function (a, b) { return a + b }) - - /** - * If we've already seen this term, field combo then we've already collected - * the matching documents and metadata, no need to go through all that again - */ - if (termFieldCache[termField]) { - continue - } - - for (var l = 0; l < matchingDocumentRefs.length; l++) { - /* - * All metadata for this term/field/document triple - * are then extracted and collected into an instance - * of lunr.MatchData ready to be returned in the query - * results - */ - var matchingDocumentRef = matchingDocumentRefs[l], - matchingFieldRef = new lunr.FieldRef (matchingDocumentRef, field), - metadata = fieldPosting[matchingDocumentRef], - fieldMatch - - if ((fieldMatch = matchingFields[matchingFieldRef]) === undefined) { - matchingFields[matchingFieldRef] = new lunr.MatchData (expandedTerm, field, metadata) - } else { - fieldMatch.add(expandedTerm, field, metadata) - } - - } - - termFieldCache[termField] = true - } - } - } - - /** - * If the presence was required we need to update the requiredMatches field sets. - * We do this after all fields for the term have collected their matches because - * the clause terms presence is required in _any_ of the fields not _all_ of the - * fields. - */ - if (clause.presence === lunr.Query.presence.REQUIRED) { - for (var k = 0; k < clause.fields.length; k++) { - var field = clause.fields[k] - requiredMatches[field] = requiredMatches[field].intersect(clauseMatches) - } - } - } - - /** - * Need to combine the field scoped required and prohibited - * matching documents into a global set of required and prohibited - * matches - */ - var allRequiredMatches = lunr.Set.complete, - allProhibitedMatches = lunr.Set.empty - - for (var i = 0; i < this.fields.length; i++) { - var field = this.fields[i] - - if (requiredMatches[field]) { - allRequiredMatches = allRequiredMatches.intersect(requiredMatches[field]) - } - - if (prohibitedMatches[field]) { - allProhibitedMatches = allProhibitedMatches.union(prohibitedMatches[field]) - } - } - - var matchingFieldRefs = Object.keys(matchingFields), - results = [], - matches = Object.create(null) - - /* - * If the query is negated (contains only prohibited terms) - * we need to get _all_ fieldRefs currently existing in the - * index. This is only done when we know that the query is - * entirely prohibited terms to avoid any cost of getting all - * fieldRefs unnecessarily. - * - * Additionally, blank MatchData must be created to correctly - * populate the results. - */ - if (query.isNegated()) { - matchingFieldRefs = Object.keys(this.fieldVectors) - - for (var i = 0; i < matchingFieldRefs.length; i++) { - var matchingFieldRef = matchingFieldRefs[i] - var fieldRef = lunr.FieldRef.fromString(matchingFieldRef) - matchingFields[matchingFieldRef] = new lunr.MatchData - } - } - - for (var i = 0; i < matchingFieldRefs.length; i++) { - /* - * Currently we have document fields that match the query, but we - * need to return documents. The matchData and scores are combined - * from multiple fields belonging to the same document. - * - * Scores are calculated by field, using the query vectors created - * above, and combined into a final document score using addition. - */ - var fieldRef = lunr.FieldRef.fromString(matchingFieldRefs[i]), - docRef = fieldRef.docRef - - if (!allRequiredMatches.contains(docRef)) { - continue - } - - if (allProhibitedMatches.contains(docRef)) { - continue - } - - var fieldVector = this.fieldVectors[fieldRef], - score = queryVectors[fieldRef.fieldName].similarity(fieldVector), - docMatch - - if ((docMatch = matches[docRef]) !== undefined) { - docMatch.score += score - docMatch.matchData.combine(matchingFields[fieldRef]) - } else { - var match = { - ref: docRef, - score: score, - matchData: matchingFields[fieldRef] - } - matches[docRef] = match - results.push(match) - } - } - - /* - * Sort the results objects by score, highest first. - */ - return results.sort(function (a, b) { - return b.score - a.score - }) -} - -/** - * Prepares the index for JSON serialization. - * - * The schema for this JSON blob will be described in a - * separate JSON schema file. - * - * @returns {Object} - */ -lunr.Index.prototype.toJSON = function () { - var invertedIndex = Object.keys(this.invertedIndex) - .sort() - .map(function (term) { - return [term, this.invertedIndex[term]] - }, this) - - var fieldVectors = Object.keys(this.fieldVectors) - .map(function (ref) { - return [ref, this.fieldVectors[ref].toJSON()] - }, this) - - return { - version: lunr.version, - fields: this.fields, - fieldVectors: fieldVectors, - invertedIndex: invertedIndex, - pipeline: this.pipeline.toJSON() - } -} - -/** - * Loads a previously serialized lunr.Index - * - * @param {Object} serializedIndex - A previously serialized lunr.Index - * @returns {lunr.Index} - */ -lunr.Index.load = function (serializedIndex) { - var attrs = {}, - fieldVectors = {}, - serializedVectors = serializedIndex.fieldVectors, - invertedIndex = Object.create(null), - serializedInvertedIndex = serializedIndex.invertedIndex, - tokenSetBuilder = new lunr.TokenSet.Builder, - pipeline = lunr.Pipeline.load(serializedIndex.pipeline) - - if (serializedIndex.version != lunr.version) { - lunr.utils.warn("Version mismatch when loading serialised index. Current version of lunr '" + lunr.version + "' does not match serialized index '" + serializedIndex.version + "'") - } - - for (var i = 0; i < serializedVectors.length; i++) { - var tuple = serializedVectors[i], - ref = tuple[0], - elements = tuple[1] - - fieldVectors[ref] = new lunr.Vector(elements) - } - - for (var i = 0; i < serializedInvertedIndex.length; i++) { - var tuple = serializedInvertedIndex[i], - term = tuple[0], - posting = tuple[1] - - tokenSetBuilder.insert(term) - invertedIndex[term] = posting - } - - tokenSetBuilder.finish() - - attrs.fields = serializedIndex.fields - - attrs.fieldVectors = fieldVectors - attrs.invertedIndex = invertedIndex - attrs.tokenSet = tokenSetBuilder.root - attrs.pipeline = pipeline - - return new lunr.Index(attrs) -} -/*! - * lunr.Builder - * Copyright (C) 2019 Oliver Nightingale - */ - -/** - * lunr.Builder performs indexing on a set of documents and - * returns instances of lunr.Index ready for querying. - * - * All configuration of the index is done via the builder, the - * fields to index, the document reference, the text processing - * pipeline and document scoring parameters are all set on the - * builder before indexing. - * - * @constructor - * @property {string} _ref - Internal reference to the document reference field. - * @property {string[]} _fields - Internal reference to the document fields to index. - * @property {object} invertedIndex - The inverted index maps terms to document fields. - * @property {object} documentTermFrequencies - Keeps track of document term frequencies. - * @property {object} documentLengths - Keeps track of the length of documents added to the index. - * @property {lunr.tokenizer} tokenizer - Function for splitting strings into tokens for indexing. - * @property {lunr.Pipeline} pipeline - The pipeline performs text processing on tokens before indexing. - * @property {lunr.Pipeline} searchPipeline - A pipeline for processing search terms before querying the index. - * @property {number} documentCount - Keeps track of the total number of documents indexed. - * @property {number} _b - A parameter to control field length normalization, setting this to 0 disabled normalization, 1 fully normalizes field lengths, the default value is 0.75. - * @property {number} _k1 - A parameter to control how quickly an increase in term frequency results in term frequency saturation, the default value is 1.2. - * @property {number} termIndex - A counter incremented for each unique term, used to identify a terms position in the vector space. - * @property {array} metadataWhitelist - A list of metadata keys that have been whitelisted for entry in the index. - */ -lunr.Builder = function () { - this._ref = "id" - this._fields = Object.create(null) - this._documents = Object.create(null) - this.invertedIndex = Object.create(null) - this.fieldTermFrequencies = {} - this.fieldLengths = {} - this.tokenizer = lunr.tokenizer - this.pipeline = new lunr.Pipeline - this.searchPipeline = new lunr.Pipeline - this.documentCount = 0 - this._b = 0.75 - this._k1 = 1.2 - this.termIndex = 0 - this.metadataWhitelist = [] -} - -/** - * Sets the document field used as the document reference. Every document must have this field. - * The type of this field in the document should be a string, if it is not a string it will be - * coerced into a string by calling toString. - * - * The default ref is 'id'. - * - * The ref should _not_ be changed during indexing, it should be set before any documents are - * added to the index. Changing it during indexing can lead to inconsistent results. - * - * @param {string} ref - The name of the reference field in the document. - */ -lunr.Builder.prototype.ref = function (ref) { - this._ref = ref -} - -/** - * A function that is used to extract a field from a document. - * - * Lunr expects a field to be at the top level of a document, if however the field - * is deeply nested within a document an extractor function can be used to extract - * the right field for indexing. - * - * @callback fieldExtractor - * @param {object} doc - The document being added to the index. - * @returns {?(string|object|object[])} obj - The object that will be indexed for this field. - * @example Extracting a nested field - * function (doc) { return doc.nested.field } - */ - -/** - * Adds a field to the list of document fields that will be indexed. Every document being - * indexed should have this field. Null values for this field in indexed documents will - * not cause errors but will limit the chance of that document being retrieved by searches. - * - * All fields should be added before adding documents to the index. Adding fields after - * a document has been indexed will have no effect on already indexed documents. - * - * Fields can be boosted at build time. This allows terms within that field to have more - * importance when ranking search results. Use a field boost to specify that matches within - * one field are more important than other fields. - * - * @param {string} fieldName - The name of a field to index in all documents. - * @param {object} attributes - Optional attributes associated with this field. - * @param {number} [attributes.boost=1] - Boost applied to all terms within this field. - * @param {fieldExtractor} [attributes.extractor] - Function to extract a field from a document. - * @throws {RangeError} fieldName cannot contain unsupported characters '/' - */ -lunr.Builder.prototype.field = function (fieldName, attributes) { - if (/\//.test(fieldName)) { - throw new RangeError ("Field '" + fieldName + "' contains illegal character '/'") - } - - this._fields[fieldName] = attributes || {} -} - -/** - * A parameter to tune the amount of field length normalisation that is applied when - * calculating relevance scores. A value of 0 will completely disable any normalisation - * and a value of 1 will fully normalise field lengths. The default is 0.75. Values of b - * will be clamped to the range 0 - 1. - * - * @param {number} number - The value to set for this tuning parameter. - */ -lunr.Builder.prototype.b = function (number) { - if (number < 0) { - this._b = 0 - } else if (number > 1) { - this._b = 1 - } else { - this._b = number - } -} - -/** - * A parameter that controls the speed at which a rise in term frequency results in term - * frequency saturation. The default value is 1.2. Setting this to a higher value will give - * slower saturation levels, a lower value will result in quicker saturation. - * - * @param {number} number - The value to set for this tuning parameter. - */ -lunr.Builder.prototype.k1 = function (number) { - this._k1 = number -} - -/** - * Adds a document to the index. - * - * Before adding fields to the index the index should have been fully setup, with the document - * ref and all fields to index already having been specified. - * - * The document must have a field name as specified by the ref (by default this is 'id') and - * it should have all fields defined for indexing, though null or undefined values will not - * cause errors. - * - * Entire documents can be boosted at build time. Applying a boost to a document indicates that - * this document should rank higher in search results than other documents. - * - * @param {object} doc - The document to add to the index. - * @param {object} attributes - Optional attributes associated with this document. - * @param {number} [attributes.boost=1] - Boost applied to all terms within this document. - */ -lunr.Builder.prototype.add = function (doc, attributes) { - var docRef = doc[this._ref], - fields = Object.keys(this._fields) - - this._documents[docRef] = attributes || {} - this.documentCount += 1 - - for (var i = 0; i < fields.length; i++) { - var fieldName = fields[i], - extractor = this._fields[fieldName].extractor, - field = extractor ? extractor(doc) : doc[fieldName], - tokens = this.tokenizer(field, { - fields: [fieldName] - }), - terms = this.pipeline.run(tokens), - fieldRef = new lunr.FieldRef (docRef, fieldName), - fieldTerms = Object.create(null) - - this.fieldTermFrequencies[fieldRef] = fieldTerms - this.fieldLengths[fieldRef] = 0 - - // store the length of this field for this document - this.fieldLengths[fieldRef] += terms.length - - // calculate term frequencies for this field - for (var j = 0; j < terms.length; j++) { - var term = terms[j] - - if (fieldTerms[term] == undefined) { - fieldTerms[term] = 0 - } - - fieldTerms[term] += 1 - - // add to inverted index - // create an initial posting if one doesn't exist - if (this.invertedIndex[term] == undefined) { - var posting = Object.create(null) - posting["_index"] = this.termIndex - this.termIndex += 1 - - for (var k = 0; k < fields.length; k++) { - posting[fields[k]] = Object.create(null) - } - - this.invertedIndex[term] = posting - } - - // add an entry for this term/fieldName/docRef to the invertedIndex - if (this.invertedIndex[term][fieldName][docRef] == undefined) { - this.invertedIndex[term][fieldName][docRef] = Object.create(null) - } - - // store all whitelisted metadata about this token in the - // inverted index - for (var l = 0; l < this.metadataWhitelist.length; l++) { - var metadataKey = this.metadataWhitelist[l], - metadata = term.metadata[metadataKey] - - if (this.invertedIndex[term][fieldName][docRef][metadataKey] == undefined) { - this.invertedIndex[term][fieldName][docRef][metadataKey] = [] - } - - this.invertedIndex[term][fieldName][docRef][metadataKey].push(metadata) - } - } - - } -} - -/** - * Calculates the average document length for this index - * - * @private - */ -lunr.Builder.prototype.calculateAverageFieldLengths = function () { - - var fieldRefs = Object.keys(this.fieldLengths), - numberOfFields = fieldRefs.length, - accumulator = {}, - documentsWithField = {} - - for (var i = 0; i < numberOfFields; i++) { - var fieldRef = lunr.FieldRef.fromString(fieldRefs[i]), - field = fieldRef.fieldName - - documentsWithField[field] || (documentsWithField[field] = 0) - documentsWithField[field] += 1 - - accumulator[field] || (accumulator[field] = 0) - accumulator[field] += this.fieldLengths[fieldRef] - } - - var fields = Object.keys(this._fields) - - for (var i = 0; i < fields.length; i++) { - var fieldName = fields[i] - accumulator[fieldName] = accumulator[fieldName] / documentsWithField[fieldName] - } - - this.averageFieldLength = accumulator -} - -/** - * Builds a vector space model of every document using lunr.Vector - * - * @private - */ -lunr.Builder.prototype.createFieldVectors = function () { - var fieldVectors = {}, - fieldRefs = Object.keys(this.fieldTermFrequencies), - fieldRefsLength = fieldRefs.length, - termIdfCache = Object.create(null) - - for (var i = 0; i < fieldRefsLength; i++) { - var fieldRef = lunr.FieldRef.fromString(fieldRefs[i]), - fieldName = fieldRef.fieldName, - fieldLength = this.fieldLengths[fieldRef], - fieldVector = new lunr.Vector, - termFrequencies = this.fieldTermFrequencies[fieldRef], - terms = Object.keys(termFrequencies), - termsLength = terms.length - - - var fieldBoost = this._fields[fieldName].boost || 1, - docBoost = this._documents[fieldRef.docRef].boost || 1 - - for (var j = 0; j < termsLength; j++) { - var term = terms[j], - tf = termFrequencies[term], - termIndex = this.invertedIndex[term]._index, - idf, score, scoreWithPrecision - - if (termIdfCache[term] === undefined) { - idf = lunr.idf(this.invertedIndex[term], this.documentCount) - termIdfCache[term] = idf - } else { - idf = termIdfCache[term] - } - - score = idf * ((this._k1 + 1) * tf) / (this._k1 * (1 - this._b + this._b * (fieldLength / this.averageFieldLength[fieldName])) + tf) - score *= fieldBoost - score *= docBoost - scoreWithPrecision = Math.round(score * 1000) / 1000 - // Converts 1.23456789 to 1.234. - // Reducing the precision so that the vectors take up less - // space when serialised. Doing it now so that they behave - // the same before and after serialisation. Also, this is - // the fastest approach to reducing a number's precision in - // JavaScript. - - fieldVector.insert(termIndex, scoreWithPrecision) - } - - fieldVectors[fieldRef] = fieldVector - } - - this.fieldVectors = fieldVectors -} - -/** - * Creates a token set of all tokens in the index using lunr.TokenSet - * - * @private - */ -lunr.Builder.prototype.createTokenSet = function () { - this.tokenSet = lunr.TokenSet.fromArray( - Object.keys(this.invertedIndex).sort() - ) -} - -/** - * Builds the index, creating an instance of lunr.Index. - * - * This completes the indexing process and should only be called - * once all documents have been added to the index. - * - * @returns {lunr.Index} - */ -lunr.Builder.prototype.build = function () { - this.calculateAverageFieldLengths() - this.createFieldVectors() - this.createTokenSet() - - return new lunr.Index({ - invertedIndex: this.invertedIndex, - fieldVectors: this.fieldVectors, - tokenSet: this.tokenSet, - fields: Object.keys(this._fields), - pipeline: this.searchPipeline - }) -} - -/** - * Applies a plugin to the index builder. - * - * A plugin is a function that is called with the index builder as its context. - * Plugins can be used to customise or extend the behaviour of the index - * in some way. A plugin is just a function, that encapsulated the custom - * behaviour that should be applied when building the index. - * - * The plugin function will be called with the index builder as its argument, additional - * arguments can also be passed when calling use. The function will be called - * with the index builder as its context. - * - * @param {Function} plugin The plugin to apply. - */ -lunr.Builder.prototype.use = function (fn) { - var args = Array.prototype.slice.call(arguments, 1) - args.unshift(this) - fn.apply(this, args) -} -/** - * Contains and collects metadata about a matching document. - * A single instance of lunr.MatchData is returned as part of every - * lunr.Index~Result. - * - * @constructor - * @param {string} term - The term this match data is associated with - * @param {string} field - The field in which the term was found - * @param {object} metadata - The metadata recorded about this term in this field - * @property {object} metadata - A cloned collection of metadata associated with this document. - * @see {@link lunr.Index~Result} - */ -lunr.MatchData = function (term, field, metadata) { - var clonedMetadata = Object.create(null), - metadataKeys = Object.keys(metadata || {}) - - // Cloning the metadata to prevent the original - // being mutated during match data combination. - // Metadata is kept in an array within the inverted - // index so cloning the data can be done with - // Array#slice - for (var i = 0; i < metadataKeys.length; i++) { - var key = metadataKeys[i] - clonedMetadata[key] = metadata[key].slice() - } - - this.metadata = Object.create(null) - - if (term !== undefined) { - this.metadata[term] = Object.create(null) - this.metadata[term][field] = clonedMetadata - } -} - -/** - * An instance of lunr.MatchData will be created for every term that matches a - * document. However only one instance is required in a lunr.Index~Result. This - * method combines metadata from another instance of lunr.MatchData with this - * objects metadata. - * - * @param {lunr.MatchData} otherMatchData - Another instance of match data to merge with this one. - * @see {@link lunr.Index~Result} - */ -lunr.MatchData.prototype.combine = function (otherMatchData) { - var terms = Object.keys(otherMatchData.metadata) - - for (var i = 0; i < terms.length; i++) { - var term = terms[i], - fields = Object.keys(otherMatchData.metadata[term]) - - if (this.metadata[term] == undefined) { - this.metadata[term] = Object.create(null) - } - - for (var j = 0; j < fields.length; j++) { - var field = fields[j], - keys = Object.keys(otherMatchData.metadata[term][field]) - - if (this.metadata[term][field] == undefined) { - this.metadata[term][field] = Object.create(null) - } - - for (var k = 0; k < keys.length; k++) { - var key = keys[k] - - if (this.metadata[term][field][key] == undefined) { - this.metadata[term][field][key] = otherMatchData.metadata[term][field][key] - } else { - this.metadata[term][field][key] = this.metadata[term][field][key].concat(otherMatchData.metadata[term][field][key]) - } - - } - } - } -} - -/** - * Add metadata for a term/field pair to this instance of match data. - * - * @param {string} term - The term this match data is associated with - * @param {string} field - The field in which the term was found - * @param {object} metadata - The metadata recorded about this term in this field - */ -lunr.MatchData.prototype.add = function (term, field, metadata) { - if (!(term in this.metadata)) { - this.metadata[term] = Object.create(null) - this.metadata[term][field] = metadata - return - } - - if (!(field in this.metadata[term])) { - this.metadata[term][field] = metadata - return - } - - var metadataKeys = Object.keys(metadata) - - for (var i = 0; i < metadataKeys.length; i++) { - var key = metadataKeys[i] - - if (key in this.metadata[term][field]) { - this.metadata[term][field][key] = this.metadata[term][field][key].concat(metadata[key]) - } else { - this.metadata[term][field][key] = metadata[key] - } - } -} -/** - * A lunr.Query provides a programmatic way of defining queries to be performed - * against a {@link lunr.Index}. - * - * Prefer constructing a lunr.Query using the {@link lunr.Index#query} method - * so the query object is pre-initialized with the right index fields. - * - * @constructor - * @property {lunr.Query~Clause[]} clauses - An array of query clauses. - * @property {string[]} allFields - An array of all available fields in a lunr.Index. - */ -lunr.Query = function (allFields) { - this.clauses = [] - this.allFields = allFields -} - -/** - * Constants for indicating what kind of automatic wildcard insertion will be used when constructing a query clause. - * - * This allows wildcards to be added to the beginning and end of a term without having to manually do any string - * concatenation. - * - * The wildcard constants can be bitwise combined to select both leading and trailing wildcards. - * - * @constant - * @default - * @property {number} wildcard.NONE - The term will have no wildcards inserted, this is the default behaviour - * @property {number} wildcard.LEADING - Prepend the term with a wildcard, unless a leading wildcard already exists - * @property {number} wildcard.TRAILING - Append a wildcard to the term, unless a trailing wildcard already exists - * @see lunr.Query~Clause - * @see lunr.Query#clause - * @see lunr.Query#term - * @example query term with trailing wildcard - * query.term('foo', { wildcard: lunr.Query.wildcard.TRAILING }) - * @example query term with leading and trailing wildcard - * query.term('foo', { - * wildcard: lunr.Query.wildcard.LEADING | lunr.Query.wildcard.TRAILING - * }) - */ - -lunr.Query.wildcard = new String ("*") -lunr.Query.wildcard.NONE = 0 -lunr.Query.wildcard.LEADING = 1 -lunr.Query.wildcard.TRAILING = 2 - -/** - * Constants for indicating what kind of presence a term must have in matching documents. - * - * @constant - * @enum {number} - * @see lunr.Query~Clause - * @see lunr.Query#clause - * @see lunr.Query#term - * @example query term with required presence - * query.term('foo', { presence: lunr.Query.presence.REQUIRED }) - */ -lunr.Query.presence = { - /** - * Term's presence in a document is optional, this is the default value. - */ - OPTIONAL: 1, - - /** - * Term's presence in a document is required, documents that do not contain - * this term will not be returned. - */ - REQUIRED: 2, - - /** - * Term's presence in a document is prohibited, documents that do contain - * this term will not be returned. - */ - PROHIBITED: 3 -} - -/** - * A single clause in a {@link lunr.Query} contains a term and details on how to - * match that term against a {@link lunr.Index}. - * - * @typedef {Object} lunr.Query~Clause - * @property {string[]} fields - The fields in an index this clause should be matched against. - * @property {number} [boost=1] - Any boost that should be applied when matching this clause. - * @property {number} [editDistance] - Whether the term should have fuzzy matching applied, and how fuzzy the match should be. - * @property {boolean} [usePipeline] - Whether the term should be passed through the search pipeline. - * @property {number} [wildcard=lunr.Query.wildcard.NONE] - Whether the term should have wildcards appended or prepended. - * @property {number} [presence=lunr.Query.presence.OPTIONAL] - The terms presence in any matching documents. - */ - -/** - * Adds a {@link lunr.Query~Clause} to this query. - * - * Unless the clause contains the fields to be matched all fields will be matched. In addition - * a default boost of 1 is applied to the clause. - * - * @param {lunr.Query~Clause} clause - The clause to add to this query. - * @see lunr.Query~Clause - * @returns {lunr.Query} - */ -lunr.Query.prototype.clause = function (clause) { - if (!('fields' in clause)) { - clause.fields = this.allFields - } - - if (!('boost' in clause)) { - clause.boost = 1 - } - - if (!('usePipeline' in clause)) { - clause.usePipeline = true - } - - if (!('wildcard' in clause)) { - clause.wildcard = lunr.Query.wildcard.NONE - } - - if ((clause.wildcard & lunr.Query.wildcard.LEADING) && (clause.term.charAt(0) != lunr.Query.wildcard)) { - clause.term = "*" + clause.term - } - - if ((clause.wildcard & lunr.Query.wildcard.TRAILING) && (clause.term.slice(-1) != lunr.Query.wildcard)) { - clause.term = "" + clause.term + "*" - } - - if (!('presence' in clause)) { - clause.presence = lunr.Query.presence.OPTIONAL - } - - this.clauses.push(clause) - - return this -} - -/** - * A negated query is one in which every clause has a presence of - * prohibited. These queries require some special processing to return - * the expected results. - * - * @returns boolean - */ -lunr.Query.prototype.isNegated = function () { - for (var i = 0; i < this.clauses.length; i++) { - if (this.clauses[i].presence != lunr.Query.presence.PROHIBITED) { - return false - } - } - - return true -} - -/** - * Adds a term to the current query, under the covers this will create a {@link lunr.Query~Clause} - * to the list of clauses that make up this query. - * - * The term is used as is, i.e. no tokenization will be performed by this method. Instead conversion - * to a token or token-like string should be done before calling this method. - * - * The term will be converted to a string by calling `toString`. Multiple terms can be passed as an - * array, each term in the array will share the same options. - * - * @param {object|object[]} term - The term(s) to add to the query. - * @param {object} [options] - Any additional properties to add to the query clause. - * @returns {lunr.Query} - * @see lunr.Query#clause - * @see lunr.Query~Clause - * @example adding a single term to a query - * query.term("foo") - * @example adding a single term to a query and specifying search fields, term boost and automatic trailing wildcard - * query.term("foo", { - * fields: ["title"], - * boost: 10, - * wildcard: lunr.Query.wildcard.TRAILING - * }) - * @example using lunr.tokenizer to convert a string to tokens before using them as terms - * query.term(lunr.tokenizer("foo bar")) - */ -lunr.Query.prototype.term = function (term, options) { - if (Array.isArray(term)) { - term.forEach(function (t) { this.term(t, lunr.utils.clone(options)) }, this) - return this - } - - var clause = options || {} - clause.term = term.toString() - - this.clause(clause) - - return this -} -lunr.QueryParseError = function (message, start, end) { - this.name = "QueryParseError" - this.message = message - this.start = start - this.end = end -} - -lunr.QueryParseError.prototype = new Error -lunr.QueryLexer = function (str) { - this.lexemes = [] - this.str = str - this.length = str.length - this.pos = 0 - this.start = 0 - this.escapeCharPositions = [] -} - -lunr.QueryLexer.prototype.run = function () { - var state = lunr.QueryLexer.lexText - - while (state) { - state = state(this) - } -} - -lunr.QueryLexer.prototype.sliceString = function () { - var subSlices = [], - sliceStart = this.start, - sliceEnd = this.pos - - for (var i = 0; i < this.escapeCharPositions.length; i++) { - sliceEnd = this.escapeCharPositions[i] - subSlices.push(this.str.slice(sliceStart, sliceEnd)) - sliceStart = sliceEnd + 1 - } - - subSlices.push(this.str.slice(sliceStart, this.pos)) - this.escapeCharPositions.length = 0 - - return subSlices.join('') -} - -lunr.QueryLexer.prototype.emit = function (type) { - this.lexemes.push({ - type: type, - str: this.sliceString(), - start: this.start, - end: this.pos - }) - - this.start = this.pos -} - -lunr.QueryLexer.prototype.escapeCharacter = function () { - this.escapeCharPositions.push(this.pos - 1) - this.pos += 1 -} - -lunr.QueryLexer.prototype.next = function () { - if (this.pos >= this.length) { - return lunr.QueryLexer.EOS - } - - var char = this.str.charAt(this.pos) - this.pos += 1 - return char -} - -lunr.QueryLexer.prototype.width = function () { - return this.pos - this.start -} - -lunr.QueryLexer.prototype.ignore = function () { - if (this.start == this.pos) { - this.pos += 1 - } - - this.start = this.pos -} - -lunr.QueryLexer.prototype.backup = function () { - this.pos -= 1 -} - -lunr.QueryLexer.prototype.acceptDigitRun = function () { - var char, charCode - - do { - char = this.next() - charCode = char.charCodeAt(0) - } while (charCode > 47 && charCode < 58) - - if (char != lunr.QueryLexer.EOS) { - this.backup() - } -} - -lunr.QueryLexer.prototype.more = function () { - return this.pos < this.length -} - -lunr.QueryLexer.EOS = 'EOS' -lunr.QueryLexer.FIELD = 'FIELD' -lunr.QueryLexer.TERM = 'TERM' -lunr.QueryLexer.EDIT_DISTANCE = 'EDIT_DISTANCE' -lunr.QueryLexer.BOOST = 'BOOST' -lunr.QueryLexer.PRESENCE = 'PRESENCE' - -lunr.QueryLexer.lexField = function (lexer) { - lexer.backup() - lexer.emit(lunr.QueryLexer.FIELD) - lexer.ignore() - return lunr.QueryLexer.lexText -} - -lunr.QueryLexer.lexTerm = function (lexer) { - if (lexer.width() > 1) { - lexer.backup() - lexer.emit(lunr.QueryLexer.TERM) - } - - lexer.ignore() - - if (lexer.more()) { - return lunr.QueryLexer.lexText - } -} - -lunr.QueryLexer.lexEditDistance = function (lexer) { - lexer.ignore() - lexer.acceptDigitRun() - lexer.emit(lunr.QueryLexer.EDIT_DISTANCE) - return lunr.QueryLexer.lexText -} - -lunr.QueryLexer.lexBoost = function (lexer) { - lexer.ignore() - lexer.acceptDigitRun() - lexer.emit(lunr.QueryLexer.BOOST) - return lunr.QueryLexer.lexText -} - -lunr.QueryLexer.lexEOS = function (lexer) { - if (lexer.width() > 0) { - lexer.emit(lunr.QueryLexer.TERM) - } -} - -// This matches the separator used when tokenising fields -// within a document. These should match otherwise it is -// not possible to search for some tokens within a document. -// -// It is possible for the user to change the separator on the -// tokenizer so it _might_ clash with any other of the special -// characters already used within the search string, e.g. :. -// -// This means that it is possible to change the separator in -// such a way that makes some words unsearchable using a search -// string. -lunr.QueryLexer.termSeparator = lunr.tokenizer.separator - -lunr.QueryLexer.lexText = function (lexer) { - while (true) { - var char = lexer.next() - - if (char == lunr.QueryLexer.EOS) { - return lunr.QueryLexer.lexEOS - } - - // Escape character is '\' - if (char.charCodeAt(0) == 92) { - lexer.escapeCharacter() - continue - } - - if (char == ":") { - return lunr.QueryLexer.lexField - } - - if (char == "~") { - lexer.backup() - if (lexer.width() > 0) { - lexer.emit(lunr.QueryLexer.TERM) - } - return lunr.QueryLexer.lexEditDistance - } - - if (char == "^") { - lexer.backup() - if (lexer.width() > 0) { - lexer.emit(lunr.QueryLexer.TERM) - } - return lunr.QueryLexer.lexBoost - } - - // "+" indicates term presence is required - // checking for length to ensure that only - // leading "+" are considered - if (char == "+" && lexer.width() === 1) { - lexer.emit(lunr.QueryLexer.PRESENCE) - return lunr.QueryLexer.lexText - } - - // "-" indicates term presence is prohibited - // checking for length to ensure that only - // leading "-" are considered - if (char == "-" && lexer.width() === 1) { - lexer.emit(lunr.QueryLexer.PRESENCE) - return lunr.QueryLexer.lexText - } - - if (char.match(lunr.QueryLexer.termSeparator)) { - return lunr.QueryLexer.lexTerm - } - } -} - -lunr.QueryParser = function (str, query) { - this.lexer = new lunr.QueryLexer (str) - this.query = query - this.currentClause = {} - this.lexemeIdx = 0 -} - -lunr.QueryParser.prototype.parse = function () { - this.lexer.run() - this.lexemes = this.lexer.lexemes - - var state = lunr.QueryParser.parseClause - - while (state) { - state = state(this) - } - - return this.query -} - -lunr.QueryParser.prototype.peekLexeme = function () { - return this.lexemes[this.lexemeIdx] -} - -lunr.QueryParser.prototype.consumeLexeme = function () { - var lexeme = this.peekLexeme() - this.lexemeIdx += 1 - return lexeme -} - -lunr.QueryParser.prototype.nextClause = function () { - var completedClause = this.currentClause - this.query.clause(completedClause) - this.currentClause = {} -} - -lunr.QueryParser.parseClause = function (parser) { - var lexeme = parser.peekLexeme() - - if (lexeme == undefined) { - return - } - - switch (lexeme.type) { - case lunr.QueryLexer.PRESENCE: - return lunr.QueryParser.parsePresence - case lunr.QueryLexer.FIELD: - return lunr.QueryParser.parseField - case lunr.QueryLexer.TERM: - return lunr.QueryParser.parseTerm - default: - var errorMessage = "expected either a field or a term, found " + lexeme.type - - if (lexeme.str.length >= 1) { - errorMessage += " with value '" + lexeme.str + "'" - } - - throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end) - } -} - -lunr.QueryParser.parsePresence = function (parser) { - var lexeme = parser.consumeLexeme() - - if (lexeme == undefined) { - return - } - - switch (lexeme.str) { - case "-": - parser.currentClause.presence = lunr.Query.presence.PROHIBITED - break - case "+": - parser.currentClause.presence = lunr.Query.presence.REQUIRED - break - default: - var errorMessage = "unrecognised presence operator'" + lexeme.str + "'" - throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end) - } - - var nextLexeme = parser.peekLexeme() - - if (nextLexeme == undefined) { - var errorMessage = "expecting term or field, found nothing" - throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end) - } - - switch (nextLexeme.type) { - case lunr.QueryLexer.FIELD: - return lunr.QueryParser.parseField - case lunr.QueryLexer.TERM: - return lunr.QueryParser.parseTerm - default: - var errorMessage = "expecting term or field, found '" + nextLexeme.type + "'" - throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end) - } -} - -lunr.QueryParser.parseField = function (parser) { - var lexeme = parser.consumeLexeme() - - if (lexeme == undefined) { - return - } - - if (parser.query.allFields.indexOf(lexeme.str) == -1) { - var possibleFields = parser.query.allFields.map(function (f) { return "'" + f + "'" }).join(', '), - errorMessage = "unrecognised field '" + lexeme.str + "', possible fields: " + possibleFields - - throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end) - } - - parser.currentClause.fields = [lexeme.str] - - var nextLexeme = parser.peekLexeme() - - if (nextLexeme == undefined) { - var errorMessage = "expecting term, found nothing" - throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end) - } - - switch (nextLexeme.type) { - case lunr.QueryLexer.TERM: - return lunr.QueryParser.parseTerm - default: - var errorMessage = "expecting term, found '" + nextLexeme.type + "'" - throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end) - } -} - -lunr.QueryParser.parseTerm = function (parser) { - var lexeme = parser.consumeLexeme() - - if (lexeme == undefined) { - return - } - - parser.currentClause.term = lexeme.str.toLowerCase() - - if (lexeme.str.indexOf("*") != -1) { - parser.currentClause.usePipeline = false - } - - var nextLexeme = parser.peekLexeme() - - if (nextLexeme == undefined) { - parser.nextClause() - return - } - - switch (nextLexeme.type) { - case lunr.QueryLexer.TERM: - parser.nextClause() - return lunr.QueryParser.parseTerm - case lunr.QueryLexer.FIELD: - parser.nextClause() - return lunr.QueryParser.parseField - case lunr.QueryLexer.EDIT_DISTANCE: - return lunr.QueryParser.parseEditDistance - case lunr.QueryLexer.BOOST: - return lunr.QueryParser.parseBoost - case lunr.QueryLexer.PRESENCE: - parser.nextClause() - return lunr.QueryParser.parsePresence - default: - var errorMessage = "Unexpected lexeme type '" + nextLexeme.type + "'" - throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end) - } -} - -lunr.QueryParser.parseEditDistance = function (parser) { - var lexeme = parser.consumeLexeme() - - if (lexeme == undefined) { - return - } - - var editDistance = parseInt(lexeme.str, 10) - - if (isNaN(editDistance)) { - var errorMessage = "edit distance must be numeric" - throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end) - } - - parser.currentClause.editDistance = editDistance - - var nextLexeme = parser.peekLexeme() - - if (nextLexeme == undefined) { - parser.nextClause() - return - } - - switch (nextLexeme.type) { - case lunr.QueryLexer.TERM: - parser.nextClause() - return lunr.QueryParser.parseTerm - case lunr.QueryLexer.FIELD: - parser.nextClause() - return lunr.QueryParser.parseField - case lunr.QueryLexer.EDIT_DISTANCE: - return lunr.QueryParser.parseEditDistance - case lunr.QueryLexer.BOOST: - return lunr.QueryParser.parseBoost - case lunr.QueryLexer.PRESENCE: - parser.nextClause() - return lunr.QueryParser.parsePresence - default: - var errorMessage = "Unexpected lexeme type '" + nextLexeme.type + "'" - throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end) - } -} - -lunr.QueryParser.parseBoost = function (parser) { - var lexeme = parser.consumeLexeme() - - if (lexeme == undefined) { - return - } - - var boost = parseInt(lexeme.str, 10) - - if (isNaN(boost)) { - var errorMessage = "boost must be numeric" - throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end) - } - - parser.currentClause.boost = boost - - var nextLexeme = parser.peekLexeme() - - if (nextLexeme == undefined) { - parser.nextClause() - return - } - - switch (nextLexeme.type) { - case lunr.QueryLexer.TERM: - parser.nextClause() - return lunr.QueryParser.parseTerm - case lunr.QueryLexer.FIELD: - parser.nextClause() - return lunr.QueryParser.parseField - case lunr.QueryLexer.EDIT_DISTANCE: - return lunr.QueryParser.parseEditDistance - case lunr.QueryLexer.BOOST: - return lunr.QueryParser.parseBoost - case lunr.QueryLexer.PRESENCE: - parser.nextClause() - return lunr.QueryParser.parsePresence - default: - var errorMessage = "Unexpected lexeme type '" + nextLexeme.type + "'" - throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end) - } -} - - /** - * export the module via AMD, CommonJS or as a browser global - * Export code from https://github.com/umdjs/umd/blob/master/returnExports.js - */ - ;(function (root, factory) { - if (typeof define === 'function' && define.amd) { - // AMD. Register as an anonymous module. - define(factory) - } else if (typeof exports === 'object') { - /** - * Node. Does not work with strict CommonJS, but - * only CommonJS-like enviroments that support module.exports, - * like Node. - */ - module.exports = factory() - } else { - // Browser globals (root is window) - root.lunr = factory() - } - }(this, function () { - /** - * Just return a value to define the module export. - * This example returns an object, but the module - * can return a function as the exported value. - */ - return lunr - })) -})(); diff --git a/search/main.js b/search/main.js deleted file mode 100755 index 0e1fc81..0000000 --- a/search/main.js +++ /dev/null @@ -1,98 +0,0 @@ -function getSearchTermFromLocation() { - var sPageURL = window.location.search.substring(1); - var sURLVariables = sPageURL.split('&'); - for (var i = 0; i < sURLVariables.length; i++) { - var sParameterName = sURLVariables[i].split('='); - if (sParameterName[0] == 'q') { - return decodeURIComponent(sParameterName[1].replace(/\+/g, '%20')); - } - } -} - -function joinUrl (base, path) { - if (path.substring(0, 1) === "/") { - // path starts with `/`. Thus it is absolute. - return path; - } - if (base.substring(base.length-1) === "/") { - // base ends with `/` - return base + path; - } - return base + "/" + path; -} - -function formatResult (location, title, summary) { - return ''; -} - -function displayResults (results) { - var search_results = document.getElementById("mkdocs-search-results"); - while (search_results.firstChild) { - search_results.removeChild(search_results.firstChild); - } - if (results.length > 0){ - for (var i=0; i < results.length; i++){ - var result = results[i]; - var html = formatResult(result.location, result.title, result.summary); - search_results.insertAdjacentHTML('beforeend', html); - } - } else { - search_results.insertAdjacentHTML('beforeend', "

    No results found

    "); - } -} - -function doSearch () { - var query = document.getElementById('mkdocs-search-query').value; - if (query.length > min_search_length) { - if (!window.Worker) { - displayResults(search(query)); - } else { - searchWorker.postMessage({query: query}); - } - } else { - // Clear results for short queries - displayResults([]); - } -} - -function initSearch () { - var search_input = document.getElementById('mkdocs-search-query'); - if (search_input) { - search_input.addEventListener("keyup", doSearch); - } - var term = getSearchTermFromLocation(); - if (term) { - search_input.value = term; - doSearch(); - } -} - -function onWorkerMessage (e) { - if (e.data.allowSearch) { - initSearch(); - } else if (e.data.results) { - var results = e.data.results; - displayResults(results); - } else if (e.data.config) { - min_search_length = e.data.config.min_search_length-1; - } -} - -if (!window.Worker) { - console.log('Web Worker API not supported'); - // load index in main thread - $.getScript(joinUrl(base_url, "search/worker.js")).done(function () { - console.log('Loaded worker'); - init(); - window.postMessage = function (msg) { - onWorkerMessage({data: msg}); - }; - }).fail(function (jqxhr, settings, exception) { - console.error('Could not load worker.js'); - }); -} else { - // Wrap search in a web worker - var searchWorker = new Worker(joinUrl(base_url, "search/worker.js")); - searchWorker.postMessage({init: true}); - searchWorker.onmessage = onWorkerMessage; -} diff --git a/search/search_index.json b/search/search_index.json deleted file mode 100755 index 138175c..0000000 --- a/search/search_index.json +++ /dev/null @@ -1 +0,0 @@ -{"config":{"lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"Python-Markdown \u00b6 This is a Python implementation of John Gruber\u2019s Markdown . It is almost completely compliant with the reference implementation, though there are a few very minor differences . See John\u2019s Syntax Documentation for the syntax rules. To get started, see the installation instructions , the library reference , and the command line interface . Goals \u00b6 The Python-Markdown project is developed with the following goals in mind: Maintain a Python library (with an optional CLI wrapper) suited to use in web server environments (never raise an exception, never write to stdout, etc.) as an implementation of the markdown parser that follows the syntax rules and the behavior of the original (markdown.pl) implementation as reasonably as possible (see differences for a few exceptions). Provide an Extension API which makes it possible to change and/or extend the behavior of the parser. Note This is not a CommonMark implementation ; nor is it trying to be! Python-Markdown was developed long before the CommonMark specification was released and has always (mostly) followed the syntax rules and behavior of the original reference implementation. No accommodations have been made to address the changes which CommonMark has suggested. It is recommended that you look elsewhere if you want an implementation which follows the CommonMark specification. Features \u00b6 In addition to the basic markdown syntax, Python-Markdown supports the following features: International Input Python-Markdown will accept input in any language supported by Unicode including bi-directional text. In fact the test suite includes documents written in Russian and Arabic. Extensions Various extensions are provided (including extra ) to change and/or extend the base syntax. Additionally, a public Extension API is available to write your own extensions. Output Formats Python-Markdown can output documents with either HTML or XHTML style tags. See the Library Reference for details. Command Line Interface In addition to being a Python Library, a command line script is available for your convenience. Differences \u00b6 While Python-Markdown strives to fully implement markdown as described in the syntax rules , the rules can be interpreted in different ways and different implementations occasionally vary in their behavior (see the Babelmark FAQ for some examples). Known and intentional differences found in Python-Markdown are summarized below: Middle-Word Emphasis Python-Markdown defaults to ignoring middle-word emphasis (and strong emphasis). In other words, some_long_filename.txt will not become somelongfilename.txt . This can be switched off if desired. See the Legacy EM Extension for details. Indentation/Tab Length The syntax rules clearly state that when a list item consists of multiple paragraphs, \u201ceach subsequent paragraph in a list item must be indented by either 4 spaces or one tab\u201d (emphasis added). However, many implementations do not enforce this rule and allow less than 4 spaces of indentation. The implementers of Python-Markdown consider it a bug to not enforce this rule. This applies to any block level elements nested in a list, including paragraphs, sub-lists, blockquotes, code blocks, etc. They must always be indented by at least four spaces (or one tab) for each level of nesting. In the event that one would prefer different behavior, tab_length can be set to whatever length is desired. Be warned however, as this will affect indentation for all aspects of the syntax (including root level code blocks). Alternatively, a third party extension may offer a solution that meets your needs. Consecutive Lists While the syntax rules are not clear on this, many implementations (including the original) do not end one list and start a second list when the list marker (asterisks, pluses, hyphens, and numbers) changes. For consistency, Python-Markdown maintains the same behavior with no plans to change in the foreseeable future. That said, the Sane List Extension is available to provide a less surprising behavior. Support \u00b6 You may report bugs, ask for help, and discuss various other issues on the bug tracker .","title":"Python-Markdown"},{"location":"#python-markdown","text":"This is a Python implementation of John Gruber\u2019s Markdown . It is almost completely compliant with the reference implementation, though there are a few very minor differences . See John\u2019s Syntax Documentation for the syntax rules. To get started, see the installation instructions , the library reference , and the command line interface .","title":"Python-Markdown"},{"location":"#goals","text":"The Python-Markdown project is developed with the following goals in mind: Maintain a Python library (with an optional CLI wrapper) suited to use in web server environments (never raise an exception, never write to stdout, etc.) as an implementation of the markdown parser that follows the syntax rules and the behavior of the original (markdown.pl) implementation as reasonably as possible (see differences for a few exceptions). Provide an Extension API which makes it possible to change and/or extend the behavior of the parser. Note This is not a CommonMark implementation ; nor is it trying to be! Python-Markdown was developed long before the CommonMark specification was released and has always (mostly) followed the syntax rules and behavior of the original reference implementation. No accommodations have been made to address the changes which CommonMark has suggested. It is recommended that you look elsewhere if you want an implementation which follows the CommonMark specification.","title":"Goals"},{"location":"#features","text":"In addition to the basic markdown syntax, Python-Markdown supports the following features: International Input Python-Markdown will accept input in any language supported by Unicode including bi-directional text. In fact the test suite includes documents written in Russian and Arabic. Extensions Various extensions are provided (including extra ) to change and/or extend the base syntax. Additionally, a public Extension API is available to write your own extensions. Output Formats Python-Markdown can output documents with either HTML or XHTML style tags. See the Library Reference for details. Command Line Interface In addition to being a Python Library, a command line script is available for your convenience.","title":"Features"},{"location":"#differences","text":"While Python-Markdown strives to fully implement markdown as described in the syntax rules , the rules can be interpreted in different ways and different implementations occasionally vary in their behavior (see the Babelmark FAQ for some examples). Known and intentional differences found in Python-Markdown are summarized below: Middle-Word Emphasis Python-Markdown defaults to ignoring middle-word emphasis (and strong emphasis). In other words, some_long_filename.txt will not become somelongfilename.txt . This can be switched off if desired. See the Legacy EM Extension for details. Indentation/Tab Length The syntax rules clearly state that when a list item consists of multiple paragraphs, \u201ceach subsequent paragraph in a list item must be indented by either 4 spaces or one tab\u201d (emphasis added). However, many implementations do not enforce this rule and allow less than 4 spaces of indentation. The implementers of Python-Markdown consider it a bug to not enforce this rule. This applies to any block level elements nested in a list, including paragraphs, sub-lists, blockquotes, code blocks, etc. They must always be indented by at least four spaces (or one tab) for each level of nesting. In the event that one would prefer different behavior, tab_length can be set to whatever length is desired. Be warned however, as this will affect indentation for all aspects of the syntax (including root level code blocks). Alternatively, a third party extension may offer a solution that meets your needs. Consecutive Lists While the syntax rules are not clear on this, many implementations (including the original) do not end one list and start a second list when the list marker (asterisks, pluses, hyphens, and numbers) changes. For consistency, Python-Markdown maintains the same behavior with no plans to change in the foreseeable future. That said, the Sane List Extension is available to provide a less surprising behavior.","title":"Differences"},{"location":"#support","text":"You may report bugs, ask for help, and discuss various other issues on the bug tracker .","title":"Support"},{"location":"authors/","text":"Primary Authors \u00b6 Waylan Limberg @waylan is the current maintainer of the code and has written much of the current code base, including a complete refactor of the core for version 2.0. He started out by authoring many of the available extensions and later was asked to join Yuri, where he began fixing numerous bugs, adding documentation and making general improvements to the existing code base. Dmitry Shachnev @mitya57 joined the team after providing a number of helpful patches and has been assisting with maintenance, reviewing pull requests and ticket triage. Isaac Muse @facelessuser joined the team after providing a number of helpful patches and has been assisting with maintenance, reviewing pull requests and ticket triage. Yuri Takhteyev 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 structure. Manfed Stienstra Manfed wrote the original version of the script and is responsible for various parts of the existing code base. Artem Yunusov Artem, who as part of a 2008 GSoC project, refactored inline patterns, replaced the NanoDOM with ElementTree support and made various other improvements. David Wolever David refactored the extension API and made other improvements as he helped to integrate Markdown into Dr.Project. Other Contributors \u00b6 The incomplete list of individuals below have provided patches or otherwise contributed to the project prior to the project being hosted on GitHub. See the GitHub commit log for a list of recent contributors. We would like to thank everyone who has contributed to the project in any way. Eric Abrahamsen Jeff Balogh Sergej Chodarev Chris Clark Tiago Cogumbreiro Kjell Magne Fauske G. Clark Haynes Daniel Krech Steward Midwinter Jack Miller Neale Pickett Paul Stansifer John Szakmeister Malcolm Tredinnick Ben Wilson and many others who helped by reporting bugs","title":"Authors"},{"location":"authors/#primary-authors","text":"Waylan Limberg @waylan is the current maintainer of the code and has written much of the current code base, including a complete refactor of the core for version 2.0. He started out by authoring many of the available extensions and later was asked to join Yuri, where he began fixing numerous bugs, adding documentation and making general improvements to the existing code base. Dmitry Shachnev @mitya57 joined the team after providing a number of helpful patches and has been assisting with maintenance, reviewing pull requests and ticket triage. Isaac Muse @facelessuser joined the team after providing a number of helpful patches and has been assisting with maintenance, reviewing pull requests and ticket triage. Yuri Takhteyev 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 structure. Manfed Stienstra Manfed wrote the original version of the script and is responsible for various parts of the existing code base. Artem Yunusov Artem, who as part of a 2008 GSoC project, refactored inline patterns, replaced the NanoDOM with ElementTree support and made various other improvements. David Wolever David refactored the extension API and made other improvements as he helped to integrate Markdown into Dr.Project.","title":"Primary Authors"},{"location":"authors/#other-contributors","text":"The incomplete list of individuals below have provided patches or otherwise contributed to the project prior to the project being hosted on GitHub. See the GitHub commit log for a list of recent contributors. We would like to thank everyone who has contributed to the project in any way. Eric Abrahamsen Jeff Balogh Sergej Chodarev Chris Clark Tiago Cogumbreiro Kjell Magne Fauske G. Clark Haynes Daniel Krech Steward Midwinter Jack Miller Neale Pickett Paul Stansifer John Szakmeister Malcolm Tredinnick Ben Wilson and many others who helped by reporting bugs","title":"Other Contributors"},{"location":"cli/","text":"Using Python-Markdown on the Command Line \u00b6 While Python-Markdown is primarily a python library, a command line script is included as well. While there are many other command line implementations of Markdown, you may not have them installed, or you may prefer to use Python-Markdown\u2019s various extensions. Generally, you will want to have the Markdown library fully installed on your system to run the command line script. See the Installation instructions for details. Python-Markdown\u2019s command line script takes advantage of Python\u2019s -m flag. Therefore, assuming the python executable is on your system path, use the following format: python -m markdown [ options ] [ args ] That will run the module as a script with the options and arguments provided. At its most basic usage, one would simply pass in a file name as the only argument: python -m markdown input_file.txt Piping input and output (on STDIN and STDOUT ) is fully supported as well. For example: echo \"Some **Markdown** text.\" | python -m markdown > output.html Use the --help option for a list all available options and arguments: python -m markdown --help If you don\u2019t want to call the python executable directly (using the -m flag), follow the instructions below to use a wrapper script: Setup \u00b6 Upon installation, the markdown_py script will have been copied to your Python \u201cScripts\u201d directory. Different systems require different methods to ensure that any files in the Python \u201cScripts\u201d directory are on your system path. Windows : Assuming a default install of Python on Windows, your \u201cScripts\u201d directory is most likely something like C:\\\\Python37\\Scripts . Verify the location of your \u201cScripts\u201d directory and add it to you system path. Calling markdown_py from the command line will call the wrapper batch file markdown_py.bat in the \"Scripts\" directory created during install. *nix (Linux, OSX, BSD, Unix, etc.): As each *nix distribution is different and we can\u2019t possibly document all of them here, we\u2019ll provide a few helpful pointers: Some systems will automatically install the script on your path. Try it and see if it works. Just run markdown_py from the command line. Other systems may maintain a separate \u201cScripts\u201d (\u201cbin\u201d) directory which you need to add to your path. Find it (check with your distribution) and either add it to your path or make a symbolic link to it from your path. If you are sure markdown_py is on your path, but it still is not being found, check the permissions of the file and make sure it is executable. As an alternative, you could just cd into the directory which contains the source distribution, and run it from there. However, remember that your markdown text files will not likely be in that directory, so it is much more convenient to have markdown_py on your path. Note Python-Markdown uses \"markdown_py\" as a script name because the Perl implementation has already taken the more obvious name \u201cmarkdown\u201d. Additionally, the default Python configuration on some systems would cause a script named \"markdown.py\" to fail by importing itself rather than the markdown library. Therefore, the script has been named \"markdown_py\" as a compromise. If you prefer a different name for the script on your system, it is suggested that you create a symbolic link to markdown_py with your preferred name. Usage \u00b6 To use markdown_py from the command line, run it as markdown_py input_file.txt or markdown_py input_file.txt > output_file.html For a complete list of options, run markdown_py --help Using Extensions \u00b6 To load a Python-Markdown extension from the command line use the -x (or --extension ) option. The extension module must be on your PYTHONPATH (see the Extension API for details). The extension can then be invoked by the name assigned to an entry point or using Python\u2019s dot notation to point to an extension For example, to load an extension with the assigned entry point name myext , run the following command: python -m markdown -x myext input.txt And to load an extension with Python\u2019s dot notation: python -m markdown -x path.to.module:MyExtClass input.txt To load multiple extensions, specify an -x option for each extension: python -m markdown -x myext -x path.to.module:MyExtClass input.txt If the extension supports configuration options (see the documentation for the extension you are using to determine what settings it supports, if any), you can pass them in as well: python -m markdown -x myext -c config.yml input.txt The -c (or --extension_configs ) option accepts a file name. The file must be in either the YAML or JSON format and contain YAML or JSON data that would map to a Python Dictionary in the format required by the extension_configs keyword of the markdown.Markdown class. Therefore, the file config.yaml referenced in the above example might look like this: myext : option1 : 'value1' option2 : True Similarly, a JSON configuration file might look like this: { \"myext\" : { \"option1\" : \"value1\" , \"option2\" : \"value2\" } } Note that while the --extension_configs option does specify the myext extension, you still need to load the extension with the -x option, or the configuration for that extension will be ignored. Further, if an extension requires a value that cannot be parsed in JSON (for example a reference to a function), one has to use a YAML configuration file. The --extension_configs option will only support YAML configuration files if PyYAML is installed on your system. JSON should work with no additional dependencies. The format of your configuration file is automatically detected.","title":"Command Line"},{"location":"cli/#using-python-markdown-on-the-command-line","text":"While Python-Markdown is primarily a python library, a command line script is included as well. While there are many other command line implementations of Markdown, you may not have them installed, or you may prefer to use Python-Markdown\u2019s various extensions. Generally, you will want to have the Markdown library fully installed on your system to run the command line script. See the Installation instructions for details. Python-Markdown\u2019s command line script takes advantage of Python\u2019s -m flag. Therefore, assuming the python executable is on your system path, use the following format: python -m markdown [ options ] [ args ] That will run the module as a script with the options and arguments provided. At its most basic usage, one would simply pass in a file name as the only argument: python -m markdown input_file.txt Piping input and output (on STDIN and STDOUT ) is fully supported as well. For example: echo \"Some **Markdown** text.\" | python -m markdown > output.html Use the --help option for a list all available options and arguments: python -m markdown --help If you don\u2019t want to call the python executable directly (using the -m flag), follow the instructions below to use a wrapper script:","title":"Using Python-Markdown on the Command Line"},{"location":"cli/#setup","text":"Upon installation, the markdown_py script will have been copied to your Python \u201cScripts\u201d directory. Different systems require different methods to ensure that any files in the Python \u201cScripts\u201d directory are on your system path. Windows : Assuming a default install of Python on Windows, your \u201cScripts\u201d directory is most likely something like C:\\\\Python37\\Scripts . Verify the location of your \u201cScripts\u201d directory and add it to you system path. Calling markdown_py from the command line will call the wrapper batch file markdown_py.bat in the \"Scripts\" directory created during install. *nix (Linux, OSX, BSD, Unix, etc.): As each *nix distribution is different and we can\u2019t possibly document all of them here, we\u2019ll provide a few helpful pointers: Some systems will automatically install the script on your path. Try it and see if it works. Just run markdown_py from the command line. Other systems may maintain a separate \u201cScripts\u201d (\u201cbin\u201d) directory which you need to add to your path. Find it (check with your distribution) and either add it to your path or make a symbolic link to it from your path. If you are sure markdown_py is on your path, but it still is not being found, check the permissions of the file and make sure it is executable. As an alternative, you could just cd into the directory which contains the source distribution, and run it from there. However, remember that your markdown text files will not likely be in that directory, so it is much more convenient to have markdown_py on your path. Note Python-Markdown uses \"markdown_py\" as a script name because the Perl implementation has already taken the more obvious name \u201cmarkdown\u201d. Additionally, the default Python configuration on some systems would cause a script named \"markdown.py\" to fail by importing itself rather than the markdown library. Therefore, the script has been named \"markdown_py\" as a compromise. If you prefer a different name for the script on your system, it is suggested that you create a symbolic link to markdown_py with your preferred name.","title":"Setup"},{"location":"cli/#usage","text":"To use markdown_py from the command line, run it as markdown_py input_file.txt or markdown_py input_file.txt > output_file.html For a complete list of options, run markdown_py --help","title":"Usage"},{"location":"cli/#using-extensions","text":"To load a Python-Markdown extension from the command line use the -x (or --extension ) option. The extension module must be on your PYTHONPATH (see the Extension API for details). The extension can then be invoked by the name assigned to an entry point or using Python\u2019s dot notation to point to an extension For example, to load an extension with the assigned entry point name myext , run the following command: python -m markdown -x myext input.txt And to load an extension with Python\u2019s dot notation: python -m markdown -x path.to.module:MyExtClass input.txt To load multiple extensions, specify an -x option for each extension: python -m markdown -x myext -x path.to.module:MyExtClass input.txt If the extension supports configuration options (see the documentation for the extension you are using to determine what settings it supports, if any), you can pass them in as well: python -m markdown -x myext -c config.yml input.txt The -c (or --extension_configs ) option accepts a file name. The file must be in either the YAML or JSON format and contain YAML or JSON data that would map to a Python Dictionary in the format required by the extension_configs keyword of the markdown.Markdown class. Therefore, the file config.yaml referenced in the above example might look like this: myext : option1 : 'value1' option2 : True Similarly, a JSON configuration file might look like this: { \"myext\" : { \"option1\" : \"value1\" , \"option2\" : \"value2\" } } Note that while the --extension_configs option does specify the myext extension, you still need to load the extension with the -x option, or the configuration for that extension will be ignored. Further, if an extension requires a value that cannot be parsed in JSON (for example a reference to a function), one has to use a YAML configuration file. The --extension_configs option will only support YAML configuration files if PyYAML is installed on your system. JSON should work with no additional dependencies. The format of your configuration file is automatically detected.","title":"Using Extensions"},{"location":"contributing/","text":"Contributing to Python-Markdown \u00b6 The following is a set of guidelines for contributing to Python-Markdown and its extensions, which are hosted in the Python-Markdown Organization on GitHub. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request. Code of Conduct \u00b6 This project and everyone participating in it is governed by the Python-Markdown Code of Conduct . By participating, you are expected to uphold this code. Please report unacceptable behavior to python.markdown@gmail.com . Project Organization \u00b6 The core Python-Markdown code base and any built-in extensions are hosted in the Python-Markdown/markdown project on GitHub. Other extensions maintained by the Python-Markdown project may be hosted as separate repositories in the Python-Markdown Organization on GitHub and must follow best practices for third-party extensions. The Python-Markdown/markdown project is organized as follows: Branch master should generally be stable and release-ready at all times. Version branches should be used for bug-fixes back-ported to the most recent PATCH release. No other branches should be created. Any other branches which exist are preserved for historical reasons only. Issues \u00b6 Feature requests, bug reports, usage questions, and other issues can all be raised on the GitHub issue tracker . When describing issues try to phrase your ticket in terms of the behavior you think needs to change rather than the code you think needs to change. Make sure you\u2019re running the latest version of Python-Markdown before reporting an issue. Search the issue list first for related items. Be sure to check closed issues and pull requests. GitHub\u2019s search only checks open issues by default. You may want to check the syntax rules and/or Babelmark to confirm that your expectations align with the rules and/or other implementations of Markdown. If reporting a syntax bug, you must provide the minimal input which exhibits the behavior, the actual output and the output you expected. All three items must be provided as textual code blocks (screen-shots are not helpful). It may also be helpful to point to the syntax rules which specifically address the area of concern. Feature requests will often be closed with a recommendation that they be implemented as third party extensions outside of the core Python-Markdown library. Keeping new feature requests implemented as third party extensions allows us to keep the maintenance overhead of Python-Markdown to a minimum, so that the focus can be on continued stability, bug fixes, and documentation. If you intend to submit a fix for your bug or provide an implementation of your feature request, it is not necessary to first open an issue. You can report a bug or make a feature request as part of a pull request. Of course, if you want to receive feedback on how to implement a bug-fix or feature before submitting a solution, then it would be appropriate to open an issue first and ask your questions there. Having your issue closed does not necessarily mean the end of a discussion. If you believe your issue has been closed incorrectly, explain why and we\u2019ll consider if it needs to be reopened. Pull Requests \u00b6 A pull request often represents the start of a discussion, and does not necessarily need to be the final, finished submission. In fact, if you discover an issue and intend to provide a fix for it, there is no need to open an issue first. You can report the issue and provide the fix together in a pull request. All pull requests should be made from your personal fork of the library hosted in your personal GitHub account. Do not create branches on the Python-Markdown/markdown project for pull requests. All pull requests should be implemented in a new branch with a unique name. Remember that if you have an outstanding pull request, pushing new commits to the related branch of your GitHub repository will also automatically update the pull request. It may help to review GitHub\u2019s documentation on Creating a pull request from a fork . If you are providing a fix for a previously reported issue, you must reference the issue in your commit message. Be sure to prefix the reference with one of GitHub\u2019s action words which will automatically close the issue when the pull request is merged. For example, fixes #42 and closes #42 would be acceptable, whereas ref #42 would not. Of course, if merging a pull request should not cause an issue to be closed, then the action word should not be included when referencing that issue. Before being accepted, each pull request must include the applicable code, new tests of all new features, updated tests for any changed features, documentation updates, and an appropriate update to the release notes. All changes must follow the applicable style guides. Failure to meet any one of the requirements is likely to delay any serious consideration of your pull request and may even cause it to be closed. Of course, if you are in the early stages of development, you may include a note in the pull request acknowledging that it is incomplete along with a request for feedback. Pull requests will generally not be accepted if any tests are failing. Therefore, it is recommended that you run the tests before submitting your pull request. After making a pull request, check the build status in the GitHub interface to ensure that all tests are running as expected. If any checks fail, you may push additional commits to your branch. GitHub will add those commits to the pull request and rerun the checks. It is generally best not to squash multiple commits and force-push your changes to a pull request. Instead, the maintainers would like to be able to follow the series of commits along with the discussion about those changes as they progress over time. If your pull request is accepted, it will be squashed at that time if deemed appropriate. Style Guides \u00b6 In an effort to maintain consistency, Python-Markdown adheres to the following style guides in its code and documentation. A pull request may be rejected if it fails to match the relevant style guides. Code Style Guide \u00b6 Except as noted below, all pull requests should follow Python\u2019s standard PEP8 Style Guide and are run through Flake8 to ensure that the style guide is followed. Legacy code which does not follow the guidelines should only be updated if and when other changes (bug fix, feature addition, etc.) are being made to that section of code. While new features should be given names that follow modern Python naming conventions, existing names should be preserved to avoid backward incompatible changes. Line length is limited to a maximum of 119 characters. When a line of code does not fit within the line length limit, continuation lines should align elements wrapped inside parentheses, brackets and braces using a hanging indent . When using a hanging indent there should be no arguments on the first line and further indentation should be used to clearly distinguish itself as a continuation line. The closing parenthesis, bracket or brace should be on a line by itself and should line up under the first character of the line that starts the multi-line construct. my_list = [ 1 , 2 , 3 , 4 , 5 , 6 , ] result = some_function_that_takes_arguments ( 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , ) When the conditional part of an if -statement is long enough to require that it be written across multiple lines, extra indentation should be included on the conditional continuation line. if ( this_is_one_thing and that_is_another_thing ): do_something () Documentation Style Guide \u00b6 Documentation should be in American English. The tone of the documentation should be simple, plain, objective and well-balanced where possible. Keep paragraphs reasonably short. With the exception of code blocks, limit line length to 79 characters. You may want to use your editor\u2019s tools to automatically hard wrap lines of text. Don\u2019t use abbreviations such as \u2018e.g.\u2019 but instead use the long form, such as \u2018For example\u2019. The documentation is built from the Markdown source files in the docs directory by the MkDocs static site generator. In addition to the basic Markdown syntax, the following extensions are supported: extra , admonition , smarty , codehilite , and toc . There are a few conventions you should follow when working on the documentation. Headers \u00b6 Headers should use the hash style. For example: ## Some important topic The underline style should not be used. Don\u2019t do this: Some important topic ==================== Links \u00b6 Links should always use the reference style, with the referenced hyperlinks kept at the end of the document. Here is a link to [ some other thing ][ other-thing ]. More text... [ other-thing ]: http://example.com/other/thing This style helps keep the documentation source consistent and readable. If you are linking to another document within Python-Markdown\u2019s documentation, you should use a relative link, and link to the .md suffix. If applicable, it is preferred that the link includes a hash fragment pointing to the specific section of the page. For example: [ authentication ]: reference.md#Markdown Linking in this style ensures that the links work when browsing the documentation on GitHub. If your Markdown editor makes links clickable, they will work there as well. When the documentation is built, these links will be converted into regular links which point to the built HTML pages. Notes and Warnings \u00b6 If you want to draw attention to a note or warning, use the syntax defined in Python-Markdown\u2019s Admonition Extension : !!! note This is the content of the note. Release Notes \u00b6 Any commit/pull request which changes the behavior of the Markdown library in any way must include an entry in the release notes. If a change only alters the documentation or tooling for the project, then an entry in the release notes is not necessary. The release notes can be found at docs/change_log . Each release must have an entry in docs/change_log/index.md which follows the format of the existing entries. A MAJOR release ( X.0.0 ) and a MINOR release ( X.X.0 ) should only include a single line in docs/change_log/index.md which links to a full document outlining all changes included in the release. However, a PATCH release (X.X.X) should include a list of single line entries summarizing each change directly in the file docs/change_log/index.md (see Versions for an explanation of MAJOR, MINOR, and PATCH releases). The description of each change should include a reference to the relevant GitHub issue in the format #123 (where 123 is the issue number). Prior to a version being released, the text *under development* should be used as a placeholder for the release date. That text will be replaced with the release date as part of the release process . If a change is the first since the last release, then the appropriate entries and/or files may need to be created and included in a pull request. A pull request should not alter an entry for an existing version which has already been released, unless it is editing an error in the release notes for that version, or is otherwise expressly deemed appropriate by the project maintainers. Commit Message Style Guide \u00b6 Use the present tense (\u201cAdd feature\u201d not \u201cAdded feature\u201d). Use the imperative mood (\u201cMove item to\u2026\u201d not \u201cMoves item to\u2026\u201d). Limit the first line to 72 characters or less. Reference issues and pull requests liberally after the first line. Include a summary of the changes/additions made without replicating the content of the documentation or release notes. This is where an explanation of the choices made should be found. References to issues and pull requests should only provide the context in which a choice was made. However, the commit should be able to stand on its own. Development Environment \u00b6 To start developing on Python-Markdown is it best to create a fork of the project on GitHub. After cloning your fork to your local system, you will want to configure a remote that points to the upstream repository so that you can sync changes made in the original repository with your fork. It is recommended that all development be done from within a Python virtual environment , which isolates any experimental code from the general system. To create a virtual environment, use the following command from the root of the local working copy of your GitHub fork: virtualenv venv That creates a virtual environment which is contained in the venv directory within your local working copy. Note that the repository is configured so that git will ignore any files within a directory named venv or ENV for this very reason. On Posix systems (Linux, BSD, MacOS, etc.), use the following command to activate the environment: source venv/bin/activate On Windows, use this command instead: venv/Scripts/activate See the User Guide for more information on using virtual environments. To be able to run the Markdown library directly while working on it, install the working copy into the environment in Development Mode after activating the virtual environment for the first time: pip install -e . Now any saved changes will immediately be available within the virtual environment. You can run the command line script with the following command: python -m markdown Before building the documentation for the first time, you will need to install some optional dependencies with the command: pip install -e . [ docs ] To build the documentation and serve it locally on a development server, run: mkdocs serve Then point your browser at http://127.0.0.1:8000/ . For a complete list of options available, view MkDocs\u2019 help with the command: mkdocs --help Before running tests for the first time, you will need to install some optional dependencies with the command: pip install -e . [ testing ] And you can directly run the tests with: python -m unittest discover tests To get a coverage report after running the tests, use these commands instead: coverage run --source = markdown -m unittest discover tests coverage report --show-missing Note Some tests require the PyTidyLib library, which depends on the HTML Tidy library. If you do not have PyTidyLib installed, the tests which depend upon it will be skipped. Given the difficulty in installing the HTML Tidy library on many systems, you may choose to leave both libraries uninstalled and depend on the continuous integration server to run those tests when you submit a pull request. The above setup will only run tests against the code in one version of Python. However, Python-Markdown supports multiple versions of Python. Therefore, a tox configuration is included in the repository, which includes test environments for all supported Python versions, a Flake8 test environment, and a spellchecker for the documentation. While it is generally fine to leave those tests for the continuous integration server to run when a pull request is submitted, for more advanced changes, you may want to run those tests locally. To do so, simply install tox: pip install tox Then, to run all configured test environments, simply call the command tox with no arguments. See help ( tox -h ) for more options. Note The tox environments expect that some dependencies are already installed on your system. For example, by default, any Python version specific environment will fail if that version of Python is not installed. Additionally, the tox environments assume that the HTML Tidy library is installed and may fail when attempting to install PyTidyLib if it is not. Finally, the spellchecker environment requires aspell and the aspell-en dictionary to be installed. Unfortunately, installing those dependencies may differ significantly from system to system and is outside the scope of this guide. See Also Python-Markdown provides test tools which simply test Markdown syntax. Understanding those tools will often help in understanding why a test may be failing. Versions \u00b6 Python-Markdown follows Semantic Versioning and uses the MAJOR.MINOR.PATCH[.dev#|a#|b#|rc#] format for identifying releases. The status of the master branch should always be identified in the __version_info__ tuple defined in markdown/__meta__.py . The contents of that tuple will automatically be converted into a normalized version which conforms to PEP 440 . An invalid __version_info__ tuple will raise an error, preventing the library from running and the package from building. Version Status \u00b6 A MAJOR version is in development status when the MINOR version is 0 , the PATCH version is 0 , and the version includes a dev segment. A MINOR version is in development status when the MINOR version is not 0 , the PATCH version is 0 , and the version includes a dev segment. At all other times, the code is considered stable and release-ready. MAJOR and MINOR releases may or may not get pre-releases (alpha, beta, release candidate, etc.) at the discretion of the project maintainers. Version Workflow \u00b6 Bug fixes may be merged from a pull request to the master branch at any time so long as all tests pass, including one or more new tests which would have failed prior to the change. New features and backward incompatible changes may only be merged to the master branch when the MAJOR and/or MINOR version is in development status pursuant to Semantic Versioning . A separate commit to the master branch should be made to bump up the MAJOR and/or MINOR version and set development status. Only then will any pull requests implementing new features or backward incompatible changes be accepted. If a bug fix is deemed to be important and the master branch is in development status, a back-port of the fix should be committed to a version branch. If the appropriate version branch does not exist, then it should be created and a pull request back-porting the fix made against that branch. The version branch should be named with the most recently released MINOR version. For example, if the master branch is at 3.1.dev0 and the most recent MINOR release was 3.0.4 , then the version branch would be named 3.0 and any releases from that branch would increment the PATCH version only ( 3.0.5 , 3.0.6 \u2026). Release Process \u00b6 When a new release is being prepared, the release manager should follow the following steps: Verify that all outstanding issues and pull requests related to the release have been resolved. Confirm that the release notes and change log have been updated and indicate the date of the new release. Update the version defined in markdown/__meta__.py . Build a local copy of the documentation, browse through the pages and confirm that no obvious issues exist with the documentation. Create a pull request with a commit message in the following format: Bump version to X.X.X After all checks have passed, merge the pull request. Create a git tag with the new version as the tag name and push to the Python-Markdown/markdown repository. The new tag should trigger a GitHub workflow which will automatically deploy the release to PyPI and update the documentation. In the event that the deployment fails, the following steps can be taken to deploy manually: Deploy the release to PyPI with the command make deploy . 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. cd Python-Markdown.github.io mkdocs gh-deploy --config-file ../markdown/mkdocs.yml --remote-branch master Issue and Pull Request Labels \u00b6 Below are the labels used to track and manages issues and pull requests. The labels are loosely grouped by their purpose, but it is not necessary for every issue to have a label from every group, and an issue may have more than one label from the same group. Type of Issue or Pull Request \u00b6 Label name Description bug Bug report. feature Feature request. support Support request. process Discussions regarding policies and development process. Category of Issue or Pull Request \u00b6 Label name Description core Related to the core parser code. extension Related to one or more of the included extensions. docs Related to the project documentation. Status of Issue \u00b6 Label name Description more-info-needed More information needs to be provided. needs-confirmation The alleged behavior needs to be confirmed. needs-decision A decision needs to be made regarding request. confirmed Confirmed bug report or approved feature request. someday-maybe Approved low priority request. duplicate The issue has been previously reported. wontfix The issue will not be fixed for the stated reasons. invalid Invalid report (user error, upstream issue, etc). 3rd-party Should be implemented as a third party extension. Status of Pull Request \u00b6 Label name Description work-in-progress A partial solution. More changes will be coming. needs-review Needs to be reviewed and/or approved. requires-changes Awaiting updates after a review. approved The pull request is ready to be merged. rejected The pull request is rejected for the stated reasons. /* GitHub Label Styles */ code.label { color: #000000; font-weight: 600; line-height: 15px; display: inline-block; padding: 4px 6px; } code.bug { background-color: #c45b46; } code.feature { background-color: #7b17d8; color: #ffffff; } code.support { background-color: #efbe62; } code.process { background-color: #eec9ff; } code.core { background-color: #0b02e1; color: #ffffff; } code.extension { background-color: #709ad8; } code.docs { background-color: #b2ffeb; } code.approved { background-color: #beed6d; } code.low { background-color: #dddddd; } code.pending { background-color: #f0f49a; } code.rejected { background-color: #f7c7be; }","title":"Contributing to Python-Markdown"},{"location":"contributing/#contributing-to-python-markdown","text":"The following is a set of guidelines for contributing to Python-Markdown and its extensions, which are hosted in the Python-Markdown Organization on GitHub. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request.","title":"Contributing to Python-Markdown"},{"location":"contributing/#code-of-conduct","text":"This project and everyone participating in it is governed by the Python-Markdown Code of Conduct . By participating, you are expected to uphold this code. Please report unacceptable behavior to python.markdown@gmail.com .","title":"Code of Conduct"},{"location":"contributing/#project-organization","text":"The core Python-Markdown code base and any built-in extensions are hosted in the Python-Markdown/markdown project on GitHub. Other extensions maintained by the Python-Markdown project may be hosted as separate repositories in the Python-Markdown Organization on GitHub and must follow best practices for third-party extensions. The Python-Markdown/markdown project is organized as follows: Branch master should generally be stable and release-ready at all times. Version branches should be used for bug-fixes back-ported to the most recent PATCH release. No other branches should be created. Any other branches which exist are preserved for historical reasons only.","title":"Project Organization"},{"location":"contributing/#issues","text":"Feature requests, bug reports, usage questions, and other issues can all be raised on the GitHub issue tracker . When describing issues try to phrase your ticket in terms of the behavior you think needs to change rather than the code you think needs to change. Make sure you\u2019re running the latest version of Python-Markdown before reporting an issue. Search the issue list first for related items. Be sure to check closed issues and pull requests. GitHub\u2019s search only checks open issues by default. You may want to check the syntax rules and/or Babelmark to confirm that your expectations align with the rules and/or other implementations of Markdown. If reporting a syntax bug, you must provide the minimal input which exhibits the behavior, the actual output and the output you expected. All three items must be provided as textual code blocks (screen-shots are not helpful). It may also be helpful to point to the syntax rules which specifically address the area of concern. Feature requests will often be closed with a recommendation that they be implemented as third party extensions outside of the core Python-Markdown library. Keeping new feature requests implemented as third party extensions allows us to keep the maintenance overhead of Python-Markdown to a minimum, so that the focus can be on continued stability, bug fixes, and documentation. If you intend to submit a fix for your bug or provide an implementation of your feature request, it is not necessary to first open an issue. You can report a bug or make a feature request as part of a pull request. Of course, if you want to receive feedback on how to implement a bug-fix or feature before submitting a solution, then it would be appropriate to open an issue first and ask your questions there. Having your issue closed does not necessarily mean the end of a discussion. If you believe your issue has been closed incorrectly, explain why and we\u2019ll consider if it needs to be reopened.","title":"Issues"},{"location":"contributing/#pull-requests","text":"A pull request often represents the start of a discussion, and does not necessarily need to be the final, finished submission. In fact, if you discover an issue and intend to provide a fix for it, there is no need to open an issue first. You can report the issue and provide the fix together in a pull request. All pull requests should be made from your personal fork of the library hosted in your personal GitHub account. Do not create branches on the Python-Markdown/markdown project for pull requests. All pull requests should be implemented in a new branch with a unique name. Remember that if you have an outstanding pull request, pushing new commits to the related branch of your GitHub repository will also automatically update the pull request. It may help to review GitHub\u2019s documentation on Creating a pull request from a fork . If you are providing a fix for a previously reported issue, you must reference the issue in your commit message. Be sure to prefix the reference with one of GitHub\u2019s action words which will automatically close the issue when the pull request is merged. For example, fixes #42 and closes #42 would be acceptable, whereas ref #42 would not. Of course, if merging a pull request should not cause an issue to be closed, then the action word should not be included when referencing that issue. Before being accepted, each pull request must include the applicable code, new tests of all new features, updated tests for any changed features, documentation updates, and an appropriate update to the release notes. All changes must follow the applicable style guides. Failure to meet any one of the requirements is likely to delay any serious consideration of your pull request and may even cause it to be closed. Of course, if you are in the early stages of development, you may include a note in the pull request acknowledging that it is incomplete along with a request for feedback. Pull requests will generally not be accepted if any tests are failing. Therefore, it is recommended that you run the tests before submitting your pull request. After making a pull request, check the build status in the GitHub interface to ensure that all tests are running as expected. If any checks fail, you may push additional commits to your branch. GitHub will add those commits to the pull request and rerun the checks. It is generally best not to squash multiple commits and force-push your changes to a pull request. Instead, the maintainers would like to be able to follow the series of commits along with the discussion about those changes as they progress over time. If your pull request is accepted, it will be squashed at that time if deemed appropriate.","title":"Pull Requests"},{"location":"contributing/#style-guides","text":"In an effort to maintain consistency, Python-Markdown adheres to the following style guides in its code and documentation. A pull request may be rejected if it fails to match the relevant style guides.","title":"Style Guides"},{"location":"contributing/#code-style-guide","text":"Except as noted below, all pull requests should follow Python\u2019s standard PEP8 Style Guide and are run through Flake8 to ensure that the style guide is followed. Legacy code which does not follow the guidelines should only be updated if and when other changes (bug fix, feature addition, etc.) are being made to that section of code. While new features should be given names that follow modern Python naming conventions, existing names should be preserved to avoid backward incompatible changes. Line length is limited to a maximum of 119 characters. When a line of code does not fit within the line length limit, continuation lines should align elements wrapped inside parentheses, brackets and braces using a hanging indent . When using a hanging indent there should be no arguments on the first line and further indentation should be used to clearly distinguish itself as a continuation line. The closing parenthesis, bracket or brace should be on a line by itself and should line up under the first character of the line that starts the multi-line construct. my_list = [ 1 , 2 , 3 , 4 , 5 , 6 , ] result = some_function_that_takes_arguments ( 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , ) When the conditional part of an if -statement is long enough to require that it be written across multiple lines, extra indentation should be included on the conditional continuation line. if ( this_is_one_thing and that_is_another_thing ): do_something ()","title":"Code Style Guide"},{"location":"contributing/#documentation-style-guide","text":"Documentation should be in American English. The tone of the documentation should be simple, plain, objective and well-balanced where possible. Keep paragraphs reasonably short. With the exception of code blocks, limit line length to 79 characters. You may want to use your editor\u2019s tools to automatically hard wrap lines of text. Don\u2019t use abbreviations such as \u2018e.g.\u2019 but instead use the long form, such as \u2018For example\u2019. The documentation is built from the Markdown source files in the docs directory by the MkDocs static site generator. In addition to the basic Markdown syntax, the following extensions are supported: extra , admonition , smarty , codehilite , and toc . There are a few conventions you should follow when working on the documentation.","title":"Documentation Style Guide"},{"location":"contributing/#headers","text":"Headers should use the hash style. For example: ## Some important topic The underline style should not be used. Don\u2019t do this: Some important topic ====================","title":"Headers"},{"location":"contributing/#links","text":"Links should always use the reference style, with the referenced hyperlinks kept at the end of the document. Here is a link to [ some other thing ][ other-thing ]. More text... [ other-thing ]: http://example.com/other/thing This style helps keep the documentation source consistent and readable. If you are linking to another document within Python-Markdown\u2019s documentation, you should use a relative link, and link to the .md suffix. If applicable, it is preferred that the link includes a hash fragment pointing to the specific section of the page. For example: [ authentication ]: reference.md#Markdown Linking in this style ensures that the links work when browsing the documentation on GitHub. If your Markdown editor makes links clickable, they will work there as well. When the documentation is built, these links will be converted into regular links which point to the built HTML pages.","title":"Links"},{"location":"contributing/#notes-and-warnings","text":"If you want to draw attention to a note or warning, use the syntax defined in Python-Markdown\u2019s Admonition Extension : !!! note This is the content of the note.","title":"Notes and Warnings"},{"location":"contributing/#release-notes","text":"Any commit/pull request which changes the behavior of the Markdown library in any way must include an entry in the release notes. If a change only alters the documentation or tooling for the project, then an entry in the release notes is not necessary. The release notes can be found at docs/change_log . Each release must have an entry in docs/change_log/index.md which follows the format of the existing entries. A MAJOR release ( X.0.0 ) and a MINOR release ( X.X.0 ) should only include a single line in docs/change_log/index.md which links to a full document outlining all changes included in the release. However, a PATCH release (X.X.X) should include a list of single line entries summarizing each change directly in the file docs/change_log/index.md (see Versions for an explanation of MAJOR, MINOR, and PATCH releases). The description of each change should include a reference to the relevant GitHub issue in the format #123 (where 123 is the issue number). Prior to a version being released, the text *under development* should be used as a placeholder for the release date. That text will be replaced with the release date as part of the release process . If a change is the first since the last release, then the appropriate entries and/or files may need to be created and included in a pull request. A pull request should not alter an entry for an existing version which has already been released, unless it is editing an error in the release notes for that version, or is otherwise expressly deemed appropriate by the project maintainers.","title":"Release Notes"},{"location":"contributing/#commit-message-style-guide","text":"Use the present tense (\u201cAdd feature\u201d not \u201cAdded feature\u201d). Use the imperative mood (\u201cMove item to\u2026\u201d not \u201cMoves item to\u2026\u201d). Limit the first line to 72 characters or less. Reference issues and pull requests liberally after the first line. Include a summary of the changes/additions made without replicating the content of the documentation or release notes. This is where an explanation of the choices made should be found. References to issues and pull requests should only provide the context in which a choice was made. However, the commit should be able to stand on its own.","title":"Commit Message Style Guide"},{"location":"contributing/#development-environment","text":"To start developing on Python-Markdown is it best to create a fork of the project on GitHub. After cloning your fork to your local system, you will want to configure a remote that points to the upstream repository so that you can sync changes made in the original repository with your fork. It is recommended that all development be done from within a Python virtual environment , which isolates any experimental code from the general system. To create a virtual environment, use the following command from the root of the local working copy of your GitHub fork: virtualenv venv That creates a virtual environment which is contained in the venv directory within your local working copy. Note that the repository is configured so that git will ignore any files within a directory named venv or ENV for this very reason. On Posix systems (Linux, BSD, MacOS, etc.), use the following command to activate the environment: source venv/bin/activate On Windows, use this command instead: venv/Scripts/activate See the User Guide for more information on using virtual environments. To be able to run the Markdown library directly while working on it, install the working copy into the environment in Development Mode after activating the virtual environment for the first time: pip install -e . Now any saved changes will immediately be available within the virtual environment. You can run the command line script with the following command: python -m markdown Before building the documentation for the first time, you will need to install some optional dependencies with the command: pip install -e . [ docs ] To build the documentation and serve it locally on a development server, run: mkdocs serve Then point your browser at http://127.0.0.1:8000/ . For a complete list of options available, view MkDocs\u2019 help with the command: mkdocs --help Before running tests for the first time, you will need to install some optional dependencies with the command: pip install -e . [ testing ] And you can directly run the tests with: python -m unittest discover tests To get a coverage report after running the tests, use these commands instead: coverage run --source = markdown -m unittest discover tests coverage report --show-missing Note Some tests require the PyTidyLib library, which depends on the HTML Tidy library. If you do not have PyTidyLib installed, the tests which depend upon it will be skipped. Given the difficulty in installing the HTML Tidy library on many systems, you may choose to leave both libraries uninstalled and depend on the continuous integration server to run those tests when you submit a pull request. The above setup will only run tests against the code in one version of Python. However, Python-Markdown supports multiple versions of Python. Therefore, a tox configuration is included in the repository, which includes test environments for all supported Python versions, a Flake8 test environment, and a spellchecker for the documentation. While it is generally fine to leave those tests for the continuous integration server to run when a pull request is submitted, for more advanced changes, you may want to run those tests locally. To do so, simply install tox: pip install tox Then, to run all configured test environments, simply call the command tox with no arguments. See help ( tox -h ) for more options. Note The tox environments expect that some dependencies are already installed on your system. For example, by default, any Python version specific environment will fail if that version of Python is not installed. Additionally, the tox environments assume that the HTML Tidy library is installed and may fail when attempting to install PyTidyLib if it is not. Finally, the spellchecker environment requires aspell and the aspell-en dictionary to be installed. Unfortunately, installing those dependencies may differ significantly from system to system and is outside the scope of this guide. See Also Python-Markdown provides test tools which simply test Markdown syntax. Understanding those tools will often help in understanding why a test may be failing.","title":"Development Environment"},{"location":"contributing/#versions","text":"Python-Markdown follows Semantic Versioning and uses the MAJOR.MINOR.PATCH[.dev#|a#|b#|rc#] format for identifying releases. The status of the master branch should always be identified in the __version_info__ tuple defined in markdown/__meta__.py . The contents of that tuple will automatically be converted into a normalized version which conforms to PEP 440 . An invalid __version_info__ tuple will raise an error, preventing the library from running and the package from building.","title":"Versions"},{"location":"contributing/#version-status","text":"A MAJOR version is in development status when the MINOR version is 0 , the PATCH version is 0 , and the version includes a dev segment. A MINOR version is in development status when the MINOR version is not 0 , the PATCH version is 0 , and the version includes a dev segment. At all other times, the code is considered stable and release-ready. MAJOR and MINOR releases may or may not get pre-releases (alpha, beta, release candidate, etc.) at the discretion of the project maintainers.","title":"Version Status"},{"location":"contributing/#version-workflow","text":"Bug fixes may be merged from a pull request to the master branch at any time so long as all tests pass, including one or more new tests which would have failed prior to the change. New features and backward incompatible changes may only be merged to the master branch when the MAJOR and/or MINOR version is in development status pursuant to Semantic Versioning . A separate commit to the master branch should be made to bump up the MAJOR and/or MINOR version and set development status. Only then will any pull requests implementing new features or backward incompatible changes be accepted. If a bug fix is deemed to be important and the master branch is in development status, a back-port of the fix should be committed to a version branch. If the appropriate version branch does not exist, then it should be created and a pull request back-porting the fix made against that branch. The version branch should be named with the most recently released MINOR version. For example, if the master branch is at 3.1.dev0 and the most recent MINOR release was 3.0.4 , then the version branch would be named 3.0 and any releases from that branch would increment the PATCH version only ( 3.0.5 , 3.0.6 \u2026).","title":"Version Workflow"},{"location":"contributing/#release-process","text":"When a new release is being prepared, the release manager should follow the following steps: Verify that all outstanding issues and pull requests related to the release have been resolved. Confirm that the release notes and change log have been updated and indicate the date of the new release. Update the version defined in markdown/__meta__.py . Build a local copy of the documentation, browse through the pages and confirm that no obvious issues exist with the documentation. Create a pull request with a commit message in the following format: Bump version to X.X.X After all checks have passed, merge the pull request. Create a git tag with the new version as the tag name and push to the Python-Markdown/markdown repository. The new tag should trigger a GitHub workflow which will automatically deploy the release to PyPI and update the documentation. In the event that the deployment fails, the following steps can be taken to deploy manually: Deploy the release to PyPI with the command make deploy . 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. cd Python-Markdown.github.io mkdocs gh-deploy --config-file ../markdown/mkdocs.yml --remote-branch master","title":"Release Process"},{"location":"contributing/#issue-and-pull-request-labels","text":"Below are the labels used to track and manages issues and pull requests. The labels are loosely grouped by their purpose, but it is not necessary for every issue to have a label from every group, and an issue may have more than one label from the same group.","title":"Issue and Pull Request Labels"},{"location":"contributing/#type-of-issue-or-pull-request","text":"Label name Description bug Bug report. feature Feature request. support Support request. process Discussions regarding policies and development process.","title":"Type of Issue or Pull Request"},{"location":"contributing/#category-of-issue-or-pull-request","text":"Label name Description core Related to the core parser code. extension Related to one or more of the included extensions. docs Related to the project documentation.","title":"Category of Issue or Pull Request"},{"location":"contributing/#status-of-issue","text":"Label name Description more-info-needed More information needs to be provided. needs-confirmation The alleged behavior needs to be confirmed. needs-decision A decision needs to be made regarding request. confirmed Confirmed bug report or approved feature request. someday-maybe Approved low priority request. duplicate The issue has been previously reported. wontfix The issue will not be fixed for the stated reasons. invalid Invalid report (user error, upstream issue, etc). 3rd-party Should be implemented as a third party extension.","title":"Status of Issue"},{"location":"contributing/#status-of-pull-request","text":"Label name Description work-in-progress A partial solution. More changes will be coming. needs-review Needs to be reviewed and/or approved. requires-changes Awaiting updates after a review. approved The pull request is ready to be merged. rejected The pull request is rejected for the stated reasons. /* GitHub Label Styles */ code.label { color: #000000; font-weight: 600; line-height: 15px; display: inline-block; padding: 4px 6px; } code.bug { background-color: #c45b46; } code.feature { background-color: #7b17d8; color: #ffffff; } code.support { background-color: #efbe62; } code.process { background-color: #eec9ff; } code.core { background-color: #0b02e1; color: #ffffff; } code.extension { background-color: #709ad8; } code.docs { background-color: #b2ffeb; } code.approved { background-color: #beed6d; } code.low { background-color: #dddddd; } code.pending { background-color: #f0f49a; } code.rejected { background-color: #f7c7be; }","title":"Status of Pull Request"},{"location":"install/","text":"Installing Python-Markdown \u00b6 The Easy Way \u00b6 The easiest way to install Python-Markdown is simply to type the following command from the command line: pip install markdown That\u2019s it! You\u2019re ready to use Python-Markdown. Enjoy! For more detailed instructions on installing Python packages, see the Installing Packages tutorial in the Python Packaging User Guide . Using the Git Repository \u00b6 If you\u2019re the type that likes to live on the edge, you may want to keep up with the latest additions and bug fixes in the repository between releases. Python-Markdown is maintained in a Git repository on GitHub.com. To get a copy of Python-Markdown from the repository do the following from the command line: pip install git+https://github.com/Python-Markdown/markdown.git","title":"Installation"},{"location":"install/#installing-python-markdown","text":"","title":"Installing Python-Markdown"},{"location":"install/#the-easy-way","text":"The easiest way to install Python-Markdown is simply to type the following command from the command line: pip install markdown That\u2019s it! You\u2019re ready to use Python-Markdown. Enjoy! For more detailed instructions on installing Python packages, see the Installing Packages tutorial in the Python Packaging User Guide .","title":"The Easy Way"},{"location":"install/#git","text":"If you\u2019re the type that likes to live on the edge, you may want to keep up with the latest additions and bug fixes in the repository between releases. Python-Markdown is maintained in a Git repository on GitHub.com. To get a copy of Python-Markdown from the repository do the following from the command line: pip install git+https://github.com/Python-Markdown/markdown.git","title":"Using the Git Repository"},{"location":"reference/","text":"Using Markdown as a Python Library \u00b6 First and foremost, Python-Markdown is intended to be a python library module used by various projects to convert Markdown syntax into HTML. The Basics \u00b6 To use markdown as a module: import markdown html = markdown . markdown ( your_text_string ) The Details \u00b6 Python-Markdown provides two public functions ( markdown.markdown and markdown.markdownFromFile ) both of which wrap the public class markdown.Markdown . If you\u2019re processing one document at a time, these functions will serve your needs. However, if you need to process multiple documents, it may be advantageous to create a single instance of the markdown.Markdown class and pass multiple documents through it. If you do use a single instance though, make sure to call the reset method appropriately ( see below ). markdown.markdown(text [, **kwargs]) \u00b6 The following options are available on the markdown.markdown function: text The source Unicode string. (required) Important Python-Markdown expects a Unicode string as input (some simple ASCII binary strings may work only by coincidence) and returns output as a Unicode string. Do not pass binary strings to it! If your input is encoded, (e.g. as UTF-8), it is your responsibility to decode it. For example: with open ( \"some_file.txt\" , \"r\" , encoding = \"utf-8\" ) as input_file : text = input_file . read () html = markdown . markdown ( text ) If you want to write the output to disk, you must encode it yourself: with open ( \"some_file.html\" , \"w\" , encoding = \"utf-8\" , errors = \"xmlcharrefreplace\" ) as output_file : output_file . write ( html ) extensions A list of extensions. Python-Markdown provides an API for third parties to write extensions to the parser adding their own additions or changes to the syntax. A few commonly used extensions are shipped with the markdown library. See the extension documentation for a list of available extensions. The list of extensions may contain instances of extensions and/or strings of extension names. extensions = [ MyExtClass (), 'myext' , 'path.to.my.ext:MyExtClass' ] Note The preferred method is to pass in an instance of an extension. Strings should only be used when it is impossible to import the Extension Class directly (from the command line or in a template). When passing in extension instances, each class instance must be a subclass of markdown.extensions.Extension and any configuration options should be defined when initiating the class instance rather than using the extension_configs keyword. For example: from markdown.extensions import Extension class MyExtClass ( Extension ): # define your extension here... markdown . markdown ( text , extensions = [ MyExtClass ( option = 'value' )]) If an extension name is provided as a string, the string must either be the registered entry point of any installed extension or the importable path using Python\u2019s dot notation. See the documentation specific to an extension for the string name assigned to an extension as an entry point. Simply include the defined name as a string in the list of extensions. For example, if an extension has the name myext assigned to it and the extension is properly installed, then do the following: markdown . markdown ( text , extensions = [ 'myext' ]) If an extension does not have a registered entry point, Python\u2019s dot notation may be used instead. The extension must be installed as a Python module on your PYTHONPATH. Generally, a class should be specified in the name. The class must be at the end of the name and be separated by a colon from the module. Therefore, if you were to import the class like this: from path.to.module import MyExtClass Then load the extension as follows: markdown . markdown ( text , extensions = [ 'path.to.module:MyExtClass' ]) If only one extension is defined within a module and the module includes a makeExtension function which returns an instance of the extension, then the class name is not necessary. For example, in that case one could do extensions=['path.to.module'] . Check the documentation for a specific extension to determine if it supports this feature. When loading an extension by name (as a string), you can only pass in configuration settings to the extension by using the extension_configs keyword. See Also See the documentation of the Extension API for assistance in creating extensions. extension_configs A dictionary of configuration settings for extensions. Any configuration settings will only be passed to extensions loaded by name (as a string). When loading extensions as class instances, pass the configuration settings directly to the class when initializing it. Note The preferred method is to pass in an instance of an extension, which does not require use of the extension_configs keyword at all. See the extensions keyword for details. The dictionary of configuration settings must be in the following format: extension_configs = { 'extension_name_1' : { 'option_1' : 'value_1' , 'option_2' : 'value_2' }, 'extension_name_2' : { 'option_1' : 'value_1' } } When specifying the extension name, be sure to use the exact same string as is used in the extensions keyword to load the extension. Otherwise, the configuration settings will not be applied to the extension. In other words, you cannot use the entry point in on place and Python dot notation in the other. While both may be valid for a given extension, they will not be recognized as being the same extension by Markdown. See the documentation specific to the extension you are using for help in specifying configuration settings for that extension. output_format : Format of output. Supported formats are: \"xhtml\" : Outputs XHTML style tags. Default . \"html\" : Outputs HTML style tags. The values can be in either lowercase or uppercase. tab_length : Length of tabs in the source. Default: 4 markdown.markdownFromFile (**kwargs) \u00b6 With a few exceptions, markdown.markdownFromFile accepts the same options as markdown.markdown . It does not accept a text (or Unicode) string. Instead, it accepts the following required options: input (required) The source text file. input may be set to one of three options: a string which contains a path to a readable file on the file system, a readable file-like object, or None (default) which will read from stdin . output The target which output is written to. output may be set to one of three options: a string which contains a path to a writable file on the file system, a writable file-like object, or None (default) which will write to stdout . encoding The encoding of the source text file. Defaults to \"utf-8\" . The same encoding will always be used for input and output. 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. If this rather naive solution does not meet your specific needs, it is suggested that you write your own code to handle your encoding/decoding needs. markdown.Markdown([**kwargs]) \u00b6 The same options are available when initializing the markdown.Markdown class as on the markdown.markdown function, except that the class does not accept a source text string on initialization. Rather, the source text string must be passed to one of two instance methods. Warning Instances of the markdown.Markdown class are only thread safe within the thread they were created in. A single instance should not be accessed from multiple threads. Markdown.convert(source) \u00b6 The source text must meet the same requirements as the text argument of the markdown.markdown function. You should also use this method if you want to process multiple strings without creating a new instance of the class for each string. md = markdown . Markdown () html1 = md . convert ( text1 ) html2 = md . convert ( text2 ) Depending on which options and/or extensions are being used, the parser may need its state reset between each call to convert . html1 = md . convert ( text1 ) md . reset () html2 = md . convert ( text2 ) To make this easier, you can also chain calls to reset together: html3 = md . reset () . convert ( text3 ) Markdown.convertFile(**kwargs) \u00b6 The arguments of this method are identical to the arguments of the same name on the markdown.markdownFromFile function ( input , output , and encoding ). As with the convert method, this method should be used to process multiple files without creating a new instance of the class for each document. State may need to be reset between each call to convertFile as is the case with convert .","title":"Library Reference"},{"location":"reference/#using-markdown-as-a-python-library","text":"First and foremost, Python-Markdown is intended to be a python library module used by various projects to convert Markdown syntax into HTML.","title":"Using Markdown as a Python Library"},{"location":"reference/#the-basics","text":"To use markdown as a module: import markdown html = markdown . markdown ( your_text_string )","title":"The Basics"},{"location":"reference/#the-details","text":"Python-Markdown provides two public functions ( markdown.markdown and markdown.markdownFromFile ) both of which wrap the public class markdown.Markdown . If you\u2019re processing one document at a time, these functions will serve your needs. However, if you need to process multiple documents, it may be advantageous to create a single instance of the markdown.Markdown class and pass multiple documents through it. If you do use a single instance though, make sure to call the reset method appropriately ( see below ).","title":"The Details"},{"location":"reference/#markdown","text":"The following options are available on the markdown.markdown function: text The source Unicode string. (required) Important Python-Markdown expects a Unicode string as input (some simple ASCII binary strings may work only by coincidence) and returns output as a Unicode string. Do not pass binary strings to it! If your input is encoded, (e.g. as UTF-8), it is your responsibility to decode it. For example: with open ( \"some_file.txt\" , \"r\" , encoding = \"utf-8\" ) as input_file : text = input_file . read () html = markdown . markdown ( text ) If you want to write the output to disk, you must encode it yourself: with open ( \"some_file.html\" , \"w\" , encoding = \"utf-8\" , errors = \"xmlcharrefreplace\" ) as output_file : output_file . write ( html ) extensions A list of extensions. Python-Markdown provides an API for third parties to write extensions to the parser adding their own additions or changes to the syntax. A few commonly used extensions are shipped with the markdown library. See the extension documentation for a list of available extensions. The list of extensions may contain instances of extensions and/or strings of extension names. extensions = [ MyExtClass (), 'myext' , 'path.to.my.ext:MyExtClass' ] Note The preferred method is to pass in an instance of an extension. Strings should only be used when it is impossible to import the Extension Class directly (from the command line or in a template). When passing in extension instances, each class instance must be a subclass of markdown.extensions.Extension and any configuration options should be defined when initiating the class instance rather than using the extension_configs keyword. For example: from markdown.extensions import Extension class MyExtClass ( Extension ): # define your extension here... markdown . markdown ( text , extensions = [ MyExtClass ( option = 'value' )]) If an extension name is provided as a string, the string must either be the registered entry point of any installed extension or the importable path using Python\u2019s dot notation. See the documentation specific to an extension for the string name assigned to an extension as an entry point. Simply include the defined name as a string in the list of extensions. For example, if an extension has the name myext assigned to it and the extension is properly installed, then do the following: markdown . markdown ( text , extensions = [ 'myext' ]) If an extension does not have a registered entry point, Python\u2019s dot notation may be used instead. The extension must be installed as a Python module on your PYTHONPATH. Generally, a class should be specified in the name. The class must be at the end of the name and be separated by a colon from the module. Therefore, if you were to import the class like this: from path.to.module import MyExtClass Then load the extension as follows: markdown . markdown ( text , extensions = [ 'path.to.module:MyExtClass' ]) If only one extension is defined within a module and the module includes a makeExtension function which returns an instance of the extension, then the class name is not necessary. For example, in that case one could do extensions=['path.to.module'] . Check the documentation for a specific extension to determine if it supports this feature. When loading an extension by name (as a string), you can only pass in configuration settings to the extension by using the extension_configs keyword. See Also See the documentation of the Extension API for assistance in creating extensions. extension_configs A dictionary of configuration settings for extensions. Any configuration settings will only be passed to extensions loaded by name (as a string). When loading extensions as class instances, pass the configuration settings directly to the class when initializing it. Note The preferred method is to pass in an instance of an extension, which does not require use of the extension_configs keyword at all. See the extensions keyword for details. The dictionary of configuration settings must be in the following format: extension_configs = { 'extension_name_1' : { 'option_1' : 'value_1' , 'option_2' : 'value_2' }, 'extension_name_2' : { 'option_1' : 'value_1' } } When specifying the extension name, be sure to use the exact same string as is used in the extensions keyword to load the extension. Otherwise, the configuration settings will not be applied to the extension. In other words, you cannot use the entry point in on place and Python dot notation in the other. While both may be valid for a given extension, they will not be recognized as being the same extension by Markdown. See the documentation specific to the extension you are using for help in specifying configuration settings for that extension. output_format : Format of output. Supported formats are: \"xhtml\" : Outputs XHTML style tags. Default . \"html\" : Outputs HTML style tags. The values can be in either lowercase or uppercase. tab_length : Length of tabs in the source. Default: 4","title":"markdown.markdown"},{"location":"reference/#markdownFromFile","text":"With a few exceptions, markdown.markdownFromFile accepts the same options as markdown.markdown . It does not accept a text (or Unicode) string. Instead, it accepts the following required options: input (required) The source text file. input may be set to one of three options: a string which contains a path to a readable file on the file system, a readable file-like object, or None (default) which will read from stdin . output The target which output is written to. output may be set to one of three options: a string which contains a path to a writable file on the file system, a writable file-like object, or None (default) which will write to stdout . encoding The encoding of the source text file. Defaults to \"utf-8\" . The same encoding will always be used for input and output. 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. If this rather naive solution does not meet your specific needs, it is suggested that you write your own code to handle your encoding/decoding needs.","title":"markdown.markdownFromFile"},{"location":"reference/#Markdown","text":"The same options are available when initializing the markdown.Markdown class as on the markdown.markdown function, except that the class does not accept a source text string on initialization. Rather, the source text string must be passed to one of two instance methods. Warning Instances of the markdown.Markdown class are only thread safe within the thread they were created in. A single instance should not be accessed from multiple threads.","title":"markdown.Markdown"},{"location":"reference/#convert","text":"The source text must meet the same requirements as the text argument of the markdown.markdown function. You should also use this method if you want to process multiple strings without creating a new instance of the class for each string. md = markdown . Markdown () html1 = md . convert ( text1 ) html2 = md . convert ( text2 ) Depending on which options and/or extensions are being used, the parser may need its state reset between each call to convert . html1 = md . convert ( text1 ) md . reset () html2 = md . convert ( text2 ) To make this easier, you can also chain calls to reset together: html3 = md . reset () . convert ( text3 )","title":"Markdown.convert"},{"location":"reference/#convertFile","text":"The arguments of this method are identical to the arguments of the same name on the markdown.markdownFromFile function ( input , output , and encoding ). As with the convert method, this method should be used to process multiple files without creating a new instance of the class for each document. State may need to be reset between each call to convertFile as is the case with convert .","title":"Markdown.convertFile"},{"location":"test_tools/","text":"Test Tools \u00b6 Python-Markdown provides some testing tools which simplify testing actual Markdown output against expected output. The tools are built on the Python standard library unittest . Therefore, no additional libraries are required. While Python-Markdown uses the tools for its own tests, they were designed and built so that third party extensions could use them as well. 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 \u00b6 The markdown.test_tools.TestCase class is a unittest.TestCase subclass with a few additional helpers to make testing Markdown output easier. Properties default_kwargs : A dict of keywords to pass to Markdown for each test. The defaults can be overridden on individual tests. Methods assertMarkdownRenders : accepts the source text, the expected output, an optional dictionary of expected_attrs , and any keywords to pass to Markdown. The default_kwargs defined on the class are used except where overridden by keyword arguments. The output and expected output are passed to TestCase.assertMultiLineEqual . An AssertionError is raised with a diff if the actual output does not equal the expected output. The optional keyword expected_attrs accepts a dictionary of attribute names as keys with expected values. Each value is checked against the attribute of that name on the instance of the Markdown class using TestCase.assertEqual . An AssertionError is raised if any value does not match the expected value. dedent : Dedent triple-quoted strings. In all other respects, markdown.test_tools.TestCase behaves as unittest.TestCase . In fact, assertMarkdownRenders tests could be mixed with other unittest style tests within the same test class. An example Markdown test might look like this: from markdown.test_tools import TestCase class TestHr ( TestCase ): def test_hr_before_paragraph ( self ): self . assertMarkdownRenders ( # The Markdown source text used as input self . dedent ( \"\"\" *** An HR followed by a paragraph with no blank line. \"\"\" ), # The expected HTML output self . dedent ( \"\"\"

    An HR followed by a paragraph with no blank line.

    \"\"\" ), # Other keyword arguments to pass to `markdown.markdown` output_format = 'html' ) markdown.test_tools.LegacyTestCase \u00b6 In the past Python-Markdown exclusively used file-based tests. Many of those tests still exist in Python-Markdown\u2019s test suite, including the test files from the reference implementation ( markdown.pl ) and PHP Markdown . Each test consists of a matching pair of text and HTML files. The text file contains a snippet of Markdown source text formatted for a specific syntax feature and the HTML file contains the expected HTML output of that snippet. When the test suite is run, each text file is run through Markdown and the output is compared with the HTML file as a separate unit test. When a test fails, the error report includes a diff of the expected output compared to the actual output to easily identify any problems. A separate markdown.test_tools.LegacyTestCase subclass must be created for each directory of test files. Various properties can be defined within the subclass to point to a directory of 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 skip. Each test name should comprise of a file name without an extension. normalize : A boolean value indicating if the HTML should be normalized. Default: False . Note: Normalization of HTML requires that PyTidyLib be installed on the system. If PyTidyLib is not installed and normalize is set to True , then the test will be skipped, regardless of any other settings. 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 markdown.test_tools.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 the directory. The property should be given the name of the file without the file extension. Any spaces and dashes in the file name should be replaced with underscores. The value of the property should be a markdown.test_tools.Kwargs instance which contains the keyword arguments that should be passed to markdown.markdown for that test file. The keyword arguments will \u201cupdate\u201d the default_kwargs . When the class instance is created during a test run, it will walk the given directory and create a separate unit test for each set of test files using the naming scheme: test_filename . One unit test will be run for each set of input and output files. The definition of an example set of tests might look like this: from markdown.test_tools import LegacyTestCase , Kwargs import os # Get location of this file and use to find text file dirs. parent_test_dir = os . path . abspath ( os . path . dirname ( __file__ )) class TestFoo ( LegacyTestCase ): # Define location of text file directory. In this case, the directory is # named \"foo\" and is in the same parent directory as this file. location = os . path . join ( parent_test_dir , 'foo' ) # Define default keyword arguments. In this case, unless specified # differently, all tests should use the output format \"html\". default_kwargs = Kwargs ( output_format = 'html' ) # The \"xhtml\" test should override the output format and use \"xhtml\". xhtml = Kwargs ( output_format = 'xhtml' ) # The \"toc\" test should use the \"toc\" extension with a custom permalink # setting. toc = Kwargs ( extensions = [ 'markdown.extensions.toc' ], extension_configs = { 'markdown.extensions.toc' : { 'permalink' : \"[link]\" }} ) Note that in the above example, the text file directory may contain many more text-based test files than xhtml ( xhtml.txt and xhtml.html ) and toc ( toc.txt and toc.html ). As long as each set of files exists as a pair, a test will be created and run for each of them. Only the xhtml and toc tests needed to be specifically identified as they had specific, non-default settings which needed to be defined. Running Python-Markdown\u2019s Tests \u00b6 As all of the tests for the markdown library are unit tests, standard unittest methods of calling tests can be used. For example, to run all of Python-Markdown\u2019s tests, from the root of the git repository, run the following command: python -m unittest discover tests That simple command will search everything in the tests directory and it\u2019s sub-directories and run all unittest tests that it finds, including unittest.TestCase , markdown.test_tools.TestCase , and markdown.test_tools.LegacyTestCase subclasses. Normal unittest discovery rules apply. See Also See the Contributing Guide for instructions on setting up a development environment for running the tests.","title":"Test Tools"},{"location":"test_tools/#test-tools","text":"Python-Markdown provides some testing tools which simplify testing actual Markdown output against expected output. The tools are built on the Python standard library unittest . Therefore, no additional libraries are required. While Python-Markdown uses the tools for its own tests, they were designed and built so that third party extensions could use them as well. 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 .","title":"Test Tools"},{"location":"test_tools/#markdowntest_toolstestcase","text":"The markdown.test_tools.TestCase class is a unittest.TestCase subclass with a few additional helpers to make testing Markdown output easier. Properties default_kwargs : A dict of keywords to pass to Markdown for each test. The defaults can be overridden on individual tests. Methods assertMarkdownRenders : accepts the source text, the expected output, an optional dictionary of expected_attrs , and any keywords to pass to Markdown. The default_kwargs defined on the class are used except where overridden by keyword arguments. The output and expected output are passed to TestCase.assertMultiLineEqual . An AssertionError is raised with a diff if the actual output does not equal the expected output. The optional keyword expected_attrs accepts a dictionary of attribute names as keys with expected values. Each value is checked against the attribute of that name on the instance of the Markdown class using TestCase.assertEqual . An AssertionError is raised if any value does not match the expected value. dedent : Dedent triple-quoted strings. In all other respects, markdown.test_tools.TestCase behaves as unittest.TestCase . In fact, assertMarkdownRenders tests could be mixed with other unittest style tests within the same test class. An example Markdown test might look like this: from markdown.test_tools import TestCase class TestHr ( TestCase ): def test_hr_before_paragraph ( self ): self . assertMarkdownRenders ( # The Markdown source text used as input self . dedent ( \"\"\" *** An HR followed by a paragraph with no blank line. \"\"\" ), # The expected HTML output self . dedent ( \"\"\"

    An HR followed by a paragraph with no blank line.

    \"\"\" ), # Other keyword arguments to pass to `markdown.markdown` output_format = 'html' )","title":"markdown.test_tools.TestCase"},{"location":"test_tools/#markdowntest_toolslegacytestcase","text":"In the past Python-Markdown exclusively used file-based tests. Many of those tests still exist in Python-Markdown\u2019s test suite, including the test files from the reference implementation ( markdown.pl ) and PHP Markdown . Each test consists of a matching pair of text and HTML files. The text file contains a snippet of Markdown source text formatted for a specific syntax feature and the HTML file contains the expected HTML output of that snippet. When the test suite is run, each text file is run through Markdown and the output is compared with the HTML file as a separate unit test. When a test fails, the error report includes a diff of the expected output compared to the actual output to easily identify any problems. A separate markdown.test_tools.LegacyTestCase subclass must be created for each directory of test files. Various properties can be defined within the subclass to point to a directory of 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 skip. Each test name should comprise of a file name without an extension. normalize : A boolean value indicating if the HTML should be normalized. Default: False . Note: Normalization of HTML requires that PyTidyLib be installed on the system. If PyTidyLib is not installed and normalize is set to True , then the test will be skipped, regardless of any other settings. 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 markdown.test_tools.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 the directory. The property should be given the name of the file without the file extension. Any spaces and dashes in the file name should be replaced with underscores. The value of the property should be a markdown.test_tools.Kwargs instance which contains the keyword arguments that should be passed to markdown.markdown for that test file. The keyword arguments will \u201cupdate\u201d the default_kwargs . When the class instance is created during a test run, it will walk the given directory and create a separate unit test for each set of test files using the naming scheme: test_filename . One unit test will be run for each set of input and output files. The definition of an example set of tests might look like this: from markdown.test_tools import LegacyTestCase , Kwargs import os # Get location of this file and use to find text file dirs. parent_test_dir = os . path . abspath ( os . path . dirname ( __file__ )) class TestFoo ( LegacyTestCase ): # Define location of text file directory. In this case, the directory is # named \"foo\" and is in the same parent directory as this file. location = os . path . join ( parent_test_dir , 'foo' ) # Define default keyword arguments. In this case, unless specified # differently, all tests should use the output format \"html\". default_kwargs = Kwargs ( output_format = 'html' ) # The \"xhtml\" test should override the output format and use \"xhtml\". xhtml = Kwargs ( output_format = 'xhtml' ) # The \"toc\" test should use the \"toc\" extension with a custom permalink # setting. toc = Kwargs ( extensions = [ 'markdown.extensions.toc' ], extension_configs = { 'markdown.extensions.toc' : { 'permalink' : \"[link]\" }} ) Note that in the above example, the text file directory may contain many more text-based test files than xhtml ( xhtml.txt and xhtml.html ) and toc ( toc.txt and toc.html ). As long as each set of files exists as a pair, a test will be created and run for each of them. Only the xhtml and toc tests needed to be specifically identified as they had specific, non-default settings which needed to be defined.","title":"markdown.test_tools.LegacyTestCase"},{"location":"test_tools/#running-python-markdowns-tests","text":"As all of the tests for the markdown library are unit tests, standard unittest methods of calling tests can be used. For example, to run all of Python-Markdown\u2019s tests, from the root of the git repository, run the following command: python -m unittest discover tests That simple command will search everything in the tests directory and it\u2019s sub-directories and run all unittest tests that it finds, including unittest.TestCase , markdown.test_tools.TestCase , and markdown.test_tools.LegacyTestCase subclasses. Normal unittest discovery rules apply. See Also See the Contributing Guide for instructions on setting up a development environment for running the tests.","title":"Running Python-Markdown's Tests"},{"location":"change_log/","text":"Python-Markdown Change Log \u00b6 July 25, 2023: version 3.4.4 (a bug-fix release). Add a special case for initial 's to smarty extension ( #1305 ). Unescape any backslash escaped inline raw HTML ( #1358 ). Unescape backslash escaped TOC token names ( #1360 ). March 23, 2023: version 3.4.3 (a bug-fix release). Restore console script ( #1327 ). March 22, 2023: version 3.4.2 (a bug-fix release). Improve standalone * and _ parsing ( #1300 ). Consider HTML tag a block-level element ( #1309 ). Officially support Python 3.11. Switch from setup.py to pyproject.toml . July 15, 2022: version 3.4.1 (a bug-fix release). Fix an import issue with importlib.util ( #1274 ). July 15, 2022: version 3.4 ( Notes ). May 5, 2022: version 3.3.7 (a bug-fix release). Disallow square brackets in reference link ids ( #1209 ). Retain configured pygments_style after first code block ( #1240 ). Ensure fenced code attributes are properly escaped ( #1247 ). Nov 17, 2021: version 3.3.6 (a bug-fix release). Fix a dependency issue ( #1195 , #1196 ). Nov 16, 2021: version 3.3.5 (a bug-fix release). Make the slugify_unicode function not remove diacritical marks ( #1118 ). Fix [toc] detection when used with nl2br extension ( #1160 ). Re-use compiled regex for block level checks ( #1169 ). Don\u2019t process shebangs in fenced code blocks when using CodeHilite ( #1156 ). Improve email address validation for Automatic Links ( #1165 ). Ensure tags are parsed correctly ( #1079 ). Support Python 3.10 ( #1124 ). Feb 24, 2021: version 3.3.4 (a bug-fix release). Properly parse unclosed tags in code spans ( #1066 ). Properly parse processing instructions in md_in_html ( #1070 ). Properly parse code spans in md_in_html ( #1069 ). Preserve text immediately before an admonition ( #1092 ). Simplified regex for HTML placeholders ( #928 ) addressing ( #932 ). Ensure permalinks and anchorlinks are not restricted by toc_depth ( #1107 ). Fix corner cases with lists under admonitions ( #1102 ). Oct 25, 2020: version 3.3.3 (a bug-fix release). Unify all block-level tags ( #1047 ). Fix issue where some empty elements would have text rendered as None when using md_in_html ( #1049 ). Avoid catastrophic backtracking in hr regex ( #1055 ). Fix hr HTML handling ( #1053 ). Oct 19, 2020: version 3.3.2 (a bug-fix release). Properly parse inline HTML in md_in_html ( #1040 & #1045 ). Avoid crashing when md_in_html fails ( #1040 ). Oct 12, 2020: version 3.3.1 (a bug-fix release). Correctly parse raw script and style tags ( #1036 ). Ensure consistent class handling by fenced_code and codehilite ( #1032 ). Oct 6, 2020: version 3.3 ( Notes ). May 8, 2020: version 3.2.2 (a bug-fix release). Add checklinks tox environment to ensure all links in documentation are good. Refactor extension API documentation ( #729 ). Load entry_points (for extensions) only once using importlib.metadata . Do not double escape entities in TOC. Correctly report if an extension raises a TypeError ( #939 ). Raise a KeyError when attempting to delete a nonexistent key from the extension registry ( #939 ). Remove import of packaging (or pkg_resources fallback) entirely. Remove setuptools as a run-time dependency ( install_required ). Feb 12, 2020: Released version 3.2.1 (a bug-fix release). The name property in toc_tokens from the TOC extension now escapes HTML special characters ( < , > , and & ). Feb 7, 2020: Released version 3.2 ( Notes ). May 20, 2019: Released version 3.1.1 (a bug-fix release). Fixed import failure in setup.py when the source directory is not on sys.path ( #823 ). Prefer public packaging module to pkg_resources\u2019 private copy of it ( #825 ). Mar 25, 2019: Released version 3.1 ( Notes ). Sept 28, 2018: Released version 3.0.1 (a bug-fix release). Brought back the version and version_info variables ( #709 ). Added support for hexadecimal HTML entities ( #712 ). Sept 21, 2018: Released version 3.0 ( Notes ). Jan 4, 2018: Released version 2.6.11 (a bug-fix release). Added a new BACKLINK-TITLE option to the footnote extension so that non-English users can provide a custom title to back links (see #610 ). Dec 7, 2017: Released version 2.6.10 (a documentation update). Aug 17, 2017: Released version 2.6.9 (a bug-fix release). Jan 25, 2017: Released version 2.6.8 (a bug-fix release). Sept 23, 2016: Released version 2.6.7 (a bug-fix release). Mar 20, 2016: Released version 2.6.6 (a bug-fix release). Nov 24, 2015: Released version 2.6.5 (a bug-fix release). Nov 6, 2015: Released version 2.6.4 (a bug-fix release). Oct 26, 2015: Released version 2.6.3 (a bug-fix release). Apr 20, 2015: Released version 2.6.2 (a bug-fix release). Mar 8, 2015: Released version 2.6.1 (a bug-fix release). The (new) yaml option has been removed from the Meta-Data Extension as it was buggy (see #390 ). Feb 19, 2015: Released version 2.6 ( Notes ). Nov 19, 2014: Released version 2.5.2 (a bug-fix release). Sept 26, 2014: Released version 2.5.1 (a bug-fix release). Sept 12, 2014: Released version 2.5.0 ( Notes ). Feb 16, 2014: Released version 2.4.0 ( Notes ). Mar 22, 2013: Released version 2.3.1 (a bug-fix release). Mar 14, 2013: Released version 2.3.0 ( Notes ) Nov 4, 2012: Released version 2.2.1 (a bug-fix release). Jul 5, 2012: Released version 2.2.0 ( Notes ). Jan 22, 2012: Released version 2.1.1 (a bug-fix release). Nov 24, 2011: Released version 2.1.0 ( Notes ). Oct 7, 2009: Released version 2.0.3. (a bug-fix release). Sept 28, 2009: Released version 2.0.2 (a bug-fix release). May 20, 2009: Released version 2.0.1 (a bug-fix release). Mar 30, 2009: Released version 2.0 ( Notes ). Mar 8, 2009: Release Candidate 2.0-rc-1. Feb 2009: Added support for multi-level lists to new Blockprocessors. Jan 2009: Added HTML 4 output as an option (thanks Eric Abrahamsen) Nov 2008: Added Definition List ext. Replaced old core with Blockprocessors. Broken up into multiple files. Oct 2008: Changed logging behavior to work better with other systems. Refactored tree traversing. Added treap implementation, then replaced with OrderedDict. Renamed various processors to better reflect what they actually do. Refactored footnote ext to match PHP Extra\u2019s output. Sept 2008: Moved prettifyTree to a Postprocessor, replaced WikiLink ext with WikiLinks (note the s) ext (uses bracketed links instead of CamelCase) and various bug fixes. August 18 2008: Reorganized directory structure. Added a \u2018docs\u2019 directory and moved all extensions into a \u2018markdown-extensions\u2019 package. Added additional documentation and a few bug fixes. (v2.0-beta) 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 various related bugs (thanks Artem Yunusov). June 2008: Fixed issues with nested inline patterns and cleaned up testing framework (thanks Artem Yunusov). May 2008: Added a number of additional extensions to the distribution and other minor changes. Moved repository to git from svn. Mar 2008: Refactored extension API to accept either an extension name (as a string) or an instance of an extension (Thanks David Wolever). Fixed various bugs and added doc strings. Feb 2008: Various bug-fixes mostly regarding extensions. Feb 18, 2008: Version 1.7. Feb 13, 2008: A little code cleanup and better documentation and inheritance for Preprocessors/Postprocessors. Feb 9, 2008: Double-quotes no longer HTML escaped and raw HTML honors , <@foo> , and <%foo> for those who run markdown on template syntax. Dec 12, 2007: Updated docs. Removed encoding argument from Markdown and markdown as per list discussion. Clean up in prep for 1.7. Nov 29, 2007: Added support for images inside links. Also fixed a few bugs in the footnote extension. Nov 19, 2007: message now uses python\u2019s logging module. Also removed limit imposed by recursion in _process_section() . You can now parse as long of a document as your memory can handle. Nov 5, 2007: Moved safe_mode code to a textPostprocessor and added escaping option. Nov 3, 2007: Fixed convert method to accept empty strings. Oct 30, 2007: Fixed BOM removal (thanks Malcolm Tredinnick). Fixed infinite loop in bracket regular expression for inline links. Oct 11, 2007: LineBreaks is now an inlinePattern . Fixed HR in blockquotes. Refactored _processSection method (see tracker #1793419 ). Oct 9, 2007: Added textPreprocessor (from 1.6b). Oct 8, 2008: Fixed Lazy Blockquote. Fixed code block on first line. Fixed empty inline image link. Oct 7, 2007: Limit recursion on inline patterns. Added a \u2018safe\u2019 tag to htmlStash . March 18, 2007: Fixed or merged a bunch of minor bugs, including multi-line comments and markup inside links. (Tracker #s: 1683066, 1671153, 1661751, 1627935, 1544371, 1458139.) -> v. 1.6b Oct 10, 2006: Fixed a bug that caused some text to be lost after comments. Added \u201csafe mode\u201d (user\u2019s HTML tags are removed). Sept 6, 2006: Added exception for PHP tags when handling HTML blocks. August 7, 2006: Incorporated Sergej Chodarev\u2019s patch to fix a problem with ampersand normalization and HTML blocks. July 10, 2006: Switched to using optparse . Added proper support for Unicode. July 9, 2006: Fixed the \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml old mode 100755 new mode 100644 index 3fc7634..ecd40b5 --- a/sitemap.xml +++ b/sitemap.xml @@ -1,163 +1,243 @@ - - https://Python-Markdown.github.io/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/install/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/reference/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/cli/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/extensions/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/extensions/abbreviations/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/extensions/admonition/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/extensions/attr_list/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/extensions/code_hilite/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/extensions/definition_lists/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/extensions/extra/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/extensions/fenced_code_blocks/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/extensions/footnotes/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/extensions/legacy_attrs/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/extensions/legacy_em/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/extensions/meta_data/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/extensions/nl2br/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/extensions/md_in_html/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/extensions/sane_lists/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/extensions/smarty/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/extensions/toc/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/extensions/tables/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/extensions/wikilinks/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/extensions/api/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/test_tools/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/contributing/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/change_log/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/change_log/release-3.4/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/change_log/release-3.3/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/change_log/release-3.2/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/change_log/release-3.1/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/change_log/release-3.0/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/change_log/release-2.6/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/change_log/release-2.5/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/change_log/release-2.4/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/change_log/release-2.3/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/change_log/release-2.2/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/change_log/release-2.1/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/change_log/release-2.0/ - 2023-07-25 - daily - - https://Python-Markdown.github.io/authors/ - 2023-07-25 - daily + + + https://Python-Markdown.github.io/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/authors/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/changelog/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/cli/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/contributing/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/install/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/reference/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/test_tools/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/change_log/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/change_log/release-2.0/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/change_log/release-2.1/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/change_log/release-2.2/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/change_log/release-2.3/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/change_log/release-2.4/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/change_log/release-2.5/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/change_log/release-2.6/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/extensions/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/extensions/abbreviations/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/extensions/admonition/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/extensions/api/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/extensions/attr_list/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/extensions/code_hilite/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/extensions/definition_lists/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/extensions/extra/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/extensions/fenced_code_blocks/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/extensions/footnotes/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/extensions/legacy_attrs/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/extensions/legacy_em/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/extensions/md_in_html/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/extensions/meta_data/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/extensions/nl2br/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/extensions/sane_lists/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/extensions/smarty/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/extensions/tables/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/extensions/toc/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/extensions/wikilinks/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/reference/SUMMARY/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/reference/markdown/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/reference/markdown/blockparser/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/reference/markdown/blockprocessors/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/reference/markdown/htmlparser/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/reference/markdown/inlinepatterns/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/reference/markdown/postprocessors/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/reference/markdown/preprocessors/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/reference/markdown/serializers/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/reference/markdown/test_tools/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/reference/markdown/treeprocessors/ + 2023-10-09 + daily + + + https://Python-Markdown.github.io/reference/markdown/util/ + 2023-10-09 + daily \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz old mode 100755 new mode 100644 index dda2b63..996ca62 Binary files a/sitemap.xml.gz and b/sitemap.xml.gz differ diff --git a/static/basic.css b/static/basic.css old mode 100755 new mode 100644 diff --git a/static/doctools.js b/static/doctools.js old mode 100755 new mode 100644 diff --git a/static/file.png b/static/file.png old mode 100755 new mode 100644 diff --git a/static/github.png b/static/github.png old mode 100755 new mode 100644 diff --git a/static/jquery.js b/static/jquery.js old mode 100755 new mode 100644 diff --git a/static/nature.css b/static/nature.css old mode 100755 new mode 100644 diff --git a/static/pygments.css b/static/pygments.css old mode 100755 new mode 100644 diff --git a/static/underscore.js b/static/underscore.js old mode 100755 new mode 100644 diff --git a/test_tools/index.html b/test_tools/index.html old mode 100755 new mode 100644 index d84e6b1..ab6f11d --- a/test_tools/index.html +++ b/test_tools/index.html @@ -9,11 +9,14 @@ - + - Test Tools — Python-Markdown 3.4.4 documentation + Test Tools — Python-Markdown 3.5 documentation + + + @@ -23,13 +26,13 @@

    Navigation

    @@ -104,29 +96,29 @@

    markdown.test_tools.TestCaseunittest.TestCase. In fact, assertMarkdownRenders tests could be mixed with other unittest style tests within the same test class.

    An example Markdown test might look like this:

    -
    from markdown.test_tools import TestCase
    +
    from markdown.test_tools import TestCase
     
    -class TestHr(TestCase):
    -    def test_hr_before_paragraph(self):
    -        self.assertMarkdownRenders(
    -            # The Markdown source text used as input
    -            self.dedent(
    -                """
    -                ***
    -                An HR followed by a paragraph with no blank line.
    -                """
    -            ),
    -            # The expected HTML output
    -            self.dedent(
    -                """
    -                <hr>
    -                <p>An HR followed by a paragraph with no blank line.</p>
    -                """
    -            ),
    -            # Other keyword arguments to pass to `markdown.markdown`
    -            output_format='html'
    -        )
    -
    +class TestHr(TestCase): + def test_hr_before_paragraph(self): + self.assertMarkdownRenders( + # The Markdown source text used as input + self.dedent( + """ + *** + An HR followed by a paragraph with no blank line. + """ + ), + # The expected HTML output + self.dedent( + """ + <hr> + <p>An HR followed by a paragraph with no blank line.</p> + """ + ), + # Other keyword arguments to pass to `markdown.markdown` + output_format='html' + ) +

    markdown.test_tools.LegacyTestCase

    In the past Python-Markdown exclusively used file-based tests. Many of those @@ -171,31 +163,31 @@

    markdown.test_tools.LegacyTestCa naming scheme: test_filename. One unit test will be run for each set of input and output files.

    The definition of an example set of tests might look like this:

    -
    from markdown.test_tools import LegacyTestCase, Kwargs
    -import os
    +
    from markdown.test_tools import LegacyTestCase, Kwargs
    +import os
     
    -# Get location of this file and use to find text file dirs.
    -parent_test_dir = os.path.abspath(os.path.dirname(__file__))
    +# Get location of this file and use to find text file dirs.
    +parent_test_dir = os.path.abspath(os.path.dirname(__file__))
     
     
    -class TestFoo(LegacyTestCase):
    -    # Define location of text file directory. In this case, the directory is
    -    # named "foo" and is in the same parent directory as this file.
    -    location = os.path.join(parent_test_dir, 'foo')
    -    # Define default keyword arguments. In this case, unless specified
    -    # differently, all tests should use the output format "html".
    -    default_kwargs = Kwargs(output_format='html')
    +class TestFoo(LegacyTestCase):
    +    # Define location of text file directory. In this case, the directory is
    +    # named "foo" and is in the same parent directory as this file.
    +    location = os.path.join(parent_test_dir, 'foo')
    +    # Define default keyword arguments. In this case, unless specified
    +    # differently, all tests should use the output format "html".
    +    default_kwargs = Kwargs(output_format='html')
     
    -    # The "xhtml" test should override the output format and use "xhtml".
    -    xhtml = Kwargs(output_format='xhtml')
    +    # The "xhtml" test should override the output format and use "xhtml".
    +    xhtml = Kwargs(output_format='xhtml')
     
    -    # The "toc" test should use the "toc" extension with a custom permalink
    -    # setting.
    -    toc = Kwargs(
    -        extensions=['markdown.extensions.toc'],
    -        extension_configs={'markdown.extensions.toc': {'permalink': "[link]"}}
    -    )
    -
    + # The "toc" test should use the "toc" extension with a custom permalink + # setting. + toc = Kwargs( + extensions=['markdown.extensions.toc'], + extension_configs={'markdown.extensions.toc': {'permalink': "[link]"}} + ) +

    Note that in the above example, the text file directory may contain many more text-based test files than xhtml (xhtml.txt and xhtml.html) and toc @@ -208,8 +200,8 @@

    Running Python-Markdown’s Testsunittest methods of calling tests can be used. For example, to run all of Python-Markdown’s tests, from the root of the git repository, run the following command:

    -
    python -m unittest discover tests
    -
    +
    python -m unittest discover tests
    +

    That simple command will search everything in the tests directory and it’s sub-directories and run all unittest tests that it finds, including @@ -257,7 +249,7 @@

    Previous topic

    Next topic

    - Contributing to Python-Markdown + markdown

    @@ -267,14 +259,6 @@

    This Page

  • Edit on GitHub
  • - - @@ -285,13 +269,13 @@

    Quick search

    Navigation

    - \ No newline at end of file