i don't rember

This commit is contained in:
liquidex 2023-08-21 21:12:06 +02:00
parent 782758f7e7
commit 02d2010808
9 changed files with 84 additions and 36 deletions

View file

@ -105,7 +105,7 @@ pub fn fix_file(
file_id: FileId, file_id: FileId,
) -> Result<String, parse::ErrorsEmitted> { ) -> Result<String, parse::ErrorsEmitted> {
parse_tree_with_diagnostics(treehouse, file_id).map(|roots| { parse_tree_with_diagnostics(treehouse, file_id).map(|roots| {
let mut source = treehouse.get_source(file_id).to_owned(); let mut source = treehouse.source(file_id).to_owned();
let mut state = State::default(); let mut state = State::default();
for branch in &roots.branches { for branch in &roots.branches {
@ -129,14 +129,14 @@ pub fn fix_file_cli(fix_args: FixArgs) -> anyhow::Result<()> {
let file = std::fs::read_to_string(&fix_args.file).context("cannot read file to fix")?; let file = std::fs::read_to_string(&fix_args.file).context("cannot read file to fix")?;
let mut treehouse = Treehouse::new(); let mut treehouse = Treehouse::new();
let file_id = treehouse.files.add(utf8_filename, file); let file_id = treehouse.add_file(utf8_filename, None, file);
if let Ok(fixed) = fix_file(&mut treehouse, file_id) { if let Ok(fixed) = fix_file(&mut treehouse, file_id) {
if fix_args.apply { if fix_args.apply {
// Try to write the backup first. If writing that fails, bail out without overwriting // Try to write the backup first. If writing that fails, bail out without overwriting
// the source file. // the source file.
if let Some(backup_path) = fix_args.backup { if let Some(backup_path) = fix_args.backup {
std::fs::write(backup_path, treehouse.get_source(file_id)) std::fs::write(backup_path, treehouse.source(file_id))
.context("cannot write backup; original file will not be overwritten")?; .context("cannot write backup; original file will not be overwritten")?;
} }
std::fs::write(&fix_args.file, fixed).context("cannot overwrite original file")?; std::fs::write(&fix_args.file, fixed).context("cannot overwrite original file")?;

View file

@ -11,7 +11,7 @@ pub fn parse_tree_with_diagnostics(
treehouse: &mut Treehouse, treehouse: &mut Treehouse,
file_id: FileId, file_id: FileId,
) -> Result<Roots, ErrorsEmitted> { ) -> Result<Roots, ErrorsEmitted> {
let input = treehouse.get_source(file_id); let input = treehouse.source(file_id);
Roots::parse(&mut treehouse_format::pull::Parser { input, position: 0 }).map_err(|error| { Roots::parse(&mut treehouse_format::pull::Parser { input, position: 0 }).map_err(|error| {
treehouse.diagnostics.push(Diagnostic { treehouse.diagnostics.push(Diagnostic {
severity: Severity::Error, severity: Severity::Error,
@ -34,7 +34,7 @@ pub fn parse_toml_with_diagnostics(
file_id: FileId, file_id: FileId,
range: Range<usize>, range: Range<usize>,
) -> Result<toml_edit::Document, ErrorsEmitted> { ) -> Result<toml_edit::Document, ErrorsEmitted> {
let input = &treehouse.get_source(file_id)[range.clone()]; let input = &treehouse.source(file_id)[range.clone()];
toml_edit::Document::from_str(input).map_err(|error| { toml_edit::Document::from_str(input).map_err(|error| {
treehouse treehouse
.diagnostics .diagnostics

View file

@ -45,14 +45,8 @@ impl Generator {
) -> anyhow::Result<FileId> { ) -> anyhow::Result<FileId> {
let source = std::fs::read_to_string(path) let source = std::fs::read_to_string(path)
.with_context(|| format!("cannot read template file {path:?}"))?; .with_context(|| format!("cannot read template file {path:?}"))?;
let file_id = treehouse let file_id = treehouse.add_file(path.to_string_lossy().into_owned(), None, source);
.files let source = treehouse.source(file_id);
.add(path.to_string_lossy().into_owned(), source);
let file = treehouse
.files
.get(file_id)
.expect("file was just added to the list");
let source = file.source();
if let Err(error) = handlebars.register_template_string(name, source) { if let Err(error) = handlebars.register_template_string(name, source) {
Self::wrangle_handlebars_error_into_diagnostic( Self::wrangle_handlebars_error_into_diagnostic(
treehouse, treehouse,
@ -90,11 +84,8 @@ impl Generator {
notes: vec![], notes: vec![],
}) })
} else { } else {
let file = treehouse let file = treehouse.filename(file_id);
.files bail!("template error in {file}: {message}");
.get(file_id)
.expect("file should already be in the list");
bail!("template error in {}: {message}", file.name());
} }
Ok(()) Ok(())
} }
@ -112,11 +103,12 @@ impl Generator {
for path in &self.tree_files { for path in &self.tree_files {
let utf8_filename = path.to_string_lossy(); let utf8_filename = path.to_string_lossy();
let target_file = path.strip_prefix(dirs.content_dir).unwrap_or(path);
let target_path = if target_file == OsStr::new("index.tree") { let tree_path = path.strip_prefix(dirs.content_dir).unwrap_or(path);
let target_path = if tree_path == OsStr::new("index.tree") {
dirs.target_dir.join("index.html") dirs.target_dir.join("index.html")
} else { } else {
dirs.target_dir.join(target_file).with_extension("html") dirs.target_dir.join(tree_path).with_extension("html")
}; };
debug!("generating: {path:?} -> {target_path:?}"); debug!("generating: {path:?} -> {target_path:?}");
@ -133,7 +125,11 @@ impl Generator {
continue; continue;
} }
}; };
let file_id = treehouse.files.add(utf8_filename.into_owned(), source); let file_id = treehouse.add_file(
utf8_filename.into_owned(),
Some(tree_path.with_extension("").to_string_lossy().into_owned()),
source,
);
if let Ok(roots) = parse_tree_with_diagnostics(&mut treehouse, file_id) { if let Ok(roots) = parse_tree_with_diagnostics(&mut treehouse, file_id) {
let mut tree = String::new(); let mut tree = String::new();

View file

@ -17,11 +17,19 @@ pub fn branch_to_html(s: &mut String, treehouse: &mut Treehouse, file_id: FileId
let attributes = parse_attributes(treehouse, file_id, branch); let attributes = parse_attributes(treehouse, file_id, branch);
// Reborrow because the closure requires unique access (it adds a new diagnostic.) // Reborrow because the closure requires unique access (it adds a new diagnostic.)
let source = treehouse.get_source(file_id); let source = treehouse.source(file_id);
let has_children = let has_children =
!branch.children.is_empty() || matches!(attributes.content, Content::Link(_)); !branch.children.is_empty() || matches!(attributes.content, Content::Link(_));
let id = format!(
"{}:{}",
treehouse
.tree_path(file_id)
.expect("file should have a tree path"),
attributes.id
);
let class = if has_children { "branch" } else { "leaf" }; let class = if has_children { "branch" } else { "leaf" };
let linked_branch = if let Content::Link(link) = &attributes.content { let linked_branch = if let Content::Link(link) = &attributes.content {
format!( format!(
@ -34,7 +42,7 @@ pub fn branch_to_html(s: &mut String, treehouse: &mut Treehouse, file_id: FileId
write!( write!(
s, s,
"<li class=\"{class}\" id=\"{}\"{linked_branch}>", "<li class=\"{class}\" id=\"{}\"{linked_branch}>",
EscapeAttribute(&attributes.id) EscapeAttribute(&id)
) )
.unwrap(); .unwrap();
{ {
@ -95,7 +103,7 @@ pub fn branch_to_html(s: &mut String, treehouse: &mut Treehouse, file_id: FileId
write!( write!(
s, s,
"<a class=\"icon icon-permalink\" href=\"#{}\" title=\"permalink\"></a>", "<a class=\"icon icon-permalink\" href=\"#{}\" title=\"permalink\"></a>",
EscapeAttribute(&attributes.id) EscapeAttribute(&id)
) )
.unwrap(); .unwrap();
} }
@ -113,7 +121,7 @@ pub fn branch_to_html(s: &mut String, treehouse: &mut Treehouse, file_id: FileId
} }
fn parse_attributes(treehouse: &mut Treehouse, file_id: usize, branch: &Branch) -> Attributes { fn parse_attributes(treehouse: &mut Treehouse, file_id: usize, branch: &Branch) -> Attributes {
let source = treehouse.get_source(file_id); let source = treehouse.source(file_id);
let mut successfully_parsed = true; let mut successfully_parsed = true;
let mut attributes = if let Some(attributes) = &branch.attributes { let mut attributes = if let Some(attributes) = &branch.attributes {
@ -160,7 +168,7 @@ fn parse_attributes(treehouse: &mut Treehouse, file_id: usize, branch: &Branch)
"note: a generated id `{}` will be used, but this id is unstable and will not persist across generations", "note: a generated id `{}` will be used, but this id is unstable and will not persist across generations",
attributes.id attributes.id
), ),
format!("help: run `treehouse fix {}` to add missing ids to branches", treehouse.get_filename(file_id)), format!("help: run `treehouse fix {}` to add missing ids to branches", treehouse.filename(file_id)),
], ],
}); });
} }

View file

@ -10,6 +10,7 @@ use log::{error, info};
mod cli; mod cli;
mod html; mod html;
mod paths;
mod state; mod state;
async fn fallible_main() -> anyhow::Result<()> { async fn fallible_main() -> anyhow::Result<()> {

View file

View file

@ -6,6 +6,7 @@ use codespan_reporting::{
files::SimpleFiles, files::SimpleFiles,
term::termcolor::{ColorChoice, StandardStream}, term::termcolor::{ColorChoice, StandardStream},
}; };
use log::debug;
use ulid::Ulid; use ulid::Ulid;
pub type Files = SimpleFiles<String, String>; pub type Files = SimpleFiles<String, String>;
@ -16,6 +17,9 @@ pub struct Treehouse {
pub files: Files, pub files: Files,
pub diagnostics: Vec<Diagnostic<FileId>>, pub diagnostics: Vec<Diagnostic<FileId>>,
// Bit of a hack because I don't wanna write my own `Files`.
tree_paths: Vec<Option<String>>,
missingno_generator: ulid::Generator, missingno_generator: ulid::Generator,
} }
@ -25,12 +29,25 @@ impl Treehouse {
files: Files::new(), files: Files::new(),
diagnostics: vec![], diagnostics: vec![],
tree_paths: vec![],
missingno_generator: ulid::Generator::new(), missingno_generator: ulid::Generator::new(),
} }
} }
pub fn add_file(
&mut self,
filename: String,
tree_path: Option<String>,
source: String,
) -> FileId {
let id = self.files.add(filename, source);
self.tree_paths.push(tree_path);
id
}
/// Get the source code of a file, assuming it was previously registered. /// Get the source code of a file, assuming it was previously registered.
pub fn get_source(&self, file_id: FileId) -> &str { pub fn source(&self, file_id: FileId) -> &str {
self.files self.files
.get(file_id) .get(file_id)
.expect("file should have been registered previously") .expect("file should have been registered previously")
@ -38,13 +55,17 @@ impl Treehouse {
} }
/// Get the name of a file, assuming it was previously registered. /// Get the name of a file, assuming it was previously registered.
pub fn get_filename(&self, file_id: FileId) -> &str { pub fn filename(&self, file_id: FileId) -> &str {
self.files self.files
.get(file_id) .get(file_id)
.expect("file should have been registered previously") .expect("file should have been registered previously")
.name() .name()
} }
pub fn tree_path(&self, file_id: FileId) -> Option<&str> {
self.tree_paths[file_id].as_deref()
}
pub fn report_diagnostics(&self) -> anyhow::Result<()> { pub fn report_diagnostics(&self) -> anyhow::Result<()> {
let writer = StandardStream::stderr(ColorChoice::Auto); let writer = StandardStream::stderr(ColorChoice::Auto);
let config = codespan_reporting::term::Config::default(); let config = codespan_reporting::term::Config::default();

View file

@ -1,17 +1,11 @@
/* The tree indents shouldn't be too spaced out */
.tree ul { .tree ul {
padding-left: clamp(12px, 2vw, 24px); padding-left: clamp(12px, 2vw, 24px);
} }
/* But the first block should not be indented. */
.tree>ul { .tree>ul {
padding-left: 0; padding-left: 0;
} }
/* Make the tree have + and - instead of the default details/summary arrow */
.tree { .tree {
--tree-icon-position: 8px 50%; --tree-icon-position: 8px 50%;
--tree-icon-space: 28px; --tree-icon-space: 28px;
@ -76,7 +70,7 @@
background-color: rgba(0, 0, 0, 5%); background-color: rgba(0, 0, 0, 5%);
} }
.tree li.leaf { .tree li>div {
background-image: url('../svg/leaf.svg'); background-image: url('../svg/leaf.svg');
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: var(--tree-icon-position); background-position: var(--tree-icon-position);
@ -157,3 +151,11 @@
padding-left: 24px; padding-left: 24px;
opacity: 50%; opacity: 50%;
} }
.tree :target>details>summary,
.tree :target>div {
border-bottom: 1px dashed rgba(0, 0, 0, 30%);
margin-bottom: -1px;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}

View file

@ -66,3 +66,23 @@ class LinkedBranch extends HTMLLIElement {
} }
customElements.define("th-linked-branch", LinkedBranch, { extends: "li" }); customElements.define("th-linked-branch", LinkedBranch, { extends: "li" });
function expandDetailsRecursively(element) {
while (element && element.tagName != "MAIN") {
if (element.tagName == "DETAILS") {
element.open = true;
}
element = element.parentElement;
}
}
// When you click on a link, and the destination is within a <details> that is not expanded,
// expand the <details> recursively.
window.addEventListener("popstate", _ => {
let element = document.getElementById(window.location.hash.substring(1));
if (element !== undefined) {
// If the element is already loaded on the page, we're good.
expandDetailsRecursively(element);
window.location.hash = window.location.hash;
}
})