make tairu work better with noscript
This commit is contained in:
parent
90de54c359
commit
a92ae02454
22 changed files with 404 additions and 238 deletions
|
@ -13,9 +13,10 @@ clap = { version = "4.3.22", features = ["derive"] }
|
|||
codespan-reporting = "0.11.1"
|
||||
copy_dir = "0.1.3"
|
||||
env_logger = "0.10.0"
|
||||
log = { workspace = true }
|
||||
handlebars = "4.3.7"
|
||||
http-body = "1.0.0"
|
||||
image = "0.24.8"
|
||||
log = { workspace = true }
|
||||
pulldown-cmark = { version = "0.9.3", default-features = false }
|
||||
rand = "0.8.5"
|
||||
serde = { version = "1.0.183", features = ["derive"] }
|
||||
|
|
|
@ -18,7 +18,7 @@ use walkdir::WalkDir;
|
|||
|
||||
use crate::{
|
||||
cli::parse::parse_tree_with_diagnostics,
|
||||
config::Config,
|
||||
config::{Config, ConfigDerivedData},
|
||||
html::{
|
||||
breadcrumbs::breadcrumbs_to_html,
|
||||
navmap::{build_navigation_map, NavigationMap},
|
||||
|
@ -175,6 +175,7 @@ impl Generator {
|
|||
parsed_trees: impl IntoIterator<Item = ParsedTree>,
|
||||
) -> anyhow::Result<()> {
|
||||
let mut handlebars = Handlebars::new();
|
||||
let mut config_derived_data = ConfigDerivedData::default();
|
||||
|
||||
let mut template_file_ids = HashMap::new();
|
||||
for entry in WalkDir::new(paths.template_dir) {
|
||||
|
@ -232,6 +233,7 @@ impl Generator {
|
|||
&mut tree,
|
||||
treehouse,
|
||||
config,
|
||||
&mut config_derived_data,
|
||||
parsed_tree.file_id,
|
||||
&roots.branches,
|
||||
);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::{collections::HashMap, ffi::OsStr, path::Path};
|
||||
use std::{collections::HashMap, ffi::OsStr, fs::File, io::BufReader, path::Path};
|
||||
|
||||
use anyhow::Context;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -108,3 +108,36 @@ impl Config {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Data derived from the config.
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct ConfigDerivedData {
|
||||
pub pic_sizes: HashMap<String, Option<PicSize>>,
|
||||
}
|
||||
|
||||
/// Picture size. This is useful for emitting <img> elements with a specific size to eliminate layout shifting.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct PicSize {
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
}
|
||||
|
||||
impl ConfigDerivedData {
|
||||
fn read_pic_size(config: &Config, pic_id: &str) -> Option<PicSize> {
|
||||
let pic_filename = config.pics.get(pic_id)?;
|
||||
let (width, height) = image::io::Reader::new(BufReader::new(
|
||||
File::open(format!("static/pic/{pic_filename}")).ok()?,
|
||||
))
|
||||
.into_dimensions()
|
||||
.ok()?;
|
||||
Some(PicSize { width, height })
|
||||
}
|
||||
|
||||
pub fn pic_size(&mut self, config: &Config, pic_id: &str) -> Option<PicSize> {
|
||||
if !self.pic_sizes.contains_key(pic_id) {
|
||||
self.pic_sizes
|
||||
.insert(pic_id.to_owned(), Self::read_pic_size(config, pic_id));
|
||||
}
|
||||
self.pic_sizes.get(pic_id).copied().flatten()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ use pulldown_cmark::escape::{escape_href, escape_html, StrWrite};
|
|||
use pulldown_cmark::{Alignment, CodeBlockKind, Event, LinkType, Tag};
|
||||
use pulldown_cmark::{CowStr, Event::*};
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::config::{Config, ConfigDerivedData, PicSize};
|
||||
use crate::state::Treehouse;
|
||||
|
||||
enum TableState {
|
||||
|
@ -41,6 +41,7 @@ enum TableState {
|
|||
struct HtmlWriter<'a, I, W> {
|
||||
treehouse: &'a Treehouse,
|
||||
config: &'a Config,
|
||||
config_derived_data: &'a mut ConfigDerivedData,
|
||||
page_id: &'a str,
|
||||
|
||||
/// Iterator supplying events.
|
||||
|
@ -68,6 +69,7 @@ where
|
|||
fn new(
|
||||
treehouse: &'a Treehouse,
|
||||
config: &'a Config,
|
||||
config_derived_data: &'a mut ConfigDerivedData,
|
||||
page_id: &'a str,
|
||||
iter: I,
|
||||
writer: W,
|
||||
|
@ -75,7 +77,9 @@ where
|
|||
Self {
|
||||
treehouse,
|
||||
config,
|
||||
config_derived_data,
|
||||
page_id,
|
||||
|
||||
iter,
|
||||
writer,
|
||||
end_newline: true,
|
||||
|
@ -247,11 +251,11 @@ where
|
|||
kind,
|
||||
program_name,
|
||||
} => {
|
||||
self.write(match kind {
|
||||
self.write(match &kind {
|
||||
LiterateCodeKind::Input => {
|
||||
"<th-literate-program data-mode=\"input\" "
|
||||
}
|
||||
LiterateCodeKind::Output => {
|
||||
LiterateCodeKind::Output { .. } => {
|
||||
"<th-literate-program data-mode=\"output\" "
|
||||
}
|
||||
})?;
|
||||
|
@ -261,7 +265,30 @@ where
|
|||
escape_html(&mut self.writer, program_name)?;
|
||||
self.write("\" data-language=\"")?;
|
||||
escape_html(&mut self.writer, language)?;
|
||||
self.write("\" role=\"code\">")
|
||||
self.write("\" role=\"code\">")?;
|
||||
|
||||
if let LiterateCodeKind::Output { placeholder_pic_id } = kind {
|
||||
if !placeholder_pic_id.is_empty() {
|
||||
self.write(
|
||||
"<img class=\"placeholder\" loading=\"lazy\" src=\"",
|
||||
)?;
|
||||
escape_html(
|
||||
&mut self.writer,
|
||||
&self.config.pic_url(placeholder_pic_id),
|
||||
)?;
|
||||
self.write("\"")?;
|
||||
if let Some(PicSize { width, height }) = self
|
||||
.config_derived_data
|
||||
.pic_size(self.config, placeholder_pic_id)
|
||||
{
|
||||
self.write(&format!(
|
||||
" width=\"{width}\" height=\"{height}\""
|
||||
))?;
|
||||
}
|
||||
self.write(">")?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
},
|
||||
CodeBlockKind::Indented => self.write("<pre><code>"),
|
||||
|
@ -556,9 +583,9 @@ where
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
enum LiterateCodeKind {
|
||||
enum LiterateCodeKind<'a> {
|
||||
Input,
|
||||
Output,
|
||||
Output { placeholder_pic_id: &'a str },
|
||||
}
|
||||
|
||||
enum CodeBlockMode<'a> {
|
||||
|
@ -568,7 +595,7 @@ enum CodeBlockMode<'a> {
|
|||
},
|
||||
LiterateProgram {
|
||||
language: &'a str,
|
||||
kind: LiterateCodeKind,
|
||||
kind: LiterateCodeKind<'a>,
|
||||
program_name: &'a str,
|
||||
},
|
||||
}
|
||||
|
@ -578,14 +605,16 @@ impl<'a> CodeBlockMode<'a> {
|
|||
if language.is_empty() {
|
||||
CodeBlockMode::PlainText
|
||||
} else if let Some((language, program_name)) = language.split_once(' ') {
|
||||
let (program_name, placeholder_pic_id) =
|
||||
program_name.split_once(' ').unwrap_or((program_name, ""));
|
||||
CodeBlockMode::LiterateProgram {
|
||||
language,
|
||||
kind: if language == "output" {
|
||||
LiterateCodeKind::Output
|
||||
LiterateCodeKind::Output { placeholder_pic_id }
|
||||
} else {
|
||||
LiterateCodeKind::Input
|
||||
},
|
||||
program_name,
|
||||
program_name: program_name.split(' ').next().unwrap(),
|
||||
}
|
||||
} else {
|
||||
CodeBlockMode::SyntaxHighlightOnly { language }
|
||||
|
@ -624,12 +653,13 @@ pub fn push_html<'a, I>(
|
|||
s: &mut String,
|
||||
treehouse: &'a Treehouse,
|
||||
config: &'a Config,
|
||||
config_derived_data: &'a mut ConfigDerivedData,
|
||||
page_id: &'a str,
|
||||
iter: I,
|
||||
) where
|
||||
I: Iterator<Item = Event<'a>>,
|
||||
{
|
||||
HtmlWriter::new(treehouse, config, page_id, iter, s)
|
||||
HtmlWriter::new(treehouse, config, config_derived_data, page_id, iter, s)
|
||||
.run()
|
||||
.unwrap();
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use pulldown_cmark::{BrokenLink, LinkType};
|
|||
use treehouse_format::pull::BranchKind;
|
||||
|
||||
use crate::{
|
||||
config::Config,
|
||||
config::{Config, ConfigDerivedData},
|
||||
html::EscapeAttribute,
|
||||
state::{FileId, Treehouse},
|
||||
tree::{
|
||||
|
@ -19,6 +19,7 @@ pub fn branch_to_html(
|
|||
s: &mut String,
|
||||
treehouse: &mut Treehouse,
|
||||
config: &Config,
|
||||
config_derived_data: &mut ConfigDerivedData,
|
||||
file_id: FileId,
|
||||
branch_id: SemaBranchId,
|
||||
) {
|
||||
|
@ -145,6 +146,7 @@ pub fn branch_to_html(
|
|||
s,
|
||||
treehouse,
|
||||
config,
|
||||
config_derived_data,
|
||||
treehouse.tree_path(file_id).expect(".tree file expected"),
|
||||
markdown_parser,
|
||||
);
|
||||
|
@ -197,7 +199,7 @@ pub fn branch_to_html(
|
|||
let num_children = branch.children.len();
|
||||
for i in 0..num_children {
|
||||
let child_id = treehouse.tree.branch(branch_id).children[i];
|
||||
branch_to_html(s, treehouse, config, file_id, child_id);
|
||||
branch_to_html(s, treehouse, config, config_derived_data, file_id, child_id);
|
||||
}
|
||||
s.push_str("</ul>");
|
||||
}
|
||||
|
@ -213,12 +215,13 @@ pub fn branches_to_html(
|
|||
s: &mut String,
|
||||
treehouse: &mut Treehouse,
|
||||
config: &Config,
|
||||
config_derived_data: &mut ConfigDerivedData,
|
||||
file_id: FileId,
|
||||
branches: &[SemaBranchId],
|
||||
) {
|
||||
s.push_str("<ul>");
|
||||
for &child in branches {
|
||||
branch_to_html(s, treehouse, config, file_id, child);
|
||||
branch_to_html(s, treehouse, config, config_derived_data, file_id, child);
|
||||
}
|
||||
s.push_str("</ul>");
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue