Code hilighting
This commit is contained in:
parent
97f5fbf901
commit
acb2d1991c
8 changed files with 229 additions and 10 deletions
145
Cargo.lock
generated
145
Cargo.lock
generated
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
15
src/hilighting.rs
Normal 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)
|
||||
}
|
|
@ -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
55
src/markdown.rs
Normal 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)
|
||||
}
|
10
src/post.rs
10
src/post.rs
|
@ -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(),
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in a new issue