#define ElementNameTable \
X(invalid) \
+ X(root) \
\
X(html) \
X(head) \
X(title) \
X(style) \
X(body) \
+ X(header) \
+ X(main) \
+ X(article) \
\
X(h1) \
X(h2) \
struct html_attribute* Next;
str Key;
- str Value;
+ str Child;
} html_attribute;
typedef struct html_element
{
struct html_element* Prev;
struct html_element* Next;
- struct html_element* Value;
+ struct html_element* Child;
u8 ElementName;
union {
};
} html_element;
+/* todo: remove? */
typedef html_element html;
-typedef struct
-{
- html_element Html;
-} html_markdownContext;
-
static void
appendElement(html_element* Sentinel, html_element* Element)
{
Element->Next = Sentinel;
}
+static html_element*
+createElement(html_element_name Name, arena* Arena)
+{
+ html_element* Element = ARENA_PUSH_STRUCT(Arena, html_element);
+
+ Element->Next = Element;
+ Element->Prev = Element;
+
+ Element->ElementName = Name;
+
+ html_element* Child = ARENA_PUSH_STRUCT(Arena, html_element);
+ {
+ Child->Next = Child;
+ Child->Prev = Child;
+ }
+ Element->Child = Child;
+
+ return Element;
+}
+
+static inline void
+addAttribute(html_element* Element, str Key, str Child, arena* Arena)
+{
+ html_attribute* Attribute = ARENA_PUSH_STRUCT(Arena, html_attribute);
+ {
+ Attribute->Key = Key;
+ Attribute->Child = Child;
+ }
+
+ Element->Attribute = Attribute;
+}
+
+static inline void
+appendValue(html_element* Target, html_element* Child)
+{
+ ASSERT(!"not yet implemented");
+}
+
+static inline void
+addContent(html_element* Target, str ContentStr, arena* Arena)
+{
+ html_element* Content = ARENA_PUSH_STRUCT(Arena, html_element);
+ {
+ Content->ElementName = HTML_ELEMENT_NAME_content;
+ Content->Content = ContentStr;
+ }
+
+ Target->Child = Content;
+}
+
+static html*
+html_createDefault(arena* Arena)
+{
+ html* Root = createElement(HTML_ELEMENT_NAME_root, Arena);
+ {
+ html_element* Doctype = createElement(HTML_ELEMENT_NAME_content, Arena);
+ {
+ addContent(Doctype, STR_LITERAL("<!DOCTYPE html>"), Arena);
+ appendValue(Root, Doctype);
+ }
+
+ html_element* Html = createElement(HTML_ELEMENT_NAME_html, Arena);
+ {
+ addAttribute(Root, STR_LITERAL("lang"), STR_LITERAL("'de-DE'"), Arena);
+ appendValue(Root, Html);
+ }
+
+ html_element* Head = createElement(HTML_ELEMENT_NAME_head, Arena);
+ {
+ appendValue(Root, Head);
+
+ html_element* MetaCharset = createElement(HTML_ELEMENT_NAME_meta, Arena);
+ {
+ addAttribute(MetaCharset, STR_LITERAL("charset"), STR_LITERAL("'utf-8'"), Arena);
+ appendValue(Head, MetaCharset);
+ }
+
+ html_element* MetaViewport = 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);
+ }
+
+ /* todo: add later? */
+ html_element* Title = createElement(HTML_ELEMENT_NAME_title, Arena);
+ {
+ addContent(Title, STR_LITERAL("<untitled>"), Arena);
+ appendValue(Head, Title);
+ }
+
+ /* todo: add style? */
+ }
+
+ html_element* Body = createElement(HTML_ELEMENT_NAME_body, Arena);
+ {
+ appendValue(Root, Body);
+
+ html_element* Header = createElement(HTML_ELEMENT_NAME_header, Arena);
+ {
+ appendValue(Body, Header);
+
+ html_element* Heading = createElement(HTML_ELEMENT_NAME_h1, Arena);
+ {
+ addContent(Heading, STR_LITERAL("Meine Rezeptsammlung"), Arena);
+ appendValue(Header, Heading);
+ }
+ }
+
+ html_element* Main = createElement(HTML_ELEMENT_NAME_main, Arena);
+ {
+ appendValue(Body, Main);
+
+ html_element* Article = createElement(HTML_ELEMENT_NAME_article, Arena);
+ {
+ appendValue(Main, Article);
+ }
+ }
+ }
+ }
+
+ return Root;
+}
+
static inline html_element*
createContent(str ContentStr, arena* Arena)
{
ContentStr = str_stripHead(ContentStr);
+ /* todo: use addContent() */
html_element* Content = ARENA_PUSH_STRUCT(Arena, html_element);
{
Content->ElementName = HTML_ELEMENT_NAME_content;
HeadingContent.Capacity -= Depth;
}
- Heading->Value = createContent(HeadingContent, Arena);
+ Heading->Child = createContent(HeadingContent, Arena);
}
/* todo: check if this is actually the sentinel! */
ListItemContent.Capacity -= 1u;
}
- ListItem->Value = createContent(ListItemContent, Arena);
+ ListItem->Child = createContent(ListItemContent, Arena);
}
/* append to unordered list */
List->ElementName = HTML_ELEMENT_NAME_ul;
}
- html_element* ListItemSentinel = List->Value;
+ html_element* ListItemSentinel = List->Child;
appendElement(ListItemSentinel, ListItem);
}
}
static void
parseParagraph(str Line, html_element* Html, arena* Arena)
{
+ /* todo: use addContent? */
html_element* ParagraphItem = ARENA_PUSH_STRUCT(Arena, html_element);
{
ParagraphItem->ElementName = HTML_ELEMENT_NAME_content;
- ParagraphItem->Value = createContent(Line, Arena);
+ ParagraphItem->Child = createContent(Line, Arena);
}
/* append to paragraph */
Paragraph = PrevElement;
}
- html_element* ParagraphSentinel = Paragraph->Value;
+ html_element* ParagraphSentinel = Paragraph->Child;
appendElement(ParagraphSentinel, ParagraphItem);
}
}
static html
html_parseMarkdown(str Source, arena* Arena)
{
- html_element Html = html_create();
+ html_element Html = html_create(Arena);
for (str Line = str_getLine(Source);
str_isValid(Line);
{
str_append(Sentinel, Attribute->Key);
str_append(Sentinel, STR_LITERAL("=\""));
- str_append(Sentinel, Attribute->Value);
+ str_append(Sentinel, Attribute->Child);
str_append(Sentinel, STR_LITERAL("\""));
}
}
str_append(Sentinel, STR_LITERAL(">"));
- serializeElement(Sentinel, Element->Value);
+ serializeElement(Sentinel, Element->Child);
str_append(Sentinel, STR_LITERAL("<"));
str_append(Sentinel, STR_LITERAL(ElementNames[Element->ElementName]));