i don't rember
This commit is contained in:
parent
782758f7e7
commit
02d2010808
|
@ -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")?;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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)),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -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<()> {
|
||||||
|
|
0
crates/treehouse/src/paths.rs
Normal file
0
crates/treehouse/src/paths.rs
Normal 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();
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
Loading…
Reference in a new issue