Add live preview for edits (fixes #54)

This commit is contained in:
Felix Ableitner 2024-10-15 12:43:31 +02:00
parent d352a33c7a
commit 0b5b60fc9c
3 changed files with 32 additions and 20 deletions

View File

@ -6,8 +6,14 @@ use markdown_it::{
NodeValue, NodeValue,
Renderer, Renderer,
}; };
use once_cell::sync::OnceCell;
pub fn markdown_parser() -> MarkdownIt { pub fn render_markdown(text: &str) -> String {
static INSTANCE: OnceCell<MarkdownIt> = OnceCell::new();
INSTANCE.get_or_init(markdown_parser).parse(text).render()
}
fn markdown_parser() -> MarkdownIt {
let mut parser = MarkdownIt::new(); let mut parser = MarkdownIt::new();
markdown_it::plugins::cmark::add(&mut parser); markdown_it::plugins::cmark::add(&mut parser);
markdown_it::plugins::extra::linkify::add(&mut parser); markdown_it::plugins::extra::linkify::add(&mut parser);

View File

@ -4,6 +4,7 @@ use crate::{
app::GlobalState, app::GlobalState,
article_title, article_title,
components::article_nav::ArticleNav, components::article_nav::ArticleNav,
markdown::render_markdown,
pages::article_resource, pages::article_resource,
}, },
}; };
@ -46,6 +47,8 @@ pub fn EditArticle() -> impl IntoView {
let (text, set_text) = create_signal(String::new()); let (text, set_text) = create_signal(String::new());
let (summary, set_summary) = create_signal(String::new()); let (summary, set_summary) = create_signal(String::new());
let (show_preview, set_show_preview) = create_signal(false);
let (preview, set_preview) = create_signal(String::new());
let (wait_for_response, set_wait_for_response) = create_signal(false); let (wait_for_response, set_wait_for_response) = create_signal(false);
let button_is_disabled = let button_is_disabled =
Signal::derive(move || wait_for_response.get() || summary.get().is_empty()); Signal::derive(move || wait_for_response.get() || summary.get().is_empty());
@ -117,6 +120,7 @@ pub fn EditArticle() -> impl IntoView {
set_summary.set(conflict.summary); set_summary.set(conflict.summary);
} }
set_text.set(article.article.text.clone()); set_text.set(article.article.text.clone());
set_preview.set(render_markdown(&article.article.text));
let article_ = article.clone(); let article_ = article.clone();
let rows = article.article.text.lines().count() + 1; let rows = article.article.text.lines().count() + 1;
view! { view! {
@ -136,11 +140,18 @@ pub fn EditArticle() -> impl IntoView {
rows=rows rows=rows
on:keyup=move |ev| { on:keyup=move |ev| {
let val = event_target_value(&ev); let val = event_target_value(&ev);
set_text.update(|p| *p = val); set_preview.set(render_markdown(&val));
set_text.set(val);
} }
> >
{article.article.text.clone()} {article.article.text.clone()}
</textarea> </textarea>
<button on:click=move |_| {
set_show_preview.update(|s| *s = !*s)
}>Preview</button>
<Show when=move || { show_preview.get() }>
<div id="preview" inner_html=move || preview.get()></div>
</Show>
<div> <div>
<a href="https://commonmark.org/help/" target="blank_"> <a href="https://commonmark.org/help/" target="blank_">
Markdown Markdown

View File

@ -1,7 +1,7 @@
use crate::frontend::{ use crate::frontend::{
article_title, article_title,
components::article_nav::ArticleNav, components::article_nav::ArticleNav,
markdown::markdown_parser, markdown::render_markdown,
pages::article_resource, pages::article_resource,
}; };
use leptos::*; use leptos::*;
@ -16,23 +16,18 @@ pub fn ReadArticle() -> impl IntoView {
view! { "Loading..." } view! { "Loading..." }
}> }>
{ {move || {
let parser = markdown_parser();
move || {
article article
.get() .get()
.map(|article| { .map(|article| {
view! { view! {
<div class="item-view"> <div class="item-view">
<h1>{article_title(&article.article)}</h1> <h1>{article_title(&article.article)}</h1>
<div inner_html=parser <div inner_html=render_markdown(&article.article.text)></div>
.parse(&article.article.text)
.render()></div>
</div> </div>
} }
}) })
} }}
}
</Suspense> </Suspense>
} }