X(head) \
X(meta) \
X(title) \
+ X(link) \
X(style) \
X(body) \
X(header) \
typedef struct
{
- str Title;
html_tag* Tags;
} html_meta;
}
static inline void
-html_addAttribute(html_element* Element, str Key, str Child, arena* Arena)
+html_prependAttribute(html_element* Element, str Key, str Child, arena* Arena)
{
html_attribute* Attribute = ARENA_PUSH_STRUCT(Arena, html_attribute);
{
Attribute->Child = Child;
}
+ Attribute->Next = Element->Attribute;
Element->Attribute = Attribute;
}
html_appendElement(Target->Child, Content);
}
+static inline html_element*
+getTitle(html* Html)
+{
+ html_element* Title = Html->Title;
+ html_element* ChildSentinel = Title->Child;
+ html_element* Content = ChildSentinel->Next;
+
+ return Content;
+}
+
+static void
+html_setTitle(html* Html, str TitleStr)
+{
+ html_element* Title = getTitle(Html);
+
+ ASSERT(Title->ElementName = HTML_ELEMENT_NAME_content);
+ Title->Content = TitleStr;
+}
+
+static str
+html_getTitleStr(html* Html)
+{
+ html_element* Title = getTitle(Html);
+
+ str TitleStr = Title->Content;
+ return TitleStr;
+}
+
static inline void
html_appendArticleSection(html* Html, html_element* Section)
{
}
str Link = str_endUnbounded(uPath);
- html_addAttribute(TagLink, STR_LITERAL("href"), Link, Arena);
+ html_prependAttribute(TagLink, STR_LITERAL("href"), Link, Arena);
html_appendContent(TagLink, STR_LITERAL("#"), Arena);
html_appendContent(TagLink, Tag->Content, Arena);
html_appendChild(TagElement, TagLink);
html_element* HtmlElement = html_createElement(HTML_ELEMENT_NAME_html, Arena);
{
- html_addAttribute(HtmlElement, STR_LITERAL("lang"), STR_LITERAL("de-DE"), Arena);
+ html_prependAttribute(HtmlElement, STR_LITERAL("lang"), STR_LITERAL("de-DE"), Arena);
html_appendChild(Root, HtmlElement);
html_element* Head = html_createElement(HTML_ELEMENT_NAME_head, Arena);
html_element* MetaCharset = html_createElement(HTML_ELEMENT_NAME_meta, Arena);
{
- html_addAttribute(MetaCharset, STR_LITERAL("charset"), STR_LITERAL("utf-8"), Arena);
+ html_prependAttribute(MetaCharset, STR_LITERAL("charset"), STR_LITERAL("utf-8"), Arena);
html_appendChild(Head, MetaCharset);
}
html_element* MetaViewport = html_createElement(HTML_ELEMENT_NAME_meta, Arena);
{
- html_addAttribute(MetaViewport, STR_LITERAL("name"), STR_LITERAL("viewport"), Arena);
- html_addAttribute(MetaViewport, STR_LITERAL("content"), STR_LITERAL("width=device-width, initial-scale=1"), Arena);
+ html_prependAttribute(MetaViewport, STR_LITERAL("name"), STR_LITERAL("viewport"), Arena);
+ html_prependAttribute(MetaViewport, STR_LITERAL("content"), STR_LITERAL("width=device-width, initial-scale=1"), Arena);
html_appendChild(Head, MetaViewport);
}
- /* todo: add later? */
html_element* Title = html_createElement(HTML_ELEMENT_NAME_title, Arena);
{
- static str Untitled = STR_LITERAL("[untitled]");
Html->Title = Title;
- html_appendContent(Title, Untitled, Arena);
+ html_appendContent(Title, STR_LITERAL("[untitled]"), Arena);
+ html_appendContent(Title, STR_LITERAL(" | lhaegele.de"), Arena);
+
html_appendChild(Head, Title);
}
+ html_element* LinkIcon = html_createElement(HTML_ELEMENT_NAME_link, Arena);
+ {
+ html_prependAttribute(LinkIcon, STR_LITERAL("rel"), STR_LITERAL("icon"), Arena);
+ html_prependAttribute(LinkIcon, STR_LITERAL("href"), STR_LITERAL("/favicon.svg"), Arena);
+ html_appendChild(Head, LinkIcon);
+ }
+
+ html_element* LinkCss = html_createElement(HTML_ELEMENT_NAME_link, Arena);
+ {
+ html_prependAttribute(LinkCss, STR_LITERAL("rel"), STR_LITERAL("stylesheet"), Arena);
+ html_prependAttribute(LinkCss, STR_LITERAL("href"), STR_LITERAL("/style.css"), Arena);
+ html_appendChild(Head, LinkCss);
+ }
+
/* todo: add style? */
}
html_element* Heading = html_createElement(HTML_ELEMENT_NAME_h1, Arena);
{
- html_appendContent(Heading, STR_LITERAL("Meine Rezeptsammlung"), Arena);
html_appendChild(Header, Heading);
+
+ html_element* HeadingLink = html_createElement(HTML_ELEMENT_NAME_a, Arena);
+ {
+ html_prependAttribute(HeadingLink, STR_LITERAL("href"), STR_LITERAL("/"), Arena);
+ html_appendContent(HeadingLink, STR_LITERAL("Meine Rezeptsammlung"), Arena);
+ html_appendChild(Heading, HeadingLink);
+ }
+
+ html_setTitle(Html, STR_LITERAL("Meine Rezeptsammlung"));
}
}
if (Heading->ElementName == HTML_ELEMENT_NAME_h1)
{
- Html->Meta->Title = HeadingContent;
+ html_setTitle(Html, HeadingContent);
}
}
}
str_append(Target, STR_LITERAL(">"));
- if (Child->ElementName != HTML_ELEMENT_NAME_meta)
+ if ((Child->ElementName == HTML_ELEMENT_NAME_meta) ||
+ (Child->ElementName == HTML_ELEMENT_NAME_link))
+ {
+ /* void elements don't have a closing tag */
+ }
+ else
{
serializeElement(Target, Child);
}
}
-static void
-html_setTitle(html* Html, str TitleStr)
-{
- html_element* Title = Html->Title;
- html_element* ChildSentinel = Title->Child;
- html_element* Content = ChildSentinel->Next;
-
- ASSERT(Content->ElementName = HTML_ELEMENT_NAME_content);
- Content->Content = TitleStr;
-}
-
-static str
-html_getTitle(html* Html)
-{
- html_meta* Meta = Html->Meta;
-
- str Title = Meta->Title;
- return Title;
-}
-
static str
html_toString(html* Html, arena* Arena)
{
* static site generator for my recipe collection
*
* @todo
- * - (german) unicode support
- *
* - markdown parser
* - multithreaded (one thread per recipe)
* - output status from main thread?
* - date created
* - date changed (optional)
*
+ * - use `section` on landing page for recipe and tag sections
+ *
* - images (optional)
*
* - output to html directory
}
str Link = str_endUnbounded(uPath);
- html_addAttribute(RecipeLink, STR_LITERAL("href"), Link, Arena);
+ html_prependAttribute(RecipeLink, STR_LITERAL("href"), Link, Arena);
html_appendContent(RecipeLink, Recipe->Name, Arena);
html_appendChild(RecipeElement, RecipeLink);
}
}
Recipe->Html = html_parseMarkdown(FileStr, &Context.MainArena);
- Recipe->Name = html_getTitle(Recipe->Html);
+ Recipe->Name = html_getTitleStr(Recipe->Html);
}
/* allocate tag sentinel */
/* todo: compress site creation? */
html* MainPage = html_createDefault(&Context.MainArena);
{
- /* todo: remove title from overview? */
- html_setTitle(MainPage, STR_LITERAL("Überblick"));
+ /* recipes */
+ html_element* Recipes = html_createElement(HTML_ELEMENT_NAME_h2, &Context.MainArena);
+ {
+ html_appendArticleSection(MainPage, Recipes);
+ html_appendContent(Recipes, STR_LITERAL("Rezepte"), &Context.MainArena);
+
+ html_element* RecipeList = html_createElement(HTML_ELEMENT_NAME_ul, &Context.MainArena);
+ {
+ html_appendArticleSection(MainPage, RecipeList);
+ html_prependAttribute(RecipeList, STR_LITERAL("class"), STR_LITERAL("recipes"), &Context.MainArena);
+
+ for (recipe* Recipe = Context.Recipes->Next;
+ Recipe != Context.Recipes;
+ Recipe = Recipe->Next)
+ {
+ html_element* RecipeElement = html_createElement(HTML_ELEMENT_NAME_li, &Context.MainArena);
+ {
+ html_appendChild(RecipeList, RecipeElement);
+ appendRecipeLink(RecipeElement, Recipe, &Context.MainArena);
+ }
+ }
+ }
+ }
/* tags */
html_element* Tags = html_createElement(HTML_ELEMENT_NAME_h2, &Context.MainArena);
html_element* TagList = html_createElement(HTML_ELEMENT_NAME_ul, &Context.MainArena);
{
html_appendArticleSection(MainPage, TagList);
+ html_prependAttribute(TagList, STR_LITERAL("class"), STR_LITERAL("tags"), &Context.MainArena);
tag* Sentinel = Context.Tags;
for (tag* Tag = Sentinel->Next; Tag != Sentinel; Tag = Tag->Next)
}
str Link = str_endUnbounded(uPath);
- html_addAttribute(TagLink, STR_LITERAL("href"), Link, &Context.MainArena);
+ html_prependAttribute(TagLink, STR_LITERAL("href"), Link, &Context.MainArena);
html_appendContent(TagLink, STR_LITERAL("#"), &Context.MainArena);
html_appendContent(TagLink, Tag->Name, &Context.MainArena);
html_appendChild(TagElement, TagLink);
}
}
- /* recipes */
- html_element* Recipes = html_createElement(HTML_ELEMENT_NAME_h2, &Context.MainArena);
- {
- html_appendArticleSection(MainPage, Recipes);
- html_appendContent(Recipes, STR_LITERAL("Rezepte"), &Context.MainArena);
-
- html_element* RecipeList = html_createElement(HTML_ELEMENT_NAME_ul, &Context.MainArena);
- {
- html_appendArticleSection(MainPage, RecipeList);
-
- for (recipe* Recipe = Context.Recipes->Next;
- Recipe != Context.Recipes;
- Recipe = Recipe->Next)
- {
- html_element* RecipeElement = html_createElement(HTML_ELEMENT_NAME_li, &Context.MainArena);
- {
- html_appendChild(RecipeList, RecipeElement);
- appendRecipeLink(RecipeElement, Recipe, &Context.MainArena);
- }
- }
- }
- }
-
/* serialize html tree */
{
arena TempArena = Context.MainArena;
}
fprintf(stdout, "Done.\n");
+ /* todo: output stats (memory consumption, runtime, ...) */
return 0;
}