add custom syntax loading support

This commit is contained in:
Gered 2023-06-30 16:40:53 -04:00
parent 4dfd946204
commit 1d83b95211
3 changed files with 35 additions and 8 deletions

View file

@ -8,6 +8,7 @@ pub struct Server {
pub bind_port: u16, pub bind_port: u16,
pub static_files_path: PathBuf, pub static_files_path: PathBuf,
pub templates_path: PathBuf, pub templates_path: PathBuf,
pub syntaxes_path: Option<PathBuf>,
pub pages_path: PathBuf, pub pages_path: PathBuf,
pub posts_path: PathBuf, pub posts_path: PathBuf,
} }
@ -78,6 +79,9 @@ pub fn load_server(path: &PathBuf, site_root: &PathBuf) -> Result<Server, Config
server_config.templates_path = [site_root, &server_config.templates_path].iter().collect(); server_config.templates_path = [site_root, &server_config.templates_path].iter().collect();
server_config.pages_path = [site_root, &server_config.pages_path].iter().collect(); server_config.pages_path = [site_root, &server_config.pages_path].iter().collect();
server_config.posts_path = [site_root, &server_config.posts_path].iter().collect(); server_config.posts_path = [site_root, &server_config.posts_path].iter().collect();
if let Some(syntaxes_path) = &server_config.syntaxes_path {
server_config.syntaxes_path = Some([site_root, syntaxes_path].iter().collect());
}
Ok(server_config) Ok(server_config)
} }

View file

@ -1,12 +1,18 @@
use itertools::Itertools;
use pulldown_cmark::{CodeBlockKind, CowStr, Event, Parser, Tag}; use pulldown_cmark::{CodeBlockKind, CowStr, Event, Parser, Tag};
use syntect::html::{ClassStyle, ClassedHTMLGenerator}; use syntect::html::{ClassStyle, ClassedHTMLGenerator};
use syntect::parsing::SyntaxSet; use syntect::parsing::SyntaxSet;
use syntect::util::LinesWithEndings; use syntect::util::LinesWithEndings;
use crate::config;
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]
pub enum MarkdownError { pub enum MarkdownError {
#[error("Syntax highlighting error")] #[error("Syntax highlighting error")]
SyntectError(#[from] syntect::Error), SyntectError(#[from] syntect::Error),
#[error("Syntax loading error")]
SyntectLoadingError(#[from] syntect::LoadingError),
} }
struct SyntectContext { struct SyntectContext {
@ -18,9 +24,20 @@ pub struct MarkdownRenderer {
} }
impl MarkdownRenderer { impl MarkdownRenderer {
pub fn new() -> Self { pub fn new(server_config: &config::Server) -> Result<Self, MarkdownError> {
let syntax_set = SyntaxSet::load_defaults_newlines(); let syntax_set = if let Some(syntaxes_path) = &server_config.syntaxes_path {
MarkdownRenderer { syntect_context: SyntectContext { syntax_set } } log::debug!("Using syntaxes path: {:?}", syntaxes_path);
let mut builder = SyntaxSet::load_defaults_newlines().into_builder();
builder.add_from_folder(syntaxes_path, true)?;
builder.build()
} else {
log::debug!("Using default syntaxes only.");
SyntaxSet::load_defaults_newlines()
};
let syntax_names: Vec<&String> =
syntax_set.syntaxes().iter().flat_map(|syntax| &syntax.file_extensions).sorted().collect();
log::debug!("Syntaxes loaded: {:?}", syntax_names);
Ok(MarkdownRenderer { syntect_context: SyntectContext { syntax_set } })
} }
fn highlight_code(&self, code: &str, language: &str) -> Result<String, MarkdownError> { fn highlight_code(&self, code: &str, language: &str) -> Result<String, MarkdownError> {

View file

@ -17,8 +17,11 @@ pub enum ContentError {
#[error("Content rendering I/O error with path {0}")] #[error("Content rendering I/O error with path {0}")]
IOError(PathBuf, #[source] std::io::Error), IOError(PathBuf, #[source] std::io::Error),
#[error("Markdown error")]
MarkdownError(#[from] markdown::MarkdownError),
#[error("Markdown rendering error with path {0}")] #[error("Markdown rendering error with path {0}")]
MarkdownError(PathBuf, #[source] markdown::MarkdownError), MarkdownRenderingError(PathBuf, #[source] markdown::MarkdownError),
} }
pub struct ContentRenderer { pub struct ContentRenderer {
@ -26,8 +29,11 @@ pub struct ContentRenderer {
} }
impl ContentRenderer { impl ContentRenderer {
pub fn new() -> Result<Self, ContentError> { pub fn new(server_config: &config::Server) -> Result<Self, ContentError> {
Ok(ContentRenderer { markdown_renderer: markdown::MarkdownRenderer::new() }) Ok(ContentRenderer {
//
markdown_renderer: markdown::MarkdownRenderer::new(server_config)?,
})
} }
pub fn render(&self, path: &PathBuf) -> Result<String, ContentError> { pub fn render(&self, path: &PathBuf) -> Result<String, ContentError> {
@ -37,7 +43,7 @@ impl ContentRenderer {
}; };
match path.extension().unwrap_or_default().to_str() { match path.extension().unwrap_or_default().to_str() {
Some("md") => match self.markdown_renderer.render_to_html(&raw_content) { Some("md") => match self.markdown_renderer.render_to_html(&raw_content) {
Err(e) => return Err(ContentError::MarkdownError(path.clone(), e)), Err(e) => return Err(ContentError::MarkdownRenderingError(path.clone(), e)),
Ok(output) => Ok(output), Ok(output) => Ok(output),
}, },
Some("html") | Some("htm") => Ok(raw_content), Some("html") | Some("htm") => Ok(raw_content),
@ -283,7 +289,7 @@ impl SiteService {
pages_config: config::Pages, pages_config: config::Pages,
posts_config: config::Posts, posts_config: config::Posts,
) -> Result<Self, SiteError> { ) -> Result<Self, SiteError> {
let content_renderer = ContentRenderer::new()?; let content_renderer = ContentRenderer::new(&server_config)?;
let content = SiteContent::new(pages_config, posts_config, &content_renderer)?; let content = SiteContent::new(pages_config, posts_config, &content_renderer)?;
let mut templates_path = PathBuf::from(&server_config.templates_path); let mut templates_path = PathBuf::from(&server_config.templates_path);
templates_path.push("**/*"); templates_path.push("**/*");