femark
femark copied to clipboard
process_markdown_to_html causes tokio-runtime-worker to panic
Describe the bug
I am using femark to render html in my leptos blog. femark::process_markdown_to_html causes tokio-runtime-worker to panic IF there are code block(s) in the input. I'm sorry if it's inappropriate to open an issue here but I have been looking at your leptos blog for reference and this issue seems specific enough, sorry for any inconvenience.
Leptos Dependencies
leptos = { version = "0.7.0-rc1", features = ["nightly"] }
leptos_meta = { version = "0.7.0-rc1" }
leptos_router = { version = "0.7.0-rc1" }
leptos_axum = { version = "0.7.0-rc1" }
axum = { version = "0.7", features = ["macros"] }
femark = "0.1.6"
sqlx = { version = "0.8", features = [
"runtime-tokio-rustls",
"macros",
"postgres",
"chrono",
] }
To Reproduce
- Struct definitions:
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct BlogPost {
pub id: i64,
pub title: String,
pub description: String,
pub hero_image: String,
pub content: String,
pub published_at: String,
pub slug: String,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub categories: Vec<Category>,
}
cfg_if! {
if #[cfg(feature = "ssr")] {
use femark::HTMLOutput;
use chrono::{DateTime, Local};
#[derive(sqlx::FromRow, sqlx::Type)]
pub struct SqlPost{
pub id: i64,
pub title: String,
pub description: String,
pub hero_image: String,
pub content: String,
pub published_at: DateTime<Local>,
pub slug: String,
pub categories: Vec<Category>,
}
impl SqlPost {
pub fn into_post(self) -> BlogPost {
// This should pull the markdown content directly from the database
let HTMLOutput{content,..} = femark::process_markdown_to_html(
r#"```Rust
move || {
async move {
match post.await {
Ok(Ok(Some(post))) => EitherOf4::A(view! { <Post post={post}/> }),
Ok(Ok(None)) => EitherOf4::B(view! { <p>"Post Not Found"</p> }),
Ok(Err(_)) => EitherOf4::C(view! { <p>"Server Error"</p> }),
Err(_) => EitherOf4::D(view! { <p>"Server Fn Error"</p> }),
}
}
.suspend()
.transition()
.with_fallback(view! { <p>"Loading..."</p> })
.track()
}
```"#
).unwrap_or_default();
BlogPost {
id: self.id,
title: self.title,
description: self.description,
hero_image: self.hero_image,
published_at: self.published_at.format("%d/%m/%Y").to_string(),
content,
slug: self.slug,
categories: self.categories,
}
}
}
}
}
- Fetching data
#[server(GetBlogPost)]
pub async fn get_blog_post(slug: String) -> Result<BlogPost, ServerFnError> {
use crate::state::AppState;
let state = expect_context::<AppState>();
state.db.get_post_by_slug(&slug)
.await
.map_err(|e| ServerFnError::ServerError(e.to_string()))
}
#[component]
pub fn BlogPost() -> impl IntoView {
let params = use_params_map();
let slug = move || params.with(|params| params.get("slug").unwrap_or_default());
let post = Resource::new(slug, get_blog_post);
view! {...
- Logs:
2024-11-18T22:53:23.426Z DEBUG [femark::parser] Got markdown event ev=Start(CodeBlock(Fenced(Borrowed("Rust"))))
2024-11-18T22:53:23.426Z DEBUG [femark::parser] Got markdown event ev=Text(Borrowed(" move || {\n async move {\n match post.await {\n Ok(Ok(Some(post))) => EitherOf4::A(view! { <Post post={post}/> }),\n Ok(Ok(None)) => EitherOf4::B(view! { <p>\"Post Not Found\"</p> }),\n Ok(Err(_)) => EitherOf4::C(view! { <p>\"Server Error\"</p> }),\n Err(_) => EitherOf4::D(view! { <p>\"Server Fn Error\"</p> }),\n }\n }\n .suspend()\n .transition()\n .with_fallback(view! { <p>\"Loading...\"</p> })\n .track()\n }\n ```"))
2024-11-18T22:53:23.426Z DEBUG [femark::parser] Got markdown event ev=End(CodeBlock(Fenced(Borrowed("Rust"))))
thread 'tokio-runtime-worker' panicked at C:\Users\KhanhTIMN\.cargo\registry\src\index.crates.io-6f17d22bba15001f\femark-0.1.6\src\tree_sitter_collection.rs:31:10:
called `Result::unwrap()` on an `Err` value: QueryError { row: 42, column: 3, offset: 1172, message: "function_expression", kind: NodeType }
stack backtrace:
0: std::panicking::begin_panic_handler
at /rustc/bc5cf994db9fb46712cefd89f78ad7fc51f184a2\library/std\src\panicking.rs:665
1: core::panicking::panic_fmt
at /rustc/bc5cf994db9fb46712cefd89f78ad7fc51f184a2\library/core\src\panicking.rs:75
2: core::result::unwrap_failed
at /rustc/bc5cf994db9fb46712cefd89f78ad7fc51f184a2\library/core\src\result.rs:1698
3: enum2$<core::result::Result<tree_sitter_highlight::HighlightConfiguration,tree_sitter::QueryError> >::unwrap
at C:\Users\KhanhTIMN\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\result.rs:1103
4: femark::tree_sitter_collection::TreeSitterCollection::typescript
at C:\Users\KhanhTIMN\.cargo\registry\src\index.crates.io-6f17d22bba15001f\femark-0.1.6\src\tree_sitter_collection.rs:25
5: femark::langs::Langs::new
at C:\Users\KhanhTIMN\.cargo\registry\src\index.crates.io-6f17d22bba15001f\femark-0.1.6\src\langs.rs:116
6: femark::langs::LANGS::closure$0
at C:\Users\KhanhTIMN\.cargo\registry\src\index.crates.io-6f17d22bba15001f\femark-0.1.6\src\langs.rs:8
7: core::ops::function::FnOnce::call_once<femark::langs::LANGS::closure_env$0,tuple$<> >
at C:\Users\KhanhTIMN\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\ops\function.rs:250
8: core::ops::function::FnOnce::call_once<femark::langs::Langs (*)(),tuple$<> >
at C:\Users\KhanhTIMN\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\ops\function.rs:250
9: once_cell::sync::impl$11::force::closure$0<femark::langs::Langs,femark::langs::Langs (*)()>
at C:\Users\KhanhTIMN\.cargo\registry\src\index.crates.io-6f17d22bba15001f\once_cell-1.20.2\src\lib.rs:1310
10: once_cell::sync::impl$6::get_or_init::closure$0<femark::langs::Langs,once_cell::sync::impl$11::force::closure_env$0<femark::langs::Langs,femark::langs::Langs (*)()> >
at C:\Users\KhanhTIMN\.cargo\registry\src\index.crates.io-6f17d22bba15001f\once_cell-1.20.2\src\lib.rs:1120
11: once_cell::imp::impl$4::initialize::closure$0<femark::langs::Langs,once_cell::sync::impl$6::get_or_init::closure_env$0<femark::langs::Langs,once_cell::sync::impl$11::force::closure_env$0<femark::langs::Langs,femark::langs::Langs (*)()> >,enum2$<once_cell::
at C:\Users\KhanhTIMN\.cargo\registry\src\index.crates.io-6f17d22bba15001f\once_cell-1.20.2\src\imp_std.rs:72
12: core::ops::function::impls::impl$3::call_mut<tuple$<>,dyn$<core::ops::function::FnMut<tuple$<>,assoc$<Output,bool> > > >
at C:\Users\KhanhTIMN\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\ops\function.rs:294
13: once_cell::imp::initialize_or_wait
at C:\Users\KhanhTIMN\.cargo\registry\src\index.crates.io-6f17d22bba15001f\once_cell-1.20.2\src\imp_std.rs:196
14: once_cell::imp::OnceCell<femark::langs::Langs>::initialize<femark::langs::Langs,once_cell::sync::impl$6::get_or_init::closure_env$0<femark::langs::Langs,once_cell::sync::impl$11::force::closure_env$0<femark::langs::Langs,femark::langs::Langs (*)()> >,enum2
at C:\Users\KhanhTIMN\.cargo\registry\src\index.crates.io-6f17d22bba15001f\once_cell-1.20.2\src\imp_std.rs:68
15: once_cell::sync::OnceCell<femark::langs::Langs>::get_or_try_init<femark::langs::Langs,once_cell::sync::impl$6::get_or_init::closure_env$0<femark::langs::Langs,once_cell::sync::impl$11::force::closure_env$0<femark::langs::Langs,femark::langs::Langs (*)()> >
at C:\Users\KhanhTIMN\.cargo\registry\src\index.crates.io-6f17d22bba15001f\once_cell-1.20.2\src\lib.rs:1161
16: once_cell::sync::OnceCell<femark::langs::Langs>::get_or_init<femark::langs::Langs,once_cell::sync::impl$11::force::closure_env$0<femark::langs::Langs,femark::langs::Langs (*)()> >
at C:\Users\KhanhTIMN\.cargo\registry\src\index.crates.io-6f17d22bba15001f\once_cell-1.20.2\src\lib.rs:1120
17: once_cell::sync::Lazy<femark::langs::Langs,femark::langs::Langs (*)()>::force<femark::langs::Langs,femark::langs::Langs (*)()>
at C:\Users\KhanhTIMN\.cargo\registry\src\index.crates.io-6f17d22bba15001f\once_cell-1.20.2\src\lib.rs:1309
18: once_cell::sync::impl$12::deref<femark::langs::Langs,femark::langs::Langs (*)()>
at C:\Users\KhanhTIMN\.cargo\registry\src\index.crates.io-6f17d22bba15001f\once_cell-1.20.2\src\lib.rs:1376
19: femark::parser::process_stream::closure$0<pulldown_cmark::parse::Parser>
at C:\Users\KhanhTIMN\.cargo\registry\src\index.crates.io-6f17d22bba15001f\femark-0.1.6\src\parser.rs:136
20: core::ops::function::impls::impl$4::call_once<tuple$<enum2$<pulldown_cmark::Event> >,femark::parser::process_stream::closure_env$0<pulldown_cmark::parse::Parser> >
at C:\Users\KhanhTIMN\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\ops\function.rs:305
21: enum2$<core::option::Option<enum2$<pulldown_cmark::Event> > >::map
at C:\Users\KhanhTIMN\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\option.rs:1112
22: core::iter::adapters::map::impl$2::next<enum2$<pulldown_cmark::Event>,pulldown_cmark::parse::Parser,femark::parser::process_stream::closure_env$0<pulldown_cmark::parse::Parser> >
at C:\Users\KhanhTIMN\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\iter\adapters\map.rs:107
23: pulldown_cmark::html::HtmlWriter<core::iter::adapters::map::Map<pulldown_cmark::parse::Parser,femark::parser::process_stream::closure_env$0<pulldown_cmark::parse::Parser> >,pulldown_cmark::escape::WriteWrapper<std::io::cursor::Cursor<ref_mut$<alloc::vec::V
at C:\Users\KhanhTIMN\.cargo\registry\src\index.crates.io-6f17d22bba15001f\pulldown-cmark-0.9.6\src\html.rs:87
24: pulldown_cmark::html::write_html<core::iter::adapters::map::Map<pulldown_cmark::parse::Parser,femark::parser::process_stream::closure_env$0<pulldown_cmark::parse::Parser> >,std::io::cursor::Cursor<ref_mut$<alloc::vec::Vec<u8,alloc::alloc::Global> > > >
at C:\Users\KhanhTIMN\.cargo\registry\src\index.crates.io-6f17d22bba15001f\pulldown-cmark-0.9.6\src\html.rs:477
25: femark::parser::process_stream<pulldown_cmark::parse::Parser>
at C:\Users\KhanhTIMN\.cargo\registry\src\index.crates.io-6f17d22bba15001f\femark-0.1.6\src\parser.rs:218
26: femark::process_markdown_to_html_with_frontmatter
at C:\Users\KhanhTIMN\.cargo\registry\src\index.crates.io-6f17d22bba15001f\femark-0.1.6\src\lib.rs:50
27: femark::process_markdown_to_html
at C:\Users\KhanhTIMN\.cargo\registry\src\index.crates.io-6f17d22bba15001f\femark-0.1.6\src\lib.rs:24
28: app::models::post::SqlPost::into_post
at .\app\src\models\post.rs:38
...
Expected behavior Code block should render without panicking the server.
Additional context Any other inputs are processed correctly and return the correct html. I'm not really sure if this has to do with leptos's server function or my implementation with sqlx though.