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,
) -> Result<String, parse::ErrorsEmitted> {
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();
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 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 fix_args.apply {
// Try to write the backup first. If writing that fails, bail out without overwriting
// the source file.
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")?;
}
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,
file_id: FileId,
) -> 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| {
treehouse.diagnostics.push(Diagnostic {
severity: Severity::Error,
@ -34,7 +34,7 @@ pub fn parse_toml_with_diagnostics(
file_id: FileId,
range: Range<usize>,
) -> 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| {
treehouse
.diagnostics

View file

@ -45,14 +45,8 @@ impl Generator {
) -> anyhow::Result<FileId> {
let source = std::fs::read_to_string(path)
.with_context(|| format!("cannot read template file {path:?}"))?;
let file_id = treehouse
.files
.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();
let file_id = treehouse.add_file(path.to_string_lossy().into_owned(), None, source);
let source = treehouse.source(file_id);
if let Err(error) = handlebars.register_template_string(name, source) {
Self::wrangle_handlebars_error_into_diagnostic(
treehouse,
@ -90,11 +84,8 @@ impl Generator {
notes: vec![],
})
} else {
let file = treehouse
.files
.get(file_id)
.expect("file should already be in the list");
bail!("template error in {}: {message}", file.name());
let file = treehouse.filename(file_id);
bail!("template error in {file}: {message}");
}
Ok(())
}
@ -112,11 +103,12 @@ impl Generator {
for path in &self.tree_files {
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")
} else {
dirs.target_dir.join(target_file).with_extension("html")
dirs.target_dir.join(tree_path).with_extension("html")
};
debug!("generating: {path:?} -> {target_path:?}");
@ -133,7 +125,11 @@ impl Generator {
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) {
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);
// 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 =
!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 linked_branch = if let Content::Link(link) = &attributes.content {
format!(
@ -34,7 +42,7 @@ pub fn branch_to_html(s: &mut String, treehouse: &mut Treehouse, file_id: FileId
write!(
s,
"<li class=\"{class}\" id=\"{}\"{linked_branch}>",
EscapeAttribute(&attributes.id)
EscapeAttribute(&id)
)
.unwrap();
{
@ -95,7 +103,7 @@ pub fn branch_to_html(s: &mut String, treehouse: &mut Treehouse, file_id: FileId
write!(
s,
"<a class=\"icon icon-permalink\" href=\"#{}\" title=\"permalink\"></a>",
EscapeAttribute(&attributes.id)
EscapeAttribute(&id)
)
.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 {
let source = treehouse.get_source(file_id);
let source = treehouse.source(file_id);
let mut successfully_parsed = true;
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",
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 html;
mod paths;
mod state;
async fn fallible_main() -> anyhow::Result<()> {

View file

View file

@ -6,6 +6,7 @@ use codespan_reporting::{
files::SimpleFiles,
term::termcolor::{ColorChoice, StandardStream},
};
use log::debug;
use ulid::Ulid;
pub type Files = SimpleFiles<String, String>;
@ -16,6 +17,9 @@ pub struct Treehouse {
pub files: Files,
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,
}
@ -25,12 +29,25 @@ impl Treehouse {
files: Files::new(),
diagnostics: vec![],
tree_paths: vec![],
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.
pub fn get_source(&self, file_id: FileId) -> &str {
pub fn source(&self, file_id: FileId) -> &str {
self.files
.get(file_id)
.expect("file should have been registered previously")
@ -38,13 +55,17 @@ impl Treehouse {
}
/// 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
.get(file_id)
.expect("file should have been registered previously")
.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<()> {
let writer = StandardStream::stderr(ColorChoice::Auto);
let config = codespan_reporting::term::Config::default();

View file

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