1
0
Fork 0

Code hilighting

This commit is contained in:
Adrian Hedqvist 2023-06-18 11:34:08 +02:00
parent 97f5fbf901
commit acb2d1991c
8 changed files with 229 additions and 10 deletions

145
Cargo.lock generated
View file

@ -174,6 +174,21 @@ version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ea22880d78093b0cbe17c89f64a7d457941e65759157ec6cb31a31d652b05e5"
[[package]]
name = "base64"
version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d"
[[package]]
name = "bincode"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
dependencies = [
"serde",
]
[[package]]
name = "bitflags"
version = "1.3.2"
@ -302,7 +317,7 @@ dependencies = [
"js-sys",
"num-traits",
"serde",
"time",
"time 0.1.45",
"wasm-bindgen",
"winapi",
]
@ -949,6 +964,21 @@ version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4"
[[package]]
name = "line-wrap"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f30344350a2a51da54c1d53be93fade8a237e545dbcc4bdbe635413f2117cab9"
dependencies = [
"safemem",
]
[[package]]
name = "linked-hash-map"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
[[package]]
name = "linux-raw-sys"
version = "0.1.4"
@ -1081,6 +1111,28 @@ version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]]
name = "onig"
version = "6.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c4b31c8722ad9171c6d77d3557db078cab2bd50afcc9d09c8b315c59df8ca4f"
dependencies = [
"bitflags",
"libc",
"once_cell",
"onig_sys",
]
[[package]]
name = "onig_sys"
version = "69.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b829e3d7e9cc74c7e315ee8edb185bf4190da5acde74afd7fc59c35b1f086e7"
dependencies = [
"cc",
"pkg-config",
]
[[package]]
name = "opentelemetry"
version = "0.18.0"
@ -1344,6 +1396,20 @@ version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
[[package]]
name = "plist"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bd9647b268a3d3e14ff09c23201133a62589c658db02bb7388c7246aafe0590"
dependencies = [
"base64 0.21.2",
"indexmap",
"line-wrap",
"quick-xml",
"serde",
"time 0.3.22",
]
[[package]]
name = "ppv-lite86"
version = "0.2.17"
@ -1407,6 +1473,15 @@ dependencies = [
"unicase",
]
[[package]]
name = "quick-xml"
version = "0.28.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ce5e73202a820a31f8a0ee32ada5e21029c81fd9e3ebf668a40832e4219d9d1"
dependencies = [
"memchr",
]
[[package]]
name = "quote"
version = "1.0.28"
@ -1519,6 +1594,12 @@ version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
[[package]]
name = "safemem"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072"
[[package]]
name = "same-file"
version = "1.0.6"
@ -1698,6 +1779,29 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
[[package]]
name = "syntect"
version = "5.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6c454c27d9d7d9a84c7803aaa3c50cd088d2906fe3c6e42da3209aa623576a8"
dependencies = [
"bincode",
"bitflags",
"flate2",
"fnv",
"lazy_static",
"once_cell",
"onig",
"plist",
"regex-syntax 0.6.29",
"serde",
"serde_derive",
"serde_json",
"thiserror",
"walkdir",
"yaml-rust",
]
[[package]]
name = "tera"
version = "1.19.0"
@ -1761,6 +1865,33 @@ dependencies = [
"winapi",
]
[[package]]
name = "time"
version = "0.3.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd"
dependencies = [
"itoa",
"serde",
"time-core",
"time-macros",
]
[[package]]
name = "time-core"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
[[package]]
name = "time-macros"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b"
dependencies = [
"time-core",
]
[[package]]
name = "tokio"
version = "1.28.2"
@ -1867,7 +1998,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d1d42a9b3f3ec46ba828e8d376aec14592ea199f70a06a548587ecd1c4ab658"
dependencies = [
"async-compression",
"base64",
"base64 0.20.0",
"bitflags",
"bytes",
"futures-core",
@ -2230,6 +2361,7 @@ dependencies = [
"serde",
"serde_derive",
"serde_json",
"syntect",
"tera",
"tokio",
"toml",
@ -2421,6 +2553,15 @@ dependencies = [
"memchr",
]
[[package]]
name = "yaml-rust"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
dependencies = [
"linked-hash-map",
]
[[package]]
name = "zstd"
version = "0.11.2+zstd.1.5.2"

View file

@ -20,6 +20,7 @@ regex = "1.7.2"
serde = "1.0.144"
serde_derive = "1.0.144"
serde_json = "1.0.85"
syntect = "5.0.0"
tera = { version = "1.17.0", features = ["builtins"] }
tokio = { version = "1.19.2", features = ["full"] }
toml = "0.7.3"

View file

@ -12,3 +12,11 @@ here have a squid kid miku to test relative paths:
modified post test, see if docker skips build using
its cache if only a post has changed.
code hilighting test:
```rs
fn main() {
println!("Hello world!")
}
```

15
src/hilighting.rs Normal file
View file

@ -0,0 +1,15 @@
use syntect::{highlighting::ThemeSet, parsing::SyntaxSet};
use tracing::error;
pub fn hilight(content: &str, lang: &str) -> color_eyre::Result<String> {
let ss = SyntaxSet::load_defaults_newlines();
let s = ss.find_syntax_by_extension(lang).unwrap_or_else(|| {
error!("Syntax not found for language: {}", lang);
ss.find_syntax_plain_text()
});
let ts = ThemeSet::load_defaults();
let theme = ts.themes.first_key_value().unwrap().1; // TODO
let res = syntect::html::highlighted_html_for_string(content, &ss, s, theme)?;
Ok(res)
}

View file

@ -14,6 +14,8 @@ use tracing_subscriber::{prelude::*, EnvFilter};
mod feed;
mod handlers;
mod hilighting;
mod markdown;
mod post;
mod tag;

55
src/markdown.rs Normal file
View file

@ -0,0 +1,55 @@
use color_eyre::Result;
use pulldown_cmark::Event;
use pulldown_cmark::Tag;
use pulldown_cmark::{Options, Parser};
use crate::hilighting;
pub fn render_markdown_to_html(markdown: &str) -> Result<String> {
let options = Options::all();
let mut content_html = String::new();
let parser = Parser::new_ext(markdown, options);
let mut code_block = false;
let mut code_lang = None;
let mut code_accumulator = String::new();
let mut events = Vec::new();
for event in parser {
match event {
Event::Text(text) => {
if code_block {
code_accumulator.push_str(&text);
}
else {
events.push(Event::Text(text));
}
}
Event::Start(Tag::CodeBlock(kind)) => {
code_block = true;
if let pulldown_cmark::CodeBlockKind::Fenced(lang) = kind {
code_lang = Some(lang);
}
}
Event::End(Tag::CodeBlock(_)) => {
code_block = false;
let lang = code_lang.take().unwrap_or("".into());
let res = hilighting::hilight(&code_accumulator, &lang).unwrap();
events.push(Event::Html(res.into()));
code_accumulator.clear();
}
_ => events.push(event),
}
}
events.retain(|e| match e {
Event::Text(t) | Event::Html(t) => !t.is_empty(),
_ => true,
});
pulldown_cmark::html::push_html(&mut content_html, events.into_iter());
Ok(content_html)
}

View file

@ -11,7 +11,7 @@ use tokio::fs;
use tracing::{instrument, log::*};
use crate::{AppState, WebsiteError};
use crate::{AppState, WebsiteError, markdown};
#[derive(Deserialize, Debug, Default)]
pub struct TomlFrontMatter {
@ -103,12 +103,8 @@ pub async fn load_post(slug: &str) -> color_eyre::eyre::Result<Post> {
let tomlfm = tomlfm.expect("Missing frontmatter");
let content = content.map(|c| {
let options = Options::all();
let mut content_html = String::new();
let parser = Parser::new_ext(&c, options);
html::push_html(&mut content_html, parser);
content_html
});
markdown::render_markdown_to_html(&c)
}).transpose()?;
Ok(Post::new(
slug.to_string(),

View file

@ -12,9 +12,10 @@
<li>✅ app metrics (page hits, etc)</li>
<li>✅ tests</li>
<li>✅ page aliases (redirects, for back-compat with old routes)</li>
<li>⬜ sass compilation (using rsass? grass?)</li>
<li>✅ rss/atom/jsonfeed (atom is good enough for now)</li>
<li>✅ proper error handling (i guess??)</li>
<li>✅ code hilighting? (good enough for now, gotta figure out themes n' stuff later)</li>
<li>⬜ sass compilation (using rsass? grass?)</li>
<li>⬜ fancy styling</li>
<li>⬜ other pages???</li>
<li>⬜ graphviz to svg rendering??</li>