Compare commits
12 Commits
main
...
7124aeb94e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7124aeb94e | ||
|
|
0f76ad666a | ||
|
|
774d1fd8eb | ||
|
|
65c6a901d2 | ||
|
|
f9f4f5d34a | ||
|
|
03292a15c8 | ||
|
|
b707360c85 | ||
|
|
6388d52499 | ||
|
|
31f2b1c5c9 | ||
|
|
e4e797fe15 | ||
|
|
c466e55169 | ||
|
|
fedfd70c50 |
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "spec"]
|
||||||
|
path = spec
|
||||||
|
url = https://github.com/mustache/spec
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
# Templateless
|
# Mustacheless
|
||||||
A lightweight, logicless templating library for the
|
A subset of {{mustache}}, logicless templating library for the
|
||||||
[Odin programming language](https://odin-lang.org/). This library allows you to
|
[Odin programming language](https://odin-lang.org/). This library allows you to
|
||||||
define templates using placeholder variables within strings and replace them
|
define templates using placeholder variables within strings and replace them
|
||||||
with values from a provided dictionary.
|
with values from a provided dictionary.
|
||||||
|
|||||||
155
decode.odin
Normal file
155
decode.odin
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
package mustache
|
||||||
|
|
||||||
|
import "base:runtime"
|
||||||
|
import "core:reflect"
|
||||||
|
import "core:strings"
|
||||||
|
import "core:mem"
|
||||||
|
|
||||||
|
import "core:log"
|
||||||
|
|
||||||
|
@private
|
||||||
|
_clean_html :: proc(s: string) -> string {
|
||||||
|
ret: strings.Builder
|
||||||
|
|
||||||
|
for c in s do switch c {
|
||||||
|
case '<':
|
||||||
|
strings.write_string(&ret, "<")
|
||||||
|
case '>':
|
||||||
|
strings.write_string(&ret, ">")
|
||||||
|
case '&':
|
||||||
|
strings.write_string(&ret, "&")
|
||||||
|
case '"':
|
||||||
|
strings.write_string(&ret, """)
|
||||||
|
case '\'':
|
||||||
|
strings.write_string(&ret, "'")
|
||||||
|
case:
|
||||||
|
strings.write_rune(&ret, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.to_string(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
decode :: proc( v: any, key: string ) -> any {
|
||||||
|
ti := type_info_of(v.id)
|
||||||
|
variant := runtime.type_info_base(ti).variant
|
||||||
|
|
||||||
|
#partial switch i in variant {
|
||||||
|
case runtime.Type_Info_Enumerated_Array:
|
||||||
|
return decode(any{v.data, ti.id}, key)
|
||||||
|
|
||||||
|
case runtime.Type_Info_Union:
|
||||||
|
return decode(any{v.data, reflect.union_variant_typeid(v) }, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
if key == "." {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
#partial switch i in variant {
|
||||||
|
case runtime.Type_Info_Struct:
|
||||||
|
newkey, err := strings.split_after_n(key, ".", 2)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
defer delete(newkey)
|
||||||
|
|
||||||
|
newkey_0 := newkey[0]
|
||||||
|
newkey_1 := "."
|
||||||
|
|
||||||
|
if len(newkey) != 2 {
|
||||||
|
newkey_0 = newkey[0][:len(newkey[0])-1]
|
||||||
|
newkey_1 = newkey[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
return decode( reflect.struct_field_value_by_name(v, newkey_0), newkey_1 )
|
||||||
|
|
||||||
|
|
||||||
|
case runtime.Type_Info_Map:
|
||||||
|
newkey, err := strings.split_after_n(key, ".", 2)
|
||||||
|
|
||||||
|
if err!= nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
defer delete(newkey)
|
||||||
|
|
||||||
|
newkey_0 := newkey[0]
|
||||||
|
newkey_1 := "."
|
||||||
|
|
||||||
|
if len(newkey) == 2 {
|
||||||
|
newkey_0 = newkey[0][:len(newkey[0])-1]
|
||||||
|
newkey_1 = newkey[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
m := (^mem.Raw_Map)(v.data)
|
||||||
|
ks, vs, _, _, _ := runtime.map_kvh_data_dynamic(m^, i.map_info)
|
||||||
|
|
||||||
|
for j in 0..<runtime.map_cap(m^) {
|
||||||
|
key_data := runtime.map_cell_index_dynamic(ks, i.map_info.ks, uintptr(j))
|
||||||
|
ky, ok := reflect.as_string(any{rawptr(key_data), i.key.id})
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if ky == newkey_0 {
|
||||||
|
t := any{rawptr(runtime.map_cell_index_dynamic(vs, i.map_info.vs, uintptr(j))), i.value.id}
|
||||||
|
return decode(t, newkey_1 )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
@private
|
||||||
|
mustache_section :: proc( r: ^strings.Reader, v, p: any, section_key: string, inv: bool = false ) -> string {
|
||||||
|
tmp := mustache(r, v, section_key)
|
||||||
|
defer delete(tmp)
|
||||||
|
|
||||||
|
tmp2 := mustache(tmp, p, section_key)
|
||||||
|
|
||||||
|
if inv {
|
||||||
|
return tmp2
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(tmp2)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
section :: proc( r: ^strings.Reader, v: any, section_key: string, inv: bool = false ) -> string {
|
||||||
|
save := r.i
|
||||||
|
|
||||||
|
t := reflect.any_base(decode(v, section_key))
|
||||||
|
ti := type_info_of(t.id)
|
||||||
|
|
||||||
|
#partial switch i in runtime.type_info_base(ti).variant {
|
||||||
|
case runtime.Type_Info_Slice:
|
||||||
|
ret : string= ""
|
||||||
|
for i in 0..<reflect.length(t) {
|
||||||
|
elem :=reflect.index(t, i);
|
||||||
|
strings.reader_seek(r, save, .Start)
|
||||||
|
|
||||||
|
tmp := mustache_section(r, elem, v, section_key, !inv)
|
||||||
|
defer delete(tmp)
|
||||||
|
|
||||||
|
ret = strings.concatenate({ret, tmp})
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
case runtime.Type_Info_Boolean:
|
||||||
|
b, _ := reflect.as_bool(t)
|
||||||
|
|
||||||
|
return mustache_section(r, t, v, section_key, b~inv)
|
||||||
|
}
|
||||||
|
|
||||||
|
if t == nil {
|
||||||
|
return mustache_section(r, t, v, section_key, inv)
|
||||||
|
}
|
||||||
|
|
||||||
|
return mustache_section(r, t, v, section_key, !inv)
|
||||||
|
}
|
||||||
157
mustache.odin
Normal file
157
mustache.odin
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
package mustache
|
||||||
|
|
||||||
|
import "core:fmt"
|
||||||
|
import "core:strings"
|
||||||
|
|
||||||
|
state :: enum {
|
||||||
|
writing,
|
||||||
|
reading_key,
|
||||||
|
open_bracket,
|
||||||
|
close_bracket,
|
||||||
|
}
|
||||||
|
|
||||||
|
mustache :: proc{mustache_reader, mustache_string}
|
||||||
|
|
||||||
|
mustache_string :: proc(fmt: string, data: any , section_key: string = "") -> string {
|
||||||
|
r : strings.Reader
|
||||||
|
strings.reader_init(&r, fmt)
|
||||||
|
return mustache(&r, data, section_key)
|
||||||
|
}
|
||||||
|
|
||||||
|
mustache_reader :: proc(r: ^strings.Reader, data: any, section_key: string = "" ) -> string {
|
||||||
|
/*
|
||||||
|
This is the main parser for mustache templates, it's a recursive decent parser, that works as a state machine,
|
||||||
|
it manipulates the processed template with data, `ret`, and the key to element on data `key`, according to the states.
|
||||||
|
This approach let us process the data as fast as posible.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ret, key: strings.Builder
|
||||||
|
defer strings.builder_destroy(&key)
|
||||||
|
|
||||||
|
s:= state.writing
|
||||||
|
|
||||||
|
for {
|
||||||
|
c, _, err := strings.reader_read_rune(r);
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
switch c {
|
||||||
|
case '{':
|
||||||
|
switch s {
|
||||||
|
case .open_bracket:
|
||||||
|
s=.reading_key
|
||||||
|
case .close_bracket:
|
||||||
|
strings.write_string(&ret, "}{" )
|
||||||
|
s=.writing
|
||||||
|
case .writing:
|
||||||
|
s=.open_bracket
|
||||||
|
case .reading_key:
|
||||||
|
strings.write_rune(&key, '{' )
|
||||||
|
}
|
||||||
|
case '}':
|
||||||
|
switch s {
|
||||||
|
case .open_bracket:
|
||||||
|
strings.write_string(&ret, "{}" )
|
||||||
|
s=.writing
|
||||||
|
case .close_bracket:
|
||||||
|
// Work with key
|
||||||
|
skey := strings.to_string(key)
|
||||||
|
strings.builder_reset(&key)
|
||||||
|
s=.writing
|
||||||
|
|
||||||
|
if len(skey) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
switch skey[0] {
|
||||||
|
case '/':
|
||||||
|
if skey[1:] == section_key {
|
||||||
|
return strings.to_string(ret)
|
||||||
|
}
|
||||||
|
case '#':
|
||||||
|
strings.write_string(&ret, section(r, data, skey[1:]) )
|
||||||
|
case '^':
|
||||||
|
strings.write_string(&ret, section(r, data, skey[1:], true) )
|
||||||
|
case '&':
|
||||||
|
strings.write_string(&ret, fmt.tprintf("%v",decode(data, skey[1:])) )
|
||||||
|
case '!':
|
||||||
|
case:
|
||||||
|
dec := decode(data, skey)
|
||||||
|
|
||||||
|
if dec == nil {
|
||||||
|
// If not decoded write as key
|
||||||
|
strings.write_string(&ret, "{{" )
|
||||||
|
strings.write_string(&ret, skey )
|
||||||
|
strings.write_string(&ret, "}}" )
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
clean := _clean_html(fmt.tprintf("%v", dec))
|
||||||
|
defer delete(clean)
|
||||||
|
|
||||||
|
strings.write_string(&ret, clean)
|
||||||
|
}
|
||||||
|
case .writing:
|
||||||
|
strings.write_rune(&ret, '}' )
|
||||||
|
s=.writing
|
||||||
|
case .reading_key:
|
||||||
|
s=.close_bracket
|
||||||
|
}
|
||||||
|
case:
|
||||||
|
switch s {
|
||||||
|
case .open_bracket:
|
||||||
|
strings.write_rune(&ret, '{' )
|
||||||
|
strings.write_rune(&ret, c )
|
||||||
|
s=.writing
|
||||||
|
case .close_bracket:
|
||||||
|
strings.write_rune(&key, '}' )
|
||||||
|
strings.write_rune(&key, c )
|
||||||
|
s=.reading_key
|
||||||
|
case .writing:
|
||||||
|
strings.write_rune(&ret, c )
|
||||||
|
s=.writing
|
||||||
|
case .reading_key:
|
||||||
|
strings.write_rune(&key, c )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch s {
|
||||||
|
case .open_bracket:
|
||||||
|
strings.write_rune(&ret, '{' )
|
||||||
|
case .reading_key:
|
||||||
|
strings.write_string(&ret,"{{")
|
||||||
|
strings.write_string(&ret,strings.to_string(key))
|
||||||
|
case .close_bracket:
|
||||||
|
strings.write_string(&ret,"{{")
|
||||||
|
strings.write_string(&ret,strings.to_string(key))
|
||||||
|
strings.write_rune(&ret, '}' )
|
||||||
|
case .writing:
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.to_string(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
1-Clause BSD NON-AI License
|
||||||
|
|
||||||
|
Copyright (c) 2025
|
||||||
|
NVIAM. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. The source code and any modifications made to it may not be used for the purpose of training or improving machine learning algorithms,
|
||||||
|
including but not limited to artificial intelligence, natural language processing, or data mining. This condition applies to any derivatives,
|
||||||
|
modifications, or updates based on the Software code. Any usage of the source code in an AI-training dataset is considered a breach of this License.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY NVIAM “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL NVIAM BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
1
spec
Submodule
1
spec
Submodule
Submodule spec added at 97c05b0652
118
template.odin
118
template.odin
@@ -1,118 +0,0 @@
|
|||||||
package template
|
|
||||||
|
|
||||||
import "core:strings"
|
|
||||||
|
|
||||||
@private
|
|
||||||
state :: enum {
|
|
||||||
writing,
|
|
||||||
reading_key,
|
|
||||||
open_bracket,
|
|
||||||
close_bracket,
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Input:
|
|
||||||
- fmt: A string with placeholders in the form `{{key}}`.
|
|
||||||
- dict: A map from string to string, where each key corresponds to a placeholder in the format string.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
A new string with all placeholders replaced by their corresponding values from
|
|
||||||
the dictionary. If a key is missing in the dictionary, the placeholder is
|
|
||||||
replaces with an empty string.
|
|
||||||
*/
|
|
||||||
template :: proc(fmt: string, dict: map[string]string ) -> string {
|
|
||||||
/*
|
|
||||||
template works as a state machine, it manipulates `b` (returned string)
|
|
||||||
and `key` (placeholder string), according to the states. No error
|
|
||||||
returns are needed because if `key` is not close it writes it as
|
|
||||||
it's not a placeholder
|
|
||||||
*/
|
|
||||||
|
|
||||||
b, key: strings.Builder
|
|
||||||
defer strings.builder_destroy(&key)
|
|
||||||
|
|
||||||
s:= state.writing
|
|
||||||
|
|
||||||
for c in fmt do switch c {
|
|
||||||
case '{':
|
|
||||||
switch s {
|
|
||||||
case .open_bracket:
|
|
||||||
s=.reading_key
|
|
||||||
case .close_bracket:
|
|
||||||
strings.write_string(&b, "}{" )
|
|
||||||
s=.writing
|
|
||||||
case .writing:
|
|
||||||
s=.open_bracket
|
|
||||||
case .reading_key:
|
|
||||||
strings.write_rune(&key, '{' )
|
|
||||||
}
|
|
||||||
case '}':
|
|
||||||
switch s {
|
|
||||||
case .open_bracket:
|
|
||||||
strings.write_string(&b, "{}" )
|
|
||||||
s=.writing
|
|
||||||
case .close_bracket:
|
|
||||||
strings.write_string(&b, dict[strings.to_string(key)] )
|
|
||||||
strings.builder_reset(&key)
|
|
||||||
s=.writing
|
|
||||||
case .writing:
|
|
||||||
strings.write_rune(&b, '}' )
|
|
||||||
s=.writing
|
|
||||||
case .reading_key:
|
|
||||||
s=.close_bracket
|
|
||||||
}
|
|
||||||
case:
|
|
||||||
switch s {
|
|
||||||
case .open_bracket:
|
|
||||||
strings.write_rune(&b, '{' )
|
|
||||||
strings.write_rune(&b, c )
|
|
||||||
s=.writing
|
|
||||||
case .close_bracket:
|
|
||||||
strings.write_rune(&key, '}' )
|
|
||||||
strings.write_rune(&key, c )
|
|
||||||
s=.reading_key
|
|
||||||
case .writing:
|
|
||||||
strings.write_rune(&b, c )
|
|
||||||
s=.writing
|
|
||||||
case .reading_key:
|
|
||||||
strings.write_rune(&key, c )
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch s {
|
|
||||||
case .open_bracket:
|
|
||||||
strings.write_rune(&b, '{' )
|
|
||||||
case .reading_key:
|
|
||||||
strings.write_string(&b,"{{")
|
|
||||||
strings.write_string(&b,strings.to_string(key))
|
|
||||||
case .close_bracket:
|
|
||||||
strings.write_string(&b,"{{")
|
|
||||||
strings.write_string(&b,strings.to_string(key))
|
|
||||||
strings.write_rune(&b, '}' )
|
|
||||||
case .writing:
|
|
||||||
}
|
|
||||||
|
|
||||||
return strings.to_string(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
1-Clause BSD NON-AI License
|
|
||||||
|
|
||||||
Copyright (c) 2025
|
|
||||||
NVIAM. All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
2. The source code and any modifications made to it may not be used for the purpose of training or improving machine learning algorithms,
|
|
||||||
including but not limited to artificial intelligence, natural language processing, or data mining. This condition applies to any derivatives,
|
|
||||||
modifications, or updates based on the Software code. Any usage of the source code in an AI-training dataset is considered a breach of this License.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY NVIAM “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
IN NO EVENT SHALL NVIAM BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
142
testing.odin
142
testing.odin
@@ -1,108 +1,62 @@
|
|||||||
#+feature dynamic-literals
|
#+feature dynamic-literals
|
||||||
#+private
|
#+private
|
||||||
package template
|
package mustache
|
||||||
|
|
||||||
|
import "core:os"
|
||||||
|
import "core:log"
|
||||||
import "core:testing"
|
import "core:testing"
|
||||||
|
import "core:encoding/json"
|
||||||
|
|
||||||
|
data_struct :: union {
|
||||||
|
map[string]data_struct,
|
||||||
|
[]data_struct,
|
||||||
|
string,
|
||||||
|
bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
test_struct :: struct {
|
||||||
|
overview: string,
|
||||||
|
tests: []struct{
|
||||||
|
name, desc, template, expected: string,
|
||||||
|
data: data_struct
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
test1 :: proc(t: ^testing.T){
|
spec_test :: proc(t: ^testing.T){
|
||||||
fmt := "{"
|
test_files := []string {
|
||||||
tmp := template(fmt,{})
|
"./spec/specs/sections.json",
|
||||||
defer delete(tmp)
|
"./spec/specs/interpolation.json",
|
||||||
testing.expect(t, tmp==fmt, tmp)
|
"./spec/specs/inverted.json",
|
||||||
|
"./spec/specs/comments.json",
|
||||||
|
/*
|
||||||
|
"./spec/specs/partials.json",
|
||||||
|
"./spec/specs/delimiters.json",
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
@(test)
|
|
||||||
test2 :: proc(t: ^testing.T){
|
|
||||||
fmt := "}"
|
|
||||||
tmp := template(fmt,{})
|
|
||||||
defer delete(tmp)
|
|
||||||
testing.expect(t, tmp==fmt, tmp)
|
|
||||||
}
|
|
||||||
@(test)
|
|
||||||
test3 :: proc(t: ^testing.T){
|
|
||||||
fmt := "{{"
|
|
||||||
tmp := template(fmt,{})
|
|
||||||
defer delete(tmp)
|
|
||||||
testing.expect(t, tmp==fmt, tmp)
|
|
||||||
}
|
|
||||||
@(test)
|
|
||||||
test4 :: proc(t: ^testing.T){
|
|
||||||
fmt := "{{}"
|
|
||||||
tmp := template(fmt,{})
|
|
||||||
defer delete(tmp)
|
|
||||||
testing.expect(t, tmp==fmt, tmp)
|
|
||||||
}
|
|
||||||
@(test)
|
|
||||||
test5 :: proc(t: ^testing.T){
|
|
||||||
fmt := "{{}}"
|
|
||||||
tmp := template(fmt,{})
|
|
||||||
defer delete(tmp)
|
|
||||||
testing.expect(t, tmp=="", tmp)
|
|
||||||
}
|
|
||||||
@(test)
|
|
||||||
test6 :: proc(t: ^testing.T){
|
|
||||||
fmt := "{{foo}}"
|
|
||||||
|
|
||||||
dict := map[string]string{"foo"="var"}
|
for i in test_files {
|
||||||
defer delete(dict)
|
data, err:=os.read_entire_file_from_filename_or_err(i)
|
||||||
|
defer delete(data)
|
||||||
|
|
||||||
tmp := template(fmt, dict)
|
if err != nil {
|
||||||
defer delete(tmp)
|
testing.expectf(t, false, "%v", err)
|
||||||
testing.expect(t, tmp=="var", tmp)
|
|
||||||
}
|
}
|
||||||
@(test)
|
|
||||||
test7 :: proc(t: ^testing.T){
|
test: test_struct
|
||||||
fmt := "{{{}}"
|
|
||||||
tmp := template(fmt,{})
|
json.unmarshal(data, &test, allocator=context.temp_allocator)
|
||||||
defer delete(tmp)
|
|
||||||
testing.expect(t, tmp=="", tmp)
|
failed := 0
|
||||||
|
for j in test.tests {
|
||||||
|
ret := mustache(j.template, j.data)
|
||||||
|
defer delete(ret)
|
||||||
|
|
||||||
|
if ret!=j.expected {
|
||||||
|
log.warnf( "[%s:%s]: %s", i, j.name, j.desc )
|
||||||
|
failed += 1
|
||||||
}
|
}
|
||||||
@(test)
|
|
||||||
test8 :: proc(t: ^testing.T){
|
|
||||||
fmt := "{{}}}"
|
|
||||||
tmp := template(fmt,{})
|
|
||||||
defer delete(tmp)
|
|
||||||
testing.expect(t, tmp=="}", tmp)
|
|
||||||
}
|
}
|
||||||
@(test)
|
log.infof( "[%s] Passed: (%d/%d)", i, len(test.tests)-failed, len(test.tests) )
|
||||||
test9 :: proc(t: ^testing.T){
|
|
||||||
fmt := "{{{}}}"
|
|
||||||
tmp := template(fmt,{})
|
|
||||||
defer delete(tmp)
|
|
||||||
testing.expect(t, tmp=="}", tmp)
|
|
||||||
}
|
}
|
||||||
@(test)
|
|
||||||
test10 :: proc(t: ^testing.T){
|
|
||||||
fmt := "{{} }}"
|
|
||||||
tmp := template(fmt,{})
|
|
||||||
defer delete(tmp)
|
|
||||||
testing.expect(t, tmp=="", tmp)
|
|
||||||
}
|
|
||||||
@(test)
|
|
||||||
test11 :: proc(t: ^testing.T){
|
|
||||||
fmt := "{{{} }}"
|
|
||||||
tmp := template(fmt,{})
|
|
||||||
defer delete(tmp)
|
|
||||||
testing.expect(t, tmp=="", tmp)
|
|
||||||
}
|
|
||||||
@(test)
|
|
||||||
test12 :: proc(t: ^testing.T){
|
|
||||||
fmt := " {{{} }}"
|
|
||||||
tmp := template(fmt,{})
|
|
||||||
defer delete(tmp)
|
|
||||||
testing.expect(t, tmp==" ", tmp)
|
|
||||||
}
|
|
||||||
@(test)
|
|
||||||
test13 :: proc(t: ^testing.T){
|
|
||||||
fmt := "{{{} }} "
|
|
||||||
tmp := template(fmt,{})
|
|
||||||
defer delete(tmp)
|
|
||||||
testing.expect(t, tmp==" ", tmp)
|
|
||||||
}
|
|
||||||
@(test)
|
|
||||||
test14 :: proc(t: ^testing.T){
|
|
||||||
fmt := "{{{}}}"
|
|
||||||
tmp := template(fmt,{})
|
|
||||||
defer delete(tmp)
|
|
||||||
testing.expect(t, tmp=="}", tmp)
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user