start implementation of frontmatter parser
authorLukas Hägele <lukas.haegele93@web.de>
Sun, 13 Oct 2024 10:06:43 +0000 (12:06 +0200)
committerLukas Hägele <lukas.haegele93@web.de>
Sun, 13 Oct 2024 10:06:43 +0000 (12:06 +0200)
Makefile [new file with mode: 0644]
content/bohnenmus.md
src/html.c
src/main.c

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..c5b1cbc
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,10 @@
+all: build
+
+build:
+       mkdir -p bin
+       cc -Wall -Wextra -o bin/converter src/main.c
+
+convert:
+       mkdir -p html
+       rm html/*
+       bin/converter content html
index 49f44db2dd286a005632a7cc99993812434f91b2..af6a5481d74afff470ed120b9bf1cb62b17b3705 100644 (file)
@@ -1,3 +1,11 @@
+---
+#!ini
+
+[tags]
+mexikanisch
+vegetarisch
+---
+
 # Bohnenmus
 
 ## Zutaten
 
 ## Zubereitung
 
-- Zwiebeln sehr fein hacken und Knoblauchzehen pressen. 
-- Die Chilischoten ebenfalls klein hacken. 
-- Etwas Erdnussöl in einem Topf erhitzen und die Zwiebeln sowie die Chilischoten darin glasig anbraten. 
-- Knoblauch und Tomatenmark hinzufügen und kurz anschwitzen. 
-- Dann die Kidneybohnen abgießen und zu den Zwiebeln geben. 
+- Zwiebeln sehr fein hacken und Knoblauchzehen pressen.
+- Die Chilischoten ebenfalls klein hacken.
+- Etwas Erdnussöl in einem Topf erhitzen und die Zwiebeln sowie die Chilischoten darin glasig anbraten.
+- Knoblauch und Tomatenmark hinzufügen und kurz anschwitzen.
+- Dann die Kidneybohnen abgießen und zu den Zwiebeln geben.
 - Mit Brühe ablöschen und die Hälfte der Flüssigkeit einreduzieren lassen.
 
-- 1/4 Limette auspressen und den Saft zu den Bohnen geben. 
-- Ich dicke die Mischung dann mit Speisestärke an. 
-- Wer dies ablehnt, lässt die Flüssigkeit einfach bis zur gewünschten Sämigkeit weiter einreduzieren. 
-- Wenn diese erreicht ist, die Bohnen vom Herd nehmen und mit einem Kartoffelstampfer gut zerdrücken. 
+- 1/4 Limette auspressen und den Saft zu den Bohnen geben.
+- Ich dicke die Mischung dann mit Speisestärke an.
+- Wer dies ablehnt, lässt die Flüssigkeit einfach bis zur gewünschten Sämigkeit weiter einreduzieren.
+- Wenn diese erreicht ist, die Bohnen vom Herd nehmen und mit einem Kartoffelstampfer gut zerdrücken.
 - Mit Salz und Pfeffer abschmecken.
 
 ## Tags
index 5fbe59bc9173b33491dee0732368307326cbe1ad..8e42ca4cc0a8d7af99d84eea43cc806b05e7b7dd 100644 (file)
@@ -62,8 +62,12 @@ typedef struct html_element
     };
 } html_element;
 
-/* todo: remove? */
-typedef html_element html;
+typedef struct
+{
+    html_element* Root;
+    html_element* Title;
+    html_element* Article;
+} html;
 
 static void
 appendElement(html_element* Sentinel, html_element* Element)
@@ -75,7 +79,7 @@ appendElement(html_element* Sentinel, html_element* Element)
 }
 
 static html_element*
-createElement(html_element_name Name, arena* Arena)
+html_createElement(html_element_name Name, arena* Arena)
 {
     html_element* Element = ARENA_PUSH_STRUCT(Arena, html_element);
 
@@ -107,13 +111,13 @@ addAttribute(html_element* Element, str Key, str Child, arena* Arena)
 }
 
 static inline void
-appendValue(html_element* Target, html_element* Child)
+html_appendValue(html_element* Target, html_element* Child)
 {
     ASSERT(!"not yet implemented");
 }
 
 static inline void
-addContent(html_element* Target, str ContentStr, arena* Arena)
+html_appendContent(html_element* Target, str ContentStr, arena* Arena)
 {
     html_element* Content = ARENA_PUSH_STRUCT(Arena, html_element);
     {
@@ -127,75 +131,82 @@ addContent(html_element* Target, str ContentStr, arena* Arena)
 static html*
 html_createDefault(arena* Arena)
 {
-    html* Root = createElement(HTML_ELEMENT_NAME_root, Arena);
+    html* Html = ARENA_PUSH_STRUCT(Arena, html);
+
+    html_element* Root = html_createElement(HTML_ELEMENT_NAME_root, Arena);
     {
-        html_element* Doctype = createElement(HTML_ELEMENT_NAME_content, Arena);
+        Html->Root = Root;
+
+        html_element* Doctype = html_createElement(HTML_ELEMENT_NAME_content, Arena);
         {
-            addContent(Doctype, STR_LITERAL("<!DOCTYPE html>"), Arena);
-            appendValue(Root, Doctype);
+            html_appendContent(Doctype, STR_LITERAL("<!DOCTYPE html>"), Arena);
+            html_appendValue(Root, Doctype);
         }
 
-        html_element* Html = createElement(HTML_ELEMENT_NAME_html, Arena);
+        html_element* HtmlElement = html_createElement(HTML_ELEMENT_NAME_html, Arena);
         {
             addAttribute(Root, STR_LITERAL("lang"), STR_LITERAL("'de-DE'"), Arena);
-            appendValue(Root, Html);
+            html_appendValue(Root, HtmlElement);
         }
 
-        html_element* Head = createElement(HTML_ELEMENT_NAME_head, Arena);
+        html_element* Head = html_createElement(HTML_ELEMENT_NAME_head, Arena);
         {
-            appendValue(Root, Head);
+            html_appendValue(Root, Head);
 
-            html_element* MetaCharset = createElement(HTML_ELEMENT_NAME_meta, Arena);
+            html_element* MetaCharset = html_createElement(HTML_ELEMENT_NAME_meta, Arena);
             {
                 addAttribute(MetaCharset, STR_LITERAL("charset"), STR_LITERAL("'utf-8'"), Arena);
-                appendValue(Head, MetaCharset);
+                html_appendValue(Head, MetaCharset);
             }
 
-            html_element* MetaViewport = createElement(HTML_ELEMENT_NAME_meta, Arena);
+            html_element* MetaViewport = html_createElement(HTML_ELEMENT_NAME_meta, Arena);
             {
                 addAttribute(MetaViewport, STR_LITERAL("name"), STR_LITERAL("'viewport'"), Arena);
                 addAttribute(MetaViewport, STR_LITERAL("content"), STR_LITERAL("'width=device-width, initial-scale=1'"), Arena);
-                appendValue(Head, MetaViewport);
+                html_appendValue(Head, MetaViewport);
             }
 
             /* todo: add later? */
-            html_element* Title = createElement(HTML_ELEMENT_NAME_title, Arena);
+            html_element* Title = html_createElement(HTML_ELEMENT_NAME_title, Arena);
             {
-                addContent(Title, STR_LITERAL("<untitled>"), Arena);
-                appendValue(Head, Title);
+                Html->Title = Title;
+
+                html_appendContent(Title, STR_LITERAL("<untitled>"), Arena);
+                html_appendValue(Head, Title);
             }
 
             /* todo: add style? */
         }
 
-        html_element* Body = createElement(HTML_ELEMENT_NAME_body, Arena);
+        html_element* Body = html_createElement(HTML_ELEMENT_NAME_body, Arena);
         {
-            appendValue(Root, Body);
+            html_appendValue(Root, Body);
 
-            html_element* Header = createElement(HTML_ELEMENT_NAME_header, Arena);
+            html_element* Header = html_createElement(HTML_ELEMENT_NAME_header, Arena);
             {
-                appendValue(Body, Header);
+                html_appendValue(Body, Header);
 
-                html_element* Heading = createElement(HTML_ELEMENT_NAME_h1, Arena);
+                html_element* Heading = html_createElement(HTML_ELEMENT_NAME_h1, Arena);
                 {
-                    addContent(Heading, STR_LITERAL("Meine Rezeptsammlung"), Arena);
-                    appendValue(Header, Heading);
+                    html_appendContent(Heading, STR_LITERAL("Meine Rezeptsammlung"), Arena);
+                    html_appendValue(Header, Heading);
                 }
             }
 
-            html_element* Main = createElement(HTML_ELEMENT_NAME_main, Arena);
+            html_element* Main = html_createElement(HTML_ELEMENT_NAME_main, Arena);
             {
-                appendValue(Body, Main);
+                html_appendValue(Body, Main);
 
-                html_element* Article = createElement(HTML_ELEMENT_NAME_article, Arena);
+                html_element* Article = html_createElement(HTML_ELEMENT_NAME_article, Arena);
                 {
-                    appendValue(Main, Article);
+                    Html->Article = Article;
+                    html_appendValue(Main, Article);
                 }
             }
         }
     }
 
-    return Root;
+    return Html;
 }
 
 static inline html_element*
@@ -203,7 +214,7 @@ createContent(str ContentStr, arena* Arena)
 {
     ContentStr = str_stripHead(ContentStr);
 
-    /* todo: use addContent() */
+    /* todo: use html_appendContent() */
     html_element* Content = ARENA_PUSH_STRUCT(Arena, html_element);
     {
         Content->ElementName = HTML_ELEMENT_NAME_content;
@@ -298,7 +309,7 @@ parseListItem(str Line, html_element* Html, arena* Arena)
 static void
 parseParagraph(str Line, html_element* Html, arena* Arena)
 {
-    /* todo: use addContent? */
+    /* todo: use html_appendContent? */
     html_element* ParagraphItem = ARENA_PUSH_STRUCT(Arena, html_element);
     {
         ParagraphItem->ElementName = HTML_ELEMENT_NAME_content;
@@ -351,16 +362,18 @@ parseLine(str Line, html_element* Html, arena* Arena)
     }
 }
 
-static html
+static html*
 html_parseMarkdown(str Source, arena* Arena)
 {
-    html_element Html = html_create(Arena);
+    html* Html = html_createDefault(Arena);
+
+    /* todo: parse front matter */
 
     for (str Line = str_getLine(Source);
          str_isValid(Line);
          Line = str_getLine(Source))
     {
-        parseLine(Line, &Html, Arena);
+        parseLine(Line, Html->Article, Arena);
         str_advance(Source, Line.Length);
     }
 
@@ -438,7 +451,7 @@ serializeElement(str* Sentinel, html_element* Element)
 }
 
 static str
-html_toString(arena* Arena, html* Html)
+html_toString(html* Html, arena* Arena)
 {
     str_unbounded Unbounded = str_startUnbounded(Arena);
     {
index b632ffb48014ddb06fd2c53408143412af1040c0..c48f312631add0ad8cd970fd6ba1e2311e7d942e 100644 (file)
@@ -37,7 +37,7 @@
 #include <unistd.h>
 
 static u32
-generateHtmlFile(str Filename, html* Html)
+generateHtmlFile(str Filename, html* Html, arena* Arena)
 {
     u32 Error = 0;
 
@@ -55,9 +55,9 @@ generateHtmlFile(str Filename, html* Html)
     }
     else
     {
-        str HtmlContent = html_toString(Html);
+        str HtmlContent = html_toString(Html, Arena);
 
-        if (write(FileDescriptor, HtmlContent.Buffer, HtmlContent.Length) == -1)
+        if (write(FileDescriptor, HtmlContent.Base, HtmlContent.Length) == -1)
         {
             perror("write");
             Error = 1;
@@ -88,7 +88,7 @@ main(int ArgumentCount, char** Arguments)
         char* OutputDir;
 
         recipe* Recipes;
-        tag*    Tag;
+        tag*    Tags;
 
         u64 RecipeCount;
         arena MainArena;
@@ -218,28 +218,45 @@ main(int ArgumentCount, char** Arguments)
     {
         /* main page */
         {
-            /* todo: assemble html */
-            html MainPage = html_create();
+            /* todo: compress site creation? */
+            html* MainPage = html_createDefault(&Context.MainArena);
             {
-                html_append(MainPage, HTML_H2, "Tags");
-                html_start(MainPage, HTML_UL);
-                for (tag* Tag = Tags; isValid(Tag); Tag = Tag->Next)
+                /* todo: remove title from overview? */
+                html_setTitle(MainPage, STR_LITERAL("Überblick"));
+
+                /* tags */
                 {
-                    html_append(MainPage, HTML_LI, Tag->Name);
+                    html_element* Tags = html_createElement(HTML_ELEMENT_NAME_h2, &Context.MainArena);
+                    html_appendArticleSection(MainPage, Tags);
+
+                    html_element* TagList = html_createElement(HTML_ELEMENT_NAME_ul, &Context.MainArena);
+                    html_appendValue(Tags, TagList);
+
+                    for (tag* Tag = Context.Tags; isValid_tag(Tag); Tag = Tag->Next)
+                    {
+                        html_element* TagElement = html_createElement(HTML_ELEMENT_NAME_li, &Context.MainArena);
+                        html_appendContent(TagElement, Tag->Name, &Context.MainArena);
+                    }
                 }
-                html_end(MainPage, HTML_UL);
 
-                html_append(MainPage, HTML_H2, "Rezepte");
-                html_start(MainPage, HTML_UL);
-                for (recipe* Recipe = Recipes; isValid(Recipe); Recipe = Recipe->Next)
+                /* recipes */
                 {
-                    html_append(MainPage, HTML_LI, Recipe->Name);
+                    html_element* Recipes = html_createElement(HTML_ELEMENT_NAME_h2, &Context.MainArena);
+                    html_appendArticleSection(MainPage, Recipes);
+
+                    html_element* RecipeList = html_createElement(HTML_ELEMENT_NAME_ul, &Context.MainArena);
+                    html_appendValue(Recipes, RecipeList);
+
+                    for (recipe* Recipe = Context.Recipes; isValid_recipe(Recipe); Recipe = Recipe->Next)
+                    {
+                        html_element* RecipeElement = html_createElement(HTML_ELEMENT_NAME_li, &Context.MainArena);
+                        html_appendContent(RecipeElement, Recipe->Name, &Context.MainArena);
+                    }
                 }
-                html_end(MainPage, HTML_UL);
             }
 
             str Filename = STR_LITERAL("index.html");
-            if (generateHtmlFile(Filename, MainPage) != 0)
+            if (generateHtmlFile(Filename, MainPage, &Context.MainArena) != 0)
             {
                 fprintf(stderr, "Error while generating main page. Stopping.\n");
                 return -1;
@@ -247,7 +264,7 @@ main(int ArgumentCount, char** Arguments)
         }
 
         /* detail pages */
-        for (recipe* Recipe = Recipes; isValid(Recipe); Recipe = Recipe->Next)
+        for (recipe* Recipe = Recipes; isValid_recipe(Recipe); Recipe = Recipe->Next)
         {
             /* recipes/... */
             str Filename = ...;
@@ -260,7 +277,7 @@ main(int ArgumentCount, char** Arguments)
         }
 
         /* tag page? */
-        for (tag* Tag = Tags; isValid(Tag); Tag = Tag->Next)
+        for (tag* Tag = Tags; isValid_tag(Tag); Tag = Tag->Next)
         {
             /* tags/... */
             str Filename = ...;