rework branches a bit to support saving

This commit is contained in:
liquidex 2023-08-22 19:23:31 +02:00
parent 6c110b61a2
commit 582447e02b
8 changed files with 99 additions and 59 deletions

View file

@ -1 +1 @@
- section under construction. sorry! in the meantime, maybe you wanna read [my ramblings about the treehouse](#01H89RFHCQCD3E1XS5XAPW86J5)?
- section under construction. sorry! in the meantime, maybe you wanna read [my ramblings about the treehouse][b:01H89RFHCQCD3E1XS5XAPW86J5]?

View file

@ -136,8 +136,10 @@
% id = "01H89RFHCQ2GWJPTAKTRGS1QAC"
- weird poems and philosophical talk are over, it's time to focus on the tech.
- call this an overview, Defense of Design, or what have you
% id = "01H89RFHCQF4N9T05B9DVWX67K"
- treehouse is built in the programming language that gives me the most pleasure while developing.
- treehouse is built in the programming language that gives me the most pleasure coding.
- no need for you to know more. :shhh:
@ -149,10 +151,10 @@
- but being the altruist I am - don't worry, it _will_ be open source one day.
- in case you're reading this in the far future, and this is still here…
you wouldn't mind [dropping me a line](#01H89P3CH8CD28KGX9GVRFK60E) would you?
you wouldn't mind [dropping me a line][b:01H89P3CH8CD28KGX9GVRFK60E] would you?
% id = "01H89RFHCQAQVXP6B2H0T8NNDS"
- personally… the language you build a personal project in almost never matters. it's rather how you execute your ideas.
- personally… the language you build a personal project with almost never matters. it's rather how you execute your ideas.
+ therefore I find boasting that my project is powered by a `$LANGUAGE` or a `$FRAMEWORK` unnecessary.
@ -162,7 +164,7 @@
- (yes, I know that website is super old, but I still find it incredibly funny :hueh:)
% id = "01H89RFHCQFWC2FWBAE9PVNC08"
- as I alluded to [here](#01H89RFHCQ3EAP0F6PRSEK7S1T), treehouse is built to decay gracefully
- as I alluded to [here][b:01H89RFHCQ3EAP0F6PRSEK7S1T], treehouse is built to decay gracefully
as you take away the fancy parts.
- you will be able to read it just fine without JavaScript, just that it'll be a little
@ -185,6 +187,14 @@
- if you have accessibility concerns about this decision, please let me know.
- it also saves your progress as you read. if you refresh the page, you'll notice you end up exactly where you left off!
- but, there is one very crucial piece of JavaScript that makes this website tick, and your experience **will be degraded** if you disable it. that feature is linking to branches.
- by default, if you link to an element by its id and it's contained within a `<details>`, the `<details>` will not expand. :ralsei_dead:
- therefore there's a bit of JS to make that work, _and_ to tie that together with lazy loading.
- treehouse will not work *as* fine without CSS though - the `<details>` will look extremely
janky, but the content should still be fully readable.
@ -193,20 +203,21 @@
- the structure of `.tree` files is extremely minimal. there are only a few syntactic features to speak of.
- here's a taste of `.tree`:
```
\% id = "root"
\- this is a branch
\% id = "child"
\- this is a child branch
- ```
\% id = "root"
\- this is a branch
\+ this is a branch that is collapsed
\% id = "child"
\- this is a child branch
\- and this is a child of that branch
\+ this is a branch that is collapsed
\% content.link = "some-other-tree"
\- and this branch links to another tree
```
\- and this is a child of that branch
\% content.link = "some-other-tree"
\- and this branch links to another tree
```
- the `.tree` format is line-based. that means the `%`, `-`, and `+` tokens are only
interpreted when at the beginning of a line.
@ -219,15 +230,15 @@
- …may or may not be expanded by default (this is the branch's _kind_) - that's what the minus `-` and plus `+` tokens do
- …are sequenced like: optional attributes, kind, content
- each branch is constructed in this order: optional attributes, kind, content
- …end when another line beginning with `%`, `-`, or `+` is found.
- and ends when another line beginning with `%`, `-`, or `+` is found.
- other than that, `.tree` assumes nothing about what format the branch attributes or content are encoded in.
- I chose TOML and Markdown for their ease of use and flexibility, but the parser couldn't care less.
- …actually, that's a lie. see that code example above? Markdown code fences \`\`\` are handled specially to let you do that kind of stuff. that's all.
- …actually, that's a lie. see that code example above? Markdown code fences \`\`\` are handled specially to let embed `.tree` source code blocks within `.tree` files. that's all.
- you may have noticed in that code example above that almost every branch has an `id` attribute.
@ -261,6 +272,16 @@
- which is cool because it's much denser while avoiding ambiguous characters - `0`, `O`, and `o` are all interpreted as `0` (zero).
- noticed how fast the treehouse restores your state? there's basically no delay.
- this is because it restores your state _as it's loading in_, by using [Web Components](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements).
- despite many people calling that API extremely low-level, I beg to differ. it's actually pretty easy and pleasant to use.
- most importantly it lets me enhance vanilla `<li>` elements with custom behavior executed on load, which I use to restore your reading progress as the page is loading in.
- linked branches also use Web Components by the way.
- while not strictly a technical topic, I'd like to shout out [Recursive](https://recursive.design) for being an awesome font :ralsei_love:
- (not to be confused with Font Awesome, which I do not use here. icon designs are my own.)

View file

@ -97,10 +97,10 @@
- [DELTARUNE](https://deltarune.com)
% id = "01H89P3CH89TQ3SFG2Z40J29HX"
- they're pretty great you should check them out (also check out [my games corner][page:/games]? :pleading_face:)
- they're pretty great you should check them out (also check out [my games corner][page:games]? :pleading_face:)
% id = "01H89P3CH8AJATQ5DJBBFXJ1NH"
- or [music][page:/music]
- or [music][page:music]
% id = "01H89P3CH8XQ59YZD3RFRYQ2BM"
- various genres from electronic through jazz and even rock
@ -153,7 +153,7 @@
- anyways you can find me on
% id = "01H89P3CH8EMM31JEMJRVRAKF4"
+ Discord - username is [this](#01H89P3CH8GAHS8DDW1HHEWA3P)
+ Discord - username is [this][b:01H89P3CH8GAHS8DDW1HHEWA3P]
% id = "01H89P3CH89HHDVHGB9GE287TR"
- I'm most active there so you'll have the best chance of getting a reply
@ -162,7 +162,7 @@
- you'll know it's me if you see a profile with a fluffy boy avatar
% id = "01H89P3CH8WTBKXP0GGN0HYQK2"
+ Matrix - username is [this](#01H89P3CH8943QGT52K7MRW12Q) at gacko.pl
+ Matrix - username is [this][b:01H89P3CH8943QGT52K7MRW12Q] at gacko.pl
% id = "01H89P3CH832E4GK0NJ77KED06"
- I try to be as active there as on Discord but my availability may be a little more

View file

@ -3,11 +3,11 @@
- welcome! make yourself at home
- this is my treehouse, the place on the Internet I like to call home.
---
% id = "about"
content.link = "about"
+ ## about yourself
+ ## about me
% id = "about-treehouse"
content.link = "about-treehouse"

View file

@ -31,17 +31,21 @@ pub fn branch_to_html(s: &mut String, treehouse: &mut Treehouse, file_id: FileId
);
let class = if has_children { "branch" } else { "leaf" };
let component = if let Content::Link(_) = attributes.content {
"th-b-linked"
} else {
"th-b"
};
let linked_branch = if let Content::Link(link) = &attributes.content {
format!(
" is=\"th-linked-branch\" data-th-link=\"{}\"",
EscapeHtml(link)
)
format!(" data-th-link=\"{}\"", EscapeHtml(link))
} else {
String::new()
};
write!(
s,
"<li class=\"{class}\" id=\"{}\"{linked_branch}>",
"<li is=\"{component}\" class=\"{class}\" id=\"{}\"{linked_branch}>",
EscapeAttribute(&id)
)
.unwrap();

View file

@ -6,7 +6,6 @@ use codespan_reporting::{
files::SimpleFiles,
term::termcolor::{ColorChoice, StandardStream},
};
use log::debug;
use ulid::Ulid;
pub type Files = SimpleFiles<String, String>;

View file

@ -1,13 +1,41 @@
class LinkedBranch extends HTMLLIElement {
const branchStateKey = "treehouse.openBranches";
let branchState = JSON.parse(localStorage.getItem(branchStateKey)) || {};
function saveBranchIsOpen(branchID, state) {
branchState[branchID] = state;
localStorage.setItem(branchStateKey, JSON.stringify(branchState));
}
function branchIsOpen(branchID) {
return branchState[branchID];
}
class Branch extends HTMLLIElement {
constructor() {
super();
this.details = this.childNodes[0];
this.innerUL = this.details.childNodes[1];
let isOpen = branchIsOpen(this.id);
if (isOpen !== undefined) {
this.details.open = isOpen;
}
this.details.addEventListener("toggle", _ => {
saveBranchIsOpen(this.id, this.details.open);
});
}
}
customElements.define("th-b", Branch, { extends: "li" });
class LinkedBranch extends Branch {
constructor() {
super();
this.linkedTree = this.getAttribute("data-th-link");
this.details = this.childNodes[0];
this.innerUL = this.details.childNodes[1];
this.state = "notloaded";
this.loadingState = "notloaded";
this.loadingText = document.createElement("p");
{
@ -19,12 +47,13 @@ class LinkedBranch extends HTMLLIElement {
this.innerUL.appendChild(this.loadingText);
// This produces a warning during static generation but we still want to handle that
// correctly. Having an expanded-by-default linked block can be useful in development.
// correctly, as Branch saves the state in localStorage. Having an expanded-by-default
// linked block can be useful in development.
if (this.details.open) {
this.loadTree();
}
this.details.addEventListener("toggle", event => {
this.details.addEventListener("toggle", _ => {
if (this.details.open) {
this.loadTree();
}
@ -32,8 +61,8 @@ class LinkedBranch extends HTMLLIElement {
}
loadTree() {
if (this.state == "notloaded") {
this.state = "loading";
if (this.loadingState == "notloaded") {
this.loadingState = "loading";
fetch(`/${this.linkedTree}.html`)
.then(response => {
@ -46,26 +75,22 @@ class LinkedBranch extends HTMLLIElement {
let parser = new DOMParser();
let linkedDocument = parser.parseFromString(text, "text/html");
let main = linkedDocument.getElementsByTagName("main")[0];
let ul /*: Element */ = main.getElementsByTagName("ul")[0];
console.log(ul);
let ul = main.getElementsByTagName("ul")[0];
this.loadingText.remove();
this.innerUL.innerHTML = ul.innerHTML;
for (let i = 0; i < ul.childNodes.length; ++i) {
this.innerUL.appendChild(ul.childNodes[i]);
}
this.state = "loaded";
this.loadingState = "loaded";
})
.catch(error => {
this.loadingText.innerText = error.toString();
this.state = "error";
this.loadingState = "error";
});
}
}
}
customElements.define("th-linked-branch", LinkedBranch, { extends: "li" });
customElements.define("th-b-linked", LinkedBranch, { extends: "li" });
function expandDetailsRecursively(element) {
while (element && element.tagName != "MAIN") {

View file

@ -33,18 +33,9 @@
miners.</strong><br>
if you don't believe me, you're free to inspect the source yourself! all the scripts are written
lovingly in vanilla JS (not minified!) by yours truly ❤️</p>
<small>and if this box is annoying, feel free to zap it with uBlock Origin or something. I have no
<small>and if this box is annoying, feel free to block it with uBlock Origin or something. I have no
way of remembering you closed it, and don't wanna host this site on a dynamic server.</small>
{{!-- <form method="dialog">
<button name="th-noscript-close" class="noscript-close">I understand and wish to proceed without
JavaScript. And don't nag me about it anymore.<br>
I consent to you storing a cookie on my device to remember this decision.</button>
</form>
--}}
{{!-- I disabled the button because I can't figure out a way to do this without storing a cookie, and I
don't like those. I'd prefer if this website were fully static. --}}
</dialog>
</div>
</noscript>
<main class="tree">