moved templating library to new package
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 2 Nov 2022 14:46:37 +0000 (09:46 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 2 Nov 2022 14:46:37 +0000 (09:46 -0500)
12 files changed:
build.onyx
onyx-pkg.ini
src/app.onyx
src/html-templates/TODO.md [deleted file]
src/html-templates/module.onyx [deleted file]
src/html-templates/src/otmp.onyx [deleted file]
src/html-templates/src/parser.onyx [deleted file]
src/html-templates/src/render.onyx [deleted file]
src/html-templates/src/types.onyx [deleted file]
www/static/css/style.css
www/templates/index.html
www/templates/matrix.html [new file with mode: 0644]

index 68a9c01bc9700213a33524858f2ac6555d436d41..75739ebe5fce38870e10b7f30aa5753c282e5940 100644 (file)
@@ -1,8 +1,9 @@
 #load "./lib/http-server/module"
 #load "./lib/postgres/module"
 #load "./lib/postgres-orm/module"
+#load "./lib/otmp/module"
 #library_path "./bin"
 
 #load_all "./src"
-#load "./src/html-templates/module"
+// #load "./src/html-templates/module"
 
index c6f22aa6defd8e1d0e9a171dbcc5912aa4bbecf1..b34c390795277627f6c94daf47f99ee887413d27 100644 (file)
@@ -8,6 +8,9 @@ version=0.0.1
 [config]
 lib_source_directory=./lib
 lib_bin_directory=./bin
+run_cmd=onyx run build
+debug_cmd=onyx run --debug build
+test_cmd=
 
 [native_library]
 build_cmd=
@@ -16,6 +19,7 @@ library=
 [dependencies]
 git://onyxlang.io/repo/http-server=0.0.17
 git://onyxlang.io/repo/postgres-orm=0.0.18
+git://onyxlang.io/repo/otmp=0.0.2
 
 [dependency_folders]
 git://onyxlang.io/repo/http-server=http-server
@@ -23,4 +27,5 @@ git://onyxlang.io/repo/postgres-orm=postgres-orm
 git://onyxlang.io/repo/json=json
 git://onyxlang.io/repo/base64=base64
 git://onyxlang.io/repo/postgres=postgres
+git://onyxlang.io/repo/otmp=otmp
 
index 9baa098ed96a33d0abe9c55d5a376c783f96f6fe..461cfe203dd4a538cb880fe6ce9338b0dfa88b90 100644 (file)
@@ -22,6 +22,11 @@ reg: otmp.TemplateRegistry;
             .[ 9, 10, 11, 12 ]
         ],
 
+        matrix2 = .[
+            .[ 1, 2 ],
+            .[ 3, 4 ],
+        ],
+
         test = req,
     });
     res->status(200);
@@ -38,9 +43,7 @@ main :: () {
 
     #if #defined(runtime.vars.Debug) {
         app->pipe((req, res) => {
-            // printf("Before: {}\n", alloc.heap.get_watermark());
             reg->refresh_templates();
-            // printf("After: {}\n", alloc.heap.get_watermark());
         });
     }
 
