Add parser for node text with support for headers
This commit is contained in:
parent
089b507299
commit
2f247f477b
5 changed files with 69 additions and 9 deletions
|
|
@ -12,10 +12,13 @@ pub async fn node(Path(id): Path<String>) -> Response<Body> {
|
||||||
|
|
||||||
context.insert("id", &id);
|
context.insert("id", &id);
|
||||||
context.insert("title", &node.title);
|
context.insert("title", &node.title);
|
||||||
context.insert("text", &node.text);
|
|
||||||
context.insert("connections", &node.connections.clone());
|
context.insert("connections", &node.connections.clone());
|
||||||
context.insert("incoming", &graph.incoming.get(&id));
|
context.insert("incoming", &graph.incoming.get(&id));
|
||||||
|
|
||||||
|
let escaped_text = tera::escape_html(&node.text);
|
||||||
|
let out_text = crate::syntax::content::parse(&escaped_text);
|
||||||
|
context.insert("text", &out_text);
|
||||||
|
|
||||||
let not_found = node.clone() == empty_node;
|
let not_found = node.clone() == empty_node;
|
||||||
let template_name = "node.html".to_string();
|
let template_name = "node.html".to_string();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
pub mod arguments;
|
pub mod arguments;
|
||||||
|
pub mod content;
|
||||||
|
|
|
||||||
57
src/syntax/content.rs
Normal file
57
src/syntax/content.rs
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
use std::fmt::Write as _;
|
||||||
|
use crate::dev::log;
|
||||||
|
|
||||||
|
pub fn parse(text: &str) -> String {
|
||||||
|
let mut out_text: Vec<String> = Vec::new();
|
||||||
|
|
||||||
|
for line in text.lines() {
|
||||||
|
if line.is_empty() || line.replace(" ", "").is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut out_line: String = line.to_owned();
|
||||||
|
let words: Vec<String> = line.split(" ").map(str::to_string).collect();
|
||||||
|
let first_word: &String =
|
||||||
|
words.first().unwrap_or_else(|| unreachable!());
|
||||||
|
|
||||||
|
if is_header(first_word) {
|
||||||
|
out_line = parse_header(&out_line, first_word);
|
||||||
|
}
|
||||||
|
// if not special, default to treating line as a paragraph
|
||||||
|
else {
|
||||||
|
out_line.insert_str(0, "<p>");
|
||||||
|
out_line.push_str("</p>");
|
||||||
|
}
|
||||||
|
|
||||||
|
out_text.push(out_line);
|
||||||
|
}
|
||||||
|
|
||||||
|
out_text.join("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_header(lexeme: &str) -> bool {
|
||||||
|
!lexeme.trim().is_empty()
|
||||||
|
&& lexeme.replace("#", "").is_empty()
|
||||||
|
&& lexeme.len() <= 6
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_header(line: &str, first_word: &str) -> String {
|
||||||
|
log(&parse_header, &format!("Parsing: {line:?}"));
|
||||||
|
|
||||||
|
let header_level = first_word.len();
|
||||||
|
log(&parse, &format!("Header level is {header_level}"));
|
||||||
|
let header_text = line.to_owned().replace(first_word, "");
|
||||||
|
let mut w = String::with_capacity(header_text.len().strict_add(9));
|
||||||
|
let alloc = w.capacity();
|
||||||
|
match write!(w, "<h{header_level}>{header_text}</h{header_level}>") {
|
||||||
|
Ok(()) => (),
|
||||||
|
Err(e) => panic!("{e:?}"),
|
||||||
|
}
|
||||||
|
if alloc != w.capacity() {
|
||||||
|
log(
|
||||||
|
&parse_header,
|
||||||
|
&format!("w reallocated to {} despite prediction", w.capacity()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
w
|
||||||
|
}
|
||||||
|
|
@ -3,7 +3,7 @@ root_node = "Documentation"
|
||||||
[nodes.Documentation]
|
[nodes.Documentation]
|
||||||
text = """
|
text = """
|
||||||
|
|
||||||
Installation
|
## Installation
|
||||||
|
|
||||||
For now, if you want to try en, you must build it yourself.
|
For now, if you want to try en, you must build it yourself.
|
||||||
|
|
||||||
|
|
@ -15,7 +15,7 @@ cargo build --release
|
||||||
|
|
||||||
The en binary will be in target/release/en.
|
The en binary will be in target/release/en.
|
||||||
|
|
||||||
Graph Syntax
|
## Graph Syntax
|
||||||
|
|
||||||
The graph is a TOML file. You can create nodes by adding text such as:
|
The graph is a TOML file. You can create nodes by adding text such as:
|
||||||
|
|
||||||
|
|
@ -31,7 +31,8 @@ A computer is a machine capable of executing arbitrary instructions.
|
||||||
|
|
||||||
Nodes can have connections between each other.
|
Nodes can have connections between each other.
|
||||||
|
|
||||||
To add a simple connection without any associated properties, you can simply add links:
|
To add a simple connection without any associated properties, you can simply
|
||||||
|
add links:
|
||||||
|
|
||||||
[nodes.Quark]
|
[nodes.Quark]
|
||||||
text = "A subatomic particle that forms hadrons."
|
text = "A subatomic particle that forms hadrons."
|
||||||
|
|
@ -48,7 +49,7 @@ anchor = "particle"
|
||||||
|
|
||||||
This will create a connection from Quark to "Particle physics", and the first occurrence of the word "particle" in the text of Quark gets anchored to this connection.
|
This will create a connection from Quark to "Particle physics", and the first occurrence of the word "particle" in the text of Quark gets anchored to this connection.
|
||||||
|
|
||||||
CLI Options
|
## CLI Options
|
||||||
|
|
||||||
You can set the hostname, port and graph file path using CLI options:
|
You can set the hostname, port and graph file path using CLI options:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,7 @@
|
||||||
<section>
|
<section>
|
||||||
<h1>{{ title }}</h1>
|
<h1>{{ title }}</h1>
|
||||||
<code style="display: inline;">ID: {{ id }}</code>
|
<code style="display: inline;">ID: {{ id }}</code>
|
||||||
{% for line in text | split(pat="\n") %}
|
{{ text | safe }}
|
||||||
{% if line %} <p>{{ line }}</p> {% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
</section>
|
</section>
|
||||||
{% if connections or incoming %}
|
{% if connections or incoming %}
|
||||||
<aside>
|
<aside>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue