pdoc3 / pdoc

:snake: :arrow_right: :scroll: Auto-generate API documentation for Python projects
https://pdoc3.github.io/pdoc/
GNU Affero General Public License v3.0
1.12k stars 145 forks source link

How to enable markdown extensions? #158

Open MPvHarmelen opened 4 years ago

MPvHarmelen commented 4 years ago

Expected Behavior

I am looking for some configuration switch to tell Python Markdown which extensions to use, specifically something like PyMdown Extensions to enable task-lists and strike-through.

Actual Behavior

The list of extensions seems to be hard-coded and not amendable using templates (or consequently command-line arguments).

See: https://github.com/pdoc3/pdoc/blob/1709915249cdbdf9d79f08628a1ff08190678adf/pdoc/html_helpers.py#L69

Steps to Reproduce

N.A.

Additional info

kernc commented 4 years ago

It's non-amendable as nobody needed/proposed it yet. Seems reasonable. I think template tunables would allow for greater configurability (e.g. extension configs). A PR would be much appreciated. :+1:

MPvHarmelen commented 4 years ago

I could spend some time on implementing this, but have no idea what you mean by "template tunables" and haven't worked with mako templates before. Could you point me in the right direction? Specifically I'm not quite sure in which of the templates this should be added.

I'm assuming you would want to move the whole list of extensions and config into some template, so users can also choose to leave out extensions, or are there any extensions that pdoc depends on, so must be kept in?

kernc commented 4 years ago

Great! Sorry, I meant config.mako template, which is consulted before rendering the real html/text/pdf templates.

users can also choose to leave out extensions, or are there any extensions that pdoc depends on

I'm not sure, best run the tests and see. toc is tested for sure. Re appending, I guess either way is fine, although the current defaults seem also quite fine, and I don't want to pollute user-facing config with pointless and never-to-be-customized internals. :thinking: Either way, with extensions defined in a template, you'll need a way to efficiently enable/cache them on the markdown converter instance, somewhat like the MathJax preprocessor is if latex_math config tunable is set: https://github.com/pdoc3/pdoc/blob/1709915249cdbdf9d79f08628a1ff08190678adf/pdoc/html_helpers.py#L356-L365 I'm afraid creating a new markdown converter instance for each piece of docstring will be too inefficient.

The alternative is a CLI switch --markdown-extension-configs taking JSON dict with its keys marking extra extensions to enable. I maybe like this simpler option ...

MPvHarmelen commented 4 years ago

Okay, let's append things then. I think I like a template-based solution, as it keeps the functionality for CLI and programmatic usage the same.

Would handling it exactly the same as the LaTeX maths be an acceptable solution? That would mean adding a list(-like?) variable to the config.mako template, propagating that to html_helpers.to_html in html.mako (like latex_math) and then registering the extensions exactly where the patterns for LaTeX maths are also registered.

https://github.com/pdoc3/pdoc/blob/1709915249cdbdf9d79f08628a1ff08190678adf/pdoc/templates/html.mako#L17-L18

A problem with this solution is that you can't deregister an extension like you can deregister patterns, meaning that you can't use different extensions during the same run. Is this a problem? If so, the global Markdown instance must be made local in some way.

https://github.com/pdoc3/pdoc/blob/1709915249cdbdf9d79f08628a1ff08190678adf/pdoc/html_helpers.py#L69-L90

Some stuff for (future) reference

Markdown.registerExtensions, to, well, register extensions...

https://github.com/Python-Markdown/markdown/blob/1de3083d82a5245015f0f0b9471a965916134d6d/markdown/core.py#L110-L120

kernc commented 4 years ago

exactly where the patterns for LaTeX maths are also registered.

https://github.com/pdoc3/pdoc/blob/1709915249cdbdf9d79f08628a1ff08190678adf/pdoc/templates/html.mako#L17-L18

I must say, this looks one hella ugly piece of hack, sending values back and forth like insane. I'm not sure that wasn't a mistake. I wonder if most preferences couldn't instead be applied earlier, like in _render_template() where the config is read? :thinking: https://github.com/pdoc3/pdoc/blob/1709915249cdbdf9d79f08628a1ff08190678adf/pdoc/__init__.py#L93-L121