fix: address code review feedback

- Remove unnecessary 'style' from ammonia whitelist (syntect uses classes)
- Log syntect parse errors instead of silently discarding them
- Simplify find_syntax fallback: return &'static directly, remove OnceLock
- Add generated/highlight.css to .gitignore (build artifact)
- Add #[cfg(feature = "server")] guard on mod highlight in main.rs
- Remove redundant code_buffer/code_lang clear on CodeBlock end
This commit is contained in:
xfy 2026-06-03 13:13:29 +08:00
parent 2e1d05cb03
commit 34e3bcdf95
5 changed files with 12 additions and 1911 deletions

1
.gitignore vendored
View File

@ -8,4 +8,5 @@
others/
public/style.css
public/tiptap
generated/highlight.css
.env

File diff suppressed because it is too large Load Diff

View File

@ -172,13 +172,11 @@ async fn ensure_unique_slug(
fn clean_html(input: &str) -> String {
let mut builder = ammonia::Builder::default();
builder
.add_generic_attributes(&["class", "style", "aria-hidden", "aria-label", "id", "role", "accesskey", "title"])
.add_generic_attributes(&["class", "aria-hidden", "aria-label", "id", "role", "accesskey", "title"])
.add_tags(&["details", "summary"])
.url_relative(ammonia::UrlRelative::PassThrough)
.add_tag_attributes("a", &["class", "aria-hidden", "aria-label"])
.add_tag_attributes("span", &["class", "style"])
.add_tag_attributes("pre", &["class", "style"])
.add_tag_attributes("code", &["class", "style"])
.add_tag_attributes("span", &["class"])
.add_tag_attributes("h1", &["id", "class"])
.add_tag_attributes("h2", &["id", "class"])
.add_tag_attributes("h3", &["id", "class"])
@ -319,8 +317,6 @@ fn render_markdown_enhanced(md: &str) -> RenderedContent {
html.push_str(&highlighted);
html.push_str("</code></pre>");
in_codeblock = false;
code_lang = None;
code_buffer.clear();
}
_ => {
if in_heading {

View File

@ -1,17 +1,15 @@
#[cfg(feature = "server")]
pub mod server {
use std::sync::{LazyLock, OnceLock};
use std::sync::LazyLock;
use syntect::html::{ClassedHTMLGenerator, ClassStyle};
use syntect::parsing::{SyntaxReference, SyntaxSet};
use syntect::parsing::SyntaxSet;
use syntect::util::LinesWithEndings;
static SYNTAX_SET: LazyLock<SyntaxSet> =
LazyLock::new(SyntaxSet::load_defaults_newlines);
static FALLBACK_SYNTAX: OnceLock<SyntaxReference> = OnceLock::new();
fn find_syntax(lang: Option<&str>) -> &'static SyntaxReference {
fn find_syntax(lang: Option<&str>) -> &'static syntect::parsing::SyntaxReference {
let ss = &*SYNTAX_SET;
if let Some(lang) = lang {
if !lang.is_empty() {
@ -23,11 +21,9 @@ pub mod server {
}
}
}
let plain = ss
.find_syntax_by_extension("txt")
ss.find_syntax_by_extension("txt")
.or_else(|| ss.find_syntax_by_name("Plain Text"))
.expect("no plain text syntax");
FALLBACK_SYNTAX.get_or_init(|| plain.clone())
.expect("no plain text syntax")
}
pub fn highlight_code(code: &str, lang: Option<&str>) -> String {
@ -37,7 +33,9 @@ pub mod server {
ClassedHTMLGenerator::new_with_class_style(syntax, ss, ClassStyle::Spaced);
for line in LinesWithEndings::from(code) {
let _ = generator.parse_html_for_line_which_includes_newline(line);
if let Err(e) = generator.parse_html_for_line_which_includes_newline(line) {
tracing::warn!("syntect parse error: {:?}", e);
}
}
generator.finalize()

View File

@ -3,6 +3,7 @@ mod auth;
mod components;
mod context;
mod db;
#[cfg(feature = "server")]
mod highlight;
mod hooks;
mod models;