add tags to model

This commit is contained in:
Maciej Jur 2024-09-23 23:22:37 +02:00
parent de976814f1
commit c74b1499a4
Signed by: kamov
GPG key ID: 191CBFF5F72ECAFD
13 changed files with 380 additions and 320 deletions

View file

@ -1,6 +1,7 @@
--- ---
title: Lambda calculus is the DNA of all computation title: Lambda calculus is the DNA of all computation
date: 2024-09-07T20:32:00.281Z date: 2024-09-07T20:32:00.281Z
tags: [lambda calculus, fun]
desc: > desc: >
Lambda calculus can be used to express any computation, but what does it entail? As it turns out first class functions are the single most powerful abstraction. Lambda calculus can be used to express any computation, but what does it entail? As it turns out first class functions are the single most powerful abstraction.
scripts: scripts:

View file

@ -1,6 +1,7 @@
--- ---
title: Remember forums? title: Remember forums?
date: 2024-09-21T19:14:29.799Z date: 2024-09-21T19:14:29.799Z
tags: [thought, internet]
desc: > desc: >
It feels to me like forums are slowly getting forgotten, replaced with more high-paced services like Discord or Twitter. It feels to me like forums are slowly getting forgotten, replaced with more high-paced services like Discord or Twitter.
In my opinion this isn't a good thing at all. In my opinion this isn't a good thing at all.

View file

@ -2,7 +2,7 @@ use camino::Utf8Path;
use hauchiwa::Sack; use hauchiwa::Sack;
use hypertext::{html_elements, maud, maud_move, GlobalAttributes, Raw, Renderable}; use hypertext::{html_elements, maud, maud_move, GlobalAttributes, Raw, Renderable};
use crate::{html::Post, text::md::parse, Link, LinkDate, MyData}; use crate::{model::Post, text::md::parse, Link, LinkDate, MyData};
const INTRO: &str = r#" const INTRO: &str = r#"
## ##

View file

@ -1,24 +0,0 @@
//! This module is supplementary to Serde, it allows you tu parse JS dates.
use chrono::{DateTime, Utc};
use serde::{self, Deserialize, Deserializer};
// pub fn serialize<S>(
// date: &DateTime<Utc>,
// serializer: S,
// ) -> Result<S::Ok, S::Error>
// where
// S: Serializer,
// {
// let s = date.to_rfc3339();
// serializer.serialize_str(&s)
// }
pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<DateTime<Utc>, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
let dt = chrono::DateTime::parse_from_rfc3339(&s).map_err(serde::de::Error::custom)?;
Ok(dt.into())
}

View file

@ -4,7 +4,7 @@ use camino::Utf8Path;
use hauchiwa::Outline; use hauchiwa::Outline;
use hypertext::{html_elements, maud_move, GlobalAttributes, Raw, Renderable}; use hypertext::{html_elements, maud_move, GlobalAttributes, Raw, Renderable};
use crate::{html::Wiki, Link, MySack}; use crate::{model::Wiki, Link, MySack};
/// Render the outline for a document /// Render the outline for a document
pub(crate) fn show_outline(outline: Outline) -> impl Renderable { pub(crate) fn show_outline(outline: Outline) -> impl Renderable {

View file

@ -1,6 +1,5 @@
mod head; mod head;
mod home; mod home;
mod isodate;
mod list; mod list;
mod misc; mod misc;
pub mod post; pub mod post;
@ -16,11 +15,8 @@ use hypertext::{html_elements, maud, maud_move, GlobalAttributes, Raw, Renderabl
pub(crate) use home::home; pub(crate) use home::home;
use post::article; use post::article;
pub(crate) use post::Post;
pub(crate) use slideshow::Slideshow;
pub(crate) use wiki::Wiki;
use crate::{LinkDate, MySack}; use crate::{model::Post, LinkDate, MySack};
fn navbar() -> impl Renderable { fn navbar() -> impl Renderable {
static ITEMS: &[(&str, &str)] = &[ static ITEMS: &[(&str, &str)] = &[
@ -219,11 +215,11 @@ pub fn as_html(
outline: Outline, outline: Outline,
bibliography: Bibliography, bibliography: Bibliography,
) -> String { ) -> String {
flox(&meta.title, parsed, sack, outline, bibliography) flox(meta, parsed, sack, outline, bibliography)
} }
pub(crate) fn flox( pub(crate) fn flox(
title: &str, meta: &Post,
parsed: &str, parsed: &str,
sack: &MySack, sack: &MySack,
outline: Outline, outline: Outline,
@ -248,7 +244,7 @@ pub(crate) fn flox(
pre #output {} pre #output {}
} }
} }
(article(title, parsed, sack, outline, bibliography)) (article(meta, parsed, sack, outline, bibliography))
} }
), ),
String::from("Flox"), String::from("Flox"),

View file

@ -1,21 +1,9 @@
use camino::Utf8Path; use camino::Utf8Path;
use chrono::{DateTime, Utc};
use hauchiwa::{Bibliography, Outline}; use hauchiwa::{Bibliography, Outline};
use hayagriva::Library; use hayagriva::Library;
use hypertext::{html_elements, maud_move, GlobalAttributes, Raw, Renderable}; use hypertext::{html_elements, maud_move, rsx, rsx_move, GlobalAttributes, Raw, Renderable};
use serde::Deserialize;
use crate::MySack; use crate::{model::Post, MySack};
/// Represents a simple post.
#[derive(Deserialize, Debug, Clone)]
pub struct Post {
pub title: String,
#[serde(with = "super::isodate")]
pub date: DateTime<Utc>,
pub desc: Option<String>,
pub scripts: Option<Vec<String>>,
}
pub fn parse_content( pub fn parse_content(
content: &str, content: &str,
@ -52,7 +40,7 @@ where
{ {
let main = maud_move!( let main = maud_move!(
main { main {
(article(&meta.title, parsed, sack, outline, bibliography)) (article(meta, parsed, sack, outline, bibliography))
} }
); );
@ -60,7 +48,7 @@ where
} }
pub fn article<'p, 's, 'html>( pub fn article<'p, 's, 'html>(
title: &'p str, meta: &'p Post,
parsed: &'p str, parsed: &'p str,
_: &'s MySack, _: &'s MySack,
outline: Outline, outline: Outline,
@ -84,17 +72,37 @@ where
(crate::html::misc::show_outline(outline)) (crate::html::misc::show_outline(outline))
} }
article .wiki-article /*class:list={classlist)*/ { (paper_page(meta, parsed, bibliography))
header class="markdown" { }
h1 #top { (title) } )
} }
section .wiki-article__markdown.markdown {
(Raw(parsed))
}
@if let Some(bib) = bibliography.0 { fn paper_page<'a>(meta: &'a Post, parsed: &'a str, bib: Bibliography) -> impl Renderable + 'a {
(crate::html::misc::emit_bibliography(bib)) maud_move!(
article .wiki-article {
header {
h1 #top {
(&meta.title)
} }
div .line {
div .date {
(meta.date.format("%Y-%m-%d").to_string())
}
@if let Some(ref tags) = meta.tags {
ul .tags {
@for tag in tags {
li { (tag) }
}
}
}
}
}
section .wiki-article__markdown.markdown {
(Raw(parsed))
}
@if let Some(bib) = bib.0 {
(crate::html::misc::emit_bibliography(bib))
} }
} }
) )

View file

