UNPKG

4.09 kBJavaScriptView Raw
1var checkFilter = require('json-filter')
2var getLocals = require('./get_locals')
3
4module.exports = function render(parts, context){
5 var result = ''
6 for (var i=0;i<parts.length;i++){
7 var part = parts[i]
8
9 if (typeof part == 'string'){ // default
10 result += part
11
12 } else if (part.r){ // repeater
13
14 var collection = context.get(part.r)
15 var collectionContext = copy(context)
16 collectionContext.source = collection
17 collectionContext.query = part.r
18 collectionContext.parentContext = context
19
20 if (Array.isArray(collection)){
21 for (var x=0;x<collection.length;x++){
22 var newContext = copy(context)
23
24 newContext.collection = collection
25 newContext.source = collection[x]
26 newContext.parent = context.source
27 newContext.query = '[' + x + ']'
28 newContext.parentContext = collectionContext
29
30 if (part.as){
31 newContext.override = copy(newContext.override)
32 newContext.override[part.as] = newContext.source
33 }
34
35 if (part.f){ // handle filters (if, unless, when)
36 if (!queryFilter(part.f, newContext)){
37 continue;
38 }
39 }
40
41 if (part.v){
42 result += render([{c: part.c, v: part.v}], newContext)
43 } else {
44 result += render(part.c, newContext)
45 }
46
47 }
48 }
49
50 } else {
51
52 if (part.as){
53 context = copy(context)
54 context.override = copy(context.override)
55 context.override[part.as] = context.source
56 }
57
58 if (part.f){ // handle filters (if, unless, when)
59 if (!queryFilter(part.f, context)){
60 continue;
61 }
62 }
63
64 // inner content
65 var content = ''
66 if (part.c){
67 content = render(part.c, context)
68 } else if (part.vc){
69 content = context.content
70 } else if (part.q){
71 var value = context.get(part.q)
72 content = format(value, part.e)
73 }
74
75
76 if (part.v){ // view
77 var newContext = copy(context)
78 newContext.content = content
79
80 if (part.q){
81 newContext.parentContext = context
82 newContext.source = context.get(part.q)
83 newContext.query = part.q
84 newContext.parent = context.source
85 }
86
87 var view = context.views[part.v]
88
89 if (view){
90 if (typeof view == 'function'){
91 result += view(newContext)
92 } else if (view.require){
93 result += require(view.require)(newContext)
94 } else {
95 newContext.views = substituteSelf(view.views)
96 newContext.locals = getLocals(view)
97 result += render(view.c, newContext)
98 }
99 }
100
101 } else {
102 result += content || ''
103 }
104 }
105 }
106 return result
107}
108
109function substituteSelf(views, self) {
110 // deal with circular stringify
111 if (views) {
112 var result = {}
113 for (var k in views) {
114 result[k] = views[k] === '$self' ?
115 self : views[k]
116 }
117 return result
118 }
119}
120
121function format(value, type){
122 if (typeof value == 'string' || typeof value == 'number' || typeof value == 'boolean'){
123 return escapeHTML(value.toString(), type)
124 } else if (Array.isArray(value)){
125 return escapeHTML(value.join(', '), type)
126 } else {
127 return ''
128 }
129}
130
131function escapeHTML(s, type) {
132 if (type !== false){
133 var result = String(s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
134 if (type === 'attr'){
135 result = result.replace(/"/g, '&quot;')
136 }
137 return result
138 } else {
139 return s
140 }
141}
142
143function queryFilter(filter, context){
144 var result = true
145 if (filter){
146 var object = {}
147
148 var keys = Object.keys(filter)
149 for (var i=0,l=keys.length;i<l;i++){
150 var key = keys[i]
151 object[key] = context.get(key)
152 }
153
154 result = checkFilter(object, filter)
155 }
156
157 return result
158}
159
160function copy(obj){
161 var result = {}
162 if (obj){
163 for (var key in obj){
164 if (key in obj){
165 result[key] = obj[key]
166 }
167 }
168 }
169 return result
170}
\No newline at end of file