Open kartva opened 2 years ago
Currently, I've modified Zola by adding to https://github.com/getzola/zola/blob/1fbe6fbbefd192276165798c936cc62195d94116/components/rendering/src/codeblock/mod.rs#L51
html.push('>');
html.push_str("<div class=\"language-name\">");
if let Some(lang) = language {
html.push_str(lang);
}
html.push_str("</div>");
html.push_str("<code");
(Right now it just writes the language name, because I was too lazy to modify the parsing logic for code fences before this was even approved)
I thought about this exact thing yesterday. I think in practice it makes much more sense to use a shortcode though. A bit reversed so you end up with something like:
(replace '''
below by backticks, can't remember how to escape those)
{% codeblock(name="example.rs") %}
'''rs
fn recursive_query() {
}
'''
{% end %}
And the shortcode be something like
<div class="codeblock">
<span class="codeblock__name">{{name | safe }}</span>
{{ body | markdown | safe }}
</div>
It's a bit flipped around compared to your version but is way more flexible.
Ah - I had actually tried to make a shortcode and even managed to make it one that took a body. I forgot about the markdown
filter though...
Oh, and it still fails if there's a shortcode inside. That's probably related to #1350. Maybe I should write a patch for that.
{% link_code_file(src="code/segtree/src/segtree.rs") %}
```rust,linenos,hide_lines=1-38 69-102
{{ load_file(path="content/competitive-programming/dsa-explanations/intermediate-segment-tree/code/segtree/src/segtree.rs") }}
{% end %}
Error: Failed to render content of content/competitive-programming/dsa-explanations/intermediate-segment-tree/index.md Reason: Failed to render link_code_file shortcode Reason: Failed to render 'shortcodes/link_code_file.html' Reason: Filter call 'markdown' failed Reason: Failed to render markdown filter: Error { kind: Msg("Failed to render load_file shortcode"), source: Some(Error { kind: Tera(Error { kind: Msg("Failed to render 'shortcodes/load_file.html'"), source: Some(Error { kind: FunctionNotFound("load_data"), source: None }) }), source: None }) }
(btw. even I had to search how to escape the backticks - you can use more backticks at the start and the end - like 4 or 5 - if other backtick sequences are smaller)
Oh - #1350 seems to have been fixed. Instead, what Zola's having a problem with is shortcode nesting?
Nested shortcodes are not currently supported
Hmm, Zola does parse the shortcode body and currently remarks that load_data
is not a function. load_data
is an inbuilt shortcode, right?
I still think that codeblock naming is a common enough feature that it might be worth explicitly supporting, especially since we otherwise quickly run into situations where the shortcode has limited usefulness (i.e. I can't load a file into a codeblock that is enclosed by a shortcode)
What's your take on the issue?
In that specific case of using the markdown filter, it should work it's just that we don't currently add any of the Tera functions to it. It might be possible to add that easily though, i'll have a look.
If you can try the next
branch, load_data
should now be working in your example.
I still think that codeblock naming is a common enough feature that it might be worth explicitly supporting,
The issue with that is that it would enforce a specific HTML structure, which is something I'm trying to avoid.
If you can try the next branch, load_data should now be working in your example.
Just tested - still no luck.
It certainly does get farther in the call stack, but it still can't find the inbuilt load_data
referenced in shortcodes/load_file.html
which the markdown
filter tries to render.
Failed to build the site
Error: Failed to render content of /home/desmond-lin-7/blog/content/competitive-programming/dsa-explanations/intermediate-segment-tree/index.md
Reason: Failed to render link_code_file shortcode
Reason: Failed to render 'shortcodes/link_code_file.html'
Reason: Filter call 'markdown' failed
Reason: Failed to render markdown filter: Error { kind: Msg("Failed to render load_file shortcode"), source: Some(Error { kind: Tera(Error { kind: Msg("Failed to render 'shortcodes/load_file.html'"), source: Some(Error { kind: FunctionNotFound("load_data"), source: None }) }), source: None }) }
The issue with that is that it would enforce a specific HTML structure, which is something I'm trying to avoid.
Thanks, that makes sense.
Ah I see what's happening there. The markdown renderer thinks the load_file
is a shortcode (I'm assuming you mean load_data
?) but doesn't find it. You cannot use Zola functions in the Markdown content. You can use them in the shortcodes but it's not going to be great to do for code blocks since we don't have set
blocks.
Would you happen to know why inserting a dbg!(&self.tera)
after https://github.com/getzola/zola/blob/1fbe6fbbefd192276165798c936cc62195d94116/components/site/src/lib.rs#L285
only prints:
[components/site/src/lib.rs:286] &self.tera = Tera {
templates: [
macros/head.html,
__zola_builtins/404.html,
shortcodes/link_code_file.html,
...
__zola_builtins/shortcodes/youtube.html,
__zola_builtins/split_sitemap_index.xml,
]
filters: [
trim_start,
slugify,
json_encode,
get,
...
group_by,
concat,
trim_end,
round,
]
testers: [
iterable,
string,
...
containing,
matching,
]
}
without any mention of the functions, or other fields in the Tera
struct? Site
derives Debug
, so it should all be standard formatting...
For reference, the Tera
struct has these fields:
#[derive(Clone)]
pub struct Tera {
// The glob used in `Tera::new`, None if Tera was instantiated differently
#[doc(hidden)]
glob: Option<String>,
#[doc(hidden)]
pub templates: HashMap<String, Template>,
#[doc(hidden)]
pub filters: HashMap<String, Arc<dyn Filter>>,
#[doc(hidden)]
pub testers: HashMap<String, Arc<dyn Test>>,
#[doc(hidden)]
pub functions: HashMap<String, Arc<dyn Function>>,
// Which extensions does Tera automatically autoescape on.
// Defaults to [".html", ".htm", ".xml"]
#[doc(hidden)]
pub autoescape_suffixes: Vec<&'static str>,
#[doc(hidden)]
escape_fn: EscapeFn,
}
```rust,linenos,hide_lines=1-38 69-102
{{ load_data(path="content/competitive-programming/dsa-explanations/intermediate-segment-tree/code/segtree/src/segtree.rs") }}
This snippet does not work as is, both on the current version and `next` branch. Fails with the error:
Error: Failed to render content of /home/desmond-lin-7/blog/content/competitive-programming/dsa-explanations/intermediate-segment-tree/index.md
Reason: Found usage of a shortcode named load_data
but we do not know about. Make sure it's not a typo and that a field name load_data.{html,md} exists in the
templates/shortcodes` directory.
What I do instead is write a wrapper shortcode around the `load_data` function called `load_file`:
{{ load_data(path=path) | safe }}
and then call _that_ in the codeblock.
{{ load_file(path="content/competitive-programming/dsa-explanations/intermediate-segment-tree/code/segtree/src/segtree.rs") }}
which works.
Ok, so I figured out a non-Zola method to do this using CSS:
pre code[data-lang]::before {
content: attr(data-lang);
color: white;
}
Just reopening to figure out what's happening with the load_data fn
It might be worth filing a separate bug/feature request for investigating the issue as a part of enabling calling Zola builtin functions inside shortcodes.
pre code[data-lang][data-linenos]::before {
content: attr(data-lang);
color: white;
}
The above pattern has turned out to be immensely useful.
How about revising the proposal to instead have
```rust,name="Shell code"
generate the following:
````html
<pre data-linenos="" data-lang="rust" data-title="Shell code" class="language-rust z-code">
<code class="language-rust" data-lang="rust">...</code>
</pre>
so it doesn't impose any custom HTML beyond what is already in use?
I created this shortcode, which can be used like this:
{% code(lang="rust", file="<filename>" %}
…
{% end %}
Maybe this'll help
I think adding the name to the data attr wouldn't be controversial. I'm just wondering if you can do everything style wise with ::before
It's certainly better than what one could do before. ::before
is somewhat limited in terms of what you can put there (strings, attributes of the element it's defined on, images and CSS counters), but it's certainly better than nothing. Since other information (data-lang
) is already defined this way and seems to work for most people, it shouldn't be too bad.
Though it is bad for accessibility.
(Take that with a pinch of salt: I actually discovered the ::before
trick from someone's blog, I don't have any substantial frontend experience)
@bemyak That looks great, and can expand to accommodate all sorts of custom HTML structures, like codeblock names, etc. I hadn't even thought of trying to construct the codeblock as a string and then render it.
Now if only there was a handy snippet for indenting and deindenting the loaded text...
Thanks for this, I used a variation of it:
pre code[data-lang]::before {
content: attr(data-lang) ': ' "
";
color: var(--a1);
}
This is the result: https://abridge.netlify.app/overview-code-blocks/
or here's a picture:
to indent it:
pre code[data-lang]::before {
content: ' ' attr(data-lang) ': ' "
";
color: var(--a1);
}
I implemented a code block copy button, not only does this not interfere, it makes sure a long line of text does not end up under the copy button:
I had another thought about this. Currently my site has a copy button for ALL code blocks. Then I got to thinking... what about the blocks where I do not want to display a code copy button....
I am thinking the best way to resolve this might be to have a way to apply a custom class to some but not all code blocks, this could be used to either apply or not apply a code copy button. Currently the script I am using applies it to all <pre>
tags but I could probably modify this to exclude ones that either have or don't have a specific class... will require some more testing.
Add some more custom syntax to the codeblock to allow for codeblock naming.
By writing