11 |
12 |
--------------------------------------------------------------------------------
/examples/homepage/templates/dark.css:
--------------------------------------------------------------------------------
1 | {%set bg "black"%}
2 | {%set fg "white"%}
3 | {%extends "base.css"%}
--------------------------------------------------------------------------------
/examples/homepage/templates/foo.html:
--------------------------------------------------------------------------------
1 | {%extends "base.html"%}
2 | {%set style "light.css"%}
3 | {%set title "FOFOFOFOFOFOFOOFOF"%}
4 | {%block "content"%}
5 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nisi accusamus dicta quis fugiat magni numquam, autem dolores quos laudantium asperiores voluptas hic perspiciatis aspernatur ratione, eius quas nam, optio distinctio?
6 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempora debitis illum minus corporis deleniti ullam iste, vitae odit ab sint blanditiis eveniet nihil recusandae, eaque architecto a explicabo suscipit numquam!
7 |
8 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempora debitis illum minus corporis deleniti ullam iste, vitae odit ab sint blanditiis eveniet nihil recusandae, eaque architecto a explicabo suscipit numquam!
9 |
10 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempora debitis illum minus corporis deleniti ullam iste, vitae odit ab sint blanditiis eveniet nihil recusandae, eaque architecto a explicabo suscipit numquam!
11 | {%endblock%}
--------------------------------------------------------------------------------
/examples/homepage/templates/index.html:
--------------------------------------------------------------------------------
1 | {%extends "base.html"%}
2 | {%set style "dark.css"%}
3 | {%set title "some index"%}
4 | {%block "content"%}Some content for the index{%endblock%}
--------------------------------------------------------------------------------
/examples/homepage/templates/light.css:
--------------------------------------------------------------------------------
1 | {%extends "base.css"%}
2 | {%set bg "white"%}
3 | {%set fg "black"%}
--------------------------------------------------------------------------------
/examples/homepage/templates/menu.html:
--------------------------------------------------------------------------------
1 | {%block "menu"%}
2 | hallo
3 | foo
4 | {# bar #}
5 | {# baz #}
6 | {%endblock%}
--------------------------------------------------------------------------------
/examples/homepage/templates/t.html:
--------------------------------------------------------------------------------
1 | {%import t2.html%}
2 | {%block foo%}asdf{%endblock%}
3 | {%block baa%}aaa{%endblock%}
--------------------------------------------------------------------------------
/examples/homepage/templates/t2.html:
--------------------------------------------------------------------------------
1 | {%block "foo"%}peter{%endblock%}
2 | {%block "baa"%}peter2{%endblock%}
--------------------------------------------------------------------------------
/examples/jestr.nim:
--------------------------------------------------------------------------------
1 | import jester
2 | import ../nwt
3 | # import nwt
4 | import times
5 | import asyncdispatch
6 | # import """D:\flatdb\flatdb.nim"""
7 | import json
8 | import tables
9 |
10 | var t = newNwt("../templates/*.html")
11 | # var db = newFlatDb("tst.db", false)
12 | # if db.nodes.len == 0:
13 | # discard db.append(%* {"site": "index.html", "content": "ich bin ein bisschen content"})
14 | routes:
15 | get "/":
16 | resp t.renderTemplate("index.html", newStringTable({"content": $epochTime()}))
17 | get "/@name":
18 | resp t.renderTemplate(@"name", newStringTable({"content": $epochTime()}))
19 | # resp t.renderTemplate("index.html", newStringTable(db.queryOne equal("site","index.html")) ))
20 | # get "/ass":
21 | # resp t.renderTemplate("ass.html", newStringTable({"content": $epochTime()}))
22 | runForever()
23 |
--------------------------------------------------------------------------------
/examples/nimhack/nimhack.nim:
--------------------------------------------------------------------------------
1 | ## what is is good for? :)
2 |
3 | import ../../nwt
4 |
5 | newNwt("templates/*.nim").freeze()
6 |
7 |
--------------------------------------------------------------------------------
/examples/nimhack/templates/base.nim:
--------------------------------------------------------------------------------
1 | import asynchttpserver, asyncdispatch
2 | import ../../../nwt
3 | import strutils
4 | import tables
5 | import os
6 |
7 |
8 | const PUBLIC_DIR = "{{publicDir}}"
9 | var t = newNwt("{{templateDir}}")
10 |
11 | when not defined release:
12 | t.freeze(staticPath = PUBLIC_DIR, outputPath = "./freezed/") ## Example for "freezing" your templates into a static site.
13 |
14 | var server = newAsyncHttpServer()
15 | proc cb(req: Request) {.async.} =
16 | let res = req.url.path.strip(leading=true, trailing=false, {'/'})
17 |
18 | case res
19 | # some routes!
20 | # be aware that freeze() only freezes the template and copies the public folder.
21 | # we do not visit your custom rules for now!
22 |
23 |
24 | {%block "routes"%}{%endblock%}
25 |
26 | else:
27 | if t.templates.contains(res): # when we have a template with this name, serve it
28 | await req.respond(Http200, t.renderTemplate(res))
29 | elif fileExists(PUBLIC_DIR / res): # when there is a static file with this name, serve it
30 | await req.respond(Http200, open(PUBLIC_DIR / res,).readAll())
31 | else: # unkown to us
32 | await req.respond(Http404, "404 not found")
33 |
34 | waitFor server.serve(Port(8080), cb)
--------------------------------------------------------------------------------
/examples/nimhack/templates/base2.nim:
--------------------------------------------------------------------------------
1 | {%block content%}
2 | echo {{foo}}
3 | {%endblock%}
--------------------------------------------------------------------------------
/examples/nimhack/templates/kunde1.nim:
--------------------------------------------------------------------------------
1 | {%extends base.nim%}
2 | {%set publicDir "./public/"%}
3 | {%set templateDir "templates/*.html"%}
4 |
5 |
6 |
7 | {%block "routes"%}
8 | of "":
9 | await req.respond(Http200, t.renderTemplate("index.html") )
10 | of "logout":
11 | await req.respond(Http200, "TODO do something usefull")
12 | {%endblock%}
--------------------------------------------------------------------------------
/examples/nojester/nojester.nim:
--------------------------------------------------------------------------------
1 | import asynchttpserver, asyncdispatch
2 | import ../../nwt
3 | import strutils
4 | import tables
5 | import os
6 | import asyncfile
7 |
8 | const PUBLIC_DIR = "./public/"
9 | var t = newNwt("templates/*.html")
10 |
11 | when not defined release:
12 | t.freeze(staticPath = PUBLIC_DIR, outputPath = "./freezed/") ## Example for "freezing" your templates into a static site.
13 |
14 | var server = newAsyncHttpServer()
15 | proc cb(req: Request) {.async.} =
16 | let res = req.url.path.strip(leading=true, trailing=false, {'/'})
17 |
18 | case res
19 | # some routes!
20 | # be aware that freeze() only freezes the template, wich are loaded by the constructor, and copies the public folder.
21 | # we do not visit your custom routes for now!
22 | of "":
23 | await req.respond(Http200, t.renderTemplate("index.html") )
24 | of "logout":
25 | await req.respond(Http200, "TODO do something usefull")
26 |
27 |
28 | else:
29 | if t.templates.contains(res): # when we have a template with this name, serve it
30 | await req.respond(Http200, t.renderTemplate(res))
31 | elif fileExists(PUBLIC_DIR / res): # when there is a static file with this name, serve it
32 | let file = openAsync(PUBLIC_DIR / res , fmRead)
33 | # let data
34 | await req.respond(Http200, await file.readAll())
35 | file.close()
36 | else: # unkown to us
37 | await req.respond(Http404, "404 not found")
38 |
39 | waitFor server.serve(Port(8080), cb)
--------------------------------------------------------------------------------
/examples/nojester/public/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | background-color: #171921;
3 | color:white;
4 | font-size: 22px;
5 | }
6 |
7 | a {
8 | color:#fff;
9 | }
10 |
11 | h1 {
12 | color:#ffe953;
13 | }
14 |
15 | #footer {
16 | color:darkgray;
17 | }
18 |
19 | #content {
20 | width: 80%;
21 | margin-left: auto;
22 | margin-right: auto;
23 | }
24 |
25 |
--------------------------------------------------------------------------------
/examples/nojester/templates/about.html:
--------------------------------------------------------------------------------
1 | {%extends base.html%}
2 | {%set title "about"%}
3 | {%block content%}
4 |
5 |
{{title}}
6 |
7 |
8 |
9 |
10 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Distinctio eius numquam ut voluptatibus fuga, porro quae, cupiditate aperiam, beatae mollitia!
11 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Distinctio eius numquam ut voluptatibus fuga, porro quae, cupiditate aperiam, beatae mollitia!
12 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Distinctio eius numquam ut voluptatibus fuga, porro quae, cupiditate aperiam, beatae mollitia!
13 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Distinctio eius numquam ut voluptatibus fuga, porro quae, cupiditate aperiam, beatae mollitia!
14 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Distinctio eius numquam ut voluptatibus fuga, porro quae, cupiditate aperiam, beatae mollitia!
15 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Distinctio eius numquam ut voluptatibus fuga, porro quae, cupiditate aperiam, beatae mollitia!
16 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Distinctio eius numquam ut voluptatibus fuga, porro quae, cupiditate aperiam, beatae mollitia!
4 | {% endfor %}
5 |
6 | {% for email in userOne.emails %}
7 | {{email.subject}}
8 | {{email.body}}
9 | {% endfor %}
10 |
11 | {% for i in [1,2,3,4] %}
12 | {{ i }}
13 | {% endfor %}
14 |
15 | {# same for tuples? #}
16 | {% for i in (1,2,3,4) %}
17 | {{ i }}
18 | {% endfor %}
19 |
20 |
21 |
--------------------------------------------------------------------------------
/future/tif.nwt:
--------------------------------------------------------------------------------
1 | {% if true %}
2 | Some text
3 | {% endif %}
4 |
5 | {% if users %}
6 | Users contains list entries
7 | {% endif %}
8 |
9 | {% if 1 %}
10 | One is true
11 | {% endif %}
12 |
13 | {% if userOne.emails %}
14 | userOne has a filled emails list
15 | {% endif %}
16 |
17 | {% if true %}
18 | Some text
19 | {% else %}
20 | Never
21 | {% endif %}
22 |
23 | {% if users.mails | len == 1 %}
24 | mails is 1
25 | {% elif users.mails | len == 2 %}
26 | mails is 2
27 | {% elif users.mails | len == 3 %}
28 | mails is 2
29 | {% else %}
30 | mails is something else
31 | {% endif %}
32 |
33 |
--------------------------------------------------------------------------------
/licence:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 David Krause
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/nwt.nimble:
--------------------------------------------------------------------------------
1 | # Package
2 |
3 | version = "0.1.7"
4 | author = "enthus1ast"
5 | description = "minimal jinja like experiment"
6 | license = "MIT"
7 |
8 |
9 | srcDir = "src"
10 |
11 | # Dependencies
12 |
13 | requires "nim >= 0.17.0"
14 | requires "https://github.com/enthus1ast/nimCommandParser"
15 |
16 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | nimWebTemplates is ABADONNED and DEPRECATED
2 | ==========
3 |
4 | for a better template engine use: [enthus1ast/nimja](https://github.com/enthus1ast/nimja)
5 |
6 |
7 | readme
8 | ======
9 |
10 | nwt is a little template engine inspired by jinja2.
11 |
12 | (warning: it lacks control statements like `if` `while` etc..)
13 |
14 | it do not enforce any web framework so use whatever you like!
15 |
16 | rudimentary freeze support with `freeze()`
17 |
18 | have a look at the other demos!
19 |
20 | if you feeling fancy today have a special look at the `dbdriven` database example and
21 | my little flatfile database [flatdb](https://github.com/enthus1ast/flatdb) for nim-lang
22 |
23 |
24 | usage
25 | =====
26 |
27 |
28 | Directory structure
29 | -----------------------
30 |
31 | To follow this example create this folder structure
32 |
33 | ```
34 | ./example.nim
35 | ./templates/base.html
36 | ./templates/index.html
37 | ./templates/about.html
38 | ./templates/stats.html
39 | ```
40 |
41 |
42 |
43 | menu.html
44 | ----------
45 |
46 | ```jinja
47 | {%block menu%}index || about || stats{%endblock%}
48 | ```
49 |
50 | base.html
51 | ----------
52 |
53 | ```jinja
54 | {%import menu.html%}
55 |
56 |
57 | {{title}}
58 |
59 |
60 |
61 |
62 | {{self.menu}}
63 |
64 |
65 |
66 |
{{title}}
67 |
68 |
69 | {%block "content"%}
70 | {# i will be replaced by my children #}
71 | {%endblock%}
72 |
73 |
74 |
75 |
76 | Made with nim
77 | {{self.footer}}
78 |
79 |
80 |
81 | ```
82 |
83 |
84 | index.html
85 | -----------
86 |
87 | ```jinja
88 | {%extends "base.html"%}
89 |
90 | {%set title "Some index and more"%}
91 |
92 | {%block content%}
93 | Lorem ipsum dolor sit amet, consectetur adipisicing elit.
94 | Ab, sint repellendus iure similique ipsa unde eos est nam numquam, laborum, sit ipsum voluptates modi impedit doloremque.
95 | Fugiat, obcaecati delectus accusantium.
96 | {%endblock%}
97 |
98 | {%block footer%}
99 | Some footer infos we only want to see on the index
100 | {%endblock%}
101 | ```
102 |
103 |
104 |
105 | about.html
106 | -----------
107 |
108 | ```jinja
109 | {%extends "base.html"%}
110 | {%set title "Some about me and stuff"%}
111 |
112 | {%block content%}
113 |
114 |
foo
115 |
baaa
116 |
117 | {%endblock%}
118 |
119 | {# we not set any additional footer here, so we omit the block #}
120 | ```
121 |
122 | stats.html
123 | -----------
124 |
125 | ```jinja
126 | {%extends "base.html"%}
127 |
128 | {%block content%}
129 |
130 |
{{foo}}
131 |
{{baa}}
132 |
133 | {%endblock%}
134 |
135 | {# we not set any additional footer here, so we omit the block #}
136 | ```
137 |
138 |
139 | example.nim
140 | ------------
141 |
142 | ```nim
143 | import asynchttpserver, asyncdispatch
144 | import json
145 | import nwt
146 |
147 | var templates = newNwt("templates/*.html") # we have all the templates in a folder called "templates"
148 |
149 | var server = newAsyncHttpServer()
150 | proc cb(req: Request) {.async.} =
151 | let res = req.url.path
152 |
153 | case res
154 | of "/", "/index.html":
155 | await req.respond(Http200, templates.renderTemplate("index.html"))
156 | of "/about.html":
157 | await req.respond(Http200, templates.renderTemplate("about.html"))
158 | of "/stats.html":
159 | var context = %* {"title": "some variables from nim", "foo": "Foo!", "baa": "Baa!"}
160 | await req.respond(Http200, templates.renderTemplate("stats.html", context))
161 | else:
162 | await req.respond(Http404, "not found")
163 |
164 | waitFor server.serve(Port(8080), cb)
165 | ```
166 |
--------------------------------------------------------------------------------
/src/nwt.nim:
--------------------------------------------------------------------------------
1 | #
2 | #
3 | # nimWebTemplates
4 | # (c) Copyright 2017 David Krause
5 | #
6 | # See the file "copying.txt", included in this
7 | # distribution, for details about the copyright.
8 | #
9 | ## :Author: David Krause (enthus1ast)
10 | ##
11 | ## a jinja like template syntax parser
12 | ##
13 | ## Works:
14 | ## - comments {# comment #}
15 | ## - variable {{variable}}
16 | ## - extends [NON recursive ATM]
17 | ## NOT:
18 | ## - evaluation (for, while, etc)
19 | ## - everything else ;)
20 | ## Example usage with jester:
21 | ## routes:
22 | ## get "/":
23 | ## resp t.renderTemplate("index.html", newStringTable({"content": $epochTime()}))
24 | ## get "/ass":
25 | ## resp t.renderTemplate("ass.html", newStringTable({"content": $epochTime()}))
26 | ## runForever()
27 | import strtabs, strutils, parseutils, sequtils, os, tables, json, cgi, options
28 | import commandParser
29 | import nwtTokenizer
30 | import stack
31 | export options
32 |
33 | type
34 | TemplateIdent = string
35 | BlockIdent = string
36 | NwtTemplate = seq[Token]
37 | NwtTemplates = Table[TemplateIdent, NwtTemplate]
38 | Nwt* = ref object of RootObj
39 | templates*: NwtTemplates
40 | templatesDir*: string
41 | echoEmptyVars*: bool ## set this to true to let nwt print an empty variable like this '{{variable}}' or '{{self.variable}}'
42 | autoEscape*: bool ## automatically html escapes variables
43 | Block = tuple[name: string, cmd: ChatCommand, posStart: int, posEnd: int]
44 | Blocks = Table[BlockIdent, Block]
45 | Context = ref object
46 | variables: JsonNode
47 | nwtTemplates: NwtTemplates
48 |
49 | proc newNwtTemplate(): NwtTemplate =
50 | result = @[]
51 |
52 | proc newNwtTemplate(templateString: string): NwtTemplate =
53 | ## parses the templateString and creates a NwtTemplate from it.
54 | result = toSeq(nwtTokenize templateString)
55 |
56 | proc newNwtTemplates(): NwtTemplates =
57 | result = initTable[TemplateIdent,seq[Token]]()
58 |
59 | proc newBlocks(): Blocks =
60 | result = initTable[BlockIdent, Block]()
61 |
62 | proc newContext(variables = %* {}): Context =
63 | result = Context()
64 | result.variables = variables
65 | # result.blocks = newBlocks()
66 | result.nwtTemplates = newNwtTemplates()
67 |
68 | proc add*(nwtTemplates: var NwtTemplates, templateName: TemplateIdent, templateStr: string) =
69 | ## parses and adds/updates a template
70 | nwtTemplates[templateName] = newNwtTemplate(templateStr)
71 |
72 | proc addTemplate*(nwt: Nwt, templateName: TemplateIdent , templateStr: string) =
73 | ## parses and adds/updates a template, given by a string
74 | nwt.templates[templateName] = toSeq(nwtTokenize templateStr)
75 |
76 | proc loadTemplates*(nwt: Nwt, templatesDir: string) =
77 | ## loads and parses the templates from the filesystem.
78 | ## basic wildcards supported:
79 | ## /foo/baa/*.html
80 | ## call this for refreshing the templates
81 | for filename in walkFiles(templatesDir):
82 | var templateName = extractFilename(filename)
83 | # echo "Load: $1 as $2", % [filename, templateName]
84 | nwt.templates[templateName] = toSeq(nwtTokenize readFile(filename))
85 |
86 | proc newNwt*(templatesDir: string = "./templates/*.html"): Nwt =
87 | ## this loads all templates from the template into memory
88 | ## if templatesDir == nil we do not load any templates
89 | ## we can add them later by `addTemplate("{%foo%}{%baa%}")`
90 | result = Nwt()
91 | result.templates = newNwtTemplates()
92 | result.templatesDir = templatesDir
93 | result.loadTemplates(templatesDir)
94 | result.echoEmptyVars = false
95 | result.autoEscape = false
96 |
97 | proc getBlocks*(nwtTemplate: NwtTemplate, starting="block", ending="endblock" ): Blocks = # TODO private
98 | # returns all {%block 'foo'%} statements as a Table of Block
99 | result = newBlocks()
100 | var stack = newSeq[(ChatCommand, int)]()
101 |
102 | var actual: Block = ("",ChatCommand(),0,0)
103 | for i, each in nwtTemplate:
104 | if each.tokenType == NwtEval and each.value.strip().startswith(starting): # block
105 | var cmd = newChatCommand(each.value)
106 | stack.pushl( (cmd, i ))
107 | elif each.tokenType == NwtEval and each.value.strip().startswith(ending):
108 | if stack.len == 0:
109 | raise newException(ValueError, "UNBALANCED BLOCKS too many closeing tags for: " & $each & " " & $nwtTemplate )
110 | var cmd: ChatCommand
111 | (cmd, actual.posStart) = stack.popl()
112 | actual.name = cmd.params[0]
113 | actual.cmd = cmd
114 | actual.posEnd = i
115 | result.add(actual.name, actual)
116 | actual = ("", ChatCommand() ,0,0)
117 | if stack.len > 0:
118 | raise newException(ValueError, "UNBALANCED BLOCKS too many opening tags for: " & starting & "\nstack:\n" & $stack )
119 |
120 | proc fillBlocks*(nwt: Nwt, baseTemplateTokens, nwtTemplate: NwtTemplate, ctx: Context): NwtTemplate = # TODO private
121 | ## This fills all the base template blocks with
122 | ## blocks from extending template
123 | # @[(name: content2, posStart: 2, posEnd: 4), (name: peter, posStart: 6, posEnd: 8)]
124 | # @[(name: content2, posStart: P, posEnd: 4), (name: peter, posStart: 6, posEnd: 8)]
125 | result = baseTemplateTokens
126 | var templateBlocks = getBlocks(nwtTemplate)
127 | var baseTemplateBlocks = getBlocks(baseTemplateTokens)
128 |
129 | ## To make {self.templateName} work
130 | for k,v in templateBlocks:
131 | ctx.nwtTemplates[k] = nwtTemplate[v.posStart .. v.posEnd]
132 |
133 | for baseBlock in baseTemplateBlocks.values:
134 |
135 | if templateBlocks.contains(baseBlock.name):
136 | var startp = templateBlocks[baseBlock.name].posStart
137 | var endp = templateBlocks[baseBlock.name].posEnd
138 | var blockTokens = nwtTemplate[startp .. endp]
139 |
140 | ctx.nwtTemplates[baseBlock.name] = blockTokens
141 |
142 | ## The main block replacement
143 | # we only do anything if we have that block in the extending template
144 | var inspos = baseTemplateBlocks[baseBlock.name].posStart
145 | result.delete(baseTemplateBlocks[baseBlock.name].posStart, baseTemplateBlocks[baseBlock.name].posEnd)
146 | result.insert(blockTokens , inspos)
147 |
148 | proc evalTemplate(nwt: Nwt, templateName: TemplateIdent, ctx: Context): NwtTemplate =
149 | result = @[]
150 | var baseTemplateTokens = newNwtTemplate()
151 | var importTemplateTokens = newNwtTemplate()
152 | var tokens = newNwtTemplate()
153 | var alreadyExtendet = false
154 |
155 | for idx, each in nwt.templates[templateName]:
156 | if each.tokenType == NwtEval and each.value.startswith("extends"):
157 | if alreadyExtendet:
158 | continue
159 | alreadyExtendet = true
160 |
161 | ## ONLY ONE BASE TEMPLATE IS SUPPORTED!! so only ONE {%extends%} __PER FILE__!
162 | baseTemplateTokens = evalTemplate(nwt, extractTemplateName(each.value), ctx)
163 | continue
164 |
165 | elif each.tokenType == NwtEval and each.value.startswith("set"):
166 | let setCmd = newChatCommand(each.value)
167 | ctx.variables[setCmd.params[0]] = %* setCmd.params[1]
168 | # echo "params[$1] = $2" % [setCmd.params[0], setCmd.params[1]]
169 |
170 | elif each.tokenType == NwtEval and each.value.startswith("if"):
171 | discard
172 |
173 | elif each.tokenType == NwtEval and each.value.startswith("for"):
174 | # for elem in
175 | discard
176 |
177 | elif each.tokenType == NwtEval and each.value.startswith("import"):
178 | let cmd = newChatCommand(each.value)
179 | let importTemplateName = cmd.params[0]
180 | if importTemplateName == templateName:
181 | raise newException(ValueError, "template $1 could not import itself" % templateName)
182 | for t in nwt.evalTemplate(importTemplateName, ctx):
183 | importTemplateTokens.add t
184 | continue
185 | else: # starwith checks passed
186 | tokens.add each
187 |
188 | if importTemplateTokens.len > 0:
189 | tokens = nwt.fillBlocks(tokens, importTemplateTokens, ctx)
190 |
191 | if baseTemplateTokens.len == 0:
192 | return tokens
193 | else:
194 | return nwt.fillBlocks(baseTemplateTokens, tokens, ctx)
195 |
196 | template decorateVariable(a: untyped): untyped =
197 | "{{" & a & "}}"
198 |
199 | proc toStr*(nwt: Nwt, token: Token, ctx: Context, autoEscape: Option[bool]): string =
200 | ## transforms the token to its string representation
201 | # TODO should this be `$`?
202 | var bufval = ""
203 |
204 | case token.tokenType
205 | of NwtString:
206 | return token.value
207 | of NwtComment:
208 | return ""
209 | of NwtVariable:
210 | if token.value == "debug":
211 | let dbg = """
212 |