1 | var checkFilter = require('json-filter')
|
2 | var getLocals = require('./get_locals')
|
3 |
|
4 | module.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'){
|
10 | result += part
|
11 |
|
12 | } else if (part.r){
|
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){
|
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){
|
59 | if (!queryFilter(part.f, context)){
|
60 | continue;
|
61 | }
|
62 | }
|
63 |
|
64 |
|
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){
|
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 |
|
109 | function substituteSelf(views, self) {
|
110 |
|
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 |
|
121 | function 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 |
|
131 | function escapeHTML(s, type) {
|
132 | if (type !== false){
|
133 | var result = String(s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
134 | if (type === 'attr'){
|
135 | result = result.replace(/"/g, '"')
|
136 | }
|
137 | return result
|
138 | } else {
|
139 | return s
|
140 | }
|
141 | }
|
142 |
|
143 | function 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 |
|
160 | function 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 |