diff --git a/src/html-templates/TODO.md b/src/html-templates/TODO.md
deleted file mode 100644 (file)
index 3c71e3b..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-- [ ] // :EscapedStrings
-
diff --git a/src/html-templates/module.onyx b/src/html-templates/module.onyx
deleted file mode 100644 (file)
index 2230b9b..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-package otmp
-
-#load_all "./src"
-
-
diff --git a/src/html-templates/src/otmp.onyx b/src/html-templates/src/otmp.onyx
deleted file mode 100644 (file)
index e1f57da..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-package otmp
-
-use core.alloc {as_allocator, arena}
-use core {array, io, os, string, tprintf, printf}
-
-//
-// Template Registry
-// 
-
-registry :: () -> TemplateRegistry {
-    t: TemplateRegistry;
-    t.arena = arena.make(context.allocator, 64 * 1024);
-    t.templates->init();
-
-    return t;
-}
-
-#overload
-delete :: (t: ^TemplateRegistry) {
-    for ^temp: t.templates.entries {
-        delete(temp.value);
-    }
-
-    delete(^t.templates);
-    arena.free(^t.arena);
-}
-
-#inject TemplateRegistry {
-    load_directory :: (self: ^TemplateRegistry, dir: str, extension: str) {
-        for os.list_directory(dir) {
-            if string.ends_with(it->name(), extension) {
-                name := it->name();
-                name = name[0 .. string.last_index_of(name, #char ".")];
-
-                self->load_template(name, tprintf("{}/{}", dir, it->name()));
-            }
-
-            if it.type == .Directory {
-                self->load_directory(tprintf("{}/{}", dir, it->name()), extension);
-            }
-        }
-    }
-
-    load_template :: (self: ^TemplateRegistry, name: str, filename: str) -> Error {
-        printf("Loading template {} from {}.\n", name, filename);
-        if self.templates->has(name) {
-            printf("[ERROR] Template '{}' already exists.\n");
-            return .Duplicate_Template;
-        }
-
-        if !os.is_file(filename) {
-            return .Template_Not_Found;
-        }
-
-        contents := os.get_contents(filename);
-        stored_contents := contents;
-        defer delete(^stored_contents);
-
-        permanent_name := string.alloc_copy(name, as_allocator(^self.arena));
-
-        temp          := template_make(as_allocator(^self.arena));
-        temp.filepath  = filename |> string.alloc_copy(as_allocator(^self.arena));
-        temp.name      = permanent_name;
-
-        if err := parse_template(temp, ^contents); err != .None {
-            return .Template_Parse_Error;
-        }
-
-        self.templates[permanent_name] = temp;
-        return .None;
-    }
-
-    refresh_templates :: (self: ^TemplateRegistry) {
-        for ^temp: self.templates.entries {
-            array.clear(^temp.value.instructions);
-            arena.clear(^temp.value.node_storage);
-
-            contents := os.get_contents(temp.value.filepath);
-            stored_contents := contents;
-            defer delete(^stored_contents);
-
-            parse_template(temp.value, ^contents);
-        }
-    }
-
-    get_template :: (self: ^TemplateRegistry, name: str) -> ^Template {
-        return self.templates[name];
-    }
-
-    render_template :: (self: ^TemplateRegistry, name: str, output: ^io.Writer, scope: any) -> Error {
-        temp := self.templates[name];
-        if temp == null {
-            return .Template_Not_Found;
-        }
-
-        tscope, _ := core.misc.any_to_map(scope);
-        defer delete(^tscope);
-
-        return temp->render(self, ^tscope, output);
-    }
-}
-
-
-
-
-//
-// Template
-//
-#package
-template_make :: (alloc: Allocator) -> ^Template {
-    t := new(Template, alloc);
-    t.node_storage = arena.make(context.allocator, 64 * 1024);
-    return t;
-}
-
-#overload
-delete :: (t: ^Template) {
-    delete(^t.instructions);
-    arena.free(^t.node_storage);
-}
-
-#inject Template {
-    render :: (self: ^Template, reg: ^TemplateRegistry, scope: ^TemplateScope, output: ^io.Writer) -> Error {
-        r := ^TemplateRenderer.{
-            t = self,
-            w = output,
-            reg = reg,
-            scope = scope
-        };
-
-        err := render_template(r);
-
-        if err != .None {
-            core.printf("Template Error: {}\n", r.error);
-        }
-
-        return err;
-    }
-}
-
-
-#package
-make_node :: macro (t: ^Template, $T: type_expr) -> ^T where IsTNode(T) {
-    r := new(T, allocator=as_allocator(^t.node_storage));
-    r.type = T;
-    return r;
-}
-
-#package
-make_expr :: macro (t: ^Template, $T: type_expr) -> ^T where IsTExpr(T) {
-    r := new(T, allocator=as_allocator(^t.node_storage));
-    r.type = T;
-    return r;
-}
-
diff --git a/src/html-templates/src/parser.onyx b/src/html-templates/src/parser.onyx
deleted file mode 100644 (file)
index 0f5cf26..0000000
+++ /dev/null
@@ -1,513 +0,0 @@
-package otmp
-
-
-use core {string, array, iter, conv}
-use core.alloc {as_allocator}
-
-ParseError :: enum {
-    None;
-    Unexpected_Token;
-    Expected_Token;
-
-    Nested_Command;
-
-    Cannot_Nest_Blocks;
-}
-
-
-#package
-TemplateLexer :: struct {
-    // The input string
-    s: ^str;
-    line: u32;
-    col:  u32;
-
-    hit_eof := false;
-
-    inside_command := false;
-    inside_expression := false;
-    error: ParseError;
-
-    token_buffer: [..] TemplateToken;
-}
-
-TemplateToken :: struct {
-    Type :: enum {
-        Error;
-        EOF;
-
-        Text;   // Raw Text
-
-        Command_Start; Command_End;
-        Expression_Start; Expression_End;
-
-        Keyword_Block;
-        Keyword_EndBlock;
-        Keyword_Foreach;
-        Keyword_EndForeach;
-        Keyword_In;
-        Keyword_Extends;
-
-        String_Literal;
-        Int_Literal;
-
-        Variable;
-        Symbol;
-
-        Dot;
-        Open_Bracket;
-        Close_Bracket;
-    }
-
-    type: Type;
-    text: str;
-    line: u32;
-    col:  u32;
-}
-
-#inject TemplateLexer {
-    peek :: (self: ^TemplateLexer, n := 0) -> TemplateToken {
-        while n >= self.token_buffer.length {
-            next := self->eat_next_token();
-            if next.type == .EOF do return next;
-
-            self.token_buffer << next;
-        }
-
-        return self.token_buffer[n];
-    }
-
-    consume :: (self: ^TemplateLexer) -> TemplateToken {
-        if !array.empty(self.token_buffer) {
-            tkn := self.token_buffer[0];
-            array.delete(^self.token_buffer, 0);
-            return tkn;
-        }
-
-        tkn := self->eat_next_token();
-        return tkn;
-    }
-
-    eat_characters :: (self: ^TemplateLexer, chars := 1) -> str {
-        for chars {
-            if self.s.data[it] == #char "\n" {
-                self.line += 1;
-                self.col   = 0;
-            }
-
-            self.col += 1;
-        }
-
-        defer string.advance(self.s, chars);
-        return self.s.data[0 .. chars];
-    }
-
-    eat_whitespace :: (self: ^TemplateLexer) {
-        while !string.empty(*self.s) {
-            switch self.s.data[0] {
-                case #char "\n", #char "\t", #char "\r", #char " " {
-                    self->eat_characters(1);
-                }
-
-                case #default {
-                    break break;
-                }
-            }
-        }
-    }
-
-    eat_next_token :: (self: ^TemplateLexer) -> TemplateToken {
-        tkn: TemplateToken; 
-        tkn.line = self.line;
-        tkn.col  = self.col;
-        
-        self->eat_whitespace();
-
-        if string.empty(*self.s) {
-            self.hit_eof = true;
-            yield_token(.EOF);
-        }
-
-        token_match("{{") {
-            if self.inside_command {
-                self.error = .Nested_Command;
-                yield_token(.Error);
-            }
-
-            self.inside_command = true;
-            yield_token(.Command_Start);
-        }
-
-        token_match("}}") {
-            if self.inside_command {
-                self.inside_command = false;
-            }
-
-            yield_token(.Command_End);
-        }
-
-        token_match("{%") {
-            if self.inside_expression {
-                self.error = .Nested_Command;
-                yield_token(.Error);
-            }
-
-            self.inside_expression = true;
-            yield_token(.Expression_Start);
-        }
-
-        token_match("%}") {
-            if self.inside_expression {
-                self.inside_expression = false;
-            }
-
-            yield_token(.Expression_End);
-        }
-
-        if self.inside_command || self.inside_expression {
-            self->eat_whitespace();
-
-            token_consume("block",      .Keyword_Block);            
-            token_consume("endblock",   .Keyword_EndBlock);            
-            token_consume("foreach",    .Keyword_Foreach);            
-            token_consume("endforeach", .Keyword_EndForeach);            
-            token_consume("in",         .Keyword_In);
-            token_consume("extends",    .Keyword_Extends);
-            token_consume(".",          .Dot);
-            token_consume("[",          .Open_Bracket);
-            token_consume("]",          .Close_Bracket);
-
-            if self.s.data[0] == #char "\"" {
-                // :TODO add escaped strings
-                self->eat_characters(1);
-
-                index := string.index_of(*self.s, #char "\"");
-                tkn.text = self->eat_characters(index);
-                self->eat_characters(1);
-                
-                yield_token(.String_Literal);
-            }
-
-            if self.s.data[0] == #char "$" {
-                self->eat_characters(1);
-
-                chars := 0;
-                while chars < self.s.length && self.s.data[chars]->is_alphanum() {
-                     chars += 1;
-                }
-
-                tkn.text = self->eat_characters(chars);
-
-                yield_token(.Variable);
-            }
-
-            if self.s.data[0]->is_num() {
-                chars := 0;
-                while chars < self.s.length && self.s.data[chars]->is_num() {
-                     chars += 1;
-                }
-
-                tkn.text = self->eat_characters(chars);
-
-                yield_token(.Int_Literal);
-            }
-
-            if self.s.data[0]->is_alphanum() {
-                chars := 0;
-                while chars < self.s.length &&
-                    (self.s.data[chars]->is_alphanum() || self.s.data[chars] == #char "_") {
-                     chars += 1;
-                }
-
-                tkn.text = self->eat_characters(chars);
-
-                yield_token(.Symbol);
-            }
-
-        } else {
-            length := 1;
-            while self.s.data[length] != #char "{" && length < self.s.length {
-                length += 1;
-            }
-
-            tkn.text = self->eat_characters(length);
-            yield_token(.Text);
-        }
-
-        yield_token :: macro (kind: TemplateToken.Type) {
-            tkn.type = kind;
-            return tkn;
-        }
-
-        token_match :: macro (t: str, body: Code) {
-            if string.starts_with(*self.s, t) {
-                tkn.text = self->eat_characters(t.length);
-
-                #unquote body;
-            }
-        }
-        
-        token_consume :: macro (t: str, kind: TemplateToken.Type) {
-            if string.starts_with(*self.s, t) {
-                tkn.text = self->eat_characters(t.length);
-                yield_token(kind);
-            }
-        }
-    }
-}
-
-#overload
-delete :: (tl: ^TemplateLexer) {
-    delete(^tl.token_buffer);
-}
-
-#overload
-iter.as_iterator :: (tl: ^TemplateLexer) => {
-    return iter.generator(
-        ^.{ tl = tl, hit_error = false },
-        
-        (ctx) => {
-            if !ctx.hit_error {
-                tkn := ctx.tl->consume();
-                if tkn.type == .Error || tkn.type == .EOF {
-                    ctx.hit_error = true;
-                }
-
-                return tkn, true;
-            }
-
-            return .{}, false;
-        }
-    );
-}
-
-
-#package
-TemplateParser :: struct {
-    t: ^Template;
-    l: ^TemplateLexer;
-
-    instruction_targets: [..] ^[..] ^TNode;
-}
-
-#package
-parse_template :: (t: ^Template, s: ^str) -> ParseError {
-    l := TemplateLexer.{s};
-    p := TemplateParser.{t, ^l};
-    p.instruction_targets << ^t.instructions;
-    defer delete(^p.instruction_targets);
-
-    return parse_statements(^p);
-}
-
-#local
-parse_statements :: (use p: ^TemplateParser) -> ParseError {
-    while !p.l.hit_eof {
-        switch tkn := p.l->consume(); tkn.type {
-            case .Command_Start {
-                if err := parse_statement(p); err != .None {
-                    return err;
-                }
-
-                expect_token(p, .Command_End);
-            }
-
-            case .Expression_Start {
-                if node, err := parse_expression(p); err != .None {
-                    return err;
-                } else {
-                    *array.get(instruction_targets, -1) << node;
-                }
-
-                expect_token(p, .Expression_End);
-            }
-
-            case .Text {
-                text_node := make_node(t, TNodeText);
-                text_node.text = string.alloc_copy(tkn.text, as_allocator(^t.node_storage));
-                *array.get(instruction_targets, -1) << text_node;
-            }
-        }
-    }
-
-    return .None;
-}
-
-#local
-parse_statement :: (use p: ^TemplateParser) -> ParseError {
-    switch tkn := p.l->consume(); tkn.type {
-        case .Keyword_Extends {
-            text, err := parse_string(p);
-            if err != .None do return err;
-
-            extend_node := make_node(t, TNodeExtend);
-            extend_node.template_name = text;
-
-            *array.get(instruction_targets, -1) << extend_node;
-        }
-
-        case .Keyword_Block {
-            text, err := parse_string(p);
-            if err != .None do return err;
-
-            block_node := make_node(t, TNodeBlock);
-            block_node.block_name = text;
-
-            *array.get(instruction_targets, -1) << block_node;
-
-            instruction_targets << ^block_node.contents;
-        }
-
-        case .Keyword_EndBlock {
-            array.pop(^instruction_targets);
-        }
-
-        case .Keyword_Foreach {
-            var_tkn: TemplateToken;
-            expect_token(p, .Variable, #(var_tkn));
-
-            expect_token(p, .Keyword_In);
-
-            iter_tkn: TemplateToken;
-            expect_token(p, .Variable, #(iter_tkn));
-
-            var_expr := do {
-                name := string.alloc_copy(iter_tkn.text, as_allocator(^t.node_storage));
-
-                var_expr := make_expr(t, TExprVar);
-                var_expr.var_name = name;
-
-                return var_expr;
-            };
-
-            for_node := make_node(t, TNodeForeach);
-            for_node.var_name = string.alloc_copy(var_tkn.text, as_allocator(^t.node_storage));
-            for_node.list = var_expr;
-
-            *array.get(instruction_targets, -1) << for_node;
-            instruction_targets << ^for_node.body;
-        }
-
-        case .Keyword_EndForeach {
-            array.pop(^instruction_targets);
-        }
-    }
-
-    return .None;
-}
-
-#local
-parse_expression :: (use p: ^TemplateParser) -> (^TExpr, ParseError) {
-    retval: ^TExpr = null;
-    err := ParseError.None;
-
-    switch tkn := p.l->consume(); tkn.type {
-        case .Keyword_Block {
-            name, err := parse_string(p);
-            if err != .None do return null, err;
-
-            block_expr := make_expr(t, TExprBlock);
-            block_expr.block_name = name;
-
-            retval = block_expr;
-        }
-
-        case .Variable {
-            name := tkn.text |> string.alloc_copy(as_allocator(^t.node_storage));
-
-            var_expr := make_expr(t, TExprVar);
-            var_expr.var_name = name;
-
-            retval = var_expr;
-        }
-
-        case .Int_Literal {
-            value: i32 = ~~ conv.str_to_i64(tkn.text);
-
-            int_expr := make_expr(t, TExprInt);
-            int_expr.val = value;
-
-            retval = int_expr;
-        }
-    }
-
-    if retval == null {
-        err = .Unexpected_Token;
-    }
-
-    while true do switch tkn := p.l->peek(); tkn.type {
-        case .Dot {
-            p.l->consume();
-
-            if (p.l->peek()).type != .Symbol {
-                err = .Unexpected_Token;
-                break break;
-            }
-
-            sym_tkn := p.l->consume();
-
-            select_expr := make_expr(t, TExprSelector);
-            select_expr.var = retval;
-            select_expr.field = sym_tkn.text |> string.alloc_copy(as_allocator(^t.node_storage));
-
-            retval = select_expr;
-        }
-
-        case .Open_Bracket {
-            p.l->consume();
-
-            expr, err' := parse_expression(p);
-            if err != .None do break break;
-
-            subscript_expr := make_expr(t, TExprSubscript);
-            subscript_expr.var = retval;
-            subscript_expr.sub = expr;
-
-            retval = subscript_expr;
-
-            if (p.l->peek()).type != .Close_Bracket {
-                err = .Unexpected_Token;
-                break break;
-            }
-
-            p.l->consume();
-        }
-
-        case #default do break break;
-    }
-
-    return retval, err;
-}
-
-#local
-parse_string :: (use p: ^TemplateParser) -> (str, ParseError) {
-    str_tkn := p.l->consume();
-    if str_tkn.type != .String_Literal {
-        return "", .Unexpected_Token;
-    }
-
-    value := str_tkn.text |> string.alloc_copy(as_allocator(^t.node_storage));
-
-    return value, .None;
-}
-
-#local
-expect_token :: #match #local {}
-
-#overload
-expect_token :: macro (p: ^TemplateParser, type: TemplateToken.Type, out: Code) {
-    if (p.l->peek()).type != type {
-        return ParseError.Expected_Token;
-    }
-
-    (#unquote out) = p.l->consume();
-}
-
-#overload
-expect_token :: macro (p: ^TemplateParser, type: TemplateToken.Type) {
-    if (p.l->peek()).type != type {
-        return ParseError.Expected_Token;
-    }
-
-    p.l->consume();
-}
diff --git a/src/html-templates/src/render.onyx b/src/html-templates/src/render.onyx
deleted file mode 100644 (file)
index 4fd012a..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-package otmp
-
-use core {io, tprintf}
-use core.misc {
-    any_iter,
-    any_dereference,
-    any_selector,
-    any_subscript
-}
-
-#package
-TemplateRenderer :: struct {
-    t: ^Template;
-    w: ^io.Writer;
-    reg: ^TemplateRegistry;
-
-    scope: ^TemplateScope;
-    blocks: Map(str, ^TNodeBlock);
-
-    error: str;
-}
-
-#package
-render_template :: (use r: ^TemplateRenderer) -> Error {
-    return render_instructions(r, t.instructions);
-}
-
-#local
-render_instructions :: (use r: ^TemplateRenderer, instrs: [..] ^TNode) -> Error {
-    for instrs {
-        switch it.type {
-            case TNodeText {
-                text := cast(^TNodeText) it;
-                io.write_str(w, text.text);
-            }    
-
-            case TNodeBlock {
-                block := cast(^TNodeBlock) it;
-                if blocks->has(block.block_name) {
-                    error = tprintf("Block '{}' defined multiple times.");
-                    return .Render_Error;
-                }
-
-                blocks[block.block_name] = block;
-            }
-
-            case TNodeExtend {
-                extend := cast(^TNodeExtend) it;
-                template := reg->get_template(extend.template_name);
-                if template == null {
-                    error = tprintf("Template '{}' not found.");
-                    return .Render_Error;
-                }
-
-                if err := render_instructions(r, template.instructions); err != .None {
-                    return err;
-                }
-            }
-
-            case TNodeForeach {
-                // :Temporary :TemplateVariables
-                for_node := cast(^TNodeForeach) it;
-                var := cast(^TExprVar) for_node.list;
-                if !(scope->has(var.var_name)) {
-                    continue;
-                }
-
-                for any_iter(scope->get(var.var_name)) {
-                    scope->put(for_node.var_name, it);
-
-                    if err := render_instructions(r, for_node.body); err != .None {
-                        return err;
-                    }
-                }
-
-                scope->delete(for_node.var_name);
-            }
-
-
-
-            case TExprBlock {
-                block := cast(^TExprBlock) it;
-                if !(blocks->has(block.block_name)) {
-                    continue;
-                }
-
-                if err := render_instructions(r, blocks[block.block_name].contents); err != .None {
-                    return err;
-                }
-            }
-
-            case TExprVar, TExprSelector, TExprSubscript {
-                var := resolve_expr_to_any(r, cast(^TExpr) it);
-                if !var.data do continue;
-
-                io.write_format_va(w, "{}", .[var]);
-            }
-
-            case #default {
-                error = tprintf("Unhandled node type '{}'", it.type);
-                return .Render_Error;
-            }
-        }
-    }
-
-    return .None;
-}
-
-#local
-resolve_expr_to_any :: (use r: ^TemplateRenderer, expr: ^TExpr) -> any {
-    switch expr.type {
-        case TExprVar {
-            var := cast(^TExprVar) expr;
-            // :ErrorHandling if variable does not exist
-            return scope->get(var.var_name);
-        }
-
-        case TExprSelector {
-            selector := cast(^TExprSelector) expr;
-
-            sub_any := resolve_expr_to_any(r, selector.var);
-            sub_any  = any_dereference(sub_any);
-            return any_selector(sub_any, selector.field);
-        }
-
-        case TExprSubscript {
-            subscript := cast(^TExprSubscript) expr;
-
-            sub_any := resolve_expr_to_any(r, subscript.var);
-            sub := any_to_int(resolve_expr_to_any(r, subscript.sub));
-
-            return any_subscript(sub_any, ~~ sub);
-        }
-    }
-
-    return .{null, void};
-}
-
-
-#local
-// :StandardLibrary
-any_to_int :: (v: any) -> i64 {
-    switch v.type {
-        C(u32);
-        C(i32);
-        C(u64);
-        C(i64);
-
-        C :: macro (T: type_expr) {
-            case T do return ~~ *cast(^T) v.data;
-        }
-    }
-
-    return 0;
-}
diff --git a/src/html-templates/src/types.onyx b/src/html-templates/src/types.onyx
deleted file mode 100644 (file)
index a97d166..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-package otmp
-
-use core.alloc.arena {Arena}
-
-TemplateRegistry :: struct {
-    templates: Map(str, ^Template);
-
-    arena: Arena;
-}
-
-Template :: struct {
-    name: str;
-    filepath: str;
-
-    instructions: [..] ^TNode;
-
-    node_storage: Arena;
-}
-
-
-TNode :: struct {
-    type: type_expr;
-}
-
-TNodeText :: struct {
-    use node: TNode;
-
-    text: str;     // storage: template.node_storage
-}
-
-TNodeExtend :: struct {
-    use node: TNode;
-
-    template_name: str; // storage: template.node_storage
-}
-
-TNodeBlock :: struct {
-    use node: TNode;
-
-    block_name: str;   // storage: template.node_storage
-    contents: [..] ^TNode;
-}
-
-TNodeForeach :: struct {
-    use node: TNode;
-
-    var_name: str;     // storage: template.node_storage
-    list: ^TExpr;
-    body: [..] ^TNode;
-}
-
-
-TExpr :: struct {
-    use node: TNode;
-}
-
-TExprBlock :: struct {
-    use expr: TExpr;
-    
-    block_name: str; // storage: template.node_storage
-}
-
-TExprVar :: struct {
-    use expr: TExpr;
-
-    var_name: str;   // storage: template.node_storage
-}
-
-TExprSelector :: struct {
-    use expr: TExpr;
-
-    var: ^TExpr;
-    field: str;     // storage: template.node_storage
-}
-
-TExprSubscript :: struct {
-    use expr: TExpr;
-
-    var: ^TExpr;
-    sub: ^TExpr;
-}
-
-TExprInt :: struct {
-    use expr: TExpr;
-
-    val: i32;
-}
-
-
-Error :: enum {
-    None;
-    Template_Not_Found;
-    Duplicate_Template;
-
-    Template_Parse_Error;
-
-    Render_Error;
-}
-
-
-TemplateScope :: #type Map(str, any);
-
-
-#package {
-    IsTNode :: interface (t: $T) {
-        { ^t } -> ^TNode;
-    }
-
-    IsTExpr :: interface (t: $T) {
-        { ^t } -> ^TExpr;
-    }
-}
index 1cefa94e9f309f3e9c99fce1e064d94f572619df..f4fc2d0a04eaca35bea51dad52bea50c9ba16b44 100644 (file)
@@ -2,9 +2,20 @@
     padding: 0;
     margin:  0;
     box-sizing: border-box;
+}
+
+@media (prefers-color-scheme: dark) {
+    * {
+        background-color: #111;
+        color: #fff;
+    }
+}
 
