From: Lukas Hägele Date: Sun, 13 Oct 2024 10:06:43 +0000 (+0200) Subject: start implementation of frontmatter parser X-Git-Url: https://git.lhaegele.de/?a=commitdiff_plain;h=c44133ac49a9469a5d28a96ab6681325a833002d;p=recipes.git start implementation of frontmatter parser --- diff --git a/Makefile b/Makefile new file mode 100644 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 diff --git a/content/bohnenmus.md b/content/bohnenmus.md index 49f44db..af6a548 100644 --- a/content/bohnenmus.md +++ b/content/bohnenmus.md @@ -1,3 +1,11 @@ +--- +#!ini + +[tags] +mexikanisch +vegetarisch +--- + # Bohnenmus ## Zutaten @@ -16,17 +24,17 @@ ## 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 diff --git a/src/html.c b/src/html.c index 5fbe59b..8e42ca4 100644 --- a/src/html.c +++ b/src/html.c @@ -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(""), Arena); - appendValue(Root, Doctype); + html_appendContent(Doctype, STR_LITERAL(""), 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(""), Arena); - appendValue(Head, Title); + Html->Title = Title; + + html_appendContent(Title, STR_LITERAL(""), 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); { diff --git a/src/main.c b/src/main.c index b632ffb..c48f312 100644 --- a/src/main.c +++ b/src/main.c @@ -37,7 +37,7 @@ #include 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 = ...;