Make default element generic
This commit is contained in:
parent
7512aeafbf
commit
5d28a2e707
6 changed files with 92 additions and 53 deletions
|
|
@ -16,8 +16,7 @@ pub async fn node(Path(id): Path<String>) -> Response<Body> {
|
||||||
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 = parser::read::<Paragraph>(&node.text);
|
||||||
let out_text = parser::read(&escaped_text);
|
|
||||||
context.insert("text", &out_text);
|
context.insert("text", &out_text);
|
||||||
|
|
||||||
let not_found = node.clone() == empty_node;
|
let not_found = node.clone() == empty_node;
|
||||||
|
|
|
||||||
|
|
@ -1,43 +1,31 @@
|
||||||
use elements::{paragraph::Paragraph, header::Header};
|
use elements::{header::Header};
|
||||||
|
use units::{Token, Lexeme};
|
||||||
|
|
||||||
mod elements;
|
mod units;
|
||||||
|
pub mod elements;
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
|
|
||||||
enum Token {
|
pub trait Parseable: Into<Token> {
|
||||||
Paragraph(Paragraph),
|
|
||||||
Header(Header),
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Lexeme<'l> {
|
|
||||||
pub raw: &'l str,
|
|
||||||
pub first: &'l str,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'l> Lexeme<'l> {
|
|
||||||
pub fn new(text: &'l str) -> Lexeme<'l> {
|
|
||||||
let vec: Vec<&'l str> = text.split(" ").collect();
|
|
||||||
|
|
||||||
Self {
|
|
||||||
raw: text,
|
|
||||||
first: vec.first().unwrap_or_else(|| unreachable!()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
trait Parseable {
|
|
||||||
fn probe(lexeme: &Lexeme) -> bool;
|
fn probe(lexeme: &Lexeme) -> bool;
|
||||||
fn lex(lexeme: &Lexeme) -> Self
|
fn lex(lexeme: &Lexeme) -> Self;
|
||||||
where
|
|
||||||
Self: Sized;
|
|
||||||
fn render(&self) -> String;
|
fn render(&self) -> String;
|
||||||
}
|
}
|
||||||
|
|
||||||
type Matcher = fn(&Lexeme) -> bool;
|
type Probe = fn(&Lexeme) -> bool;
|
||||||
type Constructor = fn(&Lexeme) -> Token;
|
type Lexer = fn(&Lexeme) -> Token;
|
||||||
|
type LexEntry = (Probe, Lexer);
|
||||||
|
type LexMap<'lm> = &'lm [LexEntry];
|
||||||
|
|
||||||
static LEXMAP: &[(Matcher, Constructor)] = &[
|
const LEXMAP: LexMap =
|
||||||
(Header::probe, |lexeme| Token::Header(Header::lex(lexeme))),
|
&[(Header::probe, |lexeme| Token::Header(Header::lex(lexeme)))];
|
||||||
(Paragraph::probe, |lexeme| {
|
|
||||||
Token::Paragraph(Paragraph::lex(lexeme))
|
fn make_lexmap<DefaultToken: Parseable>() -> Vec<LexEntry> {
|
||||||
}),
|
let mut vector: Vec<(Probe, Lexer)> = LEXMAP.to_vec();
|
||||||
];
|
|
||||||
|
fn adapter<D: Parseable>(lex: &Lexeme) -> Token {
|
||||||
|
D::lex(lex).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
vector.push((DefaultToken::probe, adapter::<DefaultToken>));
|
||||||
|
vector
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,3 @@
|
||||||
pub(super) mod paragraph;
|
pub mod header;
|
||||||
pub(super) mod header;
|
pub mod paragraph;
|
||||||
|
pub mod span;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use crate::syntax::content::{Parseable, Lexeme};
|
use crate::syntax::content::{Parseable, Lexeme};
|
||||||
|
|
||||||
pub(in crate::syntax::content) struct Paragraph {
|
pub struct Paragraph {
|
||||||
text: String,
|
text: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,17 @@
|
||||||
use super::{Parseable as _, Token, Lexeme, LEXMAP};
|
use crate::syntax::content::{Parseable, Token, Lexeme, make_lexmap};
|
||||||
|
|
||||||
pub fn read(text: &str) -> String {
|
pub fn read<DefaultToken: Parseable>(text: &str) -> String {
|
||||||
parse(&lex(text))
|
let escaped_text = tera::escape_html(text);
|
||||||
|
parse(&lex(&escaped_text, &make_lexmap::<DefaultToken>()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lex(text: &str) -> Vec<Token> {
|
fn lex(text: &str, map: super::LexMap) -> Vec<Token> {
|
||||||
let mut tokens = Vec::new();
|
let mut tokens: Vec<Token> = Vec::new();
|
||||||
|
|
||||||
for line in text.lines().filter(|x| !x.trim().is_empty()) {
|
for line in text.lines().filter(|x| !x.trim().is_empty()) {
|
||||||
let lexeme = Lexeme::new(line);
|
let lexeme = Lexeme::new(line);
|
||||||
|
|
||||||
for &(ref matcher, lexer) in LEXMAP {
|
for &(ref matcher, lexer) in map {
|
||||||
if matcher(&lexeme) {
|
if matcher(&lexeme) {
|
||||||
tokens.push(lexer(&lexeme));
|
tokens.push(lexer(&lexeme));
|
||||||
break;
|
break;
|
||||||
|
|
@ -22,13 +23,9 @@ fn lex(text: &str) -> Vec<Token> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse(tokens: &[Token]) -> String {
|
fn parse(tokens: &[Token]) -> String {
|
||||||
let mut out_text: Vec<String> = Vec::new();
|
tokens
|
||||||
for token in tokens {
|
.iter()
|
||||||
out_text.push(match *token {
|
.map(Token::render)
|
||||||
Token::Paragraph(ref d) => d.render(),
|
.collect::<Vec<_>>()
|
||||||
Token::Header(ref d) => d.render(),
|
.join("\n")
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
out_text.join("\n")
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
54
src/syntax/content/units.rs
Normal file
54
src/syntax/content/units.rs
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
use crate::syntax::content::Parseable as _;
|
||||||
|
use crate::syntax::content::elements::{
|
||||||
|
paragraph::Paragraph, header::Header, span::Span,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub enum Token {
|
||||||
|
Paragraph(Paragraph),
|
||||||
|
Header(Header),
|
||||||
|
Span(Span),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Token {
|
||||||
|
pub fn render(&self) -> String {
|
||||||
|
match *self {
|
||||||
|
Token::Paragraph(ref d) => d.render(),
|
||||||
|
Token::Header(ref d) => d.render(),
|
||||||
|
Token::Span(ref d) => d.render(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Paragraph> for Token {
|
||||||
|
fn from(d: Paragraph) -> Self {
|
||||||
|
Token::Paragraph(d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Header> for Token {
|
||||||
|
fn from(d: Header) -> Self {
|
||||||
|
Token::Header(d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Span> for Token {
|
||||||
|
fn from(d: Span) -> Self {
|
||||||
|
Token::Span(d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Lexeme<'l> {
|
||||||
|
pub raw: &'l str,
|
||||||
|
pub first: &'l str,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'l> Lexeme<'l> {
|
||||||
|
pub fn new(text: &'l str) -> Lexeme<'l> {
|
||||||
|
let vec: Vec<&'l str> = text.split(" ").collect();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
raw: text,
|
||||||
|
first: vec.first().unwrap_or_else(|| unreachable!()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue