use crate::error::SiteError;
use crate::html::{parse, Content, Element, ElementTag, HtmlPage};
use crate::name::Name;
use crate::parser::WikitextParser;
use crate::site::Site;
use crate::util::get_mtime;
use crate::wikitext::Snippet;
use log::{info, trace};
use std::path::{Path, PathBuf};
use std::time::SystemTime;
#[derive(Debug, Eq, PartialEq)]
pub struct WikitextPage {
meta: PageMeta,
wikitext: String,
}
impl WikitextPage {
pub fn new(meta: PageMeta, wikitext: String) -> Self {
Self { meta, wikitext }
}
pub fn read(name: &Name) -> Result {
info!("input file: {}", name);
let src = name.source_path();
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)?;
let meta = MetaBuilder::default()
.name(name.clone())
.mtime(mtime)
.build();
Ok(Self::new(meta, wikitext))
}
pub fn meta(&self) -> &PageMeta {
&self.meta
}
pub fn meta_mut(&mut self) -> &mut PageMeta {
&mut self.meta
}
pub fn wikitext(&self) -> &str {
&self.wikitext
}
}
#[derive(Debug)]
pub struct UnprocessedPage {
meta: PageMeta,
snippets: Vec,
}
impl UnprocessedPage {
pub fn new(meta: PageMeta, parser: &mut WikitextParser) -> Result {
Ok(Self {
meta,
snippets: Self::snippets(parser)?,
})
}
pub fn meta(&self) -> &PageMeta {
&self.meta
}
fn snippets(parser: &mut WikitextParser) -> Result, SiteError> {
let mut snippets = vec![];
while let Some(snippet) = parser.parse()? {
snippets.push(snippet);
}
Ok(snippets)
}
pub fn process(&self, site: &mut Site) -> Result {
let mut meta = self.meta.clone();
let mut m = String::new();
for snippet in self.snippets.iter() {
m.push_str(&snippet.process(site, &mut meta)?);
}
Ok(MarkdownPage::new(m, meta))
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct MarkdownPage {
meta: PageMeta,
markdown: String,
}
impl MarkdownPage {
fn new(markdown: String, meta: PageMeta) -> Self {
Self { markdown, meta }
}
pub fn markdown(&self) -> &str {
&self.markdown
}
pub fn meta(&self) -> &PageMeta {
&self.meta
}
pub fn body_to_html(&self) -> Result {
let head = Element::new(ElementTag::Head);
let body = parse(self.markdown())?;
Ok(HtmlPage::new(head, body))
}
pub fn to_html(&self) -> Result {
let mut title = Element::new(ElementTag::Title);
title.push_child(Content::Text(self.meta.title().into()));
let mut head = Element::new(ElementTag::Head);
head.push_child(Content::Elt(title));
let body = parse(self.markdown())?;
trace!("MarkdownPage::to_html: head={:?}", head);
Ok(HtmlPage::new(head, body))
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct PageMeta {
name: Name,
title: Option,
mtime: SystemTime,
}
impl PageMeta {
fn new(name: Name, title: Option, mtime: SystemTime) -> Self {
trace!(
"PageMeta: name={:?} title={:?} mtime={:?}",
name,
title,
mtime,
);
Self { name, title, mtime }
}
pub fn destination_filename(&self) -> PathBuf {
self.name.destination_path().into()
}
pub fn set_title(&mut self, title: String) {
trace!("PageMeta::set_title: title={:?}", title);
self.title = Some(title);
}
pub fn title(&self) -> &str {
if let Some(title) = &self.title {
title
} else {
self.name.page_name()
}
}
pub fn path(&self) -> &Path {
self.name.page_path()
}
pub fn mtime(&self) -> SystemTime {
self.mtime
}
pub fn set_mtime(&mut self, mtime: SystemTime) {
self.mtime = mtime;
}
}
#[derive(Debug, Default)]
pub struct MetaBuilder {
name: Option,
title: Option,
mtime: Option,
}
impl MetaBuilder {
pub fn build(self) -> PageMeta {
PageMeta::new(
self.name.expect("name set on MetaBuilder"),
self.title,
self.mtime.expect("mtime set on MetaBuilder"),
)
}
pub fn name(mut self, name: Name) -> Self {
self.name = Some(name);
self
}
pub fn title(mut self, title: String) -> Self {
self.title = Some(title);
self
}
pub fn mtime(mut self, mtime: SystemTime) -> Self {
self.mtime = Some(mtime);
self
}
}