Skip to content

Instantly share code, notes, and snippets.

@thebirk
Created August 2, 2018 14:41
Show Gist options
  • Select an option

  • Save thebirk/ac111c8c35b3f533e54a6483d7baacd0 to your computer and use it in GitHub Desktop.

Select an option

Save thebirk/ac111c8c35b3f533e54a6483d7baacd0 to your computer and use it in GitHub Desktop.
Odin issue #208
/*
Copyright (C) - Aleksander B. Birkeland 2018
Very basic HTML generator
TODO(Some way to generate xml instead of html)
Closes all tags including empty ones
*/
package html
Document :: struct {
doctype: string, // <!DOCTYPE <insert variable here> >
head: ^Element,
body: ^Element,
}
Element :: struct {
name: string,
body: string,
attributes: map[string]string,
children: [dynamic]^Element,
}
make :: proc(_doctype: string = "html") -> ^Document {
using d := new(Document);
doctype = _doctype;
head = new(Element);
head.name = "head";
body = new(Element);
body.name = "body";
return d;
}
make_element :: proc(name: string, body := "") -> ^Element {
el := new(Element);
el.name = name;
el.body = body;
return el;
}
make_paragraph :: proc(text: string) -> ^Element {
el := new(Element);
el.name = "p";
el.body = text;
return el;
}
make_list_from_elements :: proc(data: []^Element) -> ^Element {
el := new(Element);
el.name = "ul";
for child in data {
item := make_element("li");
add(item, child);
}
return el;
}
make_list_from_array :: proc(data: []string) -> ^Element {
el := new(Element);
el.name = "ul";
for str in data {
add(el, make_element(name = "li", body = str));
}
return el;
}
make_list :: proc[
make_list_from_array,
make_list_from_elements,
];
make_link :: proc(text: string, link: string) -> ^Element {
el := new(Element);
el.name = "a";
el.attributes["href"] = link;
el.body = text;
return el;
}
make_image :: proc(src: string) -> ^Element {
el := new(Element);
el.name = "img";
el.attributes["src"] = src;
return el;
}
add_to_document :: proc(using doc: ^Document, child: ^Element) {
append(&body.children, child);
}
add_to_element :: proc(using parent: ^Element, child: ^Element) {
append(&parent.children, child);
}
add :: proc[
add_to_document,
add_to_element,
];
gen_element :: proc(out: ^[dynamic]u8, using el: ^Element) {
append_string(out, "<");
append_string(out, name);
for key,value in attributes {
append_string(out, " ");
append_string(out, key);
append_string(out, "=\"");
append_string(out, value);
append_string(out, "\"");
}
append_string(out, ">\n");
append_string(out, body);
for i := 0; i < len(children); i += 1 {
child := children[i];
gen_element(out, child);
}
append_string(out, "\n</");
append_string(out, name);
append_string(out, ">\n");
}
GenOptions :: struct {
out: ^[dynamic]u8,
gen_whitespace: bool,
gen_indentation: bool,
indent: int,
}
gen :: proc(using doc: ^Document, _gen_whitespace := true, _gen_indentation := true) -> [dynamic]u8 {
out_buffer: [dynamic]u8;
using options := GenOptions {
out = &out_buffer,
gen_whitespace = _gen_whitespace,
gen_indentation = _gen_indentation,
};
append_string(out, "<!DOCTYPE ");
append_string(out, doctype);
append_string(out, ">\n");
append_string(out, "<html>\n");
gen_element(out, head);
gen_element(out, body);
append_string(out, "</html>");
return out_buffer;
}
package main
import "core:fmt"
import "core:os"
import "html"
main :: proc() {
doc := html.make();
title := html.make_element(name = "p", body = "Hello, world!");
html.add(doc, title);
image := html.make_image("Lenna.png");
html.add(doc, image);
string_list_array := []string {
"This",
"is",
"a",
"list",
"!",
};
string_list := html.make_list(string_list_array);
html.add(doc, string_list);
element_list_array := []^Element {
make_paragraph("This"),
make_paragraph("is"),
make_paragraph("another"),
make_paragraph("list"),
make_paragraph("!"),
};
element_list := html.make_list(element_list_array);
html.add(doc, element_list);
link := html.make_link("Here", "#");
html.add(doc, link);
data := html.gen(doc);
os.write_entire_file("test.html", data[:]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment