-
-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
{% markdown %} ... {% endmarkdown %}
template tag
#14
Comments
It's a bit hard finding examples of custom tags like this. The best I found was actually another Markdown one: https://github.com/jpsca/jinja-markdown/blob/main/jinja_markdown/__init__.py Markdown is also used as the example in this tutorial: https://ron.sh/how-to-write-a-jinja2-extension/ https://github.com/jinrudals/jinja2_script/blob/main/jinja_script_block/__init__.py is good too. |
Neither of those Markdown ones are quite what I want though - I would like to be able to pass custom arguments to it, as seen here: {{ render_markdown("""
## Markdown table
First Header | Second Header
------------- | -------------
Content Cell | Content Cell
Content Cell | Content Cell
""", extensions=["tables"],
extra_tags=["table", "thead", "tr", "th", "td", "tbody"])) }} I want it to work like this: {% markdown extensions='["tables"]' extra_tags='["table", "thead", "tr", "th", "td", "tbody"]' %}
## Markdown table
First Header | Second Header
------------- | -------------
Content Cell | Content Cell
Content Cell | Content Cell
{% endmarkdown %} I'm using JSON objects in single quotes here, I think that's probably the easiest option. Or I could do this: {% markdown extensions="tables" extra_tags="table thead tr th td tbody" %} And then split on spaces. But that's harder for the other option, extra_attrs={"a": ["name", "href"]} I could keep that as JSON, or I could invite syntax for it: {% markdown extra_attrs="a:name,href span:id,class" %} I quite like that invented syntax, actually. |
Parsing attributes in custom Markdown tags turns out to be pretty hard! I figured this out, eventually: def parse(self, parser):
lineno = next(parser.stream).lineno
# Gather tokens up to the next block_end ('%}')
gathered = []
while parser.stream.current.type != "block_end":
gathered.append(next(parser.stream))
# If all has gone well, we will have a sequence of triples of tokens:
# (type='name, value='attribute name'),
# (type='assign', value='='),
# (type='string', value='attribute value')
# Anything else is a parse error
if len(gathered) % 3 != 0:
raise TemplateSyntaxError("Invalid syntax for markdown tag", lineno)
attrs = {}
for i in range(0, len(gathered), 3):
if (
gathered[i].type != "name"
or gathered[i + 1].type != "assign"
or gathered[i + 2].type != "string"
):
raise TemplateSyntaxError(
(
"Invalid syntax for markdown attribute - got "
"'{}', should be name=\"value\"".format(
"".join([str(t.value) for t in gathered[i : i + 3]]),
)
),
lineno,
)
attrs[gathered[i].value] = gathered[i + 2].value
body = parser.parse_statements(["name:endmarkdown"], drop_needle=True)
return nodes.CallBlock(
self.call_method("_render_markdown", []), [], [], body
).set_lineno(lineno) |
I used ChatGPT to help get me to this point. The code it wrote was almost entirely broken, but it gave me enough hints that I could figure out how to build a non-broken version https://chat.openai.com/share/ff041b92-992d-40f0-b411-42a49ff0b3e3 |
I got the JSON attributes version working. I'm going to check that in with tests, then maybe do the non-JSON syntax alternative. |
datasette-render-markdown/datasette_render_markdown/__init__.py Lines 101 to 158 in 3055c91
|
I had to do |
Just needs documentation now and I can release it. |
Wrote a TIL about this: https://til.simonwillison.net/jinja/custom-jinja-tags-with-attributes |
While using
render_template()
for pages in https://datasette.io/tutorials I kept running into this annoyance:This raises an error - the double quotes need to be
\"
escaped.If you switch to
'''
then you need to use\'
for the single quotes instead.After some exploration, it looks like the solution is to implement this:
The text was updated successfully, but these errors were encountered: