mirror of
https://github.com/alex-s168/website.git
synced 2025-09-10 01:05:07 +02:00
atom feed!
This commit is contained in:
@@ -294,8 +294,10 @@ document.addEventListener('scroll', (event) => {
|
|||||||
#let people = (
|
#let people = (
|
||||||
alex: (
|
alex: (
|
||||||
nick: "alex_s168",
|
nick: "alex_s168",
|
||||||
|
name: "Alexander Nutz",
|
||||||
url: "https://alex.vxcc.dev",
|
url: "https://alex.vxcc.dev",
|
||||||
badge: "https://alex.vxcc.dev/res/badge.png",
|
badge: "https://alex.vxcc.dev/res/badge.png",
|
||||||
|
mail: "nutz.alexander@vxcc.dev",
|
||||||
),
|
),
|
||||||
ote: (
|
ote: (
|
||||||
nick: "otesunki",
|
nick: "otesunki",
|
||||||
@@ -309,7 +311,7 @@ document.addEventListener('scroll', (event) => {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
#metadata(json.encode(people)) <meta-people>
|
#metadata(people) <meta-people>
|
||||||
|
|
||||||
#let person(p) = {
|
#let person(p) = {
|
||||||
flink(p.url, p.nick)
|
flink(p.url, p.nick)
|
||||||
|
45
config.py
45
config.py
@@ -23,15 +23,17 @@ rule typst
|
|||||||
rule git_inp
|
rule git_inp
|
||||||
command = git log -1 --format="--input git_rev=%H --input git_commit_date=\\\"%ad\\\"" --date="format:%d. %B %Y %H:%M" -- $in > $out.temp && \
|
command = git log -1 --format="--input git_rev=%H --input git_commit_date=\\\"%ad\\\"" --date="format:%d. %B %Y %H:%M" -- $in > $out.temp && \
|
||||||
cmp -s $out.temp $out || mv $out.temp $out; \
|
cmp -s $out.temp $out || mv $out.temp $out; \
|
||||||
rm -f $out.temp
|
git log -1 --format="%cI" -- $in > $out.iso.temp && \
|
||||||
|
cmp -s $out.iso.temp $out || mv $out.iso.temp $out.iso; \
|
||||||
|
rm -f $out.temp $out.iso.temp
|
||||||
restat = 1
|
restat = 1
|
||||||
|
|
||||||
rule badges_list
|
rule badges_list
|
||||||
command = typst query $in "<meta-people>" --root . --input query=true --field value --one | jq -r . | jq -r 'to_entries[] | [.key,.value.badge] | @tsv' > $out
|
command = typst query $in "<meta-people>" --root . --input query=true --field value --one | jq -r 'to_entries[] | [.key,.value.badge] | @tsv' > $out
|
||||||
build build/badges.txt: badges_list common.typ
|
build build/badges.txt: badges_list common.typ
|
||||||
|
|
||||||
rule curl
|
rule curl
|
||||||
command = curl $url > $out
|
command = curl $curlflags $url > $out
|
||||||
|
|
||||||
rule cp
|
rule cp
|
||||||
command = cp $flags $in $out
|
command = cp $flags $in $out
|
||||||
@@ -44,7 +46,10 @@ rule runclean
|
|||||||
build clean : runclean
|
build clean : runclean
|
||||||
|
|
||||||
rule ttf2woff
|
rule ttf2woff
|
||||||
command = fonttools ttLib.woff2 compress $in -o $out
|
command = fonttools ttLib.woff2 compress $in -o $out 2>/dev/null
|
||||||
|
|
||||||
|
rule python
|
||||||
|
command = python $in
|
||||||
|
|
||||||
rule python_capture
|
rule python_capture
|
||||||
command = python $in > $out
|
command = python $in > $out
|
||||||
@@ -54,18 +59,16 @@ rule minhtml
|
|||||||
|
|
||||||
build build.ninja: regen | config.py build/badges.txt res pages
|
build build.ninja: regen | config.py build/badges.txt res pages
|
||||||
|
|
||||||
build build/deploy/coffee.js : python_capture gen_coffee_js.py
|
|
||||||
|
|
||||||
rule cargo_release_bin
|
rule cargo_release_bin
|
||||||
command = (cd $in && cargo build --release) && cp $in/target/release/$file $out
|
command = (cd $in && cargo build --release) && cp $in/target/release/$file $out
|
||||||
pool = console
|
pool = console
|
||||||
|
|
||||||
build build/coffee_server : cargo_release_bin coffee
|
|
||||||
file = coffee
|
|
||||||
|
|
||||||
rule expect_img_size
|
rule expect_img_size
|
||||||
command = eval "[ $$(ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=s=x:p=0 $in) = $size ]" && touch $out
|
command = eval "[ $$(ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=s=x:p=0 $in) = $size ]" && touch $out
|
||||||
|
|
||||||
|
rule touch
|
||||||
|
command = touch $out
|
||||||
|
|
||||||
rule ffmpeg_compress
|
rule ffmpeg_compress
|
||||||
command = ffmpeg -y -i $in -compression_level 100 $out -hide_banner -loglevel error
|
command = ffmpeg -y -i $in -compression_level 100 $out -hide_banner -loglevel error
|
||||||
|
|
||||||
@@ -73,11 +76,27 @@ rule pngquant
|
|||||||
command = pngquant $in -o $out --force --quality $quality
|
command = pngquant $in -o $out --force --quality $quality
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
gen += """
|
||||||
|
build build/deploy/coffee.js : python_capture gen_coffee_js.py
|
||||||
|
|
||||||
|
build build/coffee_server : cargo_release_bin coffee
|
||||||
|
file = coffee
|
||||||
|
"""
|
||||||
web_targets.append("build/deploy/coffee.js")
|
web_targets.append("build/deploy/coffee.js")
|
||||||
web_targets.append("build/coffee_server")
|
web_targets.append("build/coffee_server")
|
||||||
|
|
||||||
pages = [x for x in os.listdir("./pages/")]
|
pages = [x for x in os.listdir("./pages/")]
|
||||||
fonts = [x for x in os.listdir("./fonts/")]
|
|
||||||
|
gen += """
|
||||||
|
build build/pages.typ build/pages.json : python pages.gen.py | pages.in.typ
|
||||||
|
|
||||||
|
build gen_typst: phony build/pages.typ | """+ " ".join(f"build/{x}.git_rev.txt.iso" for x in pages) +"""
|
||||||
|
"""
|
||||||
|
|
||||||
|
gen += """
|
||||||
|
build build/deploy/atom.xml : python gen_feed.py | build/pages.json """ + " ".join(f"build/{x}.nano.html" for x in pages) + """
|
||||||
|
"""
|
||||||
|
web_targets.append("build/deploy/atom.xml")
|
||||||
|
|
||||||
variants = [
|
variants = [
|
||||||
{
|
{
|
||||||
@@ -101,11 +120,11 @@ variants = [
|
|||||||
for page in pages:
|
for page in pages:
|
||||||
gr = "build/" + page + ".git_rev.txt"
|
gr = "build/" + page + ".git_rev.txt"
|
||||||
gen += "\n"
|
gen += "\n"
|
||||||
gen += "build "+gr+" : git_inp pages/" + page + " | build/git_rev.txt"
|
gen += "build "+gr+" | "+gr+".iso : git_inp pages/" + page + " | build/git_rev.txt\n"
|
||||||
for var in variants:
|
for var in variants:
|
||||||
tg = "build/" + page + var["suffix"]
|
tg = "build/" + page + var["suffix"]
|
||||||
gen += "\n"
|
gen += "\n"
|
||||||
gen += "build "+tg+" : typst " + "pages/" + page + " | "+gr+"\n"
|
gen += "build "+tg+" : typst " + "pages/" + page + " | "+gr+" || gen_typst\n"
|
||||||
gen += " flags = " + var["args"] + " $$(cat "+gr+")\n"
|
gen += " flags = " + var["args"] + " $$(cat "+gr+")\n"
|
||||||
if tg.endswith(".html"):
|
if tg.endswith(".html"):
|
||||||
gen += "\n"
|
gen += "\n"
|
||||||
@@ -142,11 +161,13 @@ if os.path.isfile("build/badges.txt"):
|
|||||||
else:
|
else:
|
||||||
gen += f"curl |@ {val}\n"
|
gen += f"curl |@ {val}\n"
|
||||||
gen += " url = "+url+"\n"
|
gen += " url = "+url+"\n"
|
||||||
|
gen += " curlflags = -k"
|
||||||
|
|
||||||
gen += "\n"
|
gen += "\n"
|
||||||
gen += f"build {val} : expect_img_size {tg}\n"
|
gen += f"build {val} : expect_img_size {tg}\n"
|
||||||
gen += f" size = 88x31"
|
gen += f" size = 88x31"
|
||||||
|
|
||||||
|
fonts = [x for x in os.listdir("./fonts/")]
|
||||||
for font in fonts:
|
for font in fonts:
|
||||||
font = font.replace(".ttf", "")
|
font = font.replace(".ttf", "")
|
||||||
tg = f"build/deploy/res/{font}.woff2"
|
tg = f"build/deploy/res/{font}.woff2"
|
||||||
|
58
gen_feed.py
Normal file
58
gen_feed.py
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import sys, json
|
||||||
|
from feedgen.feed import FeedGenerator
|
||||||
|
|
||||||
|
fg = FeedGenerator()
|
||||||
|
|
||||||
|
articles = 0
|
||||||
|
with open("build/pages.json", "r") as f:
|
||||||
|
articles = json.load(f)
|
||||||
|
articles = [x for x in articles if x["in-feed"] == True]
|
||||||
|
|
||||||
|
all_authors = {}
|
||||||
|
for article in articles:
|
||||||
|
authors = article["authors"]
|
||||||
|
for author in authors:
|
||||||
|
nick = author["nick"]
|
||||||
|
name = author.get("name", nick)
|
||||||
|
mail = author.get("mail", None)
|
||||||
|
url = author.get("url", None)
|
||||||
|
out = {"name":name}
|
||||||
|
if mail:
|
||||||
|
out["email"] = mail
|
||||||
|
if url:
|
||||||
|
out["uri"] = url
|
||||||
|
all_authors[nick] = out
|
||||||
|
|
||||||
|
fg.author([v for _,v in all_authors.items()])
|
||||||
|
|
||||||
|
fg.id("https://alex.vxcc.dev")
|
||||||
|
fg.title("alex168's block")
|
||||||
|
fg.subtitle("alex_s168's blog")
|
||||||
|
fg.icon("https://vxcc.dev/alex/res/favicon.png")
|
||||||
|
fg.language("en-US")
|
||||||
|
fg.link(href="https://alex.vxcc.dev/atom.xml", rel="self")
|
||||||
|
fg.link(href="https://alex.vxcc.dev/", rel="alternate")
|
||||||
|
|
||||||
|
for article in reversed(articles):
|
||||||
|
page = article["page"]
|
||||||
|
url = article["url"]
|
||||||
|
title = article["title"]
|
||||||
|
summary = article["summary"]
|
||||||
|
modified = article["modified"]
|
||||||
|
authors = article["authors"]
|
||||||
|
|
||||||
|
content = None
|
||||||
|
with open(f"./build/{page}.nano.html", "r") as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
fe = fg.add_entry()
|
||||||
|
fe.id(f"https://vxcc.dev/alex/{url}")
|
||||||
|
fe.title(title)
|
||||||
|
fe.summary(summary)
|
||||||
|
fe.link(href=url)
|
||||||
|
fe.updated(modified)
|
||||||
|
fe.content(content, type="html")
|
||||||
|
|
||||||
|
fe.author([all_authors[x["nick"]] for x in authors])
|
||||||
|
|
||||||
|
fg.atom_file("build/deploy/atom.xml")
|
107
pages.gen.py
Normal file
107
pages.gen.py
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
import sys, json, subprocess
|
||||||
|
|
||||||
|
def typst_encode_pre(e, ind=" "):
|
||||||
|
if isinstance(e, dict):
|
||||||
|
if len(e.items()) == 0:
|
||||||
|
return ["(:)"]
|
||||||
|
elif len(e.items()) == 1:
|
||||||
|
k,v = list(e.items())[0]
|
||||||
|
v = typst_encode_pre(v, ind)
|
||||||
|
out = ["(" + k + ": " + v[0]]
|
||||||
|
out.extend(v[1:])
|
||||||
|
out[-1] = out[-1] + ")"
|
||||||
|
return out
|
||||||
|
else:
|
||||||
|
out = ["("]
|
||||||
|
first = True
|
||||||
|
for k,v in e.items():
|
||||||
|
if not first:
|
||||||
|
out[-1] = out[-1] + ","
|
||||||
|
first = False
|
||||||
|
v = typst_encode_pre(v, ind)
|
||||||
|
out.append(ind + k + ": " + v[0])
|
||||||
|
out.extend(ind+x for x in v[1:])
|
||||||
|
out[-1] = out[-1]
|
||||||
|
out.append(")")
|
||||||
|
return out
|
||||||
|
elif isinstance(e, list):
|
||||||
|
if len(e) == 0:
|
||||||
|
return ["()"]
|
||||||
|
elif len(e) == 1:
|
||||||
|
v = typst_encode_pre(e[0], ind)
|
||||||
|
out = ["(" + v[0]]
|
||||||
|
out.extend(v[1:])
|
||||||
|
out[-1] = out[-1] + ")"
|
||||||
|
return out
|
||||||
|
else:
|
||||||
|
out = ["("]
|
||||||
|
first = True
|
||||||
|
for v in e:
|
||||||
|
if not first:
|
||||||
|
out[-1] = out[-1] + ","
|
||||||
|
first = False
|
||||||
|
v = typst_encode_pre(v, ind)
|
||||||
|
out.append(ind + v[0])
|
||||||
|
out.extend(ind+x for x in v[1:])
|
||||||
|
out[-1] = out[-1]
|
||||||
|
out.append(")")
|
||||||
|
return out
|
||||||
|
elif isinstance(e, bool):
|
||||||
|
return ["true" if e else "false"]
|
||||||
|
elif isinstance(e, int) or isinstance(e, float):
|
||||||
|
return [str(e)]
|
||||||
|
elif isinstance(e, str):
|
||||||
|
# TODO: can do better (newlines)
|
||||||
|
return [json.dumps(e)]
|
||||||
|
else:
|
||||||
|
raise ValueError(f"can't typst encode {e}")
|
||||||
|
|
||||||
|
def typst_encode(e):
|
||||||
|
e = typst_encode_pre(e)
|
||||||
|
return "\n".join(e)
|
||||||
|
|
||||||
|
def typst_query_one(path, tag):
|
||||||
|
meta = subprocess.run([
|
||||||
|
"typst", "query", path, tag,
|
||||||
|
"--one",
|
||||||
|
"--field", "value",
|
||||||
|
"--root", ".",
|
||||||
|
"--input", "query=true",
|
||||||
|
"--features", "html"
|
||||||
|
], capture_output=True)
|
||||||
|
meta = meta.stdout.decode("utf-8").strip()
|
||||||
|
if len(meta) == 0:
|
||||||
|
return None
|
||||||
|
return json.loads(meta)
|
||||||
|
|
||||||
|
out = []
|
||||||
|
for page in typst_query_one("pages.in.typ", "<articles>"):
|
||||||
|
p_page = page["page"]
|
||||||
|
p_feed = page["feed"]
|
||||||
|
p_homepage = page["homepage"]
|
||||||
|
|
||||||
|
path = f"pages/{p_page}"
|
||||||
|
|
||||||
|
meta = typst_query_one(path, "<feed-ent>")
|
||||||
|
|
||||||
|
last_changed = None
|
||||||
|
with open(f"build/{p_page}.git_rev.txt.iso", "r") as f:
|
||||||
|
last_changed = f.read().strip()
|
||||||
|
|
||||||
|
res = {
|
||||||
|
"url": f"{p_page}.desktop.html",
|
||||||
|
"page": p_page,
|
||||||
|
"in-feed": p_feed,
|
||||||
|
"in-homepage": p_homepage,
|
||||||
|
"authors": meta["authors"],
|
||||||
|
"title": meta["title"],
|
||||||
|
"summary": meta["summary"],
|
||||||
|
"modified": last_changed,
|
||||||
|
}
|
||||||
|
out.append(res)
|
||||||
|
|
||||||
|
with open("build/pages.typ", "w") as f:
|
||||||
|
f.write("#let articles = " + typst_encode(out) + "\n")
|
||||||
|
|
||||||
|
with open("build/pages.json", "w") as f:
|
||||||
|
json.dump(out, f)
|
30
pages.in.typ
Normal file
30
pages.in.typ
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
|
||||||
|
// don't import this file directly! it will be post processed by the build script
|
||||||
|
// generates build/pages.typ
|
||||||
|
|
||||||
|
// first element in list will show up first in the homepage and the feed => needs to be newest article!
|
||||||
|
#let articles = (
|
||||||
|
(
|
||||||
|
page: "article-gpu-arch-1.typ",
|
||||||
|
// unfinished
|
||||||
|
feed: false,
|
||||||
|
homepage: false,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
page: "compiler-pattern-matching.typ",
|
||||||
|
feed: true,
|
||||||
|
homepage: true,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
page: "article-favicon.typ",
|
||||||
|
feed: true,
|
||||||
|
homepage: true,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
page: "article-make-regex-engine-1.typ",
|
||||||
|
feed: true,
|
||||||
|
homepage: true,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
#metadata(articles) <articles>
|
@@ -1,18 +1,27 @@
|
|||||||
#import "../common.typ": *
|
#import "../common.typ": *
|
||||||
#import "../simple-page-layout.typ": *
|
#import "../simple-page-layout.typ": *
|
||||||
#import "../core-page-style.typ": *
|
#import "../core-page-style.typ": *
|
||||||
#import "../components/header.typ": rev-and-authors
|
#import "../components/header.typ": *
|
||||||
|
|
||||||
|
#let article = (
|
||||||
|
authors: (people.alex,),
|
||||||
|
title: "The making of the favicon",
|
||||||
|
html-title: "The making of the favicon",
|
||||||
|
summary: "It turns out that websites need a favicon, and making one is hard..."
|
||||||
|
)
|
||||||
|
|
||||||
|
#metadata(article) <feed-ent>
|
||||||
|
|
||||||
#simple-page(
|
#simple-page(
|
||||||
gen-table-of-contents: true,
|
gen-table-of-contents: true,
|
||||||
[The making of the favicon]
|
article.html-title
|
||||||
)[
|
)[
|
||||||
|
|
||||||
#section[
|
#section[
|
||||||
#title[The making of the favicon]
|
#title(article.title)
|
||||||
|
|
||||||
#sized-p(small-font-size)[
|
#sized-p(small-font-size)[
|
||||||
#rev-and-authors((people.alex,))
|
#rev-and-authors(article.authors)
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@@ -3,16 +3,25 @@
|
|||||||
#import "../core-page-style.typ": *
|
#import "../core-page-style.typ": *
|
||||||
#import "../components/header.typ": *
|
#import "../components/header.typ": *
|
||||||
|
|
||||||
|
#let article = (
|
||||||
|
authors: (people.alex,),
|
||||||
|
title: "Designing a GPU architecture: Waves",
|
||||||
|
html-title: "Designing a GPU architecture: Waves",
|
||||||
|
summary: "Exploring GPU architecture and designing our own. Part 1: wavefronts / warps"
|
||||||
|
)
|
||||||
|
|
||||||
|
#metadata(article) <feed-ent>
|
||||||
|
|
||||||
#simple-page(
|
#simple-page(
|
||||||
gen-table-of-contents: true,
|
gen-table-of-contents: true,
|
||||||
[Designing a GPU architecture: Waves]
|
article.html-title
|
||||||
)[
|
)[
|
||||||
|
|
||||||
#section[
|
#section[
|
||||||
#title[Designing a GPU Architecture: Waves]
|
#title(article.title)
|
||||||
|
|
||||||
#sized-p(small-font-size)[
|
#sized-p(small-font-size)[
|
||||||
#rev-and-authors((people.alex,))
|
#rev-and-authors(article.authors)
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@@ -3,18 +3,26 @@
|
|||||||
#import "../core-page-style.typ": *
|
#import "../core-page-style.typ": *
|
||||||
#import "../components/header.typ": *
|
#import "../components/header.typ": *
|
||||||
|
|
||||||
|
#let article = (
|
||||||
|
authors: (people.alex,),
|
||||||
|
title: "Making a simple RegEx engine:
|
||||||
|
Part 1: Introduction to RegEx",
|
||||||
|
html-title: "Introduction to RegEx",
|
||||||
|
summary: "Do you also think that all RegEx engines kinda suck and you want to make your own? probably not"
|
||||||
|
)
|
||||||
|
|
||||||
|
#metadata(article) <feed-ent>
|
||||||
|
|
||||||
#simple-page(
|
#simple-page(
|
||||||
gen-table-of-contents: true,
|
gen-table-of-contents: true,
|
||||||
[Introduction to RegEx]
|
article.html-title
|
||||||
)[
|
)[
|
||||||
|
|
||||||
#section[
|
#section[
|
||||||
#title[Making a simple RegEx engine]
|
#title(article.title)
|
||||||
|
|
||||||
#title[Part 1: Introduction to RegEx]
|
|
||||||
|
|
||||||
#sized-p(small-font-size)[
|
#sized-p(small-font-size)[
|
||||||
#rev-and-authors((people.alex,))
|
#rev-and-authors(article.authors)
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@@ -3,16 +3,25 @@
|
|||||||
#import "../core-page-style.typ": *
|
#import "../core-page-style.typ": *
|
||||||
#import "../components/header.typ": *
|
#import "../components/header.typ": *
|
||||||
|
|
||||||
|
#let article = (
|
||||||
|
authors: (people.alex,),
|
||||||
|
title: "Approaches to pattern matching in compilers",
|
||||||
|
html-title: "Approaches to Compiler Pattern Matching",
|
||||||
|
summary: "If you are working an more advanced compilers, you probably had to work with pattern matching already. In this article, we will explore different approaches.",
|
||||||
|
)
|
||||||
|
|
||||||
|
#metadata(article) <feed-ent>
|
||||||
|
|
||||||
#simple-page(
|
#simple-page(
|
||||||
gen-table-of-contents: true,
|
gen-table-of-contents: true,
|
||||||
[Approaches to Pattern Matching - Alexander Nutz]
|
article.html-title
|
||||||
)[
|
)[
|
||||||
|
|
||||||
#section[
|
#section[
|
||||||
#title[Approaches to pattern matching in compilers]
|
#title(article.title)
|
||||||
|
|
||||||
#sized-p(small-font-size)[
|
#sized-p(small-font-size)[
|
||||||
#rev-and-authors((people.alex,))
|
#rev-and-authors(article.authors)
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -314,7 +323,7 @@
|
|||||||
Modern processor architecture features like superscalar execution make this even more complicated.
|
Modern processor architecture features like superscalar execution make this even more complicated.
|
||||||
|
|
||||||
\
|
\
|
||||||
As a simple, *non realistic* example, let's imagine a CPU (core) that has one bit operations execution unit,
|
As a simple, *unrealistic* example, let's imagine a CPU (core) that has one bit operations execution unit,
|
||||||
and two ALU execution units / ports. \
|
and two ALU execution units / ports. \
|
||||||
This means that the CPU can execute two instructions in the ALU unit and one instruction in the bit ops unit at the same time.
|
This means that the CPU can execute two instructions in the ALU unit and one instruction in the bit ops unit at the same time.
|
||||||
]
|
]
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
#import "../common.typ": *
|
#import "../common.typ": *
|
||||||
#import "../simple-page-layout.typ": *
|
#import "../simple-page-layout.typ": *
|
||||||
#import "../core-page-style.typ": *
|
#import "../core-page-style.typ": *
|
||||||
|
#import "../build/pages.typ": articles
|
||||||
|
|
||||||
#let tree-list(..elements) = {
|
#let tree-list(..elements) = {
|
||||||
gen-tree-from-headings(elemfn: (content, x) => [
|
gen-tree-from-headings(elemfn: (content, x) => [
|
||||||
@@ -24,14 +25,12 @@
|
|||||||
#title[alex_s168]
|
#title[alex_s168]
|
||||||
#br()
|
#br()
|
||||||
|
|
||||||
Articles
|
Articles (#html-href("atom.xml")[Atom feed])
|
||||||
#br()
|
#br()
|
||||||
#tree-list(
|
#tree-list(..articles.filter(x => x.in-homepage).map(x => (
|
||||||
(level:1, body: [ Making a simple RegEx engine ]),
|
level: 1,
|
||||||
(level:2, body: html-href("article-make-regex-engine-1.typ.desktop.html")[ Part 1: Introduction to RegEx ]),
|
body: html-href(x.url, x.title)
|
||||||
(level:1, body: html-href("compiler-pattern-matching.typ.desktop.html")[ Approaches to pattern matching in compilers ]),
|
)))
|
||||||
(level:1, body: html-href("article-favicon.typ.desktop.html")[ Making of the favicon ]),
|
|
||||||
)
|
|
||||||
#br()
|
#br()
|
||||||
|
|
||||||
Socials
|
Socials
|
||||||
|
@@ -48,6 +48,8 @@
|
|||||||
// TODO: fix and re-add - #variant-link("less bloated HTML", ".min.html")
|
// TODO: fix and re-add - #variant-link("less bloated HTML", ".min.html")
|
||||||
- #variant-link("minimal HTML", ".nano.html")
|
- #variant-link("minimal HTML", ".nano.html")
|
||||||
]],
|
]],
|
||||||
|
[#html-href("atom.xml")[Atom feed]
|
||||||
|
#context br()],
|
||||||
|
|
||||||
[#context if is-html() {
|
[#context if is-html() {
|
||||||
html.elem("style", "
|
html.elem("style", "
|
||||||
|
Reference in New Issue
Block a user