Compare commits

...

3 Commits

Author SHA1 Message Date
xfnw 70f240a656 html: add chat boxes 2024-04-10 14:14:20 -04:00
xfnw 9b7c421568 html: reorganize Handler a bit 2024-04-10 12:35:43 -04:00
xfnw 4bc535da57 css: add missed FIXME 2024-04-10 12:33:35 -04:00
3 changed files with 79 additions and 30 deletions

View File

@ -7,7 +7,10 @@ use slugify::slugify;
use std::cmp::min;
#[derive(Default)]
pub struct Handler(pub HtmlExport);
pub struct Handler {
pub exp: HtmlExport,
pub numdir: usize,
}
impl Traverser for Handler {
fn event(&mut self, event: Event, ctx: &mut TraversalContext) {
@ -28,13 +31,13 @@ impl Traverser for Handler {
slugify!(&txt)
};
self.0.push_str(format!(
self.exp.push_str(format!(
r##"<h{} id="{1}"><a role=none href="#{1}">{2}</a> "##,
lvl, id, lead
));
if let Some(keyword) = headline.todo_keyword() {
self.0.push_str(match headline.todo_type() {
self.exp.push_str(match headline.todo_type() {
Some(TodoType::Todo) => {
format!("<span class=todo>{}</span> ", HtmlEscape(keyword.as_ref()))
}
@ -49,7 +52,7 @@ impl Traverser for Handler {
self.element(e, ctx);
}
self.0.push_str(format!("</h{}>", lvl));
self.exp.push_str(format!("</h{}>", lvl));
}
// why does the default HtmlExport output keywords with literally
// zero formatting? no idea! let's instead not output them at all.
@ -75,51 +78,83 @@ impl Traverser for Handler {
if link.is_image() {
if let Some(Some(caption)) = link.caption().map(|c| c.value()) {
self.0.push_str(format!(
self.exp.push_str(format!(
r#"<img src="{}" alt="{}">"#,
HtmlEscape(&path),
HtmlEscape(caption.trim())
));
} else {
self.0
self.exp
.push_str(format!("<img src=\"{}\">", HtmlEscape(&path)));
}
return ctx.skip();
}
self.0
self.exp
.push_str(format!("<a href=\"{}\">", HtmlEscape(&path)));
if !link.has_description() {
self.0.push_str(format!("{}</a>", HtmlEscape(&path)));
self.exp.push_str(format!("{}</a>", HtmlEscape(&path)));
ctx.skip();
}
}
Event::Enter(Container::SpecialBlock(block)) => {
if let Some(Some(name)) = block.syntax().first_child().map(|n| {
n.children_with_tokens()
.filter_map(|t| t.into_token())
.nth(1)
}) {
self.0
.push_str(format!("<div class=\"{}\">", HtmlEscape(&name.text())));
if let Some(mut par) = block
.syntax()
.first_child()
.map(|n| n.children_with_tokens().filter_map(|t| t.into_token()))
{
if let Some(name) = par.nth(1) {
let name = name.text();
// strip off some exterior formatting
for child in block.syntax().children() {
for sub in child.children() {
for e in sub.children_with_tokens() {
self.element(e, ctx);
self.exp
.push_str(format!("<div class=\"{}\">", HtmlEscape(&name)));
if name.eq_ignore_ascii_case("chat") {
if let Some(usr) = par.next() {
let usr = usr.text().trim();
if !usr.is_empty() {
self.exp.push_str(
"<img class=chat-head aria-hidden=true width=42 src=\"",
);
for _ in 1..self.numdir {
self.exp.push_str("../");
}
self.exp.push_str(format!(
r#"faces/{}.png"><span class=chat-nick aria-label="{1} says">&lt;{1}&gt;</span> "#,
slugify!(usr), HtmlEscape(usr.rsplit_once('/').map_or(usr, |u| u.0))
));
}
}
}
}
self.0.push_str("</div>");
self.output_block_children(block, ctx);
self.exp.push_str("</div>");
}
}
ctx.skip();
}
Event::Enter(Container::Subscript(_)) => self.0.push_str("_"),
Event::Enter(Container::Subscript(_)) => self.exp.push_str("_"),
Event::Leave(Container::Subscript(_)) => (),
_ => self.0.event(event, ctx),
_ => self.exp.event(event, ctx),
};
}
}
impl Handler {
/// output children while stripping off some exterior formatting
fn output_block_children(
&mut self,
block: orgize::ast::SpecialBlock,
ctx: &mut TraversalContext,
) {
for child in block.syntax().children() {
for sub in child.children() {
for e in sub.children_with_tokens() {
self.element(e, ctx);
}
}
}
}
}

View File

@ -88,14 +88,19 @@ fn generate(
ctime.get(&full_path).ok_or("missing creation time")?;
let modified = mtime.get(&full_path).ok_or("missing modification time")?.0;
let mut html_export = html::Handler::default();
let numdir = full_path.iter().count();
let mut html_export = html::Handler {
numdir,
..Default::default()
};
res.traverse(&mut html_export);
let old_page = modified.seconds() - year_ago < 0;
let template = PageHtml {
title: title.clone(),
body: html_export.0.finish(),
body: html_export.exp.finish(),
commit: short_id,
author,
created: DateTime::from_timestamp(created.seconds(), 0)
@ -104,7 +109,7 @@ fn generate(
modified: DateTime::from_timestamp(modified.seconds(), 0)
.ok_or("broken modification date")?
.naive_utc(),
numdir: full_path.iter().count(),
numdir,
old_page,
};

View File

@ -35,11 +35,11 @@ code, kbd, pre, textarea {
color: #eee;
}
code, kbd, pre, .flex div, .box, textarea {
code, kbd, pre, .flex div, .box, .chat, textarea {
background: #222;
}
.box, .alert, .warning, .fixme {
.box, .alert, .warning, .chat, .fixme, .FIXME {
padding: 10px;
margin-top: 10px;
}
@ -143,6 +143,15 @@ img {
float: left;
}
.chat-head {
margin-right: 10px;
vertical-align: middle;
}
.chat-nick {
font-weight: bold;
}
@media (prefers-color-scheme: light) {
body {
background: white;
@ -167,7 +176,7 @@ img {
code, kbd, pre, textarea {
color: #111;
}
code, kbd, pre, .flex div, .box, textarea {
code, kbd, pre, .flex div, .box, .chat, textarea {
background: #ddd;
}
blockquote {