Python-Markdown / markdown

A Python implementation of John Gruber’s Markdown with Extension support.
https://python-markdown.github.io/
BSD 3-Clause "New" or "Revised" License
3.71k stars 856 forks source link

no anchors are created #1463

Closed flocsy closed 3 months ago

flocsy commented 4 months ago

I have an md file that has a TOC at the beginning and it "links" to the paragraphs. When I look at it in every place I know (github, gitlab, markdown js) it correctly creates the anchors so the links from the TOC do lead to the paragraphs. However when I use markdown it doesn't create the anchor ids.

Example file: ------------------- 8< ------------------------------------

# ANT+ HRM Heart Rate Monitor ❤️ - FAQ - Frequently Asked Questions

## Table of Contents
- [I installed ANT+ HRM to my watch but I don't see it anywhere](#i-installed-ant-hrm-to-my-watch-but-i-dont-see-it-anywhere)

## I installed ANT+ HRM to my watch but I don't see it anywhere
See: How can I add ANT+ HRM to my Run data screen?

----------------------- >8 ------------------------------------

python3 -m markdown TEST.md > TEST.html creates the following html:

------------------------------ 8< ------------------------------


<h1>ANT+ HRM Heart Rate Monitor ❤️ - FAQ - Frequently Asked Questions</h1>
<h2>Table of Contents</h2>
<ul>
<li><a href="#i-installed-ant-hrm-to-my-watch-but-i-dont-see-it-anywhere">I installed ANT+ HRM to my watch but I don't see it anywhere</a></li>
</ul>
<h2>I installed ANT+ HRM to my watch but I don't see it anywhere</h2>
<p>See: How can I add ANT+ HRM to my Run data screen?</p>

```---------------------------------- >8 -----------------------------

What is missing is something like: <a id="i-installed-ant-hrm-to-my-watch-but-i-dont-see-it-anywhere"> on or before the h2
facelessuser commented 4 months ago

You need to enable the Table of Contents extension.

flocsy commented 4 months ago

I can see how it could work, but my md file already has the TOC in it, and it works in all the places I tried, meaning that the id-s are generated on the h2 tags, it only doesn't work when I use this markup python. So I hope there is a better solution that doesn't mean I have to delete the TOC from the md file, because then I'm not sure if it'll work in the other places.

facelessuser commented 4 months ago

If you read through the documentation, the extension will only generate the TOC if you provide[TOC] in the file. If [TOC] conflicts with anything you are doing, you can change that marker with the marker parameter.

So, if all you want are anchors to be generated, enable toc without injecting the [TOC] marker (or whatever you choose as the marker) in your file.

flocsy commented 3 months ago

If I add [TOC], then it doesn't work anywhere else. If I keep it as is it works everywhere but here. Is there a way to keep the manually added links and generate the ids for the anchors as it is done everywhere else?

facelessuser commented 3 months ago

If I add [TOC], then it doesn't work anywhere else. If I keep it as is it works everywhere but here. Is there a way to keep the manually added links and generate the ids for the anchors as it is done everywhere else?

I don't understand your question, but if you want anchors, this is all that is required:

import markdown

MD = """
# ANT+ HRM Heart Rate Monitor ❤️ - FAQ - Frequently Asked Questions

## Table of Contents
- [I installed ANT+ HRM to my watch but I don't see it anywhere](#i-installed-ant-hrm-to-my-watch-but-i-dont-see-it-anywhere)

## I installed ANT+ HRM to my watch but I don't see it anywhere
See: How can I add ANT+ HRM to my Run data screen?
"""

extensions = ['toc']
extension_configs = {}

print(markdown.markdown(MD, extensions=extensions, extension_configs=extension_configs))
<h1 id="ant-hrm-heart-rate-monitor-faq-frequently-asked-questions">ANT+ HRM Heart Rate Monitor ❤️ - FAQ - Frequently Asked Questions</h1>
<h2 id="table-of-contents">Table of Contents</h2>
<ul>
<li><a href="#i-installed-ant-hrm-to-my-watch-but-i-dont-see-it-anywhere">I installed ANT+ HRM to my watch but I don't see it anywhere</a></li>
</ul>
<h2 id="i-installed-ant-hrm-to-my-watch-but-i-dont-see-it-anywhere">I installed ANT+ HRM to my watch but I don't see it anywhere</h2>
<p>See: How can I add ANT+ HRM to my Run data screen?</p>

Please be more specific (maybe with an example?) to maybe illustrate exactly what the issue is.

waylan commented 3 months ago

As a reminder, adding anchors to heading sis NOT part of Markdown's syntax. We follow the original syntax rules, which make no mention of anchors. Even GitHub's own spec (an extended CommonMark spec) does not include any provision for anchors on headings. In fact, GitHub documents there markup process in github/markup. Note that while markdown is converted to HTML in step 1, it is not until step 4 that anchors are added. GitHub does not include adding anchors as part of their Markdown-to-HTML conversion but as a later postprocessor which is run against all markup languages consistently. The point is that it is not correct to expect a Markdown parser to handle this out-of-the-box.

As @facelessuser pointed our, we do provide an extension which does auto-generate anchors for headings. You can chose to use the TOC generated by the extension or use your own. However, if you chose to use your own, you will need to be sure to use the format for anchors defined by the extension. Alternatively, you could use the attr_list extension to define your own anchors in whatever format you want.

If you are still having issues, please provide a clear reproducible example. Please provide the input, the options passed to Markdown, and the output received as well as the expected output.

flocsy commented 3 months ago

OK, that helped. Until now I used: python3 -m markdown TEST.md > TEST.html I created now: md2html.py:

#!/usr/bin/env python3
import sys
import markdown
extensions = ['toc']
extension_configs = {}

def main(argv):
    with open(argv[0], 'r') as md_file:
        md = md_file.read()
        print(markdown.markdown(md, extensions=extensions, extension_configs=extension_configs))

if __name__ == '__main__':
    main(sys.argv[1:])
facelessuser commented 3 months ago

You can use markdown from the command line, you just have to configure the extensions:

Usage: __main__.py [options] [INPUTFILE]
       (STDIN is assumed if no INPUTFILE is given)

A Python implementation of John Gruber's Markdown. https://Python-
Markdown.github.io/

Options:
  --version             show program's version number and exit
  -h, --help            show this help message and exit
  -f OUTPUT_FILE, --file=OUTPUT_FILE
                        Write output to OUTPUT_FILE. Defaults to STDOUT.
  -e ENCODING, --encoding=ENCODING
                        Encoding for input and output files.
  -o OUTPUT_FORMAT, --output_format=OUTPUT_FORMAT
                        Use output format 'xhtml' (default) or 'html'.
  -n, --no_lazy_ol      Observe number of first item of ordered lists.
  -x EXTENSION, --extension=EXTENSION
                        Load extension EXTENSION.
  -c CONFIG_FILE, --extension_configs=CONFIG_FILE
                        Read extension configurations from CONFIG_FILE.
                        CONFIG_FILE must be of JSON or YAML format. YAML
                        format requires that a python YAML library be
                        installed. The parsed JSON or YAML must result in a
                        python dictionary which would be accepted by the
                        'extension_configs' keyword on the markdown.Markdown
                        class. The extensions must also be loaded with the
                        `--extension` option.
  -q, --quiet           Suppress all warnings.
  -v, --verbose         Print all warnings.
  --noisy               Print debug messages.

I use the script I posted simply because I just copy and paste people's example into it so I can replicate their issues and provide examples. Either way, glad you have a working solution.