Collection of core plugins for markdown-it-py.
executablebooks / mdit-py-plugins Goto Github PK
View Code? Open in Web Editor NEWCollection of core plugins for markdown-it-py
Home Page: https://mdit-py-plugins.readthedocs.io
License: MIT License
Collection of core plugins for markdown-it-py
Home Page: https://mdit-py-plugins.readthedocs.io
License: MIT License
Collection of core plugins for markdown-it-py.
The dollarmath_plugin's renderer
parameter does not work after upgrading to 0.3.4
. Instead of using the given renderer function to parse the LaTeX, it just returns the name of the renderer function. Here's a simple example for repro:
In <=0.3.3
from markdown_it import MarkdownIt
md = MarkdownIt().use(dollarmath_plugin, renderer=lambda x,y:x).enable("table")
md.render("# Let's learn about $x$")
would produce:
<h1>Let\'s learn about <span class="math inline">x</span></h1>
In 0.3.4
it produces
<h1>Let's learn about <span class="math inline"><function <lambda> at 0x7fd79cb4d940></span></h1>
See above
Python 3.9
Windows, Linux
We use the wonderful markdown-it-py
and mdit-py-plugins
packages in the open-source Gradio library, where we use it to render LaTeX in machine learning demos. We'd love to continue being able to do so, so hoping this bug gets fixed. Thanks!
context
The admonition syntax is based on Python Markdown:
!!! danger "Don't try this at home"
...
expectation
I would expect the quotes to be absent from the output.
bug
With mdit-py-plugins, the quotes are present in the output:
Unexpected output generated by mdit-py-plugins (spurious quotes):
<div class="admonition danger"> <p class="admonition-title">"Don't try this at home"</p> <p>...</p> </div>
Moreover, the additional CSS classes are not supported either.
Changing the behavior might cause compatiblity issues with markdown-it-admon however.
problem
This is a problem for people migrating from Python Markdown.
Create markdown file with:
!!! danger "Don't try this at home"
...
Create script
from markdown_it import MarkdownIt
from mdit_py_plugins.admon import admon_plugin
md_opts = {
"html": True,
}
markdown_it_render = MarkdownIt("commonmark", md_opts).use(admon_plugin)
source = open("/dev/stdin", "rt").read()
res = markdown_it_render.render(source)
print(res)
Run:
python3 test.py < test.md
Output:
<div class="admonition danger">
<p class="admonition-title">"Don't try this at home"</p>
<p>...</p>
</div>
I'd like to see a fancy list plugin. I'm using this for formatting laws and they have deeply nested, ordered lists with different numbering styles for each level.
Deeply nested, ordered lists would be clearer.
There is a markdown-it plugin here: https://github.com/Moxio/markdown-it-fancy-lists
No response
It would be useful if it were possible to use spaces in labels, like so:
(my label)=
# My header
Ref for [](my label).
In executablebooks/meta#467 (comment) we discovered that, while reStructuredText supports spaces in labels, like .. _my label:
, the MyST parser does not.
This would be useful for people who are coming from the rST / Sphinx ecosystem, since this is already supported in rST. However it's probably not a huge number of people using labels this way because most seem to use -
or _
for this kind of thing.
The fix for this would probably somewhere around here:
During the packaging of the last version of mdit-py-plugins in Debian, some tests failed:
=========================== short test summary info ============================
FAILED tests/test_admon.py::test_all[306-Indented by 4 spaces, DISABLE-CODEBLOCKS- ??? note\n content\n-<div class="admonition note is-collapsible collapsible-closed">\n<p class="admonition-title">Note</p>\n<p>content</p>\n</div>\n]
FAILED tests/test_amsmath.py::test_fixtures[237-Indented by 4 spaces, DISABLE-CODEBLOCKS- \\begin{equation}\n a = 1\n \\end{equation}\n-<div class="math amsmath">\n\\begin{equation}\n a = 1\n \\end{equation}\n</div>\n]
FAILED tests/test_attrs.py::test_attrs[254-Indented by 4 spaces, DISABLE-CODEBLOCKS- {#a .a b=c}\n # head\n-<h1 id="a" b="c" class="a">head</h1>\n]
FAILED tests/test_colon_fence.py::test_fixtures[438-Indented by 4 spaces, DISABLE-CODEBLOCKS- :::name\n foo\n :::\n-<pre><code class="block-name" >foo\n</code></pre>\n]
FAILED tests/test_container.py::test_all[301-Indented by 4 spaces, DISABLE-CODEBLOCKS- ::: name\n content\n :::\n-<div class="name">\n<p>content</p>\n</div>\n]
FAILED tests/test_deflist.py::test_all[261-Indented by 4 spaces, DISABLE-CODEBLOCKS- Term 1\n\n : Definition 1\n-<dl>\n<dt>Term 1</dt>\n<dd>Definition 1</dd>\n</dl>\n]
FAILED tests/test_dollarmath.py::test_dollarmath_fixtures[575-Indented by 4 spaces, DISABLE-CODEBLOCKS- $$a$$\n-<div class="math block">\na\n</div>\n]
FAILED tests/test_field_list.py::test_all[378-Indented_by_4_spaces,_DISABLE-CODEBLOCKS]
FAILED tests/test_footnote.py::test_all[360-Indented by 4 spaces, DISABLE-CODEBLOCKS- [^1]\n\n [^1]: footnote\n-<p><sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup></p>\n<hr class="footnotes-sep">\n<section class="footnotes">\n<ol class="footnotes-list">\n<li id="fn1" class="footnote-item"><p>footnote <a href="#fnref1" class="footnote-backref">\u21a9\ufe0e</a></p>\n</li>\n</ol>\n</section>\n]
FAILED tests/test_myst_block.py::test_all[168-Indented by 4 spaces, DISABLE-CODEBLOCKS- +++\n\n % abc\n\n (a)=\n-<hr class="myst-block">\n<!-- abc --><div class="myst-target"><a href="#a">(a)=</a></div>\n]
======================== 10 failed, 400 passed in 0.45s ========================
All of those failed with the form:
@pytest.mark.parametrize("line,title,input,expected", read_fixture_file(FIXTURE_PATH))
def test_all(line, title, input, expected):
md = MarkdownIt("commonmark").use(myst_block_plugin)
if "DISABLE-CODEBLOCKS" in title:
md.disable("code")
md.options["xhtmlOut"] = False
text = md.render(input)
print(text)
> assert text.rstrip() == expected.rstrip()
E assert '<p>+++</p>\n...\n<p>(a)=</p>' == '<hr class="m...a)=</a></div>'
E - <hr class="myst-block">
E - <!-- abc --><div class="myst-target"><a href="#a">(a)=</a></div>
E + <p>+++</p>
E + <p>% abc</p>
E + <p>(a)=</p>
I figured out that updating the version of markdown-it-py package fix the error.
Looking #89, that use markdow-it-py 2.2.0, and I used version 2.1.0, seems that the dependencies variable in pyproject.toml
can be change to avoid confusion:
dependencies = ["markdown-it-py>=3.0.0,<4.0.0"]
Run tests with versions of markdown-it-py minor than 3.0.0
No response
I would suggest two improvements to the tasklists plugin:
Don't add disabled="disabled"
to the checkboxes. This makes it so you can't click them. But if you are going to add a list of check boxes to a page, it would be useful if people can actually click them. Since this might not be desired in all cases, a configuration option might be useful, or some syntax to allow or disallow it.
Add style="list-style: none;
styling to the ul
. This prevents the bullet point from appearing. This is how it works on GitHub, for instance
Item 1
Item 2
No response
No response
Github "About" text is Repository containg plugins for markdown-it-py
. Should change containg
to containing
The usage example
from markdown_it import MarkdownIt
from mdit_py_plugins import plugin1, plugin2
md = MarkdownIt().use(plugin1, keyword=value).use(plugin2, keyword=value)
html_string = md.render("some *Markdown*")
is, I feel, a little misleading, since the plugins can't actually be imported directly from the top-level mdit_py_plugins
module currently.
Maybe a real example would be better?
No response
Describe the bug
When we parse the markdown text of tasklist type, the tokens provide no information if the markdown is of type tasklist, even if we use the tasklist plugin
To Reproduce
from markdown_it import MarkdownIt
from markdown_it.token import NestedTokens, Token, nest_tokens
from mdit_py_plugins.tasklists import tasklists_plugin
def parse_markdown(md_text):
mdi = MarkdownIt("commonmark").enable("table").use(tasklists_plugin)
tokens = mdi.parse(text)
tokens = nest_tokens(tokens)
return tokens
>>> text = "- [ ] "
>>> parse_markdown(text)
[NestedTokens(opening=Token(type='bullet_list_open', tag='ul', nesting=1, attrs=None, map=[0, 1], level=0, children=None, content='', markup='-', info='', meta={}, block=True, hidden=False), closing=Toke
n(type='bullet_list_close', tag='ul', nesting=-1, attrs=None, map=None, level=0, children=None, content='', markup='-', info='', meta={}, block=True, hidden=False), children=[NestedTokens(opening=Token(t
ype='list_item_open', tag='li', nesting=1, attrs=None, map=[0, 1], level=1, children=None, content='', markup='-', info='', meta={}, block=True, hidden=False), closing=Token(type='list_item_close', tag='
li', nesting=-1, attrs=None, map=None, level=1, children=None, content='', markup='-', info='', meta={}, block=True, hidden=False), children=[NestedTokens(opening=Token(type='paragraph_open', tag='p', ne
sting=1, attrs=None, map=[0, 1], level=2, children=None, content='', markup='', info='', meta={}, block=True, hidden=True), closing=Token(type='paragraph_close', tag='p', nesting=-1, attrs=None, map=None
, level=2, children=None, content='', markup='', info='', meta={}, block=True, hidden=True), children=[Token(type='inline', tag='', nesting=0, attrs=None, map=[0, 1], level=3, children=[Token(type='text'
, tag='', nesting=0, attrs=None, map=None, level=0, children=None, content='[ ]', markup='', info='', meta={}, block=False, hidden=False)], content='[ ]', markup='', info='', meta={}, block=True, hidden=
False)])])])]
>>>
>>> # the below text will have attrs in bullet_list_open
...
>>> text = "- [ ] Tasklist 1"
>>> parse_markdown(text)
[NestedTokens(opening=Token(type='bullet_list_open', tag='ul', nesting=1, attrs=[['class', 'contains-task-list']], map=[0, 1], level=0, children=None, content='', markup='-', info='', meta={}, block=True
, hidden=False), closing=Token(type='bullet_list_close', tag='ul', nesting=-1, attrs=None, map=None, level=0, children=None, content='', markup='-', info='', meta={}, block=True, hidden=False), children=
[NestedTokens(opening=Token(type='list_item_open', tag='li', nesting=1, attrs=[['class', 'task-list-item']], map=[0, 1], level=1, children=None, content='', markup='-', info='', meta={}, block=True, hidd
en=False), closing=Token(type='list_item_close', tag='li', nesting=-1, attrs=None, map=None, level=1, children=None, content='', markup='-', info='', meta={}, block=True, hidden=False), children=[NestedT
okens(opening=Token(type='paragraph_open', tag='p', nesting=1, attrs=None, map=[0, 1], level=2, children=None, content='', markup='', info='', meta={}, block=True, hidden=True), closing=Token(type='parag
raph_close', tag='p', nesting=-1, attrs=None, map=None, level=2, children=None, content='', markup='', info='', meta={}, block=True, hidden=True), children=[Token(type='inline', tag='', nesting=0, attrs=
None, map=[0, 1], level=3, children=[Token(type='html_inline', tag='', nesting=0, attrs=None, map=None, level=0, children=None, content='<input class="task-list-item-checkbox" disabled="disabled" type="c
heckbox">', markup='', info='', meta={}, block=False, hidden=False), Token(type='text', tag='', nesting=0, attrs=None, map=None, level=0, children=None, content=' Tasklist 1', markup='', info='', meta={}
, block=False, hidden=False)], content=' Tasklist 1', markup='', info='', meta={}, block=True, hidden=False)])])])]
Expected behavior
Expected behaviour should be that a text - [ ]
should also have ['class', 'contains-task-list']
in NestedToken.opening
Environment
jupyter-book --version
:context
I used markdown_it to convert Markdown to html, but the converted formula lost its delimiters, which caused my mathjax cannot render the formula,
Code for conversion :
from markdown_it import MarkdownIt
from mdit_py_plugins.front_matter import front_matter_plugin
from mdit_py_plugins.footnote import footnote_plugin
from mdit_py_plugins.anchors import anchors_plugin
from mdit_py_plugins.texmath import texmath_plugin
from mdit_py_plugins.dollarmath import dollarmath_plugin
from mdit_py_plugins.amsmath import amsmath_plugin
from markdown_it.common import utils
import html
md = (
# MarkdownIt('gfm-like' ,{
MarkdownIt('commonmark' ,{
'breaks':True,
'html':True
})
# .use(texmath_plugin, delimiters="dollars")
.use(dollarmath_plugin)
# .use(amsmath_plugin)
.use(front_matter_plugin)
.use(footnote_plugin)
.use(anchors_plugin, permalink=True, max_level=4)
.enable('table')
)
s4=r'''a rational number like $\begin{matrix}
L & \ = \{ x \mid x \in \mathbb{Q},x \leq 0\} \cup \left\{ x \mid x \in \mathbb{Q},x > 0,x^{2} < 2 \right\} \\
U & \ = \mathbb{Q} - L = \left\{ x \mid x \in \mathbb{Q},x > 0,x^{2} > 2 \right\} \\
\end{matrix}$ .
2. A fact between two Dedekind cuts(the density of $Q$ in $R$): For any pair of real numbers $\alpha$ and $\beta$, where $\alpha > \beta$, there can always be found a real, and even in particular a rational, number $r$ which lies between them, i.e. $\alpha > r > \beta$ (and, consequently, an infinite set of such rational numbers).
'''
html_text = md.render(s4)
print(html_text)
The demo with the result at https://jsbin.com/ronasug/edit?html,output
expectation
delimiters around formula.
bug
converted formula lost its delimiters, the bug is also confirmed at https://groups.google.com/g/mathjax-users/c/aL3aqfp8DzU/m/KZoomKKvBwAJ
... but it looks like it might be an old one, as it seems to be producing jsMath-style delimiters (...) rather than MathJax-style ones. JsMath was MathJax's predecessor, active from 2004 to 2008, and while MathJax v2 includes an extension that would parse jsMath delimiters, that is not available in version 3. There is an example showing how to look for MathJax v2 <script> tags that could be modified to look for jsMath-style tags instead, if you are proficient enough with javascript.
see the above section
No response
Context
In mdit-py-plugins < 0.3 it backslashes were not allowed in MyST targets. Now they are.
Problem / Idea
This is now a valid MyST target:
(myst_target\)=
I think it would be more intuitive and in line with CommonMark if the backslash escape worked, i.e. prevented the target being parsed successfully.
Solution
Disallow backslashes in MyST targets.
Benefit
Consistency with backslashes in CommonMark.
No response
No response
Looks like with new version pytest is failing in few units.
I'm packaging your module as an rpm package so I'm using the typical PEP517 based build, install and test cycle used on building packages from non-root account.
python3 -sBm build -w --no-isolation
build
with --no-isolation
I'm using during all processes only locally installed modulescut off from access to the public network
(pytest is executed with -m "not network"
)Here is pytest output:
+ PYTHONPATH=/home/tkloczko/rpmbuild/BUILDROOT/python-mdit-py-plugins-0.4.0-2.fc35.x86_64/usr/lib64/python3.8/site-packages:/home/tkloczko/rpmbuild/BUILDROOT/python-mdit-py-plugins-0.4.0-2.fc35.x86_64/usr/lib/python3.8/site-packages
+ /usr/bin/pytest -ra -m 'not network'
==================================================================================== test session starts ====================================================================================
platform linux -- Python 3.8.16, pytest-7.3.1, pluggy-1.0.0
rootdir: /home/tkloczko/rpmbuild/BUILD/mdit-py-plugins-0.4.0
plugins: datadir-1.4.1, regressions-2.4.2
collected 410 items
tests/test_admon.py .....................F... [ 6%]
tests/test_amsmath.py ...................F [ 10%]
tests/test_anchors.py ........ [ 12%]
tests/test_attrs.py ...............................F [ 20%]
tests/test_colon_fence.py ................................F. [ 29%]
tests/test_container.py ......................F [ 34%]
tests/test_deflist.py ...............F [ 38%]
tests/test_dollarmath.py ...............................................................F [ 54%]
tests/test_field_list.py ................F [ 58%]
tests/test_footnote.py ......................F [ 63%]
tests/test_front_matter.py ......... [ 66%]
tests/test_myst_block.py ..............F.. [ 70%]
tests/test_myst_role.py ............... [ 73%]
tests/test_substitution.py .......... [ 76%]
tests/test_tasklists.py ....... [ 78%]
tests/test_texmath.py ....................................................................................... [ 99%]
tests/test_wordcount.py ... [100%]
========================================================================================= FAILURES ==========================================================================================
_ test_all[306-Indented by 4 spaces, DISABLE-CODEBLOCKS- ??? note\n content\n-<div class="admonition note is-collapsible collapsible-closed">\n<p class="admonition-title">Note</p>\n<p>content</p>\n</div>\n] _
line = 306, title = 'Indented by 4 spaces, DISABLE-CODEBLOCKS', input = ' ??? note\n content\n'
expected = '<div class="admonition note is-collapsible collapsible-closed">\n<p class="admonition-title">Note</p>\n<p>content</p>\n</div>\n'
@pytest.mark.parametrize(
"line,title,input,expected",
read_fixture_file(FIXTURE_PATH.joinpath("fixtures", "admon.md")),
)
def test_all(line, title, input, expected):
md = MarkdownIt("commonmark").use(admon_plugin)
if "DISABLE-CODEBLOCKS" in title:
md.disable("code")
md.options["xhtmlOut"] = False
text = md.render(input)
print(text)
> assert text.rstrip() == expected.rstrip()
E assert '<p>??? note\ncontent</p>' == '<div class="...t</p>\n</div>'
E + <p>??? note
E - <div class="admonition note is-collapsible collapsible-closed">
E - <p class="admonition-title">Note</p>
E - <p>content</p>
E ? --- -
E + content</p>
E - </div>
tests/test_admon.py:24: AssertionError
----------------------------------------------------------------------------------- Captured stdout call ------------------------------------------------------------------------------------
<p>??? note
content</p>
_ test_fixtures[237-Indented by 4 spaces, DISABLE-CODEBLOCKS- \\begin{equation}\n a = 1\n \\end{equation}\n-<div class="math amsmath">\n\\begin{equation}\n a = 1\n \\end{equation}\n</div>\n] _
line = 237, title = 'Indented by 4 spaces, DISABLE-CODEBLOCKS', input = ' \\begin{equation}\n a = 1\n \\end{equation}\n'
expected = '<div class="math amsmath">\n\\begin{equation}\n a = 1\n \\end{equation}\n</div>\n'
@pytest.mark.parametrize(
"line,title,input,expected",
read_fixture_file(FIXTURE_PATH.joinpath("fixtures", "amsmath.md")),
)
def test_fixtures(line, title, input, expected):
md = MarkdownIt("commonmark").use(amsmath_plugin)
if "DISABLE-CODEBLOCKS" in title:
md.disable("code")
md.options["xhtmlOut"] = False
text = md.render(input)
print(text)
> assert text.rstrip() == expected.rstrip()
E assert '<p>\\begin{e...equation}</p>' == '<div class="...tion}\n</div>'
E - <div class="math amsmath">
E - \begin{equation}
E + <p>\begin{equation}
E ? +++
E - a = 1
E ? ----
E + a = 1...
E
E ...Full output truncated (5 lines hidden), use '-vv' to show
tests/test_amsmath.py:58: AssertionError
----------------------------------------------------------------------------------- Captured stdout call ------------------------------------------------------------------------------------
<p>\begin{equation}
a = 1
\end{equation}</p>
_______________________________ test_attrs[254-Indented by 4 spaces, DISABLE-CODEBLOCKS- {#a .a b=c}\n # head\n-<h1 id="a" b="c" class="a">head</h1>\n] _______________________________
line = 254, title = 'Indented by 4 spaces, DISABLE-CODEBLOCKS', input = ' {#a .a b=c}\n # head\n', expected = '<h1 id="a" b="c" class="a">head</h1>\n'
@pytest.mark.parametrize(
"line,title,input,expected", read_fixture_file(FIXTURE_PATH / "attrs.md")
)
def test_attrs(line, title, input, expected):
md = MarkdownIt("commonmark").use(attrs_plugin, spans=True).use(attrs_block_plugin)
if "DISABLE-CODEBLOCKS" in title:
md.disable("code")
md.options["xhtmlOut"] = False
text = md.render(input)
print(text)
> assert text.rstrip() == expected.rstrip()
E assert '<p>{#a .a b=c}\n# head</p>' == '<h1 id="a" b..."a">head</h1>'
E - <h1 id="a" b="c" class="a">head</h1>
E + <p>{#a .a b=c}
E + # head</p>
tests/test_attrs.py:22: AssertionError
----------------------------------------------------------------------------------- Captured stdout call ------------------------------------------------------------------------------------
<p>{#a .a b=c}
# head</p>
______________________ test_fixtures[438-Indented by 4 spaces, DISABLE-CODEBLOCKS- :::name\n foo\n :::\n-<pre><code class="block-name" >foo\n</code></pre>\n] ______________________
line = 438, title = 'Indented by 4 spaces, DISABLE-CODEBLOCKS', input = ' :::name\n foo\n :::\n', expected = '<pre><code class="block-name" >foo\n</code></pre>\n'
@pytest.mark.parametrize("line,title,input,expected", read_fixture_file(FIXTURE_PATH))
def test_fixtures(line, title, input, expected):
md = MarkdownIt("commonmark").use(colon_fence_plugin)
if "DISABLE-CODEBLOCKS" in title:
md.disable("code")
md.options["xhtmlOut"] = False
text = md.render(input)
try:
> assert text.rstrip() == expected.rstrip()
E assert '<p>:::name\nfoo\n:::</p>' == '<pre><code c...</code></pre>'
E - <pre><code class="block-name" >foo
E - </code></pre>
E + <p>:::name
E + foo
E + :::</p>
tests/test_colon_fence.py:21: AssertionError
----------------------------------------------------------------------------------- Captured stdout call ------------------------------------------------------------------------------------
<p>:::name
foo
:::</p>
_________________________ test_all[301-Indented by 4 spaces, DISABLE-CODEBLOCKS- ::: name\n content\n :::\n-<div class="name">\n<p>content</p>\n</div>\n] __________________________
line = 301, title = 'Indented by 4 spaces, DISABLE-CODEBLOCKS', input = ' ::: name\n content\n :::\n', expected = '<div class="name">\n<p>content</p>\n</div>\n'
@pytest.mark.parametrize("line,title,input,expected", read_fixture_file(FIXTURE_PATH))
def test_all(line, title, input, expected):
md = MarkdownIt("commonmark").use(container_plugin, "name")
if "DISABLE-CODEBLOCKS" in title:
md.disable("code")
md.options["xhtmlOut"] = False
text = md.render(input)
print(text)
> assert text.rstrip() == expected.rstrip()
E assert '<p>::: name\...tent\n:::</p>' == '<div class="...t</p>\n</div>'
E - <div class="name">
E - <p>content</p>
E - </div>
E + <p>::: name
E + content
E + :::</p>
tests/test_container.py:50: AssertionError
----------------------------------------------------------------------------------- Captured stdout call ------------------------------------------------------------------------------------
<p>::: name
content
:::</p>
______________________ test_all[261-Indented by 4 spaces, DISABLE-CODEBLOCKS- Term 1\n\n : Definition 1\n-<dl>\n<dt>Term 1</dt>\n<dd>Definition 1</dd>\n</dl>\n] ______________________
line = 261, title = 'Indented by 4 spaces, DISABLE-CODEBLOCKS', input = ' Term 1\n\n : Definition 1\n', expected = '<dl>\n<dt>Term 1</dt>\n<dd>Definition 1</dd>\n</dl>\n'
@pytest.mark.parametrize("line,title,input,expected", read_fixture_file(FIXTURE_PATH))
def test_all(line, title, input, expected):
md = MarkdownIt("commonmark").use(deflist_plugin)
if "DISABLE-CODEBLOCKS" in title:
md.disable("code")
md.options["xhtmlOut"] = False
text = md.render(input)
print(text)
> assert text.rstrip() == expected.rstrip()
E AssertionError: assert '<p>Term 1</p...inition 1</p>' == '<dl>\n<dt>Te...1</dd>\n</dl>'
E - <dl>
E - <dt>Term 1</dt>
E ? ^^ ^^
E + <p>Term 1</p>
E ? ^ ^
E - <dd>Definition 1</dd>
E ? ^^ ^^ -...
E
E ...Full output truncated (3 lines hidden), use '-vv' to show
tests/test_deflist.py:39: AssertionError
----------------------------------------------------------------------------------- Captured stdout call ------------------------------------------------------------------------------------
<p>Term 1</p>
<p>: Definition 1</p>
_________________________________ test_dollarmath_fixtures[575-Indented by 4 spaces, DISABLE-CODEBLOCKS- $$a$$\n-<div class="math block">\na\n</div>\n] __________________________________
line = 575, title = 'Indented by 4 spaces, DISABLE-CODEBLOCKS', input = ' $$a$$\n', expected = '<div class="math block">\na\n</div>\n'
@pytest.mark.parametrize(
"line,title,input,expected",
read_fixture_file(FIXTURE_PATH.joinpath("dollar_math.md")),
)
def test_dollarmath_fixtures(line, title, input, expected):
md = MarkdownIt("commonmark").use(
dollarmath_plugin,
allow_space=False,
allow_digits=False,
double_inline=True,
allow_blank_lines=False,
)
if "DISABLE-CODEBLOCKS" in title:
md.disable("code")
md.options.xhtmlOut = False
text = md.render(input)
print(text)
> assert text.rstrip() == expected.rstrip()
E assert '<p><div clas...">a</div></p>' == '<div class="...">\na\n</div>'
E + <p><div class="math inline">a</div></p>
E - <div class="math block">
E - a
E - </div>
tests/test_dollarmath.py:106: AssertionError
----------------------------------------------------------------------------------- Captured stdout call ------------------------------------------------------------------------------------
<p><div class="math inline">a</div></p>
__________________________________________________________________ test_all[378-Indented_by_4_spaces,_DISABLE-CODEBLOCKS] ___________________________________________________________________
line = 378, title = 'Indented by 4 spaces, DISABLE-CODEBLOCKS', input = ' :name: text\n indented\n'
expected = '<dl class="field-list">\n<dt>name</dt>\n<dd>\n<p>text\nindented</p>\n</dd>\n</dl>\n'
@pytest.mark.parametrize(
"line,title,input,expected",
fixtures,
ids=[f"{f[0]}-{f[1].replace(' ', '_')}" for f in fixtures],
)
def test_all(line, title, input, expected):
md = MarkdownIt("commonmark").use(fieldlist_plugin)
if "DISABLE-CODEBLOCKS" in title:
md.disable("code")
md.options["xhtmlOut"] = False
text = md.render(input)
print(text)
> assert text.rstrip() == expected.rstrip()
E assert '<p>:name: text\nindented</p>' == '<dl class="f...n</dd>\n</dl>'
E + <p>:name: text
E - <dl class="field-list">
E - <dt>name</dt>
E - <dd>
E - <p>text
E - indented</p>
E ? -...
E
E ...Full output truncated (3 lines hidden), use '-vv' to show
tests/test_field_list.py:41: AssertionError
----------------------------------------------------------------------------------- Captured stdout call ------------------------------------------------------------------------------------
<p>:name: text
indented</p>
_ test_all[360-Indented by 4 spaces, DISABLE-CODEBLOCKS- [^1]\n\n [^1]: footnote\n-<p><sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup></p>\n<hr class="footnotes-sep">\n<section class="footnotes">\n<ol class="footnotes-list">\n<li id="fn1" class="footnote-item"><p>footnote <a href="#fnref1" class="footnote-backref">\u21a9\ufe0e</a></p>\n</li>\n</ol>\n</section>\n] _
line = 360, title = 'Indented by 4 spaces, DISABLE-CODEBLOCKS', input = ' [^1]\n\n [^1]: footnote\n'
expected = '<p><sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup></p>\n<hr class="footnotes-sep">\n<section class...1" class="footnote-item"><p>footnote <a href="#fnref1" class="footnote-backref">↩︎</a></p>\n</li>\n</ol>\n</section>\n'
@pytest.mark.parametrize("line,title,input,expected", read_fixture_file(FIXTURE_PATH))
def test_all(line, title, input, expected):
md = MarkdownIt("commonmark").use(footnote_plugin)
if "DISABLE-CODEBLOCKS" in title:
md.disable("code")
md.options["xhtmlOut"] = False
text = md.render(input)
print(text)
> assert text.rstrip().replace("↩︎", "<-").replace(
"↩", "<-"
) == expected.rstrip().replace("↩︎", "<-").replace("↩", "<-")
E assert '<p>[^1]</p>\... footnote</p>' == '<p><sup clas...>\n</section>'
E + <p>[^1]</p>
E + <p>[^1]: footnote</p>
E - <p><sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup></p>
E - <hr class="footnotes-sep">
E - <section class="footnotes">
E - <ol class="footnotes-list">
E - <li id="fn1" class="footnote-item"><p>footnote <a href="#fnref1" class="footnote-backref"><-</a></p>...
E
E ...Full output truncated (3 lines hidden), use '-vv' to show
tests/test_footnote.py:459: AssertionError
----------------------------------------------------------------------------------- Captured stdout call ------------------------------------------------------------------------------------
<p>[^1]</p>
<p>[^1]: footnote</p>
___ test_all[168-Indented by 4 spaces, DISABLE-CODEBLOCKS- +++\n\n % abc\n\n (a)=\n-<hr class="myst-block">\n<!-- abc --><div class="myst-target"><a href="#a">(a)=</a></div>\n] ___
line = 168, title = 'Indented by 4 spaces, DISABLE-CODEBLOCKS', input = ' +++\n\n % abc\n\n (a)=\n'
expected = '<hr class="myst-block">\n<!-- abc --><div class="myst-target"><a href="#a">(a)=</a></div>\n'
@pytest.mark.parametrize("line,title,input,expected", read_fixture_file(FIXTURE_PATH))
def test_all(line, title, input, expected):
md = MarkdownIt("commonmark").use(myst_block_plugin)
if "DISABLE-CODEBLOCKS" in title:
md.disable("code")
md.options["xhtmlOut"] = False
text = md.render(input)
print(text)
> assert text.rstrip() == expected.rstrip()
E assert '<p>+++</p>\n...\n<p>(a)=</p>' == '<hr class="m...a)=</a></div>'
E - <hr class="myst-block">
E - <!-- abc --><div class="myst-target"><a href="#a">(a)=</a></div>
E + <p>+++</p>
E + <p>% abc</p>
E + <p>(a)=</p>
tests/test_myst_block.py:21: AssertionError
----------------------------------------------------------------------------------- Captured stdout call ------------------------------------------------------------------------------------
<p>+++</p>
<p>% abc</p>
<p>(a)=</p>
================================================================================== short test summary info ==================================================================================
FAILED tests/test_admon.py::test_all[306-Indented by 4 spaces, DISABLE-CODEBLOCKS- ??? note\n content\n-<div class="admonition note is-collapsible collapsible-closed">\n<p class="admonition-title">Note</p>\n<p>content</p>\n</div>\n] - assert '<p>??? note\ncontent</p>' == '<div class="...t</p>\n</div>'
FAILED tests/test_amsmath.py::test_fixtures[237-Indented by 4 spaces, DISABLE-CODEBLOCKS- \\begin{equation}\n a = 1\n \\end{equation}\n-<div class="math amsmath">\n\\begin{equation}\n a = 1\n \\end{equation}\n</div>\n] - assert '<p>\\begin{e...equation}</p>' == '<div class="...tion}\n</div>'
FAILED tests/test_attrs.py::test_attrs[254-Indented by 4 spaces, DISABLE-CODEBLOCKS- {#a .a b=c}\n # head\n-<h1 id="a" b="c" class="a">head</h1>\n] - assert '<p>{#a .a b=c}\n# head</p>' == '<h1 id="a" b..."a">head</h1>'
FAILED tests/test_colon_fence.py::test_fixtures[438-Indented by 4 spaces, DISABLE-CODEBLOCKS- :::name\n foo\n :::\n-<pre><code class="block-name" >foo\n</code></pre>\n] - assert '<p>:::name\nfoo\n:::</p>' == '<pre><code c...</code></pre>'
FAILED tests/test_container.py::test_all[301-Indented by 4 spaces, DISABLE-CODEBLOCKS- ::: name\n content\n :::\n-<div class="name">\n<p>content</p>\n</div>\n] - assert '<p>::: name\...tent\n:::</p>' == '<div class="...t</p>\n</div>'
FAILED tests/test_deflist.py::test_all[261-Indented by 4 spaces, DISABLE-CODEBLOCKS- Term 1\n\n : Definition 1\n-<dl>\n<dt>Term 1</dt>\n<dd>Definition 1</dd>\n</dl>\n] - AssertionError: assert '<p>Term 1</p...inition 1</p>' == '<dl>\n<dt>Te...1</dd>\n</dl>'
FAILED tests/test_dollarmath.py::test_dollarmath_fixtures[575-Indented by 4 spaces, DISABLE-CODEBLOCKS- $$a$$\n-<div class="math block">\na\n</div>\n] - assert '<p><div clas...">a</div></p>' == '<div class="...">\na\n</div>'
FAILED tests/test_field_list.py::test_all[378-Indented_by_4_spaces,_DISABLE-CODEBLOCKS] - assert '<p>:name: text\nindented</p>' == '<dl class="f...n</dd>\n</dl>'
FAILED tests/test_footnote.py::test_all[360-Indented by 4 spaces, DISABLE-CODEBLOCKS- [^1]\n\n [^1]: footnote\n-<p><sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup></p>\n<hr class="footnotes-sep">\n<section class="footnotes">\n<ol class="footnotes-list">\n<li id="fn1" class="footnote-item"><p>footnote <a href="#fnref1" class="footnote-backref">\u21a9\ufe0e</a></p>\n</li>\n</ol>\n</section>\n] - assert '<p>[^1]</p>\... footnote</p>' == '<p><sup clas...>\n</section>'
FAILED tests/test_myst_block.py::test_all[168-Indented by 4 spaces, DISABLE-CODEBLOCKS- +++\n\n % abc\n\n (a)=\n-<hr class="myst-block">\n<!-- abc --><div class="myst-target"><a href="#a">(a)=</a></div>\n] - assert '<p>+++</p>\n...\n<p>(a)=</p>' == '<hr class="m...a)=</a></div>'
============================================================================== 10 failed, 400 passed in 1.22s ===============================================================================
Here is list of installed modules in build env
Package Version
----------------------------- -------
alabaster 0.7.13
asttokens 2.2.1
Babel 2.12.1
backcall 0.2.0
build 0.10.0
charset-normalizer 3.1.0
decorator 5.1.1
distro 1.8.0
docutils 0.19
exceptiongroup 1.1.1
executing 1.2.0
gpg 1.20.0
idna 3.4
imagesize 1.4.1
importlib-metadata 6.6.0
iniconfig 2.0.0
installer 0.7.0
ipython 8.12.0
jedi 0.18.2
Jinja2 3.1.2
libcomps 0.1.19
markdown-it-py 2.2.0
MarkupSafe 2.1.2
matplotlib-inline 0.1.6
mdit-py-plugins 0.3.5
mdurl 0.1.2
myst-parser 1.0.0
packaging 23.1
parso 0.8.3
pexpect 4.8.0
pickleshare 0.7.5
pluggy 1.0.0
prompt-toolkit 3.0.38
ptyprocess 0.7.0
pure-eval 0.2.2
Pygments 2.15.1
pyproject_hooks 1.0.0
pytest 7.3.1
pytest-datadir 1.4.1
pytest-regressions 2.4.2
python-dateutil 2.8.2
pytz 2023.2
PyYAML 6.0
requests 2.30.0
setuptools 67.7.2
six 1.16.0
snowballstemmer 2.2.0
Sphinx 6.2.1
sphinxcontrib-applehelp 1.0.4
sphinxcontrib-devhelp 1.0.2
sphinxcontrib-htmlhelp 2.0.0
sphinxcontrib-jsmath 1.0.1
sphinxcontrib-qthelp 1.0.3
sphinxcontrib-serializinghtml 1.1.5
stack-data 0.6.2
tomli 2.0.1
traitlets 5.9.0
typing_extensions 4.5.0
urllib3 1.26.15
wcwidth 0.2.6
wheel 0.40.0
zipp 3.15.0
I've just created markdown-it-dollarmath
, and in particular here: executablebooks/markdown-it-dollarmath@e3eb244, I added the extra token math_inline_double
and renamed math_block_eqno
to math_block_label
.
Also, there is the labelNormalizer
option and the render hook (and similarly with amsmath).
Note, this will also require a change in myst-parser, so should be followed by a minor (breaking) version release
Should link to the JS plugin demonstration pages as well.
According to hukkin/mdformat-gfm#23 (comment) there is an issue with the parser regarding how tabs are handled.
I do not know how exactly, but they produce a side effect in the mdformat-gfm plugin.
Use mdformat with the mdformat-gfm plugin.
Some brackets are escaped even when using mdformat-gfm in cases where the closing bracket is followed with a tab.
mdformat 0.7.13 (mdformat_gfm: 0.3.5, mdformat_tables: 0.4.1, mdformat_toc:
0.3.0)
context
myst_role misparses inlines that begin with a role occurences and end with \
because its checks for leading \
unintentionally wraps around the end of srcCharCode
and checks the last char code instead.
expectation
>>> md.render("{foo}`ar`\\")
'<p><code class="myst role">{foo}[ar]</code>\\</p>\n'
bug
>>> md.render("{foo}`ar`\\")
'<p>{foo}<code>ar</code>\\</p>\n'
problem
This is a pretty clear misparse that causes rendering errors. admittedly it's not very likely to be hit in the grand scheme of things, but we've hit it nevertheless.
render any string that contains only a myst_role followed by \
, with no leading or trailing whitespace.
Github and gitlab flavored markdown have their own parsing tools to detection links to issues with a simple #<number>
or !<number>
for gitlab's MR.
Example here : #103 #14 automatically add links to the corresponding issue and pull requests
Would it be interesting to have a dedicated plugin for myst ?
Many projects do have a CHANGELOG.md file, which uses this syntaxe and it would be nice to be able to convert it to a sphinx page with myst. See a changelog example here : https://github.com/github-tools/github-release-notes/blob/master/CHANGELOG.md
Also, note that there exists a project that tries to recreate the #{number}
feel for changelog with sphinx, but it works directive that are then not parsed by github/gitlab : https://github.com/sloria/sphinx-issues .
In a sense, we want the other way around, to transform #{number}
patterns into proper directives 😃
Provide a plugin that you can parameter so that {character}{number}
are substituted to links to the corresponding issue/PR of you own project {website}/{user}/{project}/{task}/{number}
for e.g. this project, the parameters would be :
website = "https://github.com/"
user = "exectuablebooks"
project = "mdit-py-plugins"
issue_character = "#"
issue_task = "issues"
For a project in gitlab the parameters would be :
website = "https://gitlab.com/"
user = "exectuablebooks"
project = "mdit-py-plugins"
issue_character = "#"
issue_task = "issues"
pull_request_character="!"
pull_request_task = "merge_requests"
Note that for github, there is a confusion between patterns for issues and pull requests, but that's ok since github automatically redirect to the right url. For example #105 automatically redirects to #105
No response
I want a list of the title, unique slug-id pairs for my generated anchors so I can create a navbar linking to the content. In MarkdownIt for JS a callback exists with this data:
"The callback option is a function that will be called at the end of rendering with the token and an info object. The info object has title and slug properties with the token content and the slug used for the identifier."
How can this be done with the current plugin?
I thought about a custom parsing function for heading_open token, but how to get inline after?
I considering passing a custom slug_func to anchors_plugin, but it doesn't have access to the slugs param so it can not retrieve the unique_slug id for the heading.
I tried parsing first, then rendering, but the plugin maintains state and so the unique_slug ids in the token stream don't match what is rendered.
Since the admon plugin was initially ported to mdit-py-plugins
, there have been requests for improvements (supporting collapsible MKDocs-style admonitions, MKDocs content tabs, etc.)
In response, I've refactored the logic to make it more extensible and published new versions of mdformat-mkdocs
(for the mkdocs-related code) and mdformat-admon
with the extensible version of the python-markdown !!!
syntax (https://github.com/KyleKing/mdformat-admon/blob/d48ca09eb3160dbfbb2c8219319cba7e63ff8e4a/mdformat_admon/mdit_plugins/_python_markdown_admon.py)
Because there is currently duplicate implementations of the admon
logic (here and in mdformat-admon
), we should try to reduce the duplication. I think there are a couple of options:
admon
plugin from mdit-py-plugins
and point users to mdformat-admon if they want that functionality (we could have mdit-py-plugins raise an exception if someone tries to import with a better error or just remove entirely to reduce the maintenance burdenmdformat-admon
into mdit-py-plugins (the extensible factories and updated plugin) to replace what is currently hereOption 2 has the benefit of being easier to support because any issues with admonitions will be on a repo I maintain and all bug issues will go directly to me. Option 1 would be better because of backward compatibility and the usage of the the factory code without the dependency on mdformat
.
What is your preference moving forward?
No response
The admonition module supports ???
and ???+
for collapsible admonitions. This is inspired by mkdocs-material.
In this case, mdit-py-plugins generates:
<div class="admonition note is-collapsible collapsible-closed">
<div class="admonition-title"></div>
</div>
<div class="admonition note is-collapsible collapsible-open">
<div class="admonition-title"></div>
</div>
On the other hand, mkdocs-material generates:
<details class="note">
<summary></summary>
</detail>
<details class="note" open="open">
<summary></summary>
</detail>
It should be possible to generate <details>
and <summary>
using ???
and ???+
. An option should be provided to opt-in the new behavior (or bring back the current one).
???
with details
and summary
The following markdown is a valid footnote:
[^lorem]
[^lorem]:
ipsum
GitHub screenshot:
However, mdit parses it as if it was invalid becase the first line is empty.
(See executablebooks/mdformat-footnote#6).
See above.
No jupyter.
python --version
Python 3.10.5
Ubuntu 22.10
context
my code
from markdown_it import MarkdownIt
from mdit_py_plugins.front_matter import front_matter_plugin
from mdit_py_plugins.footnote import footnote_plugin
from mdit_py_plugins.texmath import texmath_plugin
md = (
MarkdownIt()
.use(front_matter_plugin)
.use(footnote_plugin)
.use(texmath_plugin)
.enable('image')
.enable('table')
)
all_the_text = open('markdown.md').read()
tokens = md.parse(all_the_text)
html_text = md.render(all_the_text)
expectation
The code is highlighted and the mathematical formula is displayed normally
I checked the output HTML, no head tag, no CSS, no JS file. Why? What do I need to do?
1.code is like this:
from markdown_it import MarkdownIt
from mdit_py_plugins.front_matter import front_matter_plugin
from mdit_py_plugins.footnote import footnote_plugin
from mdit_py_plugins.texmath import texmath_plugin
md = (
MarkdownIt()
.use(front_matter_plugin)
.use(footnote_plugin)
.use(texmath_plugin)
.enable('image')
.enable('table')
)
all_the_text = open('markdown.txt').read()
tokens = md.parse(all_the_text)
html_text = md.render(all_the_text)
No response
H~2~0
29^th^
(and integrate with myst-parser)
(also amsmath is still to be integrated, see executablebooks/MyST-NB#126 (comment))
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.