Optional html blocks in markdown#856
Conversation
…nsafe optional parameter to MarkdownHelper, add tests for various permutations, extend text.handlebars to pass through parameter
…with the rust keyword)
| pub trait MarkdownConfig { | ||
| fn allow_dangerous_html(&self) -> bool; | ||
| fn allow_dangerous_protocol(&self) -> bool; | ||
| } | ||
|
|
||
| impl MarkdownConfig for AppConfig { | ||
| fn allow_dangerous_html(&self) -> bool { | ||
| self.markdown_allow_dangerous_html | ||
| } | ||
|
|
||
| fn allow_dangerous_protocol(&self) -> bool { | ||
| self.markdown_allow_dangerous_protocol | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
I think this is overkill
There was a problem hiding this comment.
I was trying to avoid testing with a full AppConfig. Do you have a better alternative in mind?
src/template_helpers.rs
Outdated
|
|
||
| if !options.compile.allow_dangerous_html && args.len() > 1 { | ||
| let arg = &args[1]; | ||
| if arg.relative_path() == Some(&Self::ALLOW_UNSAFE.to_string()) { |
There was a problem hiding this comment.
It's strange to use the path instead of the value. This means you cannot pass a variable to your helper. We should probably read the string value of the argument here.
There was a problem hiding this comment.
This was based on my logging of what was going on with different combinations passed into the handler; I'll switch it to use the variable.
sqlpage/templates/text.handlebars
Outdated
| {{~#if contents_md~}} | ||
| <div class="remove-bottom-margin {{#if center}}mx-auto{{/if}} {{#if article}}markdown article-text{{/if}}"> | ||
| {{{~markdown contents_md~}}} | ||
| {{{~markdown contents_md allow_unsafe~}}} |
There was a problem hiding this comment.
I think the syntax should look like
| {{{~markdown contents_md allow_unsafe~}}} | |
| {{{~markdown contents_md 'allow_unsafe'~}}} |
(pass a string to the helper)
|
We don't want to take any existing safe code and make it unsafe. If we enable allow_unsafe somewhere, it should be in a new argument, with a big warning in the documentation. |
|
We should also document the new options to the markdown helper: https://sql-page.com/custom_components.sql |
OK can you elaborate a bit further on this point so that I can better understand, specifically around the implementation details? If we use a hard coded string |
|
I mean that all sqlpage code that exists today should continue to work as is in the next version. So we cannot take an existing |
Right - gotcha; thanks for the explanation +1 |
|
OK I've updated the implementation and extended the docs. Let me know what you think. |
|
@guspower , what about this: diff --git a/src/template_helpers.rs b/src/template_helpers.rs
index 7be62c9..f6590c6 100644
--- a/src/template_helpers.rs
+++ b/src/template_helpers.rs
@@ -274,8 +274,6 @@ struct MarkdownHelper {
}
impl MarkdownHelper {
- const ALLOW_UNSAFE: &'static str = "allow_unsafe";
-
fn new(config: &impl MarkdownConfig) -> Self {
Self {
allow_dangerous_html: config.allow_dangerous_html(),
@@ -283,38 +281,39 @@ impl MarkdownHelper {
}
}
- fn calculate_options(&self, args: &[PathAndJson]) -> markdown::Options {
- let mut options = self.system_options();
-
- if !options.compile.allow_dangerous_html && args.len() > 1 {
- if let Some(arg) = args.get(1) {
- if arg.value().as_str() == Some(Self::ALLOW_UNSAFE) {
- options.compile.allow_dangerous_html = true;
- }
- }
- }
-
- options
- }
-
- fn system_options(&self) -> markdown::Options {
+ fn system_options(&self, preset_name: &str) -> Result<markdown::Options, String> {
let mut options = markdown::Options::gfm();
options.compile.allow_dangerous_html = self.allow_dangerous_html;
options.compile.allow_dangerous_protocol = self.allow_dangerous_protocol;
options.compile.allow_any_img_src = true;
- options
+ match preset_name {
+ "default" => {}
+ "allow_unsafe" => {
+ options.compile.allow_dangerous_html = true;
+ options.compile.allow_dangerous_protocol = true;
+ }
+ _ => return Err(format!("unknown markdown preset: {preset_name}")),
+ }
+
+ Ok(options)
}
}
impl CanHelp for MarkdownHelper {
fn call(&self, args: &[PathAndJson]) -> Result<JsonValue, String> {
- let options = self.calculate_options(args);
- let as_str = match args {
- [v] | [v, _] => v.value(),
- _ => return Err("expected one or two arguments".to_string()),
+ let (markdown_src_value, preset_name) = match args {
+ [v] => (v.value(), "default"),
+ [v, preset] => (
+ v.value(),
+ preset
+ .value()
+ .as_str()
+ .ok_or("markdown template helper expects a string as preset name")?,
+ ),
+ _ => return Err("markdown template helper expects one or two arguments".to_string()),
};
- let as_str = match as_str {
+ let markdown_src = match markdown_src_value {
JsonValue::String(s) => Cow::Borrowed(s),
JsonValue::Array(arr) => Cow::Owned(
arr.iter()
@@ -326,7 +325,8 @@ impl CanHelp for MarkdownHelper {
other => Cow::Owned(other.to_string()),
};
- markdown::to_html_with_options(&as_str, &options)
+ let options = self.system_options(preset_name)?;
+ markdown::to_html_with_options(&markdown_src, &options)
.map(JsonValue::String)
.map_err(|e| e.to_string())
} |
|
This produces more meaningful errors when the helper is not used as expected |
|
Yep that looks good to me. My only comment would be to rename |
|
Thanks @guspower ! It's merged ! |
No description provided.