diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 9df20b0..9229b59 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -149,4 +149,4 @@ jobs: run: | ssh -i ${{ secrets.SSH_PRIVATE_KEY_PATH }}/${{ secrets.SSH_PRIVATE_KEY_NAME }} ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} "\ cd ${{ secrets.DEVBLOG_ROOT_PATH }} && \ - docker-compose up -d --force-recreate" + docker compose up -d --force-recreate" diff --git a/client/Cargo.lock b/client/Cargo.lock index 124335e..5adaca1 100644 --- a/client/Cargo.lock +++ b/client/Cargo.lock @@ -17,6 +17,15 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + [[package]] name = "android-tzdata" version = "0.1.1" @@ -129,6 +138,7 @@ dependencies = [ "chrono", "gloo 0.11.0", "gloo-net 0.5.0", + "regex", "serde", "serde_json", "stylist", @@ -1100,6 +1110,35 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "regex" +version = "1.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + [[package]] name = "route-recognizer" version = "0.3.1" diff --git a/client/Cargo.toml b/client/Cargo.toml index beb0117..f457bfd 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -9,6 +9,7 @@ edition = "2021" chrono = { version = "0.4.33", features = ["serde"] } gloo = "0.11.0" gloo-net = "0.5.0" +regex = "1.10.5" serde = "1.0.196" serde_json = "1.0.113" stylist = { version = "0.13.0", features = ["yew", "parser"] } diff --git a/client/src/components/markdown.rs b/client/src/components/markdown.rs index 8c76e2b..0de8ade 100644 --- a/client/src/components/markdown.rs +++ b/client/src/components/markdown.rs @@ -1,4 +1,4 @@ -use stylist::Style; +use regex::Regex; use yew::{function_component, html, Html, Properties}; #[derive(Properties, PartialEq, Clone)] @@ -6,32 +6,54 @@ pub struct Props { pub content: String, } -const STYLE: &str = include_str!("styles/markdown.css"); - #[function_component(Markdown)] pub fn markdown(props: &Props) -> Html { - let style = Style::new(STYLE).unwrap(); - - let html = props.content.lines().map(|line| match line { - l if l.starts_with("# ") => html! {

{&l[1..]}

}, - l if l.starts_with("## ") => html! {

{&l[2..]}

}, - l if l.starts_with("### ") => html! {

{&l[3..]}

}, - l if l.starts_with("#### ") => html! {

{&l[4..]}

}, - l if l.starts_with("```") => { - html! {

{line.replace("```", "")}

} + let link_regex = Regex::new(r"\[([^\]]+)\]\((https?://[^\)]+)\)").unwrap(); + + let html = props.content.lines().map(|line| { + // replace markdown links with anchor tags + // eg: [thedevblog](https://thedevblog.net) -> thedevblog + let mut line_html = vec![]; + let mut last_pos = 0; + for chars in link_regex.captures_iter(line) { + let mat = chars.get(0).unwrap(); + let before_match = &line[last_pos..mat.start()]; + let link_text = &chars[1]; + let link_url = &chars[2]; + + if !before_match.is_empty() { + line_html.push(html! {<>{before_match}}); + } + + line_html.push(html! {{link_text}}); + last_pos = mat.end(); + } + + if last_pos < line.len() { + line_html.push(html! {<>{&line[last_pos..]}}); + } + + let combined_html = html! { <>{for line_html} }; + + match line { + l if l.starts_with("# ") => html! {

{&l[1..]}

}, + l if l.starts_with("## ") => html! {

{&l[2..]}

}, + l if l.starts_with("### ") => html! {

{&l[3..]}

}, + l if l.starts_with("#### ") => html! {

{&l[4..]}

}, + l if l.starts_with("```") => { + html! {

{line.replace("```", "")}

} + } + l if l.starts_with("---") => html! {
}, + l if l.starts_with("___") => html! {
}, + l if l.starts_with("-") => html! {
  • {&l[1..]}
  • }, + l if l.is_empty() => html! {
    }, + _ => html! {

    {combined_html}

    }, } - l if l.starts_with("---") => html! {
    }, - l if l.starts_with("___") => html! {
    }, - l if l.starts_with("-") => html! {
  • {&l[1..]}
  • }, - l if l.is_empty() => html! {
    }, - _ => html! {

    {line}

    }, }); html! { -
    -
    - {for html} -
    +
    + {for html}
    } }