Skip to content

Commit b7b1b21

Browse files
authored
Add markdown rendering options to the sqlpage configuration (#823)
* Add markdown rendering options to the sqlpage configuration * fmt * silence clippy * revert changes to conf * docs * fmt
1 parent e75fc22 commit b7b1b21

File tree

6 files changed

+66
-18
lines changed

6 files changed

+66
-18
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# CHANGELOG.md
22

3+
## 0.34.0 (unreleased)
4+
5+
- New configuration options:
6+
- `markdown_allow_dangerous_html`: allow the usage of html in markdown (default: false)
7+
- `markdown_allow_dangerous_protocol`: allow the usage of custom protocols in markdown (default: false)
8+
- see [configuration.md](./configuration.md) for more details.
9+
310
## 0.33.1 (2025-02-25)
411

512
- Fix a bug where the table component would not format numbers if sorting was not enabled.

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "sqlpage"
3-
version = "0.33.1"
3+
version = "0.34.0"
44
edition = "2021"
55
description = "Build data user interfaces entirely in SQL. A web server that takes .sql files and formats the query result using pre-made configurable professional-looking components."
66
keywords = ["web", "sql", "framework"]

configuration.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ Here are the available configuration options and their default values:
3434
| `content_security_policy` | `script-src 'self' 'nonce-XXX` | The [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) to set in the HTTP headers. If you get CSP errors in the browser console, you can set this to the empty string to disable CSP. |
3535
| `system_root_ca_certificates` | false | Whether to use the system root CA certificates to validate SSL certificates when making http requests with `sqlpage.fetch`. If set to false, SQLPage will use its own set of root CA certificates. If the `SSL_CERT_FILE` or `SSL_CERT_DIR` environment variables are set, they will be used instead of the system root CA certificates. |
3636
| `max_recursion_depth` | 10 | Maximum depth of recursion allowed in the `run_sql` function. Maximum value is 255. |
37+
| `markdown_allow_dangerous_html` | false | Whether to allow raw HTML in markdown content. Only enable this if the markdown content is fully trusted (not user generated). |
38+
| `markdown_allow_dangerous_protocol` | false | Whether to allow dangerous protocols (like javascript:) in markdown links. Only enable this if the markdown content is fully trusted (not user generated). |
3739

3840
Multiple configuration file formats are supported:
3941
you can use a [`.json5`](https://json5.org/) file, a [`.toml`](https://toml.io/) file, or a [`.yaml`](https://en.wikipedia.org/wiki/YAML#Syntax) file.

src/app_config.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ pub fn load_from_env() -> anyhow::Result<AppConfig> {
143143
}
144144

145145
#[derive(Debug, Deserialize, PartialEq, Clone)]
146+
#[allow(clippy::struct_excessive_bools)]
146147
pub struct AppConfig {
147148
#[serde(default = "default_database_url")]
148149
pub database_url: String,
@@ -248,6 +249,12 @@ pub struct AppConfig {
248249
/// Maximum depth of recursion allowed in the `run_sql` function.
249250
#[serde(default = "default_max_recursion_depth")]
250251
pub max_recursion_depth: u8,
252+
253+
#[serde(default = "default_markdown_allow_dangerous_html")]
254+
pub markdown_allow_dangerous_html: bool,
255+
256+
#[serde(default = "default_markdown_allow_dangerous_protocol")]
257+
pub markdown_allow_dangerous_protocol: bool,
251258
}
252259

253260
impl AppConfig {
@@ -506,6 +513,14 @@ fn default_max_recursion_depth() -> u8 {
506513
10
507514
}
508515

516+
fn default_markdown_allow_dangerous_html() -> bool {
517+
false
518+
}
519+
520+
fn default_markdown_allow_dangerous_protocol() -> bool {
521+
false
522+
}
523+
509524
#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy, Eq, Default)]
510525
#[serde(rename_all = "lowercase")]
511526
pub enum DevOrProd {

src/template_helpers.rs

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ pub fn register_all_helpers(h: &mut Handlebars<'_>, config: &AppConfig) {
6363

6464
// icon helper: generate an image with the specified icon
6565
h.register_helper("icon_img", Box::new(IconImgHelper(site_prefix)));
66-
register_helper(h, "markdown", markdown_helper as EH);
66+
register_helper(h, "markdown", MarkdownHelper::new(config));
6767
register_helper(h, "buildinfo", buildinfo_helper as EH);
6868
register_helper(h, "typeof", typeof_helper as H);
6969
register_helper(h, "rfc2822_date", rfc2822_date_helper as EH);
@@ -247,21 +247,45 @@ fn typeof_helper(v: &JsonValue) -> JsonValue {
247247
.into()
248248
}
249249

250-
fn markdown_helper(x: &JsonValue) -> anyhow::Result<JsonValue> {
251-
let as_str = match x {
252-
JsonValue::String(s) => Cow::Borrowed(s),
253-
JsonValue::Array(arr) => Cow::Owned(
254-
arr.iter()
255-
.map(|v| v.as_str().unwrap_or_default())
256-
.collect::<Vec<_>>()
257-
.join("\n"),
258-
),
259-
JsonValue::Null => Cow::Owned(String::new()),
260-
other => Cow::Owned(other.to_string()),
261-
};
262-
markdown::to_html_with_options(&as_str, &markdown::Options::gfm())
263-
.map(JsonValue::String)
264-
.map_err(|e| anyhow::anyhow!("markdown error: {e}"))
250+
/// Helper to render markdown with configurable options
251+
struct MarkdownHelper {
252+
allow_dangerous_html: bool,
253+
allow_dangerous_protocol: bool,
254+
}
255+
256+
impl MarkdownHelper {
257+
fn new(config: &AppConfig) -> Self {
258+
Self {
259+
allow_dangerous_html: config.markdown_allow_dangerous_html,
260+
allow_dangerous_protocol: config.markdown_allow_dangerous_protocol,
261+
}
262+
}
263+
}
264+
265+
impl CanHelp for MarkdownHelper {
266+
fn call(&self, args: &[PathAndJson]) -> Result<JsonValue, String> {
267+
let as_str = match args {
268+
[v] => v.value(),
269+
_ => return Err("expected one argument".to_string()),
270+
};
271+
let as_str = match as_str {
272+
JsonValue::String(s) => Cow::Borrowed(s),
273+
JsonValue::Array(arr) => Cow::Owned(
274+
arr.iter()
275+
.map(|v| v.as_str().unwrap_or_default())
276+
.collect::<Vec<_>>()
277+
.join("\n"),
278+
),
279+
JsonValue::Null => Cow::Owned(String::new()),
280+
other => Cow::Owned(other.to_string()),
281+
};
282+
let mut options = markdown::Options::gfm();
283+
options.compile.allow_dangerous_html = self.allow_dangerous_html;
284+
options.compile.allow_dangerous_protocol = self.allow_dangerous_protocol;
285+
markdown::to_html_with_options(&as_str, &options)
286+
.map(JsonValue::String)
287+
.map_err(|e| e.to_string())
288+
}
265289
}
266290

267291
fn buildinfo_helper(x: &JsonValue) -> anyhow::Result<JsonValue> {

0 commit comments

Comments
 (0)