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:
parent
2e1d05cb03
commit
34e3bcdf95
1
.gitignore
vendored
1
.gitignore
vendored
@ -8,4 +8,5 @@
|
|||||||
others/
|
others/
|
||||||
public/style.css
|
public/style.css
|
||||||
public/tiptap
|
public/tiptap
|
||||||
|
generated/highlight.css
|
||||||
.env
|
.env
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -172,13 +172,11 @@ async fn ensure_unique_slug(
|
|||||||
fn clean_html(input: &str) -> String {
|
fn clean_html(input: &str) -> String {
|
||||||
let mut builder = ammonia::Builder::default();
|
let mut builder = ammonia::Builder::default();
|
||||||
builder
|
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"])
|
.add_tags(&["details", "summary"])
|
||||||
.url_relative(ammonia::UrlRelative::PassThrough)
|
.url_relative(ammonia::UrlRelative::PassThrough)
|
||||||
.add_tag_attributes("a", &["class", "aria-hidden", "aria-label"])
|
.add_tag_attributes("a", &["class", "aria-hidden", "aria-label"])
|
||||||
.add_tag_attributes("span", &["class", "style"])
|
.add_tag_attributes("span", &["class"])
|
||||||
.add_tag_attributes("pre", &["class", "style"])
|
|
||||||
.add_tag_attributes("code", &["class", "style"])
|
|
||||||
.add_tag_attributes("h1", &["id", "class"])
|
.add_tag_attributes("h1", &["id", "class"])
|
||||||
.add_tag_attributes("h2", &["id", "class"])
|
.add_tag_attributes("h2", &["id", "class"])
|
||||||
.add_tag_attributes("h3", &["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(&highlighted);
|
||||||
html.push_str("</code></pre>");
|
html.push_str("</code></pre>");
|
||||||
in_codeblock = false;
|
in_codeblock = false;
|
||||||
code_lang = None;
|
|
||||||
code_buffer.clear();
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
if in_heading {
|
if in_heading {
|
||||||
|
|||||||
@ -1,17 +1,15 @@
|
|||||||
#[cfg(feature = "server")]
|
#[cfg(feature = "server")]
|
||||||
pub mod server {
|
pub mod server {
|
||||||
use std::sync::{LazyLock, OnceLock};
|
use std::sync::LazyLock;
|
||||||
|
|
||||||
use syntect::html::{ClassedHTMLGenerator, ClassStyle};
|
use syntect::html::{ClassedHTMLGenerator, ClassStyle};
|
||||||
use syntect::parsing::{SyntaxReference, SyntaxSet};
|
use syntect::parsing::SyntaxSet;
|
||||||
use syntect::util::LinesWithEndings;
|
use syntect::util::LinesWithEndings;
|
||||||
|
|
||||||
static SYNTAX_SET: LazyLock<SyntaxSet> =
|
static SYNTAX_SET: LazyLock<SyntaxSet> =
|
||||||
LazyLock::new(SyntaxSet::load_defaults_newlines);
|
LazyLock::new(SyntaxSet::load_defaults_newlines);
|
||||||
|
|
||||||
static FALLBACK_SYNTAX: OnceLock<SyntaxReference> = OnceLock::new();
|
fn find_syntax(lang: Option<&str>) -> &'static syntect::parsing::SyntaxReference {
|
||||||
|
|
||||||
fn find_syntax(lang: Option<&str>) -> &'static SyntaxReference {
|
|
||||||
let ss = &*SYNTAX_SET;
|
let ss = &*SYNTAX_SET;
|
||||||
if let Some(lang) = lang {
|
if let Some(lang) = lang {
|
||||||
if !lang.is_empty() {
|
if !lang.is_empty() {
|
||||||
@ -23,11 +21,9 @@ pub mod server {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let plain = ss
|
ss.find_syntax_by_extension("txt")
|
||||||
.find_syntax_by_extension("txt")
|
|
||||||
.or_else(|| ss.find_syntax_by_name("Plain Text"))
|
.or_else(|| ss.find_syntax_by_name("Plain Text"))
|
||||||
.expect("no plain text syntax");
|
.expect("no plain text syntax")
|
||||||
FALLBACK_SYNTAX.get_or_init(|| plain.clone())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn highlight_code(code: &str, lang: Option<&str>) -> String {
|
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);
|
ClassedHTMLGenerator::new_with_class_style(syntax, ss, ClassStyle::Spaced);
|
||||||
|
|
||||||
for line in LinesWithEndings::from(code) {
|
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()
|
generator.finalize()
|
||||||
|
|||||||
@ -3,6 +3,7 @@ mod auth;
|
|||||||
mod components;
|
mod components;
|
||||||
mod context;
|
mod context;
|
||||||
mod db;
|
mod db;
|
||||||
|
#[cfg(feature = "server")]
|
||||||
mod highlight;
|
mod highlight;
|
||||||
mod hooks;
|
mod hooks;
|
||||||
mod models;
|
mod models;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user