Bug:Fix file validation issue
[vnfsdk/refrepo.git] / vnfmarket / src / main / webapp / vnfmarket / node_modules / handlebars / lib / handlebars / compiler / whitespace-control.js
1 import Visitor from './visitor';
2
3 function WhitespaceControl(options = {}) {
4   this.options = options;
5 }
6 WhitespaceControl.prototype = new Visitor();
7
8 WhitespaceControl.prototype.Program = function(program) {
9   const doStandalone = !this.options.ignoreStandalone;
10
11   let isRoot = !this.isRootSeen;
12   this.isRootSeen = true;
13
14   let body = program.body;
15   for (let i = 0, l = body.length; i < l; i++) {
16     let current = body[i],
17         strip = this.accept(current);
18
19     if (!strip) {
20       continue;
21     }
22
23     let _isPrevWhitespace = isPrevWhitespace(body, i, isRoot),
24         _isNextWhitespace = isNextWhitespace(body, i, isRoot),
25
26         openStandalone = strip.openStandalone && _isPrevWhitespace,
27         closeStandalone = strip.closeStandalone && _isNextWhitespace,
28         inlineStandalone = strip.inlineStandalone && _isPrevWhitespace && _isNextWhitespace;
29
30     if (strip.close) {
31       omitRight(body, i, true);
32     }
33     if (strip.open) {
34       omitLeft(body, i, true);
35     }
36
37     if (doStandalone && inlineStandalone) {
38       omitRight(body, i);
39
40       if (omitLeft(body, i)) {
41         // If we are on a standalone node, save the indent info for partials
42         if (current.type === 'PartialStatement') {
43           // Pull out the whitespace from the final line
44           current.indent = (/([ \t]+$)/).exec(body[i - 1].original)[1];
45         }
46       }
47     }
48     if (doStandalone && openStandalone) {
49       omitRight((current.program || current.inverse).body);
50
51       // Strip out the previous content node if it's whitespace only
52       omitLeft(body, i);
53     }
54     if (doStandalone && closeStandalone) {
55       // Always strip the next node
56       omitRight(body, i);
57
58       omitLeft((current.inverse || current.program).body);
59     }
60   }
61
62   return program;
63 };
64
65 WhitespaceControl.prototype.BlockStatement =
66 WhitespaceControl.prototype.DecoratorBlock =
67 WhitespaceControl.prototype.PartialBlockStatement = function(block) {
68   this.accept(block.program);
69   this.accept(block.inverse);
70
71   // Find the inverse program that is involed with whitespace stripping.
72   let program = block.program || block.inverse,
73       inverse = block.program && block.inverse,
74       firstInverse = inverse,
75       lastInverse = inverse;
76
77   if (inverse && inverse.chained) {
78     firstInverse = inverse.body[0].program;
79
80     // Walk the inverse chain to find the last inverse that is actually in the chain.
81     while (lastInverse.chained) {
82       lastInverse = lastInverse.body[lastInverse.body.length - 1].program;
83     }
84   }
85
86   let strip = {
87     open: block.openStrip.open,
88     close: block.closeStrip.close,
89
90     // Determine the standalone candiacy. Basically flag our content as being possibly standalone
91     // so our parent can determine if we actually are standalone
92     openStandalone: isNextWhitespace(program.body),
93     closeStandalone: isPrevWhitespace((firstInverse || program).body)
94   };
95
96   if (block.openStrip.close) {
97     omitRight(program.body, null, true);
98   }
99
100   if (inverse) {
101     let inverseStrip = block.inverseStrip;
102
103     if (inverseStrip.open) {
104       omitLeft(program.body, null, true);
105     }
106
107     if (inverseStrip.close) {
108       omitRight(firstInverse.body, null, true);
109     }
110     if (block.closeStrip.open) {
111       omitLeft(lastInverse.body, null, true);
112     }
113
114     // Find standalone else statments
115     if (!this.options.ignoreStandalone
116         && isPrevWhitespace(program.body)
117         && isNextWhitespace(firstInverse.body)) {
118       omitLeft(program.body);
119       omitRight(firstInverse.body);
120     }
121   } else if (block.closeStrip.open) {
122     omitLeft(program.body, null, true);
123   }
124
125   return strip;
126 };
127
128 WhitespaceControl.prototype.Decorator =
129 WhitespaceControl.prototype.MustacheStatement = function(mustache) {
130   return mustache.strip;
131 };
132
133 WhitespaceControl.prototype.PartialStatement =
134     WhitespaceControl.prototype.CommentStatement = function(node) {
135   /* istanbul ignore next */
136   let strip = node.strip || {};
137   return {
138     inlineStandalone: true,
139     open: strip.open,
140     close: strip.close
141   };
142 };
143
144
145 function isPrevWhitespace(body, i, isRoot) {
146   if (i === undefined) {
147     i = body.length;
148   }
149
150   // Nodes that end with newlines are considered whitespace (but are special
151   // cased for strip operations)
152   let prev = body[i - 1],
153       sibling = body[i - 2];
154   if (!prev) {
155     return isRoot;
156   }
157
158   if (prev.type === 'ContentStatement') {
159     return (sibling || !isRoot ? (/\r?\n\s*?$/) : (/(^|\r?\n)\s*?$/)).test(prev.original);
160   }
161 }
162 function isNextWhitespace(body, i, isRoot) {
163   if (i === undefined) {
164     i = -1;
165   }
166
167   let next = body[i + 1],
168       sibling = body[i + 2];
169   if (!next) {
170     return isRoot;
171   }
172
173   if (next.type === 'ContentStatement') {
174     return (sibling || !isRoot ? (/^\s*?\r?\n/) : (/^\s*?(\r?\n|$)/)).test(next.original);
175   }
176 }
177
178 // Marks the node to the right of the position as omitted.
179 // I.e. {{foo}}' ' will mark the ' ' node as omitted.
180 //
181 // If i is undefined, then the first child will be marked as such.
182 //
183 // If mulitple is truthy then all whitespace will be stripped out until non-whitespace
184 // content is met.
185 function omitRight(body, i, multiple) {
186   let current = body[i == null ? 0 : i + 1];
187   if (!current || current.type !== 'ContentStatement' || (!multiple && current.rightStripped)) {
188     return;
189   }
190
191   let original = current.value;
192   current.value = current.value.replace(multiple ? (/^\s+/) : (/^[ \t]*\r?\n?/), '');
193   current.rightStripped = current.value !== original;
194 }
195
196 // Marks the node to the left of the position as omitted.
197 // I.e. ' '{{foo}} will mark the ' ' node as omitted.
198 //
199 // If i is undefined then the last child will be marked as such.
200 //
201 // If mulitple is truthy then all whitespace will be stripped out until non-whitespace
202 // content is met.
203 function omitLeft(body, i, multiple) {
204   let current = body[i == null ? body.length - 1 : i - 1];
205   if (!current || current.type !== 'ContentStatement' || (!multiple && current.leftStripped)) {
206     return;
207   }
208
209   // We omit the last node if it's whitespace only and not preceeded by a non-content node.
210   let original = current.value;
211   current.value = current.value.replace(multiple ? (/\s+$/) : (/[ \t]+$/), '');
212   current.leftStripped = current.value !== original;
213   return current.leftStripped;
214 }
215
216 export default WhitespaceControl;