Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-Markdown for openSUSE:Factory 
checked in at 2026-02-11 18:47:35
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-Markdown (Old)
 and      /work/SRC/openSUSE:Factory/.python-Markdown.new.1670 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-Markdown"

Wed Feb 11 18:47:35 2026 rev:60 rq:1332278 version:3.10.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-Markdown/python-Markdown.changes  
2026-01-27 16:06:58.444653917 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-Markdown.new.1670/python-Markdown.changes    
    2026-02-11 18:48:03.607393387 +0100
@@ -1,0 +2,7 @@
+Mon Feb  9 19:12:02 UTC 2026 - BenoĆ®t Monin <[email protected]>
+
+- update to version 3.10.2:
+  * Fix a regression related to comment handling (#1590).
+  * More reliable fix for </ (#1593).
+
+-------------------------------------------------------------------

Old:
----
  markdown-3.10.1.tar.gz

New:
----
  markdown-3.10.2.tar.gz

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

Other differences:
------------------
++++++ python-Markdown.spec ++++++
--- /var/tmp/diff_new_pack.MLzgOD/_old  2026-02-11 18:48:04.547432863 +0100
+++ /var/tmp/diff_new_pack.MLzgOD/_new  2026-02-11 18:48:04.551433031 +0100
@@ -32,7 +32,7 @@
 %endif
 %{?sle15_python_module_pythons}
 Name:           python-Markdown%{psuffix}
-Version:        3.10.1
+Version:        3.10.2
 Release:        0
 Summary:        Python implementation of Markdown
 License:        BSD-3-Clause

++++++ markdown-3.10.1.tar.gz -> markdown-3.10.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/markdown-3.10.1/Markdown.egg-info/PKG-INFO 
new/markdown-3.10.2/Markdown.egg-info/PKG-INFO
--- old/markdown-3.10.1/Markdown.egg-info/PKG-INFO      2026-01-21 
19:09:17.000000000 +0100
+++ new/markdown-3.10.2/Markdown.egg-info/PKG-INFO      2026-02-09 
15:57:16.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: Markdown
-Version: 3.10.1
+Version: 3.10.2
 Summary: Python implementation of John Gruber's Markdown.
 Author: Manfred Stienstra, Yuri Takhteyev
 Author-email: Waylan limberg <[email protected]>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/markdown-3.10.1/Markdown.egg-info/SOURCES.txt 
new/markdown-3.10.2/Markdown.egg-info/SOURCES.txt
--- old/markdown-3.10.1/Markdown.egg-info/SOURCES.txt   2026-01-21 
19:09:17.000000000 +0100
+++ new/markdown-3.10.2/Markdown.egg-info/SOURCES.txt   2026-02-09 
15:57:16.000000000 +0100
@@ -23,6 +23,7 @@
 docs/mkdocstrings.css
 docs/py.png
 docs/reference.md
+docs/sanitization.md
 docs/test_tools.md
 docs/change_log/index.md
 docs/change_log/release-2.0.md
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/markdown-3.10.1/PKG-INFO new/markdown-3.10.2/PKG-INFO
--- old/markdown-3.10.1/PKG-INFO        2026-01-21 19:09:17.219820000 +0100
+++ new/markdown-3.10.2/PKG-INFO        2026-02-09 15:57:16.674457600 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: Markdown
-Version: 3.10.1
+Version: 3.10.2
 Summary: Python implementation of John Gruber's Markdown.
 Author: Manfred Stienstra, Yuri Takhteyev
 Author-email: Waylan limberg <[email protected]>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/markdown-3.10.1/docs/changelog.md 
new/markdown-3.10.2/docs/changelog.md
--- old/markdown-3.10.1/docs/changelog.md       2026-01-21 19:09:10.000000000 
+0100
+++ new/markdown-3.10.2/docs/changelog.md       2026-02-09 15:57:10.000000000 
+0100
@@ -10,6 +10,13 @@
 [Python Version 
Specification](https://packaging.python.org/en/latest/specifications/version-specifiers/).
 See the [Contributing Guide](contributing.md) for details.
 
+## [3.10.2] - 2026-02-09
+
+### Fixed
+
+* Fix a regression related to comment handling (#1590).
+* More reliable fix for `</` (#1593).
+
 ## [3.10.1] - 2026-01-21
 
 ### Fixed
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/markdown-3.10.1/docs/cli.md 
new/markdown-3.10.2/docs/cli.md
--- old/markdown-3.10.1/docs/cli.md     2026-01-21 19:09:10.000000000 +0100
+++ new/markdown-3.10.2/docs/cli.md     2026-02-09 15:57:10.000000000 +0100
@@ -12,6 +12,8 @@
 system to run the command line script. See the
 [Installation instructions](install.md) for details.
 
+## Basic Usage
+
 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:
@@ -28,92 +30,62 @@
 python -m markdown input_file.txt
 ```
 
-Piping input and output (on `STDIN` and `STDOUT`) is fully supported as well.
-For example:
-
-```bash
-echo "Some **Markdown** text." | python -m markdown > output.html
-```
-
-Use the `--help` option for a list all available options and arguments:
+Use the `--help` option for a list of all available options and arguments:
 
 ```bash
 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:
-
-Setup
------
-
-Upon installation, the `markdown_py` script will have been copied to
-your Python "Scripts" directory. Different systems require different methods to
-ensure that any files in the Python "Scripts" directory are on your system
-path.
-
-* **Windows**:
-
-    Assuming a default install of Python on Windows, your "Scripts" directory
-    is most likely something like `C:\\Python37\Scripts`. Verify the location
-    of your "Scripts" directory and add it to you system path.
+!!! warning
 
-    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.):
+    The Python-Markdown library does ***not*** sanitize its HTML output. If
+    you are processing Markdown input from an untrusted source, it is your
+    responsibility to ensure that it is properly sanitized. For more
+    information see [Sanitizing HTML Output](sanitization.md).
 
-    As each \*nix distribution is different and we can't possibly document all
-    of them here, we'll 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 "Scripts" ("bin") 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.
+## Piping Input and Output
 
-    * 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 "markdown".
-    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
------
-
-To use `markdown_py` from the command line, run it as
+Piping input and output (on `STDIN` and `STDOUT`) is fully supported.
+For example:
 
 ```bash
-markdown_py input_file.txt
+echo "Some **Markdown** text." | python -m markdown > output.html
 ```
 
-or
+The above command would generate a file named `output.html` with the following 
content:
+```html
+<p>Some <strong>Markdown</strong> Text.</p>
+```
+
+As Python-Markdown only ever outputs HTML fragments (no `<html>`, `<head>`,
+and `<body>` tags), it is generally expected that the command line interface
+will always be used to pipe output to a templating engine. In the event that
+no additional content is needed and the output only needs to be wrapped in
+otherwise empty `<html>`, `<head>`, and `<body>` tags, 
+[JustHTML](https://emilstenstrom.github.io/justhtml/) can do that with with
+a single command:
 
 ```bash
-markdown_py input_file.txt > output_file.html
+echo "Some **Markdown** text." | python -m markdown | justhtml - --fragment > 
output.html
 ```
 
-For a complete list of options, run
+The above command would generate a file named `output.html` with the following 
content:
 
-```bash
-markdown_py --help
+```html
+<html>
+  <head></head>
+  <body>
+    <p>Some <strong>Markdown</strong> Text.</p>
+  </body>
+</html>
 ```
 
-Using Extensions
-----------------
+If you don't need or want JustHTML's HTML sanitation, you can disable it with 
the
+`--unsafe` flag, although that is not recommended. See JustHTML's 
+[Command Line Interface](https://emilstenstrom.github.io/justhtml/cli.html)
+documentation for details.
+
+## Using Extensions
 
 To load a Python-Markdown extension from the command line use the `-x`
 (or `--extension`) option. The extension module must be on your `PYTHONPATH`
@@ -187,3 +159,74 @@
 [JSON]: https://json.org/
 [PyYAML]: https://pyyaml.org/
 [2.5 release notes]: change_log/release-2.5.md
+
+## Using the `markdown_py` Command
+
+If you don't want to call the python executable directly (using the `-m` flag),
+follow the instructions below to use a wrapper script:
+
+### Setup `markdown_py`
+
+Upon installation, the `markdown_py` script will have been copied to
+your Python "Scripts" directory. Different systems require different methods to
+ensure that any files in the Python "Scripts" directory are on your system
+path.
+
+* **Windows**:
+
+    Assuming a default install of Python on Windows, your "Scripts" directory
+    is most likely something like `C:\\Python37\Scripts`. Verify the location
+    of your "Scripts" 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't possibly document all
+    of them here, we'll 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 "Scripts" ("bin") 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 "markdown".
+    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.
+
+### Using `markdown_py`
+
+To use `markdown_py` from the command line, run it as
+
+```bash
+markdown_py input_file.txt
+```
+
+or
+
+```bash
+markdown_py input_file.txt > output_file.html
+```
+
+For a complete list of options, run
+
+```bash
+markdown_py --help
+```
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/markdown-3.10.1/docs/reference.md 
new/markdown-3.10.2/docs/reference.md
--- old/markdown-3.10.1/docs/reference.md       2026-01-21 19:09:10.000000000 
+0100
+++ new/markdown-3.10.2/docs/reference.md       2026-02-09 15:57:10.000000000 
+0100
@@ -25,7 +25,16 @@
 it. If you do use a single instance though, make sure to call the `reset`
 method appropriately ([see below](#convert)).
 
-### markdown.markdown(text [, **kwargs]) {: #markdown 
data-toc-label='markdown.markdown' }
+### `markdown.markdown(text [, **kwargs])` {: #markdown 
data-toc-label='markdown.markdown' }
+
+!!! warning
+
+    The Python-Markdown library does ***not*** sanitize its HTML output. If
+    you are processing Markdown input from an untrusted source, it is your
+    responsibility to ensure that it is properly sanitized. For more
+    information see [Sanitizing HTML Output].
+
+[Sanitizing HTML Output]: sanitization.md
 
 The following options are available on the `markdown.markdown` function:
 
@@ -179,6 +188,15 @@
 
 ### `markdown.markdownFromFile (**kwargs)` {: #markdownFromFile 
data-toc-label='markdown.markdownFromFile' }
 
+!!! warning
+
+    The Python-Markdown library does ***not*** sanitize its HTML output. As
+    `markdown.markdownFromFile` writes directly to the file system, there is
+    no easy way to sanitize the output from Python code. Therefore, it is
+    recommended that the `markdown.markdownFromFile` function not be used on
+    input from an untrusted source. For more information see [Sanitizing HTML
+    Output].
+
 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:
@@ -216,7 +234,7 @@
         meet your specific needs, it is suggested that you write your own code
         to handle your encoding/decoding needs.
 
-### markdown.Markdown([**kwargs]) {: #Markdown 
data-toc-label='markdown.Markdown' }
+### `markdown.Markdown([**kwargs])` {: #Markdown 
data-toc-label='markdown.Markdown' }
 
 The same options are available when initializing the `markdown.Markdown` class
 as on the [`markdown.markdown`](#markdown) function, except that the class does
@@ -229,7 +247,14 @@
     the thread they were created in. A single instance should not be accessed
     from multiple threads.
 
-#### Markdown.convert(source) {: #convert data-toc-label='Markdown.convert' }
+#### `Markdown.convert(source)` {: #convert data-toc-label='Markdown.convert' }
+
+!!! warning
+
+    The Python-Markdown library does ***not*** sanitize its HTML output. If
+    you are processing Markdown input from an untrusted source, it is your
+    responsibility to ensure that it is properly sanitized. For more
+    information see [Sanitizing HTML Output].
 
 The `source` text must meet the same requirements as the [`text`](#text)
 argument of the [`markdown.markdown`](#markdown) function.
@@ -258,7 +283,16 @@
 html3 = md.reset().convert(text3)
 ```
 
-#### Markdown.convertFile(**kwargs) {: #convertFile 
data-toc-label='Markdown.convertFile' }
+#### `Markdown.convertFile(**kwargs)` {: #convertFile 
data-toc-label='Markdown.convertFile' }
+
+!!! warning
+
+    The Python-Markdown library does ***not*** sanitize its HTML output. As
+    `Markdown.convertFile` writes directly to the file system, there is no
+    easy way to sanitize the output from Python code. Therefore, it is
+    recommended that the `Markdown.convertFile` method not be used on input
+    from an untrusted source.  For more information see [Sanitizing HTML
+    Output].
 
 The arguments of this method are identical to the arguments of the same
 name on the `markdown.markdownFromFile` function ([`input`](#input),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/markdown-3.10.1/docs/sanitization.md 
new/markdown-3.10.2/docs/sanitization.md
--- old/markdown-3.10.1/docs/sanitization.md    1970-01-01 01:00:00.000000000 
+0100
+++ new/markdown-3.10.2/docs/sanitization.md    2026-02-09 15:57:10.000000000 
+0100
@@ -0,0 +1,76 @@
+title: Sanitization and Security
+
+# Sanitizing HTML Output
+
+The Python-Markdown library does ***not*** sanitize its HTML output. If you
+are processing Markdown input from an untrusted source, it is your
+responsibility to ensure that it is properly sanitized. See _[Markdown and
+XSS]_ for an overview of some of the dangers and _[Improper markup sanitization
+in popular software]_ for notes on best practices to ensure HTML is properly
+sanitized. With those concerns in mind, some recommendations are provided
+below to ensure that any input from an untrusted source is properly
+sanitized.
+
+That said, if you fully trust the source of your input, you may choose to do
+nothing. Conversely, you may find solutions other than those suggested here.
+However, you do so at your own risk.
+
+## Using `JustHTML`
+
+[`JustHTML`][JustHTML] is recommended as a sanitizer on the output of 
`markdown.markdown`
+or `Markdown.convert`. When you pass HTML output through `JustHTML`, it is
+sanitized by default according to a strict [allow list policy]. The policy
+can be [customized] if necessary.
+
+``` python
+import markdown
+from justhtml import JustHTML
+
+html =  markdown.markdown(text)
+safe_html = JustHTML(html, fragment=True).to_html()
+```
+
+## Using `nh3` or `bleach`
+
+If you cannot use `JustHTML` for some reason, some alternatives include 
[`nh3`][nh3] or
+[`bleach`][bleach][^1]. However, be aware that these libraries will not be 
sufficient
+in themselves and will require customization. Some useful lists of allowed
+tags and attributes can be found in the [`bleach-allowlist`]
+[bleach-allowlist] library, which should work with both `nh3` and `bleach` as 
`nh3`
+mirrors `bleach`'s API.
+
+``` python
+import markdown
+import bleach
+from bleach_allowlist import markdown_tags, markdown_attrs
+
+html =  markdown.markdown(text)
+safe_html = bleach.clean(html, markdown_tags, markdown_attrs)
+```
+
+[^1]: The [`bleach`][bleach] project has been 
[deprecated](https://github.com/mozilla/bleach/issues/698). 
+However, it may be the only option for some users as `nh3` is a set of Python 
bindings to a Rust library.
+
+## Sanitizing on the Command Line
+
+Both Python-Markdown and `JustHTML` provide command line interfaces which read
+from `STDIN` and write to `STDOUT`. Therefore, they can be used together to
+ensure that the output from untrusted input is properly sanitized.
+
+```sh
+echo "Some **Markdown** text." | python -m markdown | justhtml - --fragment > 
safe_output.html
+```
+
+For more information on `JustHTML`'s Command Line Interface, see the
+[documentation][JustHTML_CLI]. Use the `--help` option for a list of all 
available
+options and arguments to the `markdown` command.
+
+[Markdown and XSS]: https://michelf.ca/blog/2010/markdown-and-xss/
+[Improper markup sanitization in popular software]: 
https://github.com/ChALkeR/notes/blob/master/Improper-markup-sanitization.md
+[JustHTML]: https://emilstenstrom.github.io/justhtml/
+[allow list policy]: 
https://emilstenstrom.github.io/justhtml/html-cleaning.html#default-sanitization-policy
+[customized]: 
https://emilstenstrom.github.io/justhtml/html-cleaning.html#use-a-custom-sanitization-policy
+[nh3]: https://nh3.readthedocs.io/en/latest/
+[bleach]: http://bleach.readthedocs.org/en/latest/
+[bleach-allowlist]: https://github.com/yourcelf/bleach-allowlist
+[JustHTML_CLI]: https://emilstenstrom.github.io/justhtml/cli.html
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/markdown-3.10.1/markdown/__main__.py 
new/markdown-3.10.2/markdown/__main__.py
--- old/markdown-3.10.1/markdown/__main__.py    2026-01-21 19:09:10.000000000 
+0100
+++ new/markdown-3.10.2/markdown/__main__.py    2026-02-09 15:57:10.000000000 
+0100
@@ -49,10 +49,14 @@
     usage = """%prog [options] [INPUTFILE]
        (STDIN is assumed if no INPUTFILE is given)"""
     desc = "A Python implementation of John Gruber's Markdown. " \
-           "https://Python-Markdown.github.io/";
+           "https://python-markdown.github.io/";
     ver = "%%prog %s" % markdown.__version__
+    epilog = "WARNING: The Python-Markdown library does NOT sanitize its HTML 
output. If " \
+             "you are processing Markdown input from an untrusted source, it 
is your " \
+             "responsibility to ensure that it is properly sanitized. For more 
" \
+             "information see 
<https://python-markdown.github.io/sanitization/>."
 
-    parser = optparse.OptionParser(usage=usage, description=desc, version=ver)
+    parser = optparse.OptionParser(usage=usage, description=desc, version=ver, 
epilog=epilog)
     parser.add_option("-f", "--file", dest="filename", default=None,
                       help="Write output to OUTPUT_FILE. Defaults to STDOUT.",
                       metavar="OUTPUT_FILE")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/markdown-3.10.1/markdown/__meta__.py 
new/markdown-3.10.2/markdown/__meta__.py
--- old/markdown-3.10.1/markdown/__meta__.py    2026-01-21 19:09:10.000000000 
+0100
+++ new/markdown-3.10.2/markdown/__meta__.py    2026-02-09 15:57:10.000000000 
+0100
@@ -28,7 +28,7 @@
 from __future__ import annotations
 
 
-__version_info__ = (3, 10, 1, 'final', 0)
+__version_info__ = (3, 10, 2, 'final', 0)
 
 
 def _get_version(version_info):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/markdown-3.10.1/markdown/core.py 
new/markdown-3.10.2/markdown/core.py
--- old/markdown-3.10.1/markdown/core.py        2026-01-21 19:09:10.000000000 
+0100
+++ new/markdown-3.10.2/markdown/core.py        2026-02-09 15:57:10.000000000 
+0100
@@ -335,6 +335,12 @@
            [`ElementTree`][xml.etree.ElementTree.ElementTree] object has been 
serialized into text.
         5. The output is returned as a string.
 
+        !!! warning
+            The Python-Markdown library does ***not*** sanitize its HTML 
output.
+            If you are processing Markdown input from an untrusted source, it 
is your
+            responsibility to ensure that it is properly sanitized. For more
+            information see [Sanitizing HTML Output](../../sanitization.md).
+
         """
 
         # Fix up the source text
@@ -392,9 +398,9 @@
         encoding: str | None = None,
     ) -> Markdown:
         """
-        Converts a Markdown file and returns the HTML as a Unicode string.
+        Read Markdown text from a file or stream and write HTML output to a 
file or stream.
 
-        Decodes the file using the provided encoding (defaults to `utf-8`),
+        Decodes the input 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
@@ -410,6 +416,14 @@
             output: File object or path. Writes to `stdout` if `None`.
             encoding: Encoding of input and output files. Defaults to `utf-8`.
 
+        !!! warning
+            The Python-Markdown library does ***not*** sanitize its HTML 
output.
+            As `Markdown.convertFile` writes directly to the file system, 
there is no
+            easy way to sanitize the output from Python code. Therefore, it is
+            recommended that the `Markdown.convertFile` method not be used on 
input
+            from an untrusted source.  For more information see [Sanitizing 
HTML
+            Output](../../sanitization.md).
+
         """
 
         encoding = encoding or "utf-8"
@@ -477,6 +491,12 @@
     Returns:
         A string in the specified output format.
 
+    !!! warning
+        The Python-Markdown library does ***not*** sanitize its HTML output.
+        If you are processing Markdown input from an untrusted source, it is 
your
+        responsibility to ensure that it is properly sanitized. For more
+        information see [Sanitizing HTML Output](../../sanitization.md).
+
     """
     md = Markdown(**kwargs)
     return md.convert(text)
@@ -484,7 +504,7 @@
 
 def markdownFromFile(**kwargs: Any):
     """
-    Read Markdown text from a file and write output to a file or a stream.
+    Read Markdown text from a file or stream and write HTML output to a file 
or stream.
 
     This is a shortcut function which initializes an instance of 
[`Markdown`][markdown.Markdown],
     and calls the [`convertFile`][markdown.Markdown.convertFile] method rather 
than
@@ -496,6 +516,14 @@
         encoding (str): Encoding of input and output.
         **kwargs: Any arguments accepted by the `Markdown` class.
 
+    !!! warning
+        The Python-Markdown library does ***not*** sanitize its HTML output.
+        As `markdown.markdownFromFile` writes directly to the file system, 
there is no
+        easy way to sanitize the output from Python code. Therefore, it is
+        recommended that the `markdown.markdownFromFile` function not be used 
on input
+        from an untrusted source.  For more information see [Sanitizing HTML
+        Output](../../sanitization.md).
+
     """
     md = Markdown(**kwargs)
     md.convertFile(kwargs.get('input', None),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/markdown-3.10.1/markdown/htmlparser.py 
new/markdown-3.10.2/markdown/htmlparser.py
--- old/markdown-3.10.1/markdown/htmlparser.py  2026-01-21 19:09:10.000000000 
+0100
+++ new/markdown-3.10.2/markdown/htmlparser.py  2026-02-09 15:57:10.000000000 
+0100
@@ -35,7 +35,6 @@
 
 # Included for versions which do not have current comment fix
 commentclose = re.compile(r'--!?>')
-commentabruptclose = re.compile(r'-?>')
 
 # Import a copy of the html.parser lib as `htmlparser` so we can monkeypatch 
it.
 # Users can still do `from html import parser` and get the default behavior.
@@ -48,6 +47,8 @@
 # throwing it away. When we see it, we will process it as data.
 htmlparser.starttagopen = re.compile('<[a-zA-Z]|</>')
 
+htmlparser.endtagopen = re.compile('</[a-zA-Z]?')
+
 # Monkeypatch `HTMLParser` to only accept `?>` to close Processing 
Instructions.
 htmlparser.piclose = re.compile(r'\?>')
 # Monkeypatch `HTMLParser` to only recognize entity references with a closing 
semicolon.
@@ -92,6 +93,30 @@
 blank_line_re = re.compile(r'^([ ]*\n){2}')
 
 
+class _HTMLParser(htmlparser.HTMLParser):
+    """Handle special start and end tags."""
+
+    def parse_endtag(self, i):
+        start = self.rawdata[i:i+3]
+        c = ord(start[-1])
+        if len(start) < 3 or not (65 <= c <= 90 or 97 <= c <= 122):
+            self.handle_data(self.rawdata[i:i + 2])
+            return i + 2
+        return super().parse_endtag(i)
+
+    def parse_starttag(self, i: int) -> int:  # pragma: no cover
+        # Treat `</>` as normal data as it is not a real tag.
+        if self.rawdata[i:i + 3] == '</>':
+            self.handle_data(self.rawdata[i:i + 3])
+            return i + 3
+
+        return super().parse_starttag(i)
+
+
+# Overwrite our custom one for people like MkDocs that pull it in
+htmlparser.HTMLParser = _HTMLParser
+
+
 class HTMLExtractor(htmlparser.HTMLParser):
     """
     Extract raw HTML from text.
@@ -110,9 +135,6 @@
 
         self.lineno_start_cache = [0]
 
-        self.override_comment_update = False
-        self.override_comment_start = 0
-
         # This calls self.reset
         super().__init__(*args, **kwargs)
         self.md = md
@@ -125,8 +147,6 @@
         self._cache: list[str] = []
         self.cleandoc: list[str] = []
         self.lineno_start_cache = [0]
-        self.override_comment_start = 0
-        self.override_comment_update = False
 
         super().reset()
 
@@ -276,22 +296,8 @@
 
     def handle_comment(self, data: str):
         # Check if the comment is unclosed, if so, we need to override position
-        j = len(self.rawdata) - len(data)
-        i = j - 2
-        if self.rawdata[i:j] == '</':
-            self.handle_data('<')
-            self.override_comment_start = i
-            self.override_comment_update = True
-            return
         self.handle_empty_tag('<!--{}-->'.format(data), is_block=True)
 
-    def updatepos(self, i: int, j: int) -> int:
-        if self.override_comment_update:
-            self.override_comment_update = False
-            i = self.override_comment_start
-            j = self.override_comment_start + 1
-        return super().updatepos(i, j)
-
     def handle_decl(self, data: str):
         self.handle_empty_tag('<!{}>'.format(data), is_block=True)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/markdown-3.10.1/mkdocs.yml 
new/markdown-3.10.2/mkdocs.yml
--- old/markdown-3.10.1/mkdocs.yml      2026-01-21 19:09:10.000000000 +0100
+++ new/markdown-3.10.2/mkdocs.yml      2026-02-09 15:57:10.000000000 +0100
@@ -22,6 +22,7 @@
   - Installation: install.md
   - Library Reference: reference.md
   - Command Line: cli.md
+  - Sanitization and Security: sanitization.md
   - Extensions: extensions/index.md
   - Officially Supported Extensions:
       - Abbreviations: extensions/abbreviations.md
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/markdown-3.10.1/tests/test_syntax/blocks/test_html_blocks.py 
new/markdown-3.10.2/tests/test_syntax/blocks/test_html_blocks.py
--- old/markdown-3.10.1/tests/test_syntax/blocks/test_html_blocks.py    
2026-01-21 19:09:10.000000000 +0100
+++ new/markdown-3.10.2/tests/test_syntax/blocks/test_html_blocks.py    
2026-02-09 15:57:10.000000000 +0100
@@ -1706,3 +1706,84 @@
             'Test `<!--[if mso]>` and `<!--[if !mso]>`',
             '<p>Test <code>&lt;!--[if mso]&gt;</code> and <code>&lt;!--[if 
!mso]&gt;</code></p>'
         )
+
+    def test_issue_1590(self):
+        """Test case with comments in table for issue #1590."""
+
+        self.assertMarkdownRenders(
+            self.dedent(
+                '''
+                <table>
+                <!--[if mso]>-->
+                <td>foo</td>
+                <!--<!endif]-->
+                <td>bar</td>
+                </table>
+                '''
+            ),
+            self.dedent(
+                '''
+                <table>
+                <!--[if mso]>-->
+                <td>foo</td>
+                <!--<!endif]-->
+                <td>bar</td>
+                </table>
+                '''
+            )
+        )
+
+    def test_stress_comment_handling(self):
+        """Stress test the comment handling."""
+
+        self.assertMarkdownRenders(
+            self.dedent(
+                '''
+                `</` <!-- `<!--[if mso]>` and <!-- </> and `<!--[if mso]>`
+
+                <!-- and <!-- `<!--[if mso]>` and </> `</` and `<!--[if mso]>`
+
+                <!-- Real comment -->
+
+                `<!--[if mso]>` `</` `<!--[if mso]>` and </> <!-- and <!--
+
+                </> `<!--[if mso]>` `</` <!--  and <!--  and `<!--[if mso]>`
+                '''
+            ),
+            self.dedent(
+                '''
+                <p><code>&lt;/</code> &lt;!-- <code>&lt;!--[if mso]&gt;</code> 
and &lt;!-- &lt;/&gt; and <code>&lt;!--[if mso]&gt;</code></p>
+                <p>&lt;!-- and &lt;!-- <code>&lt;!--[if mso]&gt;</code> and 
&lt;/&gt; <code>&lt;/</code> and <code>&lt;!--[if mso]&gt;</code></p>
+                <!-- Real comment -->
+                <p><code>&lt;!--[if mso]&gt;</code> <code>&lt;/</code> 
<code>&lt;!--[if mso]&gt;</code> and &lt;/&gt; &lt;!-- and &lt;!--</p>
+                <p>&lt;/&gt; <code>&lt;!--[if mso]&gt;</code> 
<code>&lt;/</code> &lt;!--  and &lt;!--  and <code>&lt;!--[if 
mso]&gt;</code></p>
+                '''  # noqa: E501
+            )
+        )
+
+    def test_unclosed_endtag(self):
+        """Ensure unclosed end tag does not have side effects."""
+
+        self.assertMarkdownRenders(
+            self.dedent(
+                '''
+                `</`
+
+                <div>
+                <!--[if mso]>-->
+                <p>foo</p>
+                <!--<!endif]-->
+                </div>
+                '''
+            ),
+            self.dedent(
+                '''
+                <p><code>&lt;/</code></p>
+                <div>
+                <!--[if mso]>-->
+                <p>foo</p>
+                <!--<!endif]-->
+                </div>
+                '''
+            )
+        )

Reply via email to