add config
This commit is contained in:
parent
2c2d529056
commit
00947ec966
|
@ -105,7 +105,7 @@
|
|||
- but without overwhelming your computer or bandwidth
|
||||
|
||||
% id = "01H89RFHCQ1XA3BB3BTKXH36CX"
|
||||
- you can disable the JavaScript, and everything will still work
|
||||
- you can disable the JavaScript, and everything will mostly work
|
||||
|
||||
% id = "01H89RFHCQS2WW7PBP1YV0BEJZ"
|
||||
- but you may not find the experience favorable
|
||||
|
@ -123,7 +123,9 @@
|
|||
+ can you even call it that?
|
||||
|
||||
% id = "01H89RFHCQ48R7BCZV8JWPVFCY"
|
||||
- have I invented something new here?
|
||||
+ have I invented something new here?
|
||||
|
||||
- the "Choose Your Own Poem" lol
|
||||
|
||||
% id = "01H89RFHCQAXJ0ST31TP1A104V"
|
||||
+ ### the treehouse is a mostly statically generated website
|
||||
|
|
|
@ -20,6 +20,7 @@ use walkdir::WalkDir;
|
|||
|
||||
use crate::{
|
||||
cli::parse::parse_tree_with_diagnostics,
|
||||
config::Config,
|
||||
html::{navmap::build_navigation_map, tree::branches_to_html},
|
||||
tree::SemaRoots,
|
||||
};
|
||||
|
@ -95,7 +96,7 @@ impl Generator {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn generate_all_files(&self, dirs: &Dirs<'_>) -> anyhow::Result<Treehouse> {
|
||||
fn generate_all_files(&self, config: &Config, paths: &Paths<'_>) -> anyhow::Result<Treehouse> {
|
||||
let mut treehouse = Treehouse::new();
|
||||
|
||||
let mut handlebars = Handlebars::new();
|
||||
|
@ -103,7 +104,7 @@ impl Generator {
|
|||
&mut handlebars,
|
||||
&mut treehouse,
|
||||
"tree",
|
||||
&dirs.template_dir.join("tree.hbs"),
|
||||
&paths.template_dir.join("tree.hbs"),
|
||||
)?;
|
||||
|
||||
struct ParsedTree {
|
||||
|
@ -116,11 +117,11 @@ impl Generator {
|
|||
for path in &self.tree_files {
|
||||
let utf8_filename = path.to_string_lossy();
|
||||
|
||||
let tree_path = path.strip_prefix(dirs.content_dir).unwrap_or(path);
|
||||
let tree_path = path.strip_prefix(paths.content_dir).unwrap_or(path);
|
||||
let target_path = if tree_path == OsStr::new("index.tree") {
|
||||
dirs.target_dir.join("index.html")
|
||||
paths.target_dir.join("index.html")
|
||||
} else {
|
||||
dirs.target_dir.join(tree_path).with_extension("html")
|
||||
paths.target_dir.join(tree_path).with_extension("html")
|
||||
};
|
||||
debug!("generating: {path:?} -> {target_path:?}");
|
||||
|
||||
|
@ -162,12 +163,19 @@ impl Generator {
|
|||
branches_to_html(
|
||||
&mut tree,
|
||||
&mut treehouse,
|
||||
config,
|
||||
parsed_tree.file_id,
|
||||
&roots.branches,
|
||||
);
|
||||
treehouse.roots.insert(parsed_tree.tree_path, roots);
|
||||
|
||||
let template_data = TemplateData { tree };
|
||||
#[derive(Serialize)]
|
||||
pub struct TemplateData<'a> {
|
||||
pub config: &'a Config,
|
||||
pub tree: String,
|
||||
}
|
||||
|
||||
let template_data = TemplateData { config, tree };
|
||||
let templated_html = match handlebars.render("tree", &template_data) {
|
||||
Ok(html) => html,
|
||||
Err(error) => {
|
||||
|
@ -196,37 +204,38 @@ impl Generator {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Dirs<'a> {
|
||||
pub struct Paths<'a> {
|
||||
pub target_dir: &'a Path,
|
||||
pub static_dir: &'a Path,
|
||||
pub template_dir: &'a Path,
|
||||
pub content_dir: &'a Path,
|
||||
|
||||
pub config_file: &'a Path,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct TemplateData {
|
||||
pub tree: String,
|
||||
}
|
||||
|
||||
pub fn regenerate(dirs: &Dirs<'_>) -> anyhow::Result<()> {
|
||||
pub fn regenerate(paths: &Paths<'_>) -> anyhow::Result<()> {
|
||||
let start = Instant::now();
|
||||
|
||||
info!("loading config");
|
||||
let mut config = Config::load(paths.config_file)?;
|
||||
config.site = std::env::var("TREEHOUSE_SITE").unwrap_or(config.site);
|
||||
|
||||
info!("cleaning target directory");
|
||||
let _ = std::fs::remove_dir_all(dirs.target_dir);
|
||||
std::fs::create_dir_all(dirs.target_dir)?;
|
||||
let _ = std::fs::remove_dir_all(paths.target_dir);
|
||||
std::fs::create_dir_all(paths.target_dir)?;
|
||||
|
||||
info!("copying static directory to target directory");
|
||||
copy_dir(dirs.static_dir, dirs.target_dir.join("static"))?;
|
||||
copy_dir(paths.static_dir, paths.target_dir.join("static"))?;
|
||||
|
||||
info!("generating standalone pages");
|
||||
let mut generator = Generator::default();
|
||||
generator.add_directory_rec(dirs.content_dir)?;
|
||||
let treehouse = generator.generate_all_files(dirs)?;
|
||||
generator.add_directory_rec(paths.content_dir)?;
|
||||
let treehouse = generator.generate_all_files(&config, paths)?;
|
||||
|
||||
info!("generating navigation map");
|
||||
let navigation_map = build_navigation_map(&treehouse, "index");
|
||||
std::fs::write(
|
||||
dirs.target_dir.join("navmap.js"),
|
||||
paths.target_dir.join("navmap.js"),
|
||||
navigation_map.to_javascript(),
|
||||
)?;
|
||||
|
||||
|
@ -238,10 +247,10 @@ pub fn regenerate(dirs: &Dirs<'_>) -> anyhow::Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn regenerate_or_report_error(dirs: &Dirs<'_>) {
|
||||
pub fn regenerate_or_report_error(paths: &Paths<'_>) {
|
||||
info!("regenerating site content");
|
||||
|
||||
match regenerate(dirs) {
|
||||
match regenerate(paths) {
|
||||
Ok(_) => (),
|
||||
Err(error) => eprintln!("error: {error:?}"),
|
||||
}
|
||||
|
|
25
crates/treehouse/src/config.rs
Normal file
25
crates/treehouse/src/config.rs
Normal file
|
@ -0,0 +1,25 @@
|
|||
use std::{collections::HashMap, path::Path};
|
||||
|
||||
use anyhow::Context;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct Config {
|
||||
/// Website root; used when generating links.
|
||||
/// Can also be specified using the environment variable `$TREEHOUSE_SITE`. (this is the
|
||||
/// preferred way of setting this in production, so as not to clobber treehouse.toml.)
|
||||
pub site: String,
|
||||
|
||||
/// User-defined keys.
|
||||
pub user: HashMap<String, String>,
|
||||
|
||||
/// Links exported to Markdown for use with reference syntax `[text][key]`.
|
||||
pub links: HashMap<String, String>,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn load(path: &Path) -> anyhow::Result<Self> {
|
||||
let string = std::fs::read_to_string(path).context("cannot read config file")?;
|
||||
toml_edit::de::from_str(&string).context("error in config file")
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ use pulldown_cmark::{BrokenLink, LinkType};
|
|||
use treehouse_format::pull::BranchKind;
|
||||
|
||||
use crate::{
|
||||
config::Config,
|
||||
html::EscapeAttribute,
|
||||
state::{FileId, Treehouse},
|
||||
tree::{attributes::Content, SemaBranchId},
|
||||
|
@ -14,6 +15,7 @@ use super::{markdown, EscapeHtml};
|
|||
pub fn branch_to_html(
|
||||
s: &mut String,
|
||||
treehouse: &mut Treehouse,
|
||||
config: &Config,
|
||||
file_id: FileId,
|
||||
branch_id: SemaBranchId,
|
||||
) {
|
||||
|
@ -110,7 +112,8 @@ pub fn branch_to_html(
|
|||
if let Content::Link(link) = &branch.attributes.content {
|
||||
write!(
|
||||
s,
|
||||
"<noscript><a class=\"navigate icon-go\" href=\"{}.html\">Go to linked tree: <code>{}</code></a></noscript>",
|
||||
"<noscript><a class=\"navigate icon-go\" href=\"{}/{}.html\">Go to linked tree: <code>{}</code></a></noscript>",
|
||||
EscapeAttribute(&config.site),
|
||||
EscapeAttribute(link),
|
||||
EscapeHtml(link),
|
||||
)
|
||||
|
@ -122,7 +125,8 @@ pub fn branch_to_html(
|
|||
if let Content::Link(link) = &branch.attributes.content {
|
||||
write!(
|
||||
s,
|
||||
"<a class=\"icon icon-go\" href=\"{}.html\" title=\"linked tree\"></a>",
|
||||
"<a class=\"icon icon-go\" href=\"{}/{}.html\" title=\"linked tree\"></a>",
|
||||
EscapeAttribute(&config.site),
|
||||
EscapeAttribute(link),
|
||||
)
|
||||
.unwrap();
|
||||
|
@ -144,7 +148,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, file_id, child_id);
|
||||
branch_to_html(s, treehouse, config, file_id, child_id);
|
||||
}
|
||||
s.push_str("</ul>");
|
||||
}
|
||||
|
@ -159,12 +163,13 @@ pub fn branch_to_html(
|
|||
pub fn branches_to_html(
|
||||
s: &mut String,
|
||||
treehouse: &mut Treehouse,
|
||||
config: &Config,
|
||||
file_id: FileId,
|
||||
branches: &[SemaBranchId],
|
||||
) {
|
||||
s.push_str("<ul>");
|
||||
for &child in branches {
|
||||
branch_to_html(s, treehouse, file_id, child);
|
||||
branch_to_html(s, treehouse, config, file_id, child);
|
||||
}
|
||||
s.push_str("</ul>");
|
||||
}
|
||||
|
|
|
@ -3,12 +3,13 @@ use std::path::Path;
|
|||
use clap::Parser;
|
||||
use cli::{
|
||||
fix::fix_file_cli,
|
||||
regenerate::{self, regenerate_or_report_error, Dirs},
|
||||
regenerate::{self, regenerate_or_report_error, Paths},
|
||||
Command, ProgramArgs,
|
||||
};
|
||||
use log::{error, info};
|
||||
|
||||
mod cli;
|
||||
mod config;
|
||||
mod html;
|
||||
mod paths;
|
||||
mod state;
|
||||
|
@ -19,8 +20,9 @@ async fn fallible_main() -> anyhow::Result<()> {
|
|||
|
||||
match args.command {
|
||||
Command::Regenerate(regenerate_args) => {
|
||||
let dirs = Dirs {
|
||||
let dirs = Paths {
|
||||
target_dir: Path::new("target/site"),
|
||||
config_file: Path::new("treehouse.toml"),
|
||||
|
||||
// NOTE: These are intentionally left unconfigurable from within treehouse.toml
|
||||
// because this is is one of those things that should be consistent between sites.
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// This is definitely not a three.js ripoff.
|
||||
|
||||
import { navigationMap } from "/navmap.js";
|
||||
|
||||
const branchStateKey = "treehouse.openBranches";
|
||||
|
@ -68,7 +70,7 @@ class LinkedBranch extends Branch {
|
|||
|
||||
async loadTreePromise(_initiator) {
|
||||
try {
|
||||
let response = await fetch(`/${this.linkedTree}.html`);
|
||||
let response = await fetch(`${TREEHOUSE_SITE}/${this.linkedTree}.html`);
|
||||
if (response.status == 404) {
|
||||
throw `Hmm, seems like the tree "${this.linkedTree}" does not exist.`;
|
||||
}
|
||||
|
@ -107,7 +109,7 @@ function expandDetailsRecursively(element) {
|
|||
}
|
||||
|
||||
function navigateToPage(page) {
|
||||
window.location.pathname = `/${page}.html`
|
||||
window.location.href = `${TREEHOUSE_SITE}/${page}.html`
|
||||
}
|
||||
|
||||
async function navigateToBranch(fragment) {
|
||||
|
|
|
@ -9,18 +9,19 @@
|
|||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<link rel="stylesheet" href="{{ site }}/static/css/main.css">
|
||||
<link rel="stylesheet" href="{{ site }}/static/css/tree.css">
|
||||
<link rel="stylesheet" href="{{ site }}/static/font/font.css">
|
||||
<link rel="stylesheet" href="{{ config.site }}/static/css/main.css">
|
||||
<link rel="stylesheet" href="{{ config.site }}/static/css/tree.css">
|
||||
<link rel="stylesheet" href="{{ config.site }}/static/font/font.css">
|
||||
|
||||
<script type="module" src="{{ site }}/navmap.js"></script>
|
||||
<script type="module" src="{{ site }}/static/js/tree.js"></script>
|
||||
<script type="module" src="{{ site }}/static/js/usability.js"></script>
|
||||
<script>const TREEHOUSE_SITE = `{{ config.site }}`;</script>
|
||||
<script type="module" src="{{ config.site }}/navmap.js"></script>
|
||||
<script type="module" src="{{ config.site }}/static/js/tree.js"></script>
|
||||
<script type="module" src="{{ config.site }}/static/js/usability.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav>
|
||||
<a href="{{ site }}/" title="Back to homepage">
|
||||
<a href="{{ config.site }}/" title="Back to homepage">
|
||||
<svg class="logo" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M8 3H7H6V4V5H4V6H6V9V10H7H10V12H11V10H12H13V9V8V7H12H11H10V8V9H7V6H8H9V5V4V3H8ZM12 9H11V8H12V9ZM7 5V4H8V5H7ZM3 5H2V6H3V5ZM10 13H11V14H10V13Z"
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
# User settings go here. These are (string, string) key-value pairs.
|
||||
# They are available under `config.user`.
|
||||
site = "http://localhost:8080"
|
||||
|
||||
[user]
|
||||
title = "treehouse"
|
||||
title = "liquidex's treehouse"
|
||||
author = "liquidex"
|
||||
|
||||
[links]
|
||||
"stitchkit/repo" = "https://github.com/liquidev/stitchkit"
|
||||
"dawd3/repo" = "https://github.com/liquidev/dawd3"
|
||||
|
|
Loading…
Reference in a new issue