@ -1,13 +1,11 @@
use std::fmt::Write; use std::fmt::Write;
use camino::Utf8Path; use camino::Utf8Path;
use chrono::{DateTime, Utc};
use hauchiwa::{Bibliography, Outline}; use hauchiwa::{Bibliography, Outline};
use hayagriva::Library; use hayagriva::Library;
use hypertext::{html_elements, maud, GlobalAttributes, Raw, Renderable}; use hypertext::{html_elements, maud, GlobalAttributes, Raw, Renderable};
use serde::Deserialize;
use crate::MySack; use crate::{model::Slideshow, MySack};
const CSS: &str = r#" const CSS: &str = r#"
.slides img { .slides img {
@ -17,15 +15,6 @@ const CSS: &str = r#"
} }
"#; "#;
/// Represents a slideshow
#[derive(Deserialize, Debug, Clone)]
pub(crate) struct Slideshow {
pub title: String,
#[serde(with = "super::isodate")]
pub date: DateTime<Utc>,
pub desc: Option<String>,
}
pub fn parse_content( pub fn parse_content(
content: &str, content: &str,
sack: &MySack, sack: &MySack,

View file

@ -2,15 +2,8 @@ use camino::Utf8Path;
use hauchiwa::{Bibliography, Outline}; use hauchiwa::{Bibliography, Outline};
use hayagriva::Library; use hayagriva::Library;
use hypertext::{html_elements, maud_move, GlobalAttributes, Raw, Renderable}; use hypertext::{html_elements, maud_move, GlobalAttributes, Raw, Renderable};
use serde::Deserialize;
use crate::MySack; use crate::{model::Wiki, MySack};
/// Represents a wiki page
#[derive(Deserialize, Debug, Clone)]
pub struct Wiki {
pub title: String,
}
pub fn parse_content( pub fn parse_content(
content: &str, content: &str,

View file

@ -1,4 +1,5 @@
mod html; mod html;
mod model;
mod text; mod text;
mod ts; mod ts;
@ -8,8 +9,8 @@ use camino::{Utf8Path, Utf8PathBuf};
use chrono::{DateTime, Datelike, Utc}; use chrono::{DateTime, Datelike, Utc};
use clap::{Parser, ValueEnum}; use clap::{Parser, ValueEnum};
use hauchiwa::{Collection, Processor, Sack, Website}; use hauchiwa::{Collection, Processor, Sack, Website};
use html::{Post, Slideshow, Wiki};
use hypertext::Renderable; use hypertext::Renderable;
use model::{Post, Slideshow, Wiki};
#[derive(Parser, Debug, Clone)] #[derive(Parser, Debug, Clone)]
struct Args { struct Args {

53
src/model.rs Normal file
View file

@ -0,0 +1,53 @@
use chrono::{DateTime, Utc};
use serde::Deserialize;
/// Represents a simple post.
#[derive(Deserialize, Debug, Clone)]
pub struct Post {
pub title: String,
#[serde(with = "isodate")]
pub date: DateTime<Utc>,
pub desc: Option<String>,
pub tags: Option<Vec<String>>,
pub scripts: Option<Vec<String>>,
}
/// Represents a slideshow
#[derive(Deserialize, Debug, Clone)]
pub(crate) struct Slideshow {
pub title: String,
#[serde(with = "isodate")]
pub date: DateTime<Utc>,
pub desc: Option<String>,
}
/// Represents a wiki page
#[derive(Deserialize, Debug, Clone)]
pub struct Wiki {
pub title: String,
}
mod isodate {
use chrono::{DateTime, Utc};
use serde::{self, Deserialize, Deserializer};
// pub fn serialize<S>(
// date: &DateTime<Utc>,
// serializer: S,
// ) -> Result<S::Ok, S::Error>
// where
// S: Serializer,
// {
// let s = date.to_rfc3339();
// serializer.serialize_str(&s)
// }
pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<DateTime<Utc>, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
let dt = chrono::DateTime::parse_from_rfc3339(&s).map_err(serde::de::Error::custom)?;
Ok(dt.into())
}
}

View file

@ -1,191 +1,200 @@
.markdown { .markdown {
h1 { h1 {
font-size: 2.5rem; font-size: 2.5rem;
} }
h2 { h2 {
font-size: 1.8rem; font-size: 1.8rem;
} }
h3 { h3 {
font-size: 1.5rem; font-size: 1.5rem;
} }
h4, > h5, > h6 { h4,
font-size: 1.2rem; > h5,
} > h6 {
font-size: 1.2rem;
}
p { p {
margin: 0.5em 0; margin: 0.5em 0;
hyphens: auto; hyphens: auto;
text-align: justify; text-align: justify;
line-height: 1.5em; line-height: 1.5em;
} }
ul, ol { ul,
padding-left: 1em; ol {
padding-left: 1em;
ul, ol { ul,
padding-left: 1em; ol {
} padding-left: 1em;
} }
}
li { li {
line-height: 1.5em; line-height: 1.5em;
} }
a { a {
color: var(--c-primary); color: var(--c-primary);
font-family: var(--serif); font-family: var(--serif);
font-weight: 500; font-weight: 500;
font-style: italic; font-style: italic;
text-decoration: unset; text-decoration: unset;
&:hover { &:hover {
text-decoration: underline; text-decoration: underline;
} }
} }
> h1, > h2, > h3, > h4, > h5, > h6 { > h1,
margin-bottom: 0.5em; > h2,
font-family: var(--serif); > h3,
font-weight: 500; > h4,
> h5,
> h6 {
margin-bottom: 0.5em;
font-family: var(--serif);
font-weight: 500;
&:not(:first-child) { &:not(:first-child) {
margin-top: 1em; margin-top: 1em;
} }
} }
img:not([class]) {
max-width: 100%;
height: auto;
margin-block: 1em;
}
img:not([class]) { blockquote {
max-width: 100%; position: relative;
height: auto; margin: 1em 2em;
margin-block: 1em;
}
blockquote { &::before {
position: relative; content: "";
margin: 1em 2em; display: block;
position: absolute;
left: -1em;
width: 4px;
height: 100%;
background-color: var(--c-secondary);
border-radius: 2px;
}
}
&::before { > table {
content: ""; margin: 1em auto 1em auto;
display: block; border-collapse: collapse;
position: absolute; overflow-x: auto;
left: -1em;
width: 4px;
height: 100%;
background-color: var(--c-secondary);
border-radius: 2px;
}
}
> table { th,
margin: 1em auto 1em auto; td {
border-collapse: collapse; padding: 0.2em 0.5em;
overflow-x: auto; border: 1px solid #dbdbdb;
}
th, td { th {
padding: 0.2em 0.5em; background-color: #f3f3f3;
border: 1px solid #dbdbdb; }
}
th { p {
background-color: #f3f3f3; white-space: pre-line;
} }
}
p { code {
white-space: pre-line; font-family: var(--monospace);
} }
}
code { :not(pre) > code {
font-family: var(--monospace); padding-inline: 0.25em;
} background-color: white;
border-radius: 0.33em;
border: 1px dashed lightgray;
}
:not(pre) > code { .listing {
padding-inline: 0.25em; position: relative;
background-color: white; margin: 1em -1em;
border-radius: 0.33em; border-width: 0.25em 0;
border: 1px dashed lightgray; border-style: solid;
}
.listing { @media (min-width: 600px) {
position: relative; margin: 1em 0.5em;
margin: 1em -1em; border-width: 0.25rem;
border-width: 0.25em 0; border-radius: 0.5rem;
border-style: solid; }
@media (min-width: 600px) { &::before {
margin: 1em 0.5em; content: attr(data-lang);
border-width: 0.25rem; display: block;
border-radius: 0.5rem; top: 0;
} right: 0;
position: absolute;
padding: 0.1em 0.2em 0 0.3em;
border-radius: 0 0 0 0.5rem;
}
&::before { pre {
content: attr(data-lang); padding: 0.5em;
display: block; max-width: 100%;
top: 0; overflow-x: auto;
right: 0; tab-size: 2;
position: absolute;
padding: 0.1em 0.2em 0 0.3em;
border-radius: 0 0 0 0.5rem;
}
pre { > code {
padding: 0.5em; display: block;
max-width: 100%; line-height: 1.5em;
overflow-x: auto; }
tab-size: 2; }
}
> code { .math-display {
display: block; margin-block: 1em;
line-height: 1.5em; font-size: 1.1em;
} overflow-x: auto;
} overflow-y: hidden;
} }
.math-display { .marginnote {
margin-block: 1em; display: block;
font-size: 1.1em; margin: 1em 1.5em;
overflow-x: auto; padding-block: 0.5em;
overflow-y: hidden; border-block: 1px dashed gray;
} color: gray;
.marginnote { @media (min-width: 38em) {
display: block; float: right;
margin: 1em 1.5em; clear: right;
padding-block: 0.5em; max-width: 14rem;
border-block: 1px dashed gray; margin-right: 0;
color: gray; text-align: justify;
hyphens: auto;
}
@media (min-width: 38em) { @media (min-width: 80em) {
float: right; margin: 2em -17rem;
clear: right; }
max-width: 14rem;
margin-right: 0;
text-align: justify;
hyphens: auto;
}
@media (min-width: 80em) { a {
margin: 2em -17rem; color: var(--c-primary);
} }
}
a { // TODO: clean this
color: var(--c-primary); .md-icon {
} display: inline-block;
} height: 1.2em;
width: auto;
vertical-align: middle;
margin: 0.1em 0;
// TODO: clean this &.big {
.md-icon { height: 4em;
display: inline-block; }
height: 1.2em; }
width: auto;
vertical-align: middle;
margin: 0.1em 0;
&.big {
height: 4em;
}
}
} }

View file

@ -1,115 +1,148 @@
$bp-m: 58rem; $bp-m: 58rem;
$bp-l: 80rem; $bp-l: 80rem;
.wiki-main { .wiki-main {
position: relative; position: relative;
display: grid; display: grid;
grid-template-columns: auto minmax(0, 1fr); grid-template-columns: auto minmax(0, 1fr);
@media (min-width: $bp-m) { @media (min-width: $bp-m) {
grid-template-columns: 16rem minmax(0, 1fr); grid-template-columns: 16rem minmax(0, 1fr);
} }
@media (min-width: $bp-l) { @media (min-width: $bp-l) {
grid-template-columns: 16rem minmax(0, 1fr) 16rem; grid-template-columns: 16rem minmax(0, 1fr) 16rem;
} }
} }
.wiki-aside { .wiki-aside {
position: absolute; position: absolute;
width: 16rem; width: 16rem;
height: 100%; height: 100%;
transition: margin-left linear 0.1s; transition: margin-left linear 0.1s;
background-color: var(--c-bg-main); background-color: var(--c-bg-main);
z-index: 5; z-index: 5;
@media (min-width: $bp-m) { @media (min-width: $bp-m) {
position: static; position: static;
background-color: unset; background-color: unset;
} }
.link-tree { .link-tree {
position: sticky; position: sticky;
top: 0; top: 0;
} }
&__slider { &__slider {
position: absolute; position: absolute;
top: 0.5em; top: 0.5em;
right: -2em; right: -2em;
cursor: pointer; cursor: pointer;
@media (min-width: $bp-m) { @media (min-width: $bp-m) {
display: none; display: none;
} }
} }
} }
#wiki-aside-shown { #wiki-aside-shown {
&:checked { &:checked {
~ .wiki-aside { ~ .wiki-aside {
box-shadow: var(--shadow-m); box-shadow: var(--shadow-m);
@media (min-width: $bp-m) { @media (min-width: $bp-m) {
box-shadow: unset; box-shadow: unset;
} }
> .wiki-aside__slider { > .wiki-aside__slider {
transform: rotate(180deg); transform: rotate(180deg);
} }
} }
} }
&:not(:checked) { &:not(:checked) {
~ .wiki-aside { ~ .wiki-aside {
margin-left: -16rem; margin-left: -16rem;
@media (min-width: $bp-m) { @media (min-width: $bp-m) {
margin-left: unset; margin-left: unset;
} }
} }
} }
} }
.wiki-icon { .wiki-icon {
max-height: 1.5em; max-height: 1.5em;
max-width: 1.5em; max-width: 1.5em;
} }
.wiki-article { .wiki-article {
min-width: 0; min-width: 0;
margin-inline: auto; margin-inline: auto;
padding: 1em; padding: 1em;
padding-top: 2em; padding-top: 2em;
background-color: white; background-color: white;
transition: margin ease-in-out 0.2s, padding ease-in-out 0.2s; transition:
margin ease-in-out 0.2s,
padding ease-in-out 0.2s;
@media (min-width: $bp-m) { @media (min-width: $bp-m) {
max-width: min(100%, 50em); max-width: min(100%, 50em);
height: fit-content; height: fit-content;
margin-block: 1em; margin-block: 1em;
padding-top: 1em; padding-top: 1em;
border-radius: 0.5em; border-radius: 0.5em;
box-shadow: var(--shadow-l); box-shadow: var(--shadow-l);
} }
@media (min-width: $bp-l) { @media (min-width: $bp-l) {
margin-block: 2em; margin-block: 2em;
padding: 2em; padding: 2em;
} }
&__markdown { header {
max-width: calc(100vw - 2em); margin-bottom: 1em;
}
&.has-icon { h1 {
background-position: top right; font-size: 2.5rem;
background-repeat: no-repeat; font-family: var(--serif);
background-size: 20% auto; font-weight: 500;
line-height: 1em;
margin-bottom: 0.3em;
}
&.icon-haskell { .line {
background-image: url("/static/sketch/haskell.png"); display: flex;
} flex-direction: row;
} gap: 0.5em;
}
.tags {
display: inline;
list-style: none;
padding: 0px;
li {
display: inline;
&:not(:last-child)::after {
content: ", ";
}
}
}
}
&__markdown {
max-width: calc(100vw - 2em);
}
&.has-icon {
background-position: top right;
background-repeat: no-repeat;
background-size: 20% auto;
&.icon-haskell {
background-image: url("/static/sketch/haskell.png");
}
}
} }