From 7aacf10a296b0286685c4ff64d9d3bc8333bdbc2 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Wed, 9 Nov 2022 13:22:24 +0200 Subject: chore: remove unnecessary borrows Found by clippy. Sponsored-by: author --- src/directive/inline.rs | 2 +- src/page.rs | 2 +- src/site.rs | 2 +- src/util.rs | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/directive/inline.rs b/src/directive/inline.rs index 78872b4..e6577b2 100644 --- a/src/directive/inline.rs +++ b/src/directive/inline.rs @@ -40,7 +40,7 @@ impl Inline { let matches: Vec = site .markdown_pages() .iter() - .filter(|page| pagespec.matches(&site, page.meta().path())) + .filter(|page| pagespec.matches(site, page.meta().path())) .map(|page| format!("* {}\n", Self::link(meta.path(), page.meta()))) .collect(); Ok(matches.join("")) diff --git a/src/page.rs b/src/page.rs index 2b4bd9f..fb2159d 100644 --- a/src/page.rs +++ b/src/page.rs @@ -24,7 +24,7 @@ impl WikitextPage { info!("input file: {}", name); let src = name.source_path(); - let data = std::fs::read(&src).map_err(|e| SiteError::FileRead(src.into(), e))?; + let data = std::fs::read(src).map_err(|e| SiteError::FileRead(src.into(), e))?; let wikitext = String::from_utf8(data).map_err(|e| SiteError::Utf8(src.into(), e))?; let mtime = get_mtime(src)?; diff --git a/src/site.rs b/src/site.rs index 6fa4625..0b03c85 100644 --- a/src/site.rs +++ b/src/site.rs @@ -131,7 +131,7 @@ impl Site { let mut names = vec![]; for path in srcdir.files().iter().filter(|x| filter.is_included(x)) { - let relative = path.strip_prefix(&self.builder.srcdir()).unwrap(); + let relative = path.strip_prefix(self.builder.srcdir()).unwrap(); let mtime = whatchanged.get(relative).copied().unwrap_or(UNIX_EPOCH); if Self::is_markdown(path) { names.push(self.builder.page(path, mtime)); diff --git a/src/util.rs b/src/util.rs index 064e556..bf78404 100644 --- a/src/util.rs +++ b/src/util.rs @@ -107,13 +107,13 @@ pub fn make_relative_link>(page: P, target: P) -> PathBuf { } pub fn make_path_relative_to(dir: &Path, path: &Path) -> PathBuf { - path.strip_prefix(&dir) + path.strip_prefix(dir) .unwrap_or_else(|_| panic!("remove prefix {} from {}", dir.display(), path.display())) .into() } pub fn make_path_absolute(path: &Path) -> PathBuf { - Path::new("/").join(&path) + Path::new("/").join(path) } fn timespec(time: SystemTime) -> Result { -- cgit v1.2.1 From e93a903cb50deaf4ae7f9055be4730e1f27e698a Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Wed, 9 Nov 2022 13:09:17 +0200 Subject: refactor: processing a directive returns Processed type, not String This paves way for non-Markdown placeholders that can be post-processed. Sponsored-by: author --- src/directive/mod.rs | 11 ++++++++--- src/wikitext.rs | 9 ++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/directive/mod.rs b/src/directive/mod.rs index e33f572..5bc8ef6 100644 --- a/src/directive/mod.rs +++ b/src/directive/mod.rs @@ -6,6 +6,10 @@ use crate::wikitext::ParsedDirective; use log::{debug, trace}; use std::collections::HashSet; +pub enum Processed { + Markdown(String), +} + #[derive(Debug, Eq, PartialEq)] pub enum Directive { Simple, @@ -204,8 +208,8 @@ impl Directive { Ok(()) } - pub fn process(&self, site: &mut Site, meta: &mut PageMeta) -> Result { - match self { + pub fn process(&self, site: &mut Site, meta: &mut PageMeta) -> Result { + let markdown = match self { Self::Simple | Self::UnnamedArg | Self::SimpleArg @@ -227,7 +231,8 @@ impl Directive { Self::Tag(x) => x.process(site, meta), Self::Toc(x) => x.process(site, meta), Self::TrailLink(x) => x.process(site, meta), - } + }; + Ok(Processed::Markdown(markdown?)) } } diff --git a/src/wikitext.rs b/src/wikitext.rs index 81514f0..25da818 100644 --- a/src/wikitext.rs +++ b/src/wikitext.rs @@ -1,4 +1,4 @@ -use crate::directive::Directive; +use crate::directive::{Directive, Processed}; use crate::error::SiteError; use crate::page::PageMeta; use crate::site::Site; @@ -43,8 +43,11 @@ impl Snippet { Snippet::Directive(p) => { let e = Directive::try_from(p); if let Ok(d) = e { - d.process(site, meta) - .map_err(|e| SiteError::PageProblem(meta.path().into(), Box::new(e)))? + let processed = d.process(site, meta) + .map_err(|e| SiteError::PageProblem(meta.path().into(), Box::new(e)))?; + match processed { + Processed::Markdown(s) => s, + } } else if let Some(shortcut) = site.shortcut(p.name()) { let arg = p.unnamed_args().first().unwrap().to_string(); format!("[{}]({})", shortcut.desc(&arg), shortcut.url(&arg)) -- cgit v1.2.1 From d208687a7c62dfbec0e4941d47db2f897c47a933 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Wed, 9 Nov 2022 13:16:14 +0200 Subject: add trait for directive implementations Sponsored-by: author --- src/directive/mod.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/directive/mod.rs b/src/directive/mod.rs index 5bc8ef6..899980d 100644 --- a/src/directive/mod.rs +++ b/src/directive/mod.rs @@ -10,6 +10,14 @@ pub enum Processed { Markdown(String), } +trait DirectiveImplementation { + const REQUIRED: &'static [&'static str]; + const ALLOWED: &'static [&'static str]; + const ALLOW_ANY_UNNAMED: bool; + fn from_parsed(p: &ParsedDirective) -> Self; + fn process(&self, site: &Site, meta: &mut PageMeta) -> Result; +} + #[derive(Debug, Eq, PartialEq)] pub enum Directive { Simple, -- cgit v1.2.1 From 8db80a826f401f680fb78e45a53371ebfe2f4459 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Wed, 9 Nov 2022 13:19:11 +0200 Subject: use DirectiveImplementation for Calendar Sponsored-by: author --- src/directive/calendar.rs | 19 +++++++++---------- src/directive/mod.rs | 2 +- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/directive/calendar.rs b/src/directive/calendar.rs index a11cc52..a3d199a 100644 --- a/src/directive/calendar.rs +++ b/src/directive/calendar.rs @@ -1,3 +1,4 @@ +use crate::directive::DirectiveImplementation; use crate::error::SiteError; use crate::page::PageMeta; use crate::site::Site; @@ -6,9 +7,9 @@ use crate::wikitext::ParsedDirective; #[derive(Debug, Default, Eq, PartialEq)] pub struct Calendar {} -impl Calendar { - pub const REQUIRED: &'static [&'static str] = &[]; - pub const ALLOWED: &'static [&'static str] = &[ +impl DirectiveImplementation for Calendar { + const REQUIRED: &'static [&'static str] = &[]; + const ALLOWED: &'static [&'static str] = &[ "type", "pages", "year", @@ -17,15 +18,13 @@ impl Calendar { "months_per_row", "archivebase", ]; - pub const ALLOW_ANY_UNNAMED: bool = true; + const ALLOW_ANY_UNNAMED: bool = true; - pub fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { - Err(SiteError::UnimplementedDirective("calendar".into())) + fn from_parsed(_: &ParsedDirective) -> Self { + Self::default() } -} -impl From<&ParsedDirective> for Calendar { - fn from(_: &ParsedDirective) -> Self { - Calendar::default() + fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { + Err(SiteError::UnimplementedDirective("calendar".into())) } } diff --git a/src/directive/mod.rs b/src/directive/mod.rs index 899980d..40def2f 100644 --- a/src/directive/mod.rs +++ b/src/directive/mod.rs @@ -83,7 +83,7 @@ impl TryFrom<&ParsedDirective> for Directive { Calendar::ALLOWED, Calendar::ALLOW_ANY_UNNAMED, )?; - Directive::Calendar(Calendar::from(p)) + Directive::Calendar(Calendar::from_parsed(p)) } "format" => { Self::check_args( -- cgit v1.2.1 From 3421ef66def1b0ad140a11fa35f101d8eaf4934d Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Wed, 9 Nov 2022 13:44:54 +0200 Subject: refactor: use trait for all directive implementations Sponsored-by: author --- src/directive/format.rs | 19 ++--- src/directive/graph.rs | 20 ++--- src/directive/img.rs | 199 +++++++++++++++++++++++---------------------- src/directive/inline.rs | 31 +++---- src/directive/map.rs | 19 ++--- src/directive/meta.rs | 48 ++++++----- src/directive/mod.rs | 33 ++++---- src/directive/pagestats.rs | 19 ++--- src/directive/shortcut.rs | 31 +++---- src/directive/sidebar.rs | 19 ++--- src/directive/table.rs | 21 ++--- src/directive/tag.rs | 23 +++--- src/directive/toc.rs | 19 ++--- src/directive/traillink.rs | 19 ++--- 14 files changed, 255 insertions(+), 265 deletions(-) diff --git a/src/directive/format.rs b/src/directive/format.rs index ee9c7ec..f76ba9a 100644 --- a/src/directive/format.rs +++ b/src/directive/format.rs @@ -1,3 +1,4 @@ +use crate::directive::DirectiveImplementation; use crate::error::SiteError; use crate::page::PageMeta; use crate::site::Site; @@ -6,18 +7,16 @@ use crate::wikitext::ParsedDirective; #[derive(Debug, Default, Eq, PartialEq)] pub struct Format {} -impl Format { - pub const REQUIRED: &'static [&'static str] = &[]; - pub const ALLOWED: &'static [&'static str] = &[]; - pub const ALLOW_ANY_UNNAMED: bool = true; +impl DirectiveImplementation for Format { + const REQUIRED: &'static [&'static str] = &[]; + const ALLOWED: &'static [&'static str] = &[]; + const ALLOW_ANY_UNNAMED: bool = true; - pub fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { - Err(SiteError::UnimplementedDirective("format".into())) + fn from_parsed(_: &ParsedDirective) -> Self { + Self::default() } -} -impl From<&ParsedDirective> for Format { - fn from(_: &ParsedDirective) -> Self { - Format::default() + fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { + Err(SiteError::UnimplementedDirective("format".into())) } } diff --git a/src/directive/graph.rs b/src/directive/graph.rs index 8234ed2..e7ae5fe 100644 --- a/src/directive/graph.rs +++ b/src/directive/graph.rs @@ -1,3 +1,4 @@ +use crate::directive::DirectiveImplementation; use crate::error::SiteError; use crate::page::PageMeta; use crate::site::Site; @@ -6,18 +7,17 @@ use crate::wikitext::ParsedDirective; #[derive(Debug, Default, Eq, PartialEq)] pub struct Graph {} -impl Graph { - pub const REQUIRED: &'static [&'static str] = &[]; - pub const ALLOWED: &'static [&'static str] = &["src", "type"]; - pub const ALLOW_ANY_UNNAMED: bool = true; +impl DirectiveImplementation for Graph { + const REQUIRED: &'static [&'static str] = &[]; + const ALLOWED: &'static [&'static str] = &["src", "type"]; + const ALLOW_ANY_UNNAMED: bool = true; - pub fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { - Err(SiteError::UnimplementedDirective("graph".into())) + fn from_parsed(_: &ParsedDirective) -> Self { + Self::default() } -} -impl From<&ParsedDirective> for Graph { - fn from(_: &ParsedDirective) -> Self { - Graph::default() + fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { + Err(SiteError::UnimplementedDirective("graph".into())) } + } diff --git a/src/directive/img.rs b/src/directive/img.rs index 3ee6501..29efe0c 100644 --- a/src/directive/img.rs +++ b/src/directive/img.rs @@ -1,3 +1,4 @@ +use crate::directive::DirectiveImplementation; use crate::error::SiteError; use crate::page::PageMeta; use crate::site::Site; @@ -21,70 +22,67 @@ pub struct Img { width: Option, } -impl Img { - pub const REQUIRED: &'static [&'static str] = &[]; - pub const ALLOWED: &'static [&'static str] = &[ +impl DirectiveImplementation for Img { + const REQUIRED: &'static [&'static str] = &[]; + const ALLOWED: &'static [&'static str] = &[ "align", "alt", "class", "hspace", "id", "link", "size", "title", "vspace", ]; - pub const ALLOW_ANY_UNNAMED: bool = true; + const ALLOW_ANY_UNNAMED: bool = true; - fn new(src: String) -> Self { - Self { - src, - link: true, - align: None, - alt: None, - class: None, - height: None, - hspace: None, - id: None, - title: None, - vspace: None, - width: None, - } - } + fn from_parsed(p: &ParsedDirective) -> Self { + let unnamed = p.unnamed_args().pop().unwrap(); + let mut img = Img::new(unnamed.into()); + let args = p.args(); - fn link(&mut self, link: bool) { - self.link = link; - } + if let Some(link) = args.get("link") { + if *link == "no" { + img.link(false); + } + } - fn align(&mut self, align: String) { - self.align = Some(align); - } + if let Some(size) = args.get("size") { + if let Some((w, h)) = size.split_once('x') { + if let Ok(w) = w.parse() { + img.width(w); + } + if let Ok(h) = h.parse() { + img.height(h); + } + } + } - fn alt(&mut self, alt: String) { - self.alt = Some(alt); - } + if let Some(align) = args.get("align") { + img.align(align.to_string()); + } - fn class(&mut self, class: String) { - self.class = Some(class); - } + if let Some(alt) = args.get("alt") { + img.alt(alt.to_string()); + } - fn height(&mut self, h: usize) { - self.height = Some(h); - } + if let Some(class) = args.get("class") { + img.class(class.to_string()); + } - fn hspace(&mut self, hspace: String) { - self.hspace = Some(hspace); - } + if let Some(hspace) = args.get("hspace") { + img.hspace(hspace.to_string()); + } - fn id(&mut self, id: String) { - self.id = Some(id); - } + if let Some(id) = args.get("id") { + img.id(id.to_string()); + } - fn title(&mut self, title: String) { - self.title = Some(title); - } + if let Some(title) = args.get("title") { + img.title(title.to_string()); + } - fn vspace(&mut self, vspace: String) { - self.vspace = Some(vspace); - } + if let Some(vspace) = args.get("vspace") { + img.vspace(vspace.to_string()); + } - fn width(&mut self, w: usize) { - self.width = Some(w); + img } - pub fn process(&self, site: &Site, meta: &mut PageMeta) -> Result { + fn process(&self, site: &Site, meta: &mut PageMeta) -> Result { trace!( "verify image exists: {} on {}", self.src, @@ -127,67 +125,70 @@ impl Img { } } -fn push_attr(s: &mut String, name: &str, value: &Option) { - if let Some(v) = value { - s.push_str(&format!( - " {}=\"{}\"", - name, - encode_double_quoted_attribute(v) - )); +impl Img { + fn new(src: String) -> Self { + Self { + src, + link: true, + align: None, + alt: None, + class: None, + height: None, + hspace: None, + id: None, + title: None, + vspace: None, + width: None, + } } -} -impl From<&ParsedDirective> for Img { - fn from(p: &ParsedDirective) -> Self { - let unnamed = p.unnamed_args().pop().unwrap(); - let mut img = Img::new(unnamed.into()); - let args = p.args(); + fn link(&mut self, link: bool) { + self.link = link; + } - if let Some(link) = args.get("link") { - if *link == "no" { - img.link(false); - } - } + fn align(&mut self, align: String) { + self.align = Some(align); + } - if let Some(size) = args.get("size") { - if let Some((w, h)) = size.split_once('x') { - if let Ok(w) = w.parse() { - img.width(w); - } - if let Ok(h) = h.parse() { - img.height(h); - } - } - } + fn alt(&mut self, alt: String) { + self.alt = Some(alt); + } - if let Some(align) = args.get("align") { - img.align(align.to_string()); - } + fn class(&mut self, class: String) { + self.class = Some(class); + } - if let Some(alt) = args.get("alt") { - img.alt(alt.to_string()); - } + fn height(&mut self, h: usize) { + self.height = Some(h); + } - if let Some(class) = args.get("class") { - img.class(class.to_string()); - } + fn hspace(&mut self, hspace: String) { + self.hspace = Some(hspace); + } - if let Some(hspace) = args.get("hspace") { - img.hspace(hspace.to_string()); - } + fn id(&mut self, id: String) { + self.id = Some(id); + } - if let Some(id) = args.get("id") { - img.id(id.to_string()); - } + fn title(&mut self, title: String) { + self.title = Some(title); + } - if let Some(title) = args.get("title") { - img.title(title.to_string()); - } + fn vspace(&mut self, vspace: String) { + self.vspace = Some(vspace); + } - if let Some(vspace) = args.get("vspace") { - img.vspace(vspace.to_string()); - } + fn width(&mut self, w: usize) { + self.width = Some(w); + } +} - img +fn push_attr(s: &mut String, name: &str, value: &Option) { + if let Some(v) = value { + s.push_str(&format!( + " {}=\"{}\"", + name, + encode_double_quoted_attribute(v) + )); } } diff --git a/src/directive/inline.rs b/src/directive/inline.rs index e6577b2..0dafa69 100644 --- a/src/directive/inline.rs +++ b/src/directive/inline.rs @@ -1,3 +1,4 @@ +use crate::directive::DirectiveImplementation; use crate::error::SiteError; use crate::page::PageMeta; use crate::pagespec::PageSpec; @@ -11,9 +12,9 @@ pub struct Inline { pages: String, } -impl Inline { - pub const REQUIRED: &'static [&'static str] = &["pages"]; - pub const ALLOWED: &'static [&'static str] = &[ +impl DirectiveImplementation for Inline { + const REQUIRED: &'static [&'static str] = &["pages"]; + const ALLOWED: &'static [&'static str] = &[ "actions", "archive", "description", @@ -29,13 +30,15 @@ impl Inline { "template", "trail", ]; - pub const ALLOW_ANY_UNNAMED: bool = true; + const ALLOW_ANY_UNNAMED: bool = true; - pub fn new(pages: String) -> Self { - Self { pages } + fn from_parsed(p: &ParsedDirective) -> Self { + let args = p.args(); + let pages = args.get("pages").unwrap(); + Inline::new(pages.to_string()) } - pub fn process(&self, site: &Site, meta: &mut PageMeta) -> Result { + fn process(&self, site: &Site, meta: &mut PageMeta) -> Result { let pagespec = PageSpec::new(meta.path(), &self.pages)?; let matches: Vec = site .markdown_pages() @@ -45,17 +48,15 @@ impl Inline { .collect(); Ok(matches.join("")) } +} + +impl Inline { + pub fn new(pages: String) -> Self { + Self { pages } + } fn link(container: &Path, meta: &PageMeta) -> String { let link = make_relative_link(container, meta.path()); format!("[{}]({})", meta.title(), link.display()) } } - -impl From<&ParsedDirective> for Inline { - fn from(p: &ParsedDirective) -> Self { - let args = p.args(); - let pages = args.get("pages").unwrap(); - Inline::new(pages.to_string()) - } -} diff --git a/src/directive/map.rs b/src/directive/map.rs index 960b339..009bf64 100644 --- a/src/directive/map.rs +++ b/src/directive/map.rs @@ -1,3 +1,4 @@ +use crate::directive::DirectiveImplementation; use crate::error::SiteError; use crate::page::PageMeta; use crate::site::Site; @@ -6,18 +7,16 @@ use crate::wikitext::ParsedDirective; #[derive(Debug, Default, Eq, PartialEq)] pub struct Map {} -impl Map { - pub const REQUIRED: &'static [&'static str] = &["pages"]; - pub const ALLOWED: &'static [&'static str] = &["show"]; - pub const ALLOW_ANY_UNNAMED: bool = true; +impl DirectiveImplementation for Map { + const REQUIRED: &'static [&'static str] = &["pages"]; + const ALLOWED: &'static [&'static str] = &["show"]; + const ALLOW_ANY_UNNAMED: bool = true; - pub fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { - Err(SiteError::UnimplementedDirective("map".into())) + fn from_parsed(_: &ParsedDirective) -> Self { + Self::default() } -} -impl From<&ParsedDirective> for Map { - fn from(_: &ParsedDirective) -> Self { - Map::default() + fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { + Err(SiteError::UnimplementedDirective("map".into())) } } diff --git a/src/directive/meta.rs b/src/directive/meta.rs index 490ffb1..1e8ec8c 100644 --- a/src/directive/meta.rs +++ b/src/directive/meta.rs @@ -1,3 +1,4 @@ +use crate::directive::DirectiveImplementation; use crate::error::SiteError; use crate::page::PageMeta; use crate::site::Site; @@ -10,20 +11,24 @@ pub struct Meta { date: Option, } -impl Meta { - pub const REQUIRED: &'static [&'static str] = &[]; - pub const ALLOWED: &'static [&'static str] = &["date", "link", "title", "author"]; - pub const ALLOW_ANY_UNNAMED: bool = false; - - fn set_date(&mut self, date: &str) { - self.date = Some(date.into()); - } +impl DirectiveImplementation for Meta { + const REQUIRED: &'static [&'static str] = &[]; + const ALLOWED: &'static [&'static str] = &["date", "link", "title", "author"]; + const ALLOW_ANY_UNNAMED: bool = false; - fn set_title(&mut self, title: &str) { - self.title = Some(title.into()); + fn from_parsed(p: &ParsedDirective) -> Self { + let mut meta = Self::default(); + let args = p.args(); + if let Some(title) = args.get("title") { + meta.set_title(title); + } + if let Some(date) = args.get("date") { + meta.set_date(date); + } + meta } - pub fn process(&self, _site: &Site, meta: &mut PageMeta) -> Result { + fn process(&self, _site: &Site, meta: &mut PageMeta) -> Result { if let Some(title) = &self.title { meta.set_title(title.into()); } @@ -34,19 +39,12 @@ impl Meta { } } -impl From<&ParsedDirective> for Meta { - fn from(p: &ParsedDirective) -> Self { - let mut meta = Meta::default(); - let args = p.args(); - if let Some(title) = args.get("title") { - meta.set_title(title); - } - if let Some(date) = args.get("date") { - meta.set_date(date); - } - meta +impl Meta { + fn set_date(&mut self, date: &str) { + self.date = Some(date.into()); } -} -#[cfg(test)] -mod test {} + fn set_title(&mut self, title: &str) { + self.title = Some(title.into()); + } +} diff --git a/src/directive/mod.rs b/src/directive/mod.rs index 40def2f..e885404 100644 --- a/src/directive/mod.rs +++ b/src/directive/mod.rs @@ -10,12 +10,17 @@ pub enum Processed { Markdown(String), } -trait DirectiveImplementation { +pub trait DirectiveImplementation { const REQUIRED: &'static [&'static str]; const ALLOWED: &'static [&'static str]; const ALLOW_ANY_UNNAMED: bool; + fn from_parsed(p: &ParsedDirective) -> Self; fn process(&self, site: &Site, meta: &mut PageMeta) -> Result; + + fn prepare(&self, _site: &mut Site) -> Result<(), SiteError> { + Ok(()) + } } #[derive(Debug, Eq, PartialEq)] @@ -92,15 +97,15 @@ impl TryFrom<&ParsedDirective> for Directive { Format::ALLOWED, Format::ALLOW_ANY_UNNAMED, )?; - Directive::Format(Format::from(p)) + Directive::Format(Format::from_parsed(p)) } "graph" => { Self::check_args(p, Graph::REQUIRED, Graph::ALLOWED, Graph::ALLOW_ANY_UNNAMED)?; - Directive::Graph(Graph::from(p)) + Directive::Graph(Graph::from_parsed(p)) } "img" => { Self::check_args(p, Img::REQUIRED, Img::ALLOWED, Img::ALLOW_ANY_UNNAMED)?; - Directive::Img(Img::from(p)) + Directive::Img(Img::from_parsed(p)) } "inline" => { Self::check_args( @@ -109,15 +114,15 @@ impl TryFrom<&ParsedDirective> for Directive { Inline::ALLOWED, Inline::ALLOW_ANY_UNNAMED, )?; - Directive::Inline(Inline::from(p)) + Directive::Inline(Inline::from_parsed(p)) } "map" => { Self::check_args(p, Map::REQUIRED, Map::ALLOWED, Map::ALLOW_ANY_UNNAMED)?; - Directive::Map(Map::from(p)) + Directive::Map(Map::from_parsed(p)) } "meta" => { Self::check_args(p, Meta::REQUIRED, Meta::ALLOWED, Meta::ALLOW_ANY_UNNAMED)?; - Directive::Meta(Meta::from(p)) + Directive::Meta(Meta::from_parsed(p)) } "pagestats" => { Self::check_args( @@ -126,7 +131,7 @@ impl TryFrom<&ParsedDirective> for Directive { PageStats::ALLOWED, PageStats::ALLOW_ANY_UNNAMED, )?; - Directive::PageStats(PageStats::from(p)) + Directive::PageStats(PageStats::from_parsed(p)) } "shortcut" => { Self::check_args( @@ -135,7 +140,7 @@ impl TryFrom<&ParsedDirective> for Directive { Shortcut::ALLOWED, Shortcut::ALLOW_ANY_UNNAMED, )?; - Directive::Shortcut(Shortcut::from(p)) + Directive::Shortcut(Shortcut::from_parsed(p)) } "sidebar" => { Self::check_args( @@ -144,19 +149,19 @@ impl TryFrom<&ParsedDirective> for Directive { Sidebar::ALLOWED, Sidebar::ALLOW_ANY_UNNAMED, )?; - Directive::Sidebar(Sidebar::from(p)) + Directive::Sidebar(Sidebar::from_parsed(p)) } "tag" => { Self::check_args(p, Tag::REQUIRED, Tag::ALLOWED, Tag::ALLOW_ANY_UNNAMED)?; - Directive::Tag(Tag::from(p)) + Directive::Tag(Tag::from_parsed(p)) } "table" => { Self::check_args(p, Table::REQUIRED, Table::ALLOWED, Table::ALLOW_ANY_UNNAMED)?; - Directive::Table(Table::from(p)) + Directive::Table(Table::from_parsed(p)) } "toc" => { Self::check_args(p, Toc::REQUIRED, Toc::ALLOWED, Toc::ALLOW_ANY_UNNAMED)?; - Directive::Toc(Toc::from(p)) + Directive::Toc(Toc::from_parsed(p)) } "traillink" => { Self::check_args( @@ -165,7 +170,7 @@ impl TryFrom<&ParsedDirective> for Directive { TrailLink::ALLOWED, TrailLink::ALLOW_ANY_UNNAMED, )?; - Directive::TrailLink(TrailLink::from(p)) + Directive::TrailLink(TrailLink::from_parsed(p)) } _ => return Err(SiteError::UnknownDirective(p.name().into())), }; diff --git a/src/directive/pagestats.rs b/src/directive/pagestats.rs index 89ba57e..08df39d 100644 --- a/src/directive/pagestats.rs +++ b/src/directive/pagestats.rs @@ -1,3 +1,4 @@ +use crate::directive::DirectiveImplementation; use crate::error::SiteError; use crate::page::PageMeta; use crate::site::Site; @@ -6,22 +7,16 @@ use crate::wikitext::ParsedDirective; #[derive(Debug, Default, Eq, PartialEq)] pub struct PageStats {} -impl PageStats { - pub const REQUIRED: &'static [&'static str] = &["pages"]; - pub const ALLOWED: &'static [&'static str] = &["among", "style"]; - pub const ALLOW_ANY_UNNAMED: bool = true; +impl DirectiveImplementation for PageStats { + const REQUIRED: &'static [&'static str] = &["pages"]; + const ALLOWED: &'static [&'static str] = &["among", "style"]; + const ALLOW_ANY_UNNAMED: bool = true; - pub fn new() -> Self { + fn from_parsed(_: &ParsedDirective) -> Self { Self::default() } - pub fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { + fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { Err(SiteError::UnimplementedDirective("pagestat".into())) } } - -impl From<&ParsedDirective> for PageStats { - fn from(_p: &ParsedDirective) -> Self { - Self::new() - } -} diff --git a/src/directive/shortcut.rs b/src/directive/shortcut.rs index 7b397d4..fa3f783 100644 --- a/src/directive/shortcut.rs +++ b/src/directive/shortcut.rs @@ -1,3 +1,4 @@ +use crate::directive::DirectiveImplementation; use crate::error::SiteError; use crate::page::PageMeta; use crate::site::{Shortcut as S, Site}; @@ -10,32 +11,32 @@ pub struct Shortcut { shortcut: S, } -impl Shortcut { - pub const REQUIRED: &'static [&'static str] = &["name", "url"]; - pub const ALLOWED: &'static [&'static str] = &["desc"]; - pub const ALLOW_ANY_UNNAMED: bool = false; +impl DirectiveImplementation for Shortcut { + const REQUIRED: &'static [&'static str] = &["name", "url"]; + const ALLOWED: &'static [&'static str] = &["desc"]; + const ALLOW_ANY_UNNAMED: bool = false; - pub fn new(shortcut: S) -> Self { - Self { shortcut } + fn from_parsed(p: &ParsedDirective) -> Self { + let args = p.args(); + let name = args.get("name").unwrap(); + let desc = args.get("desc").unwrap_or(&""); + let url = args.get("url").unwrap(); + Self::new(S::new(name, desc, url)) } - pub fn prepare(&self, site: &mut Site) -> Result<(), SiteError> { + fn prepare(&self, site: &mut Site) -> Result<(), SiteError> { trace!("shortcut: prepare"); site.add_shortcut(self.shortcut.clone()); Ok(()) } - pub fn process(&self, _site: &mut Site, _meta: &mut PageMeta) -> Result { + fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { Ok("".into()) } } -impl From<&ParsedDirective> for Shortcut { - fn from(p: &ParsedDirective) -> Self { - let args = p.args(); - let name = args.get("name").unwrap(); - let desc = args.get("desc").unwrap_or(&""); - let url = args.get("url").unwrap(); - Self::new(S::new(name, desc, url)) +impl Shortcut { + pub fn new(shortcut: S) -> Self { + Self { shortcut } } } diff --git a/src/directive/sidebar.rs b/src/directive/sidebar.rs index 5148086..a13292c 100644 --- a/src/directive/sidebar.rs +++ b/src/directive/sidebar.rs @@ -1,3 +1,4 @@ +use crate::directive::DirectiveImplementation; use crate::error::SiteError; use crate::page::PageMeta; use crate::site::Site; @@ -6,18 +7,16 @@ use crate::wikitext::ParsedDirective; #[derive(Debug, Default, Eq, PartialEq)] pub struct Sidebar {} -impl Sidebar { - pub const REQUIRED: &'static [&'static str] = &[]; - pub const ALLOWED: &'static [&'static str] = &["content"]; - pub const ALLOW_ANY_UNNAMED: bool = true; +impl DirectiveImplementation for Sidebar { + const REQUIRED: &'static [&'static str] = &[]; + const ALLOWED: &'static [&'static str] = &["content"]; + const ALLOW_ANY_UNNAMED: bool = true; - pub fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { - Err(SiteError::UnimplementedDirective("sidebar".into())) + fn from_parsed(_: &ParsedDirective) -> Self { + Self::default() } -} -impl From<&ParsedDirective> for Sidebar { - fn from(_: &ParsedDirective) -> Self { - Sidebar::default() + fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { + Err(SiteError::UnimplementedDirective("sidebar".into())) } } diff --git a/src/directive/table.rs b/src/directive/table.rs index 7610a6b..b11a39f 100644 --- a/src/directive/table.rs +++ b/src/directive/table.rs @@ -1,3 +1,4 @@ +use crate::directive::DirectiveImplementation; use crate::error::SiteError; use crate::page::PageMeta; use crate::site::Site; @@ -9,16 +10,16 @@ pub struct Table { data: String, } -impl Table { - pub const REQUIRED: &'static [&'static str] = &["data"]; - pub const ALLOWED: &'static [&'static str] = &[]; - pub const ALLOW_ANY_UNNAMED: bool = true; +impl DirectiveImplementation for Table { + const REQUIRED: &'static [&'static str] = &["data"]; + const ALLOWED: &'static [&'static str] = &[]; + const ALLOW_ANY_UNNAMED: bool = true; - pub fn new(data: String) -> Self { - Self { data } + fn from_parsed(p: &ParsedDirective) -> Self { + Self::new(p.args().get("data").unwrap().to_string()) } - pub fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { + fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { let mut table = String::new(); let mut lines = self.data.trim().lines(); if let Some(first) = lines.next() { @@ -40,8 +41,8 @@ impl Table { } } -impl From<&ParsedDirective> for Table { - fn from(p: &ParsedDirective) -> Self { - Table::new(p.args().get("data").unwrap().to_string()) +impl Table { + pub fn new(data: String) -> Self { + Self { data } } } diff --git a/src/directive/tag.rs b/src/directive/tag.rs index c64acfc..07c92ea 100644 --- a/src/directive/tag.rs +++ b/src/directive/tag.rs @@ -1,3 +1,4 @@ +use crate::directive::DirectiveImplementation; use crate::error::SiteError; use crate::page::PageMeta; use crate::site::Site; @@ -8,23 +9,23 @@ pub struct Tag { tags: Vec, } -impl Tag { - pub const REQUIRED: &'static [&'static str] = &[]; - pub const ALLOWED: &'static [&'static str] = &["class"]; - pub const ALLOW_ANY_UNNAMED: bool = true; +impl DirectiveImplementation for Tag { + const REQUIRED: &'static [&'static str] = &[]; + const ALLOWED: &'static [&'static str] = &["class"]; + const ALLOW_ANY_UNNAMED: bool = true; - pub fn new(tags: Vec) -> Self { - Self { tags } + fn from_parsed(p: &ParsedDirective) -> Self { + let tags = p.unnamed_args().iter().map(|s| s.to_string()).collect(); + Tag::new(tags) } - pub fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { + fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { Ok("".into()) } } -impl From<&ParsedDirective> for Tag { - fn from(p: &ParsedDirective) -> Self { - let tags = p.unnamed_args().iter().map(|s| s.to_string()).collect(); - Tag::new(tags) +impl Tag { + pub fn new(tags: Vec) -> Self { + Self { tags } } } diff --git a/src/directive/toc.rs b/src/directive/toc.rs index af1bba9..ff03b0b 100644 --- a/src/directive/toc.rs +++ b/src/directive/toc.rs @@ -1,3 +1,4 @@ +use crate::directive::DirectiveImplementation; use crate::error::SiteError; use crate::page::PageMeta; use crate::site::Site; @@ -6,22 +7,16 @@ use crate::wikitext::ParsedDirective; #[derive(Debug, Default, Eq, PartialEq)] pub struct Toc {} -impl Toc { - pub const REQUIRED: &'static [&'static str] = &[]; - pub const ALLOWED: &'static [&'static str] = &["levels"]; - pub const ALLOW_ANY_UNNAMED: bool = true; +impl DirectiveImplementation for Toc { + const REQUIRED: &'static [&'static str] = &[]; + const ALLOWED: &'static [&'static str] = &["levels"]; + const ALLOW_ANY_UNNAMED: bool = true; - pub fn new() -> Self { + fn from_parsed(_: &ParsedDirective) -> Self { Self::default() } - pub fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { + fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { Err(SiteError::UnimplementedDirective("toc".into())) } } - -impl From<&ParsedDirective> for Toc { - fn from(_p: &ParsedDirective) -> Self { - Self::new() - } -} diff --git a/src/directive/traillink.rs b/src/directive/traillink.rs index 9acfa6b..492f009 100644 --- a/src/directive/traillink.rs +++ b/src/directive/traillink.rs @@ -1,3 +1,4 @@ +use crate::directive::DirectiveImplementation; use crate::error::SiteError; use crate::page::PageMeta; use crate::site::Site; @@ -6,22 +7,16 @@ use crate::wikitext::ParsedDirective; #[derive(Debug, Default, Eq, PartialEq)] pub struct TrailLink {} -impl TrailLink { - pub const REQUIRED: &'static [&'static str] = &[]; - pub const ALLOWED: &'static [&'static str] = &["text"]; - pub const ALLOW_ANY_UNNAMED: bool = true; +impl DirectiveImplementation for TrailLink { + const REQUIRED: &'static [&'static str] = &[]; + const ALLOWED: &'static [&'static str] = &["text"]; + const ALLOW_ANY_UNNAMED: bool = true; - pub fn new() -> Self { + fn from_parsed(_: &ParsedDirective) -> Self { Self::default() } - pub fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { + fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { Err(SiteError::UnimplementedDirective("traillink".into())) } } - -impl From<&ParsedDirective> for TrailLink { - fn from(_p: &ParsedDirective) -> Self { - Self::new() - } -} -- cgit v1.2.1 From 249323a6009a35dd2e77be794ed45b5f1cf4263f Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Wed, 9 Nov 2022 13:56:37 +0200 Subject: refactor: directive processing returns Processed value Sponsored-by: author --- src/directive/calendar.rs | 4 ++-- src/directive/format.rs | 4 ++-- src/directive/graph.rs | 4 ++-- src/directive/img.rs | 6 +++--- src/directive/inline.rs | 6 +++--- src/directive/map.rs | 4 ++-- src/directive/meta.rs | 6 +++--- src/directive/mod.rs | 7 +++---- src/directive/pagestats.rs | 4 ++-- src/directive/shortcut.rs | 6 +++--- src/directive/sidebar.rs | 4 ++-- src/directive/table.rs | 6 +++--- src/directive/tag.rs | 6 +++--- src/directive/toc.rs | 4 ++-- src/directive/traillink.rs | 4 ++-- 15 files changed, 37 insertions(+), 38 deletions(-) diff --git a/src/directive/calendar.rs b/src/directive/calendar.rs index a3d199a..f29aaf9 100644 --- a/src/directive/calendar.rs +++ b/src/directive/calendar.rs @@ -1,4 +1,4 @@ -use crate::directive::DirectiveImplementation; +use crate::directive::{DirectiveImplementation, Processed}; use crate::error::SiteError; use crate::page::PageMeta; use crate::site::Site; @@ -24,7 +24,7 @@ impl DirectiveImplementation for Calendar { Self::default() } - fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { + fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { Err(SiteError::UnimplementedDirective("calendar".into())) } } diff --git a/src/directive/format.rs b/src/directive/format.rs index f76ba9a..66741ff 100644 --- a/src/directive/format.rs +++ b/src/directive/format.rs @@ -1,4 +1,4 @@ -use crate::directive::DirectiveImplementation; +use crate::directive::{DirectiveImplementation, Processed}; use crate::error::SiteError; use crate::page::PageMeta; use crate::site::Site; @@ -16,7 +16,7 @@ impl DirectiveImplementation for Format { Self::default() } - fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { + fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { Err(SiteError::UnimplementedDirective("format".into())) } } diff --git a/src/directive/graph.rs b/src/directive/graph.rs index e7ae5fe..ae90050 100644 --- a/src/directive/graph.rs +++ b/src/directive/graph.rs @@ -1,4 +1,4 @@ -use crate::directive::DirectiveImplementation; +use crate::directive::{DirectiveImplementation, Processed}; use crate::error::SiteError; use crate::page::PageMeta; use crate::site::Site; @@ -16,7 +16,7 @@ impl DirectiveImplementation for Graph { Self::default() } - fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { + fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { Err(SiteError::UnimplementedDirective("graph".into())) } diff --git a/src/directive/img.rs b/src/directive/img.rs index 29efe0c..8b74e5e 100644 --- a/src/directive/img.rs +++ b/src/directive/img.rs @@ -1,4 +1,4 @@ -use crate::directive::DirectiveImplementation; +use crate::directive::{DirectiveImplementation, Processed}; use crate::error::SiteError; use crate::page::PageMeta; use crate::site::Site; @@ -82,7 +82,7 @@ impl DirectiveImplementation for Img { img } - fn process(&self, site: &Site, meta: &mut PageMeta) -> Result { + fn process(&self, site: &Site, meta: &mut PageMeta) -> Result { trace!( "verify image exists: {} on {}", self.src, @@ -121,7 +121,7 @@ impl DirectiveImplementation for Img { img.push_str(""); } - Ok(img) + Ok(Processed::Markdown(img)) } } diff --git a/src/directive/inline.rs b/src/directive/inline.rs index 0dafa69..9ddeef4 100644 --- a/src/directive/inline.rs +++ b/src/directive/inline.rs @@ -1,4 +1,4 @@ -use crate::directive::DirectiveImplementation; +use crate::directive::{DirectiveImplementation, Processed}; use crate::error::SiteError; use crate::page::PageMeta; use crate::pagespec::PageSpec; @@ -38,7 +38,7 @@ impl DirectiveImplementation for Inline { Inline::new(pages.to_string()) } - fn process(&self, site: &Site, meta: &mut PageMeta) -> Result { + fn process(&self, site: &Site, meta: &mut PageMeta) -> Result { let pagespec = PageSpec::new(meta.path(), &self.pages)?; let matches: Vec = site .markdown_pages() @@ -46,7 +46,7 @@ impl DirectiveImplementation for Inline { .filter(|page| pagespec.matches(site, page.meta().path())) .map(|page| format!("* {}\n", Self::link(meta.path(), page.meta()))) .collect(); - Ok(matches.join("")) + Ok(Processed::Markdown(matches.join(""))) } } diff --git a/src/directive/map.rs b/src/directive/map.rs index 009bf64..e468aad 100644 --- a/src/directive/map.rs +++ b/src/directive/map.rs @@ -1,4 +1,4 @@ -use crate::directive::DirectiveImplementation; +use crate::directive::{DirectiveImplementation, Processed}; use crate::error::SiteError; use crate::page::PageMeta; use crate::site::Site; @@ -16,7 +16,7 @@ impl DirectiveImplementation for Map { Self::default() } - fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { + fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { Err(SiteError::UnimplementedDirective("map".into())) } } diff --git a/src/directive/meta.rs b/src/directive/meta.rs index 1e8ec8c..882288b 100644 --- a/src/directive/meta.rs +++ b/src/directive/meta.rs @@ -1,4 +1,4 @@ -use crate::directive::DirectiveImplementation; +use crate::directive::{DirectiveImplementation, Processed}; use crate::error::SiteError; use crate::page::PageMeta; use crate::site::Site; @@ -28,14 +28,14 @@ impl DirectiveImplementation for Meta { meta } - fn process(&self, _site: &Site, meta: &mut PageMeta) -> Result { + fn process(&self, _site: &Site, meta: &mut PageMeta) -> Result { if let Some(title) = &self.title { meta.set_title(title.into()); } if let Some(mtime) = &self.date { meta.set_mtime(parse_timestamp(mtime)?); } - Ok("".into()) + Ok(Processed::Markdown("".into())) } } diff --git a/src/directive/mod.rs b/src/directive/mod.rs index e885404..c8fe1f7 100644 --- a/src/directive/mod.rs +++ b/src/directive/mod.rs @@ -16,7 +16,7 @@ pub trait DirectiveImplementation { const ALLOW_ANY_UNNAMED: bool; fn from_parsed(p: &ParsedDirective) -> Self; - fn process(&self, site: &Site, meta: &mut PageMeta) -> Result; + fn process(&self, site: &Site, meta: &mut PageMeta) -> Result; fn prepare(&self, _site: &mut Site) -> Result<(), SiteError> { Ok(()) @@ -222,7 +222,7 @@ impl Directive { } pub fn process(&self, site: &mut Site, meta: &mut PageMeta) -> Result { - let markdown = match self { + match self { Self::Simple | Self::UnnamedArg | Self::SimpleArg @@ -244,8 +244,7 @@ impl Directive { Self::Tag(x) => x.process(site, meta), Self::Toc(x) => x.process(site, meta), Self::TrailLink(x) => x.process(site, meta), - }; - Ok(Processed::Markdown(markdown?)) + } } } diff --git a/src/directive/pagestats.rs b/src/directive/pagestats.rs index 08df39d..11edc29 100644 --- a/src/directive/pagestats.rs +++ b/src/directive/pagestats.rs @@ -1,4 +1,4 @@ -use crate::directive::DirectiveImplementation; +use crate::directive::{DirectiveImplementation, Processed}; use crate::error::SiteError; use crate::page::PageMeta; use crate::site::Site; @@ -16,7 +16,7 @@ impl DirectiveImplementation for PageStats { Self::default() } - fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { + fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { Err(SiteError::UnimplementedDirective("pagestat".into())) } } diff --git a/src/directive/shortcut.rs b/src/directive/shortcut.rs index fa3f783..48bc482 100644 --- a/src/directive/shortcut.rs +++ b/src/directive/shortcut.rs @@ -1,4 +1,4 @@ -use crate::directive::DirectiveImplementation; +use crate::directive::{DirectiveImplementation, Processed}; use crate::error::SiteError; use crate::page::PageMeta; use crate::site::{Shortcut as S, Site}; @@ -30,8 +30,8 @@ impl DirectiveImplementation for Shortcut { Ok(()) } - fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { - Ok("".into()) + fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { + Ok(Processed::Markdown("".into())) } } diff --git a/src/directive/sidebar.rs b/src/directive/sidebar.rs index a13292c..1c25144 100644 --- a/src/directive/sidebar.rs +++ b/src/directive/sidebar.rs @@ -1,4 +1,4 @@ -use crate::directive::DirectiveImplementation; +use crate::directive::{DirectiveImplementation, Processed}; use crate::error::SiteError; use crate::page::PageMeta; use crate::site::Site; @@ -16,7 +16,7 @@ impl DirectiveImplementation for Sidebar { Self::default() } - fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { + fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { Err(SiteError::UnimplementedDirective("sidebar".into())) } } diff --git a/src/directive/table.rs b/src/directive/table.rs index b11a39f..2bbfbc8 100644 --- a/src/directive/table.rs +++ b/src/directive/table.rs @@ -1,4 +1,4 @@ -use crate::directive::DirectiveImplementation; +use crate::directive::{DirectiveImplementation, Processed}; use crate::error::SiteError; use crate::page::PageMeta; use crate::site::Site; @@ -19,7 +19,7 @@ impl DirectiveImplementation for Table { Self::new(p.args().get("data").unwrap().to_string()) } - fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { + fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { let mut table = String::new(); let mut lines = self.data.trim().lines(); if let Some(first) = lines.next() { @@ -37,7 +37,7 @@ impl DirectiveImplementation for Table { } debug!("table data: {}", self.data); debug!("table: {}", table); - Ok(table) + Ok(Processed::Markdown(table)) } } diff --git a/src/directive/tag.rs b/src/directive/tag.rs index 07c92ea..6d4377d 100644 --- a/src/directive/tag.rs +++ b/src/directive/tag.rs @@ -1,4 +1,4 @@ -use crate::directive::DirectiveImplementation; +use crate::directive::{DirectiveImplementation, Processed}; use crate::error::SiteError; use crate::page::PageMeta; use crate::site::Site; @@ -19,8 +19,8 @@ impl DirectiveImplementation for Tag { Tag::new(tags) } - fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { - Ok("".into()) + fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { + Ok(Processed::Markdown("".into())) } } diff --git a/src/directive/toc.rs b/src/directive/toc.rs index ff03b0b..e00cb24 100644 --- a/src/directive/toc.rs +++ b/src/directive/toc.rs @@ -1,4 +1,4 @@ -use crate::directive::DirectiveImplementation; +use crate::directive::{DirectiveImplementation, Processed}; use crate::error::SiteError; use crate::page::PageMeta; use crate::site::Site; @@ -16,7 +16,7 @@ impl DirectiveImplementation for Toc { Self::default() } - fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { + fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { Err(SiteError::UnimplementedDirective("toc".into())) } } diff --git a/src/directive/traillink.rs b/src/directive/traillink.rs index 492f009..b3e8cb7 100644 --- a/src/directive/traillink.rs +++ b/src/directive/traillink.rs @@ -1,4 +1,4 @@ -use crate::directive::DirectiveImplementation; +use crate::directive::{DirectiveImplementation, Processed}; use crate::error::SiteError; use crate::page::PageMeta; use crate::site::Site; @@ -16,7 +16,7 @@ impl DirectiveImplementation for TrailLink { Self::default() } - fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { + fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { Err(SiteError::UnimplementedDirective("traillink".into())) } } -- cgit v1.2.1 From 8f17b2a721d2369691ff2e3d4950a436aa9533ab Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Wed, 9 Nov 2022 15:56:55 +0200 Subject: feat: implement rudimentary table of contents, without links The links will be added later. Sponsored-by: author --- riki.md | 20 +++++++++++++++ src/directive/mod.rs | 3 ++- src/directive/toc.rs | 72 +++++++++++++++++++++++++++++++++++++++++++++++++--- src/error.rs | 3 +++ src/html.rs | 8 ++++-- src/page.rs | 21 +++++++++++++-- src/wikitext.rs | 21 ++++++++------- 7 files changed, 128 insertions(+), 20 deletions(-) diff --git a/riki.md b/riki.md index 4c78f11..980e5b4 100644 --- a/riki.md +++ b/riki.md @@ -677,6 +677,26 @@ goodbye | cruel world """]] ~~~ +### `toc` + +_Requirement: the `toc` directive creates a table of contents._ + +~~~scenario +given an installed riki +given file site/index.mdwn from toc +when I run riki build site output +when I run cat output/index.html +then file output/index.html contains "
  • Introduction
  • " +then file output/index.html contains "
  • Acknowledgements
  • " +~~~ + +~~~{#toc .file .markdown} +[[!toc]] + +# Introduction +## Acknowledgements +~~~ + ## Source file tree ### Listing source files diff --git a/src/directive/mod.rs b/src/directive/mod.rs index c8fe1f7..ae2dc09 100644 --- a/src/directive/mod.rs +++ b/src/directive/mod.rs @@ -8,6 +8,7 @@ use std::collections::HashSet; pub enum Processed { Markdown(String), + Toc(usize), } pub trait DirectiveImplementation { @@ -279,7 +280,7 @@ mod tag; use tag::Tag; mod toc; -use toc::Toc; +pub use toc::Toc; mod traillink; use traillink::TrailLink; diff --git a/src/directive/toc.rs b/src/directive/toc.rs index e00cb24..f027931 100644 --- a/src/directive/toc.rs +++ b/src/directive/toc.rs @@ -1,22 +1,86 @@ use crate::directive::{DirectiveImplementation, Processed}; use crate::error::SiteError; +use crate::html::{Content, Element, ElementTag}; use crate::page::PageMeta; use crate::site::Site; use crate::wikitext::ParsedDirective; #[derive(Debug, Default, Eq, PartialEq)] -pub struct Toc {} +pub struct Toc { + levels: String, +} impl DirectiveImplementation for Toc { const REQUIRED: &'static [&'static str] = &[]; const ALLOWED: &'static [&'static str] = &["levels"]; const ALLOW_ANY_UNNAMED: bool = true; - fn from_parsed(_: &ParsedDirective) -> Self { - Self::default() + fn from_parsed(p: &ParsedDirective) -> Self { + let args = p.args(); + let levels = args.get("levels").unwrap_or(&"9"); + Self::new(levels.to_string()) } fn process(&self, _site: &Site, _meta: &mut PageMeta) -> Result { - Err(SiteError::UnimplementedDirective("toc".into())) + let levels: usize = self + .levels + .parse() + .map_err(|e| SiteError::LevelsParse(self.levels.clone(), e))?; + Ok(Processed::Toc(levels)) + } +} + +impl Toc { + fn new(levels: String) -> Self { + Self { levels } + } + + pub fn post_process(html: &Element, levels: usize) -> String { + let headings: Vec<(usize, &[Content])> = html + .children() + .iter() + .filter_map(|c| match c { + Content::Elt(e) => Some(e), + _ => None, + }) + .filter_map(|e| match e.tag() { + ElementTag::H1 => Some((1, e.children())), + ElementTag::H2 => Some((2, e.children())), + ElementTag::H3 => Some((3, e.children())), + ElementTag::H4 => Some((4, e.children())), + ElementTag::H5 => Some((5, e.children())), + ElementTag::H6 => Some((6, e.children())), + _ => None, + }) + .collect(); + let mut html = String::new(); + let mut prev_level: usize = 0; + for (level, text) in headings.iter() { + if *level > levels { + continue; + } else if *level > prev_level { + html.push_str("
      "); + } else if *level < prev_level { + html.push_str("
    \n"); + } + html.push_str("
  • "); + Self::stringify(&mut html, text); + html.push_str("
  • \n"); + prev_level = *level; + } + for _ in 0..prev_level { + html.push_str("\n"); + } + html + } + + fn stringify(buf: &mut String, bits: &[Content]) { + for c in bits.iter() { + match c { + Content::Text(s) => buf.push_str(s), + Content::Elt(e) => Self::stringify(buf, e.children()), + Content::Html(h) => buf.push_str(h), + } + } } } diff --git a/src/error.rs b/src/error.rs index 90046b2..d58924e 100644 --- a/src/error.rs +++ b/src/error.rs @@ -91,6 +91,9 @@ pub enum SiteError { #[error("directive isn't implemented yet: {0}")] UnimplementedDirective(String), + + #[error("toc directive arguments 'levels' could not be parsed as an integer: {0}")] + LevelsParse(String, #[source] std::num::ParseIntError), } impl SiteError { diff --git a/src/html.rs b/src/html.rs index 6605333..6d4d009 100644 --- a/src/html.rs +++ b/src/html.rs @@ -236,7 +236,11 @@ impl Element { self.children.push(child); } - fn children(&self) -> &[Content] { + pub fn tag(&self) -> ElementTag { + self.tag + } + + pub fn children(&self) -> &[Content] { &self.children } @@ -306,7 +310,7 @@ impl Element { } } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum ElementTag { Html, Head, diff --git a/src/page.rs b/src/page.rs index fb2159d..832e71e 100644 --- a/src/page.rs +++ b/src/page.rs @@ -1,3 +1,4 @@ +use crate::directive::{Processed, Toc}; use crate::error::SiteError; use crate::html::{parse, Content, Element, ElementTag, HtmlPage}; use crate::name::Name; @@ -84,10 +85,26 @@ impl UnprocessedPage { pub fn process(&self, site: &mut Site) -> Result { let mut meta = self.meta.clone(); - let mut m = String::new(); + let mut processed = vec![]; trace!("UnprocessedPage: processing snippets"); for snippet in self.snippets.iter() { - m.push_str(&snippet.process(site, &mut meta)?); + processed.push(snippet.process(site, &mut meta)?); + } + let page_text = processed + .iter() + .filter_map(|p| match p { + Processed::Markdown(s) => Some(s.as_str()), + _ => None, + }) + .collect::>() + .join(""); + let body = parse(&page_text)?; + let mut m = String::new(); + for p in processed { + match p { + Processed::Markdown(s) => m.push_str(&s), + Processed::Toc(levels) => m.push_str(&Toc::post_process(&body, levels)), + } } Ok(MarkdownPage::new(m, meta)) } diff --git a/src/wikitext.rs b/src/wikitext.rs index 25da818..b78cd66 100644 --- a/src/wikitext.rs +++ b/src/wikitext.rs @@ -29,34 +29,33 @@ impl Snippet { Ok(()) } - pub fn process(&self, site: &mut Site, meta: &mut PageMeta) -> Result { + pub fn process(&self, site: &mut Site, meta: &mut PageMeta) -> Result { trace!("Snippet::process: self={:?}", self); - let s = match self { - Snippet::Markdown(text) => text.into(), + let processed = match self { + Snippet::Markdown(text) => Processed::Markdown(text.into()), Snippet::WikiLink(w) => { let resolved = site .resolve(meta.path(), Path::new(w.target())) .map_err(|e| SiteError::PageProblem(meta.path().into(), Box::new(e)))?; trace!("resolved {} to {}", w.target(), resolved.display()); - format!("[{}]({})", w.link_text(), resolved.display()) + let link = format!("[{}]({})", w.link_text(), resolved.display()); + Processed::Markdown(link) } Snippet::Directive(p) => { let e = Directive::try_from(p); if let Ok(d) = e { - let processed = d.process(site, meta) - .map_err(|e| SiteError::PageProblem(meta.path().into(), Box::new(e)))?; - match processed { - Processed::Markdown(s) => s, - } + d.process(site, meta) + .map_err(|e| SiteError::PageProblem(meta.path().into(), Box::new(e)))? } else if let Some(shortcut) = site.shortcut(p.name()) { let arg = p.unnamed_args().first().unwrap().to_string(); - format!("[{}]({})", shortcut.desc(&arg), shortcut.url(&arg)) + let link = format!("[{}]({})", shortcut.desc(&arg), shortcut.url(&arg)); + Processed::Markdown(link) } else { return Err(e.unwrap_err()); } } }; - Ok(s) + Ok(processed) } } -- cgit v1.2.1