flox article
This commit is contained in:
parent
29428092ab
commit
bf3341850b
48
content/projects/flox.md
Normal file
48
content/projects/flox.md
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
---
|
||||||
|
title: Flox
|
||||||
|
date: 2024-08-25T09:59:41Z
|
||||||
|
desc: >
|
||||||
|
Small functional language written in Rust and compiled to WebAssembly
|
||||||
|
---
|
||||||
|
|
||||||
|
## Grammar
|
||||||
|
|
||||||
|
```
|
||||||
|
Program ::= Sequence "EOF"
|
||||||
|
Sequence ::= Expression? (";" Expression)*
|
||||||
|
|
||||||
|
Expression ::= Data
|
||||||
|
| Match
|
||||||
|
| Let
|
||||||
|
| If
|
||||||
|
| While
|
||||||
|
| Return
|
||||||
|
| Block
|
||||||
|
| Assignment
|
||||||
|
|
||||||
|
Data ::= "data" IDENTIFIER ("|" IDENTIFIER (IDENTIFIER)*)*
|
||||||
|
Match ::= "match" Expression ( "|" Expression IDENTIFIER* "->" Expression )*
|
||||||
|
Let ::= "let" IDENTIFIER (IDENTIFIER)* "=" Expression
|
||||||
|
If ::= "if" Expression Expression ("else" Expression)?
|
||||||
|
While ::= "while" Expression Expression
|
||||||
|
Return ::= "return" Expression?
|
||||||
|
Block ::= "{" Sequence "}"
|
||||||
|
Assignment ::= Call ("=" Assignment)?
|
||||||
|
Call ::= Index (Index)*
|
||||||
|
Index ::= Primary ("." IDENTIFIER)?
|
||||||
|
|
||||||
|
Primary ::= IDENTIFIER
|
||||||
|
| NUMBER
|
||||||
|
| STRING
|
||||||
|
| "true"
|
||||||
|
| "false"
|
||||||
|
| "nil"
|
||||||
|
| Lambda
|
||||||
|
| Parenthesized
|
||||||
|
| Array
|
||||||
|
|
||||||
|
Lambda ::= "fn" IDENTIFIER+ "->" Expression
|
||||||
|
Parenthesized ::= "(" (Expression ("," Expression)*)? ")"
|
||||||
|
Array ::= "[" (Expression ("," Expression)*)? "]"
|
||||||
|
Arguments ::= "(" (Expression ("," Expression)*)? ")"
|
||||||
|
```
|
|
@ -10,13 +10,16 @@ mod head;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use camino::Utf8Path;
|
use camino::{Utf8Path, Utf8PathBuf};
|
||||||
use chrono::Datelike;
|
use chrono::{DateTime, Datelike, Utc};
|
||||||
use hauchiwa::{LinkDate, Sack};
|
use hauchiwa::{Bibliography, Content, Link, LinkDate, Linkable, Outline, Sack};
|
||||||
|
use hayagriva::Library;
|
||||||
use hypertext::{html_elements, maud, maud_move, GlobalAttributes, Raw, Renderable};
|
use hypertext::{html_elements, maud, maud_move, GlobalAttributes, Raw, Renderable};
|
||||||
|
|
||||||
pub(crate) use home::home;
|
pub(crate) use home::home;
|
||||||
|
use post::article;
|
||||||
pub(crate) use post::Post;
|
pub(crate) use post::Post;
|
||||||
|
use serde::Deserialize;
|
||||||
pub(crate) use slideshow::Slideshow;
|
pub(crate) use slideshow::Slideshow;
|
||||||
pub(crate) use wiki::Wiki;
|
pub(crate) use wiki::Wiki;
|
||||||
|
|
||||||
|
@ -215,8 +218,56 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub(crate) fn editor<'s, 'html>(sack: &'s Sack) -> impl Renderable + 'html
|
/// Represents a simple post.
|
||||||
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
|
pub(crate) struct Flox {
|
||||||
|
pub(crate) title: String,
|
||||||
|
#[serde(with = "isodate")]
|
||||||
|
pub(crate) date: DateTime<Utc>,
|
||||||
|
pub(crate) desc: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Content for Flox {
|
||||||
|
fn parse_content(
|
||||||
|
content: &str,
|
||||||
|
sack: &Sack,
|
||||||
|
path: &Utf8Path,
|
||||||
|
library: Option<&Library>,
|
||||||
|
) -> (String, Outline, Bibliography) {
|
||||||
|
crate::text::md::parse(content, sack, path, library)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_html(
|
||||||
|
&self,
|
||||||
|
parsed: &str,
|
||||||
|
sack: &Sack,
|
||||||
|
outline: Outline,
|
||||||
|
bibliography: Bibliography,
|
||||||
|
) -> String {
|
||||||
|
flox(&self.title, parsed, sack, outline, bibliography).render().into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_link(&self, path: Utf8PathBuf) -> Option<Linkable> {
|
||||||
|
Some(Linkable::Date(LinkDate {
|
||||||
|
link: Link {
|
||||||
|
path,
|
||||||
|
name: self.title.to_owned(),
|
||||||
|
desc: self.desc.to_owned(),
|
||||||
|
},
|
||||||
|
date: self.date.to_owned(),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn flox<'p, 's, 'html>(
|
||||||
|
title: &'p str,
|
||||||
|
parsed: &'p str,
|
||||||
|
sack: &'s Sack,
|
||||||
|
outline: Outline,
|
||||||
|
bibliography: Bibliography,
|
||||||
|
) -> impl Renderable + 'html
|
||||||
where
|
where
|
||||||
|
'p: 'html,
|
||||||
's: 'html,
|
's: 'html,
|
||||||
{
|
{
|
||||||
page(
|
page(
|
||||||
|
@ -238,6 +289,7 @@ where
|
||||||
pre #output {}
|
pre #output {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
(article(title, parsed, sack, outline, bibliography))
|
||||||
}
|
}
|
||||||
script type="module" { (Raw("import 'editor';")) }
|
script type="module" { (Raw("import 'editor';")) }
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
use camino::{Utf8Path, Utf8PathBuf};
|
use camino::{Utf8Path, Utf8PathBuf};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use hauchiwa::{Bibliography, Content, Link, LinkDate, Linkable, Outline, Sack};
|
use hauchiwa::{Bibliography, Content, Link, LinkDate, Linkable, Outline, Sack};
|
||||||
|
@ -59,9 +57,28 @@ where
|
||||||
's: 'html,
|
's: 'html,
|
||||||
'p: 'html,
|
'p: 'html,
|
||||||
{
|
{
|
||||||
let heading = metadata.title.clone();
|
let main = maud_move!(
|
||||||
let main = maud_move!(
|
main {
|
||||||
main .wiki-main {
|
(article(&metadata.title, parsed, sack, outline, bibliography))
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
crate::html::page(sack, main, metadata.title.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn article<'p, 's, 'html>(
|
||||||
|
title: &'p str,
|
||||||
|
parsed: &'p str,
|
||||||
|
_: &'s Sack,
|
||||||
|
outline: Outline,
|
||||||
|
bibliography: Bibliography,
|
||||||
|
) -> impl Renderable + 'html
|
||||||
|
where
|
||||||
|
's: 'html,
|
||||||
|
'p: 'html,
|
||||||
|
{
|
||||||
|
maud_move!(
|
||||||
|
div .wiki-main {
|
||||||
|
|
||||||
// Slide in/out for mobile
|
// Slide in/out for mobile
|
||||||
input #wiki-aside-shown type="checkbox" hidden;
|
input #wiki-aside-shown type="checkbox" hidden;
|
||||||
|
@ -76,7 +93,7 @@ where
|
||||||
|
|
||||||
article .wiki-article /*class:list={classlist)*/ {
|
article .wiki-article /*class:list={classlist)*/ {
|
||||||
header class="markdown" {
|
header class="markdown" {
|
||||||
h1 #top { (heading) }
|
h1 #top { (title) }
|
||||||
}
|
}
|
||||||
section .wiki-article__markdown.markdown {
|
section .wiki-article__markdown.markdown {
|
||||||
(Raw(parsed))
|
(Raw(parsed))
|
||||||
|
@ -87,8 +104,5 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
)
|
||||||
|
|
||||||
crate::html::page(sack, main, metadata.title.clone())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
10
src/main.rs
10
src/main.rs
|
@ -4,7 +4,7 @@ mod ts;
|
||||||
|
|
||||||
use clap::{Parser, ValueEnum};
|
use clap::{Parser, ValueEnum};
|
||||||
use hauchiwa::Website;
|
use hauchiwa::Website;
|
||||||
use html::{Post, Slideshow, Wiki};
|
use html::{Flox, Post, Slideshow, Wiki};
|
||||||
use hypertext::Renderable;
|
use hypertext::Renderable;
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
|
@ -27,7 +27,7 @@ fn main() {
|
||||||
.content::<Post>("content/posts/**/*", ["md", "mdx"].into())
|
.content::<Post>("content/posts/**/*", ["md", "mdx"].into())
|
||||||
.content::<Slideshow>("content/slides/**/*", ["md", "lhs"].into())
|
.content::<Slideshow>("content/slides/**/*", ["md", "lhs"].into())
|
||||||
.content::<Wiki>("content/wiki/**/*", ["md"].into())
|
.content::<Wiki>("content/wiki/**/*", ["md"].into())
|
||||||
.content::<Post>("content/projects/**/*", ["md"].into())
|
.content::<Flox>("content/projects/flox.md", ["md"].into())
|
||||||
.js("search", "./js/search/dist/search.js")
|
.js("search", "./js/search/dist/search.js")
|
||||||
.js("photos", "./js/vanilla/photos.js")
|
.js("photos", "./js/vanilla/photos.js")
|
||||||
.js("reveal", "./js/vanilla/reveal.js")
|
.js("reveal", "./js/vanilla/reveal.js")
|
||||||
|
@ -40,12 +40,6 @@ fn main() {
|
||||||
|sack| crate::html::search(sack).render().to_owned().into(),
|
|sack| crate::html::search(sack).render().to_owned().into(),
|
||||||
"search/index.html".into(),
|
"search/index.html".into(),
|
||||||
)
|
)
|
||||||
.add_virtual_linked(
|
|
||||||
|sack| crate::html::editor(sack).render().to_owned().into(),
|
|
||||||
"projects/flox/index.html".into(),
|
|
||||||
"Flox".into(),
|
|
||||||
"Small functional language written in Rust and compiled to WebAssembly.".into()
|
|
||||||
)
|
|
||||||
.add_virtual(
|
.add_virtual(
|
||||||
|sack| crate::html::to_list(sack, sack.get_links("projects/**/*.html"), "Projects".into()),
|
|sack| crate::html::to_list(sack, sack.get_links("projects/**/*.html"), "Projects".into()),
|
||||||
"projects/index.html".into(),
|
"projects/index.html".into(),
|
||||||
|
|
Loading…
Reference in a new issue