}
if (self.opts.template) |t| {
+ // TODO: Avoid so many allocations.
const replaced = try strings.replace(alloc, t, "{body}", self.buffer.items);
self.buffer.deinit(alloc);
- self.buffer = std.ArrayList(u8).fromOwnedSlice(replaced);
+ defer alloc.free(replaced);
+
+ const withTitle = try strings.replace(alloc, replaced, "{title}", doc.title);
+ defer alloc.free(withTitle);
+
+ const withDate = try strings.replace(alloc, withTitle, "{date}", doc.date);
+
+ self.buffer = std.ArrayList(u8).fromOwnedSlice(withDate);
}
return self.buffer.items;
};
pub const MarkdownDoc = struct {
+ title: []const u8,
date: []const u8,
- summary: []const u8,
content: std.ArrayList(MarkdownNode),
pub fn deinit(self: *@This(), alloc: std.mem.Allocator) void {
var start: usize = 0;
var current: usize = 0;
+ var title: []const u8 = undefined;
var date: []const u8 = undefined;
- var summary: []const u8 = undefined;
var nodes: std.ArrayList(MarkdownNode) = .empty;
while (current < doc.len) {
start = current;
const c = doc[current];
switch (c) {
- '-' => try parse_frontmatter(¤t, doc, &date, &summary),
+ '-' => try parse_frontmatter(¤t, doc, &title, &date),
else => try parse_body(alloc, doc, ¤t, &nodes),
}
}
return .{
+ .title = title,
.date = date,
- .summary = summary,
.content = nodes,
};
}
fn parse_frontmatter(
current: *usize,
doc: []const u8,
- date: *[]const u8,
- summary: *[]const u8,
+ title: *[]const u8,
+ date: *[]const u8,
) MarkdownParserError!void {
assert(doc[current.*] == '-');
advanceWhile(doc, current, '-');
try expectToken(doc, '\n', current);
+ try parse_frontmatter_value(current, doc, title);
try parse_frontmatter_value(current, doc, date);
- try parse_frontmatter_value(current, doc, summary);
try expectToken(doc, '-', current);
advanceWhile(doc, current, '-');
test "can parse date in frontmatter" {
const doc =
\\----
+ \\title: This is the shit!
\\date: 12/04/2026
- \\summary: This is the shit!
\\----
;
try std.testing.expectEqualStrings("12/04/2026", result.date);
}
-test "can parse summary in frontmatter" {
+test "can parse title in frontmatter" {
const doc =
\\----
+ \\title: This is the shit!
\\date: 12/04/2026
- \\summary: This is the shit!
\\----
;
const result = comptime MarkdownDoc.parse(doc, alloc) catch unreachable;
- try std.testing.expectEqualStrings("This is the shit!", result.summary);
+ try std.testing.expectEqualStrings("This is the shit!", result.title);
}
test "can parse h1 in body without newline at end" {
const doc =
\\----
+ \\title: This is the shit!
\\date: 12/04/2026
- \\summary: This is the shit!
\\----
\\
\\# The Post's Title
test "can parse h2 in body without newline at end" {
const doc =
\\----
+ \\title: This is the shit!
\\date: 12/04/2026
- \\summary: This is the shit!
\\----
\\
\\## The Post's Subtitle
test "can parse single multi-line paragraph at the beginning of document" {
const doc =
\\----
+ \\title: This is the shit!
\\date: 12/04/2026
- \\summary: This is the shit!
\\----
\\
\\Hello world,
test "can parse two single-line paragraphs at the beginning of document" {
const doc =
\\----
+ \\title: This is the shit!
\\date: 12/04/2026
- \\summary: This is the shit!
\\----
\\
\\Hello world,
test "can parse single-line paragraph and multi-line parapgraphs at once at the beginning of document" {
const doc =
\\----
+ \\title: This is the shit!
\\date: 12/04/2026
- \\summary: This is the shit!
\\----
\\
\\Hello world,
test "can parse a header and paragraph" {
const doc =
\\----
+ \\title: This is the shit!
\\date: 12/04/2026
- \\summary: This is the shit!
\\----
\\# Post title
\\
test "can parse two consecutive paragraphs" {
const doc =
\\----
+ \\title: This is the shit!
\\date: 12/04/2026
- \\summary: This is the shit!
\\----
\\Hello world,
\\
+++ /dev/null
-<!DOCTYPE html>
-<html>
-
- <head>
- <meta charset="utf-8">
- <title>Alexander Goussas | Programming</title>
- <meta name="author" content="Alexander Goussas">
- <meta name="description" content="Blog about programming">
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <link href="https://cdn.jsdelivr.net/npm/
[email protected]/dist/cdn/beer.min.css" rel="stylesheet">
- <link href="../styles.css" rel="stylesheet">
- </head>
-
- <body>
- <h1>How I Read 500 Page Books in a Weekend</h1>
- <p>
- There are two types of books that I can read in a weekend, no matter how large they are:
- programming [language] books and fantasy books that I'm hooked. The latter is self-explanatory,
- I think, but the former might require some explanation.
- </p>
- <p>
- The thing is, most programming languages hide the same semantics behind different syntax.
- For example, right now I am reading a Zig book. I am already fairly experienced with C and C++,
- so I don't need to waste time reading how pointers and memory allocation works. I just need to know
- how to do these things with Zig's syntax.
- </p>
- <p>
- Thus, I can skim/skip most of the content. Now, I do skim most of the times rather than skipping, because
- there <em>might</em> something that I don't know, some way in which the semantics of the concept changes for
- this programming language. So, I <em>do</em> read everything, I just do it super fast.
- </p>
- <p>
- Another point is that most of the times, if a programming book is 500 pages long, chances are most of its
- contents is not 100% relevant. The book I'm reading right now for example is full with the author's "humor."
- Humor in programming books is welcomed, at least by me, in sparse quantities. If I wanted to laugh I'd listen to
- audios of americans trying to speak French instead.
- </p>
- <p>
- So yeah, the key to reading programming books fast is reading so many of them that you can skim/skip a lot.
- And in terms of fiction or whatever you like reading, the key is liking the book and not having social life.
- </p>
- </body>
-
-</html>
+++ /dev/null
----
-title: Language Checkpoint April
-summary: shit
----
-
-This is my April 2026 language checkpoint.
-
-## Spanish
-
-I can still speak it. I think. I think I did not speak any Spanish today at all. Yikes.
-
-## English
-
-Good.
-
-## French
-
-I can understand 99% of what I hear without any effort at all. The same goes for reading, depending on what I'm
-reading of course. Last test I had was reading "La BĂȘte Humaine" by Zola and I knew 99% of the words. Speaking
-is still my greatest weakness, but last Sunday I spoke one hour with my new Russian friend Valery and I'm pretty
-proud of how I expressed myself.
-
-## German
-
-I can now understand 99% of what is said in the Easy German Podcast. I think the use easy language there, for the
-surprise of no one I guess. I say this because most YouTube content targeted for a German audience still sounds like
-gibberish to me haha. I'm starting to get a grasp of the form of German, grammar is starting to become more natural.
-I can write about my day without much trouble.
-
-## Portuguese
-
-My Portuguese is my greatest shame, honestly. I cannot get myself to practice it seriously outside of work. I'll
-get there eventually, I swear.
<meta name="author" content="Alexander Goussas">
<meta name="description" content="Blog about programming">
<meta name="viewport" content="width=device-width, initial-scale=1">
- <link href="styles.css" rel="stylesheet">
+ <link href="./styles.css" rel="stylesheet">
</head>
<body>
- <h1>Alexander Goussas</h1>
- <h2>Blog about programming and friends</h2>
+ <header>
+ <nav>
+ <ul>
+ <li class="nav-item" style="background-color: yellow; color: black;">
+ <a href="/">home</a>
+ </li>
+ <li class="nav-item">
+ <a href="">youtube</a>
+ </li>
+ <li class="nav-item" style="background-color: purple;">
+ <a href="">github</a>
+ </li>
+ <li class="nav-item" style="background-color: blue;">
+ <a href="">linkedin</a>
+ </li>
+ </ul>
+ </nav>
+ </header>
+
+ <h1 style="color: yellow;">Alexander Goussas</h1>
+ <h2 style="color: green; text-align: center;">Blog about programming and friends</h2>
<section id="posts">
+ <h2 style="color: yellow;">Posts</h2>
<ul>
+ <li><a href="./06-05-2026-language-checkpoint-april.md.html">Language Checkpoint - April 2026</a></li>
</ul>
</section>
<script src="js/script.js"></script>
margin: auto;
margin-top: 1rem;
margin-bottom: 1rem;
+ background-color: black;
+ color: white;
}
-h1, h2 {
+h1 {
text-align: center;
}
+h1 {
+ color: yellow;
+}
+
+h2 {
+ color: green;
+}
+
a {
text-decoration: underline;
}
+
+nav {
+ ul {
+ list-style: none;
+ display: flex;
+ justify-content: space-between;
+ }
+}
+
+.nav-item {
+ background-color: #ff0000;
+ padding: 1rem;
+ width: fit-content;
+ border: 2px solid black;
+ box-shadow:
+ inset rgba(0 0 0 / 20%) 5px 0px,
+ inset rgba(0 0 0 / 20%) -5px 0px,
+ inset rgba(0 0 0 / 20%) 0px -5px,
+ inset rgba(255 255 255 / 40%) 0px 5px;
+}
<script src=""></script>
<body>
<div class="">
+ <h1>{title}</h1>
+ <div>
+ <span>Last updated: {date}</span>
+ </div>
{body}
</div>
</body>