-    background-color: #111;
-    color: #fff;
+@media (prefers-color-scheme: light) {
+    * {
+        background-color: #ffd;
+        color: #000;
+    }
 }
 
 
index e18027d0a87e7cf22e9c4771b05983c9ce37737a..460c22ecf3c22f0851560ac7c978e0f431b4f239 100644 (file)
     {{endforeach}}
     </ol>
 
-    <table>
-        <tbody>
-            {{foreach $row in $matrix}}
-            <tr>
-                {{foreach $col in $row}}
-                <td>{% $col %}</td>
-                {{endforeach}}
-            </tr>
-            {{endforeach}}
-        </tbody>
-    </table>
+    {% partial "matrix" $matrix2 $matrix %}
 
     <p>Name: {% $test.headers %} </p>
     <p>Age:  {% $test.cookies %} </p>
diff --git a/www/templates/matrix.html b/www/templates/matrix.html
new file mode 100644 (file)
index 0000000..067fd47
--- /dev/null
@@ -0,0 +1,25 @@
+<table>
+    <tbody>
+        {{foreach $row in $1}}
+        <tr>
+            {{foreach $col in $row}}
+            <td>Value: {% $col %}</td>
+            {{endforeach}}
+        </tr>
+        {{endforeach}}
+    </tbody>
+</table>
+
+
+<table>
+    <tbody>
+        {{foreach $row in $0}}
+        <tr>
+            {{foreach $col in $row}}
+            <td>Value: {% $col %}</td>
+            {{endforeach}}
+        </tr>
+        {{endforeach}}
+    </tbody>
+</table>
+