Commit 420ea6ab22154b7e1bb293b248599106ece52615

Authored by Renato De Donato
1 parent 82f84018

workcicle...

Showing 39 changed files with 68 additions and 53186 deletions
alasql-utility/alasql-utility.js
1   -function alasql_selectData (data, fields, filters) {
2   - if(fields.length == 0)
3   - return [];
4   -
5   - var _fields = _addParenthesis(fields);
6   -
7   - var select = _alasql_SELECT(_fields);
8   -
9   - var where = "";
10   - if(filters && filters.length) {
11   - var _filters = _copy(filters);
12   - where = _alasql_WHERE(_filters);
13   - }
14   -
15   - var query = select + " FROM ?" + where;
16   -
17   - return alasql(query, [data]);
18   -}
19   -
20   -function alasql_complexSelectData (data, fields, filters, aggregators, orders) {
  1 +function alasql_QUERY (data, fields, filters, aggregators, orders) {
21 2 if(fields.length == 0)
22 3 return [];
23 4  
... ... @@ -134,17 +115,13 @@ function _addParenthesis (fields) {
134 115 }
135 116  
136 117 function _normalizeField (field) {
137   - /*DEPRECATED*/return "[" + field.substring(field.lastIndexOf(",") + 1, field.length) + "]";
138   - //return "[" + field + "]";
  118 + return "[" + field + "]";
139 119 }
140 120  
141   -function transformData (data, fields, truncate) {
  121 +function alasql_transformData (data, fields, truncate) {
142 122 if(!data || data.length == 0)
143 123 return [];
144 124  
145   - /*DEPRECATED*/for (var i=0; i < fields.length; i++)
146   - fields[i] = fields[i].substring(fields[i].lastIndexOf(",") + 1, fields[i].length);
147   -
148 125 var tData = [];
149 126  
150 127 for (var i in fields){
... ...
bower_components/l20n/.bower.json deleted
1   -{
2   - "name": "l20n",
3   - "description": "A natural-language localization framework",
4   - "version": "3.4.1",
5   - "homepage": "http://l20n.org",
6   - "repository": {
7   - "type": "git",
8   - "url": "git://github.com/l20n/l20n.js.git"
9   - },
10   - "authors": [
11   - "Mozilla <l10n-drivers@mozilla.org>",
12   - "Zbigniew Braniecki",
13   - "Staś Małolepszy"
14   - ],
15   - "license": "Apache 2.0",
16   - "keywords": [
17   - "localization",
18   - "l10n",
19   - "l20n"
20   - ],
21   - "main": [],
22   - "ignore": [
23   - "**/*",
24   - "!dist/**/*"
25   - ],
26   - "_release": "3.4.1",
27   - "_resolution": {
28   - "type": "version",
29   - "tag": "v3.4.1",
30   - "commit": "4b5428be54003e8dc7243665a5f844a546ddd226"
31   - },
32   - "_source": "git://github.com/l20n/l20n.js.git",
33   - "_target": "v3.x",
34   - "_originalSource": "l20n",
35   - "_direct": true
36   -}
37 0 \ No newline at end of file
bower_components/l20n/bower.json deleted
1   -{
2   - "name": "l20n",
3   - "description": "A natural-language localization framework",
4   - "version": "3.4.1",
5   - "homepage": "http://l20n.org",
6   - "repository": {
7   - "type": "git",
8   - "url": "git://github.com/l20n/l20n.js.git"
9   - },
10   - "authors": [
11   - "Mozilla <l10n-drivers@mozilla.org>",
12   - "Zbigniew Braniecki",
13   - "Staś Małolepszy"
14   - ],
15   - "license": "Apache 2.0",
16   - "keywords": [
17   - "localization",
18   - "l10n",
19   - "l20n"
20   - ],
21   - "main": [],
22   - "ignore": [
23   - "**/*",
24   - "!dist/**/*"
25   - ]
26   -}
bower_components/l20n/dist/bundle/aisle/l20n.js deleted
1   -define(['exports'], function (exports) { 'use strict';
2   -
3   - class Node {
4   - constructor() {
5   - this.type = this.constructor.name;
6   - }
7   - }
8   -
9   - class Entry extends Node {
10   - constructor() {
11   - super();
12   - }
13   - }
14   -
15   - class Identifier extends Node {
16   - constructor(name) {
17   - super();
18   - this.name = name;
19   - }
20   - }
21   -
22   - class Variable extends Node {
23   - constructor(name) {
24   - super();
25   - this.name = name;
26   - }
27   - }
28   -
29   - class Global extends Node {
30   - constructor(name) {
31   - super();
32   - this.name = name;
33   - }
34   - }
35   -
36   - class Value extends Node {
37   - constructor() {
38   - super();
39   - }
40   - }
41   -
42   - class String extends Value {
43   - constructor(source, content) {
44   - super();
45   - this.source = source;
46   - this.content = content;
47   -
48   - this._opchar = '"';
49   - }
50   - }
51   -
52   - class Hash extends Value {
53   - constructor(items) {
54   - super();
55   - this.items = items;
56   - }
57   - }
58   -
59   -
60   - class Entity extends Entry {
61   - constructor(id, value = null, index = null, attrs = []) {
62   - super();
63   - this.id = id;
64   - this.value = value;
65   - this.index = index;
66   - this.attrs = attrs;
67   - }
68   - }
69   -
70   - class Resource extends Node {
71   - constructor() {
72   - super();
73   - this.body = [];
74   - }
75   - }
76   -
77   - class Attribute extends Node {
78   - constructor(id, value, index = null) {
79   - super();
80   - this.id = id;
81   - this.value = value;
82   - this.index = index;
83   - }
84   - }
85   -
86   - class HashItem extends Node {
87   - constructor(id, value, defItem) {
88   - super();
89   - this.id = id;
90   - this.value = value;
91   - this.default = defItem;
92   - }
93   - }
94   -
95   - class Comment extends Entry {
96   - constructor(body) {
97   - super();
98   - this.body = body;
99   - }
100   - }
101   -
102   - class Expression extends Node {
103   - constructor() {
104   - super();
105   - }
106   - }
107   -
108   - class PropertyExpression extends Expression {
109   - constructor(idref, exp, computed = false) {
110   - super();
111   - this.idref = idref;
112   - this.exp = exp;
113   - this.computed = computed;
114   - }
115   - }
116   -
117   - class CallExpression extends Expression {
118   - constructor(callee, args) {
119   - super();
120   - this.callee = callee;
121   - this.args = args;
122   - }
123   - }
124   -
125   - class JunkEntry extends Entry {
126   - constructor(content) {
127   - super();
128   - this.content = content;
129   - }
130   - }
131   -
132   - var AST = {
133   - Node,
134   - Identifier,
135   - Value,
136   - String,
137   - Hash,
138   - Entity,
139   - Resource,
140   - Attribute,
141   - HashItem,
142   - Comment,
143   - Variable,
144   - Global,
145   - Expression,
146   - PropertyExpression,
147   - CallExpression,
148   - JunkEntry,
149   - };
150   -
151   - function L10nError(message, id, lang) {
152   - this.name = 'L10nError';
153   - this.message = message;
154   - this.id = id;
155   - this.lang = lang;
156   - }
157   - L10nError.prototype = Object.create(Error.prototype);
158   - L10nError.prototype.constructor = L10nError;
159   -
160   - const MAX_PLACEABLES = 100;
161   -
162   -
163   - class ParseContext {
164   - constructor(string, pos) {
165   - this._config = {
166   - pos: pos
167   - };
168   - this._source = string;
169   - this._index = 0;
170   - this._length = string.length;
171   - this._curEntryStart = 0;
172   - }
173   -
174   - setPosition(node, start, end) {
175   - if (!this._config.pos) {
176   - return;
177   - }
178   - node._pos = {start, end};
179   - }
180   -
181   - getResource() {
182   - let resource = new AST.Resource();
183   - this.setPosition(resource, 0, this._length);
184   - resource._errors = [];
185   -
186   - this.getWS();
187   - while (this._index < this._length) {
188   - try {
189   - resource.body.push(this.getEntry());
190   - } catch (e) {
191   - if (e instanceof L10nError) {
192   - resource._errors.push(e);
193   - resource.body.push(this.getJunkEntry());
194   - } else {
195   - throw e;
196   - }
197   - }
198   - if (this._index < this._length) {
199   - this.getWS();
200   - }
201   - }
202   -
203   - return resource;
204   - }
205   -
206   - getEntry() {
207   - this._curEntryStart = this._index;
208   -
209   - if (this._source[this._index] === '<') {
210   - ++this._index;
211   - const id = this.getIdentifier();
212   - if (this._source[this._index] === '[') {
213   - ++this._index;
214   - return this.getEntity(id, this.getItemList(this.getExpression, ']'));
215   - }
216   - return this.getEntity(id);
217   - }
218   -
219   - if (this._source.startsWith('/*', this._index)) {
220   - return this.getComment();
221   - }
222   -
223   - throw this.error('Invalid entry');
224   - }
225   -
226   - getEntity(id, index) {
227   - if (!this.getRequiredWS()) {
228   - throw this.error('Expected white space');
229   - }
230   -
231   - const ch = this._source.charAt(this._index);
232   - const value = this.getValue(ch, index === undefined);
233   - let attrs;
234   -
235   - if (value === null) {
236   - if (ch === '>') {
237   - throw this.error('Expected ">"');
238   - }
239   - attrs = this.getAttributes();
240   - } else {
241   - const ws1 = this.getRequiredWS();
242   - if (this._source[this._index] !== '>') {
243   - if (!ws1) {
244   - throw this.error('Expected ">"');
245   - }
246   - attrs = this.getAttributes();
247   - }
248   - }
249   -
250   - // skip '>'
251   - ++this._index;
252   -
253   - const entity = new AST.Entity(id, value, index, attrs);
254   - this.setPosition(entity, this._curEntryStart, this._index);
255   - return entity;
256   - }
257   -
258   - getValue(ch = this._source[this._index], optional = false) {
259   - switch (ch) {
260   - case '\'':
261   - case '"':
262   - return this.getString(ch, 1);
263   - case '{':
264   - return this.getHash();
265   - }
266   -
267   - if (!optional) {
268   - throw this.error('Unknown value type');
269   - }
270   - return null;
271   - }
272   -
273   - getWS() {
274   - let cc = this._source.charCodeAt(this._index);
275   - // space, \n, \t, \r
276   - while (cc === 32 || cc === 10 || cc === 9 || cc === 13) {
277   - cc = this._source.charCodeAt(++this._index);
278   - }
279   - }
280   -
281   - getRequiredWS() {
282   - const pos = this._index;
283   - let cc = this._source.charCodeAt(pos);
284   - // space, \n, \t, \r
285   - while (cc === 32 || cc === 10 || cc === 9 || cc === 13) {
286   - cc = this._source.charCodeAt(++this._index);
287   - }
288   - return this._index !== pos;
289   - }
290   -
291   - getIdentifier() {
292   - const start = this._index;
293   - let cc = this._source.charCodeAt(this._index);
294   -
295   - if ((cc >= 97 && cc <= 122) || // a-z
296   - (cc >= 65 && cc <= 90) || // A-Z
297   - cc === 95) { // _
298   - cc = this._source.charCodeAt(++this._index);
299   - } else {
300   - throw this.error('Identifier has to start with [a-zA-Z_]');
301   - }
302   -
303   - while ((cc >= 97 && cc <= 122) || // a-z
304   - (cc >= 65 && cc <= 90) || // A-Z
305   - (cc >= 48 && cc <= 57) || // 0-9
306   - cc === 95) { // _
307   - cc = this._source.charCodeAt(++this._index);
308   - }
309   -
310   - const id = new AST.Identifier(this._source.slice(start, this._index));
311   - this.setPosition(id, start, this._index);
312   - return id;
313   - }
314   -
315   - getUnicodeChar() {
316   - for (let i = 0; i < 4; i++) {
317   - let cc = this._source.charCodeAt(++this._index);
318   - if ((cc > 96 && cc < 103) || // a-f
319   - (cc > 64 && cc < 71) || // A-F
320   - (cc > 47 && cc < 58)) { // 0-9
321   - continue;
322   - }
323   - throw this.error('Illegal unicode escape sequence');
324   - }
325   - return '\\u' + this._source.slice(this._index - 3, this._index + 1);
326   - }
327   -
328   - getString(opchar, opcharLen) {
329   - let body = [];
330   - let buf = '';
331   - let placeables = 0;
332   -
333   - this._index += opcharLen - 1;
334   -
335   - const start = this._index + 1;
336   -
337   - let closed = false;
338   -
339   - while (!closed) {
340   - let ch = this._source[++this._index];
341   -
342   - switch (ch) {
343   - case '\\':
344   - const ch2 = this._source[++this._index];
345   - if (ch2 === 'u') {
346   - buf += this.getUnicodeChar();
347   - } else if (ch2 === opchar || ch2 === '\\') {
348   - buf += ch2;
349   - } else if (ch2 === '{' && this._source[this._index + 1] === '{') {
350   - buf += '{';
351   - } else {
352   - throw this.error('Illegal escape sequence');
353   - }
354   - break;
355   - case '{':
356   - if (this._source[this._index + 1] === '{') {
357   - if (placeables > MAX_PLACEABLES - 1) {
358   - throw this.error('Too many placeables, maximum allowed is ' +
359   - MAX_PLACEABLES);
360   - }
361   - if (buf.length) {
362   - body.push(buf);
363   - buf = '';
364   - }
365   - this._index += 2;
366   - this.getWS();
367   - body.push(this.getExpression());
368   - this.getWS();
369   - if (!this._source.startsWith('}}', this._index)) {
370   - throw this.error('Expected "}}"');
371   - }
372   - this._index += 1;
373   - placeables++;
374   - break;
375   - }
376   - /* falls through */
377   - default:
378   - if (ch === opchar) {
379   - this._index++;
380   - closed = true;
381   - break;
382   - }
383   -
384   - buf += ch;
385   - if (this._index + 1 >= this._length) {
386   - throw this.error('Unclosed string literal');
387   - }
388   - }
389   - }
390   -
391   - if (buf.length) {
392   - body.push(buf);
393   - }
394   -
395   - const string = new AST.String(
396   - this._source.slice(start, this._index - 1), body);
397   - this.setPosition(string, start, this._index);
398   - string._opchar = opchar;
399   -
400   - return string;
401   - }
402   -
403   - getAttributes() {
404   - const attrs = [];
405   -
406   - while (true) {
407   - const attr = this.getAttribute();
408   - attrs.push(attr);
409   - const ws1 = this.getRequiredWS();
410   - const ch = this._source.charAt(this._index);
411   - if (ch === '>') {
412   - break;
413   - } else if (!ws1) {
414   - throw this.error('Expected ">"');
415   - }
416   - }
417   - return attrs;
418   - }
419   -
420   - getAttribute() {
421   - const start = this._index;
422   - const key = this.getIdentifier();
423   - let index;
424   -
425   - if (this._source[this._index]=== '[') {
426   - ++this._index;
427   - this.getWS();
428   - index = this.getItemList(this.getExpression, ']');
429   - }
430   - this.getWS();
431   - if (this._source[this._index] !== ':') {
432   - throw this.error('Expected ":"');
433   - }
434   - ++this._index;
435   - this.getWS();
436   - const attr = new AST.Attribute(key, this.getValue(), index);
437   - this.setPosition(attr, start, this._index);
438   - return attr;
439   - }
440   -
441   - getHash() {
442   - const start = this._index;
443   - let items = [];
444   -
445   - ++this._index;
446   - this.getWS();
447   -
448   - while (true) {
449   - items.push(this.getHashItem());
450   - this.getWS();
451   -
452   - const comma = this._source[this._index] === ',';
453   - if (comma) {
454   - ++this._index;
455   - this.getWS();
456   - }
457   - if (this._source[this._index] === '}') {
458   - ++this._index;
459   - break;
460   - }
461   - if (!comma) {
462   - throw this.error('Expected "}"');
463   - }
464   - }
465   -
466   - const hash = new AST.Hash(items);
467   - this.setPosition(hash, start, this._index);
468   - return hash;
469   - }
470   -
471   - getHashItem() {
472   - const start = this._index;
473   -
474   - let defItem = false;
475   - if (this._source[this._index] === '*') {
476   - ++this._index;
477   - defItem = true;
478   - }
479   -
480   - const key = this.getIdentifier();
481   - this.getWS();
482   - if (this._source[this._index] !== ':') {
483   - throw this.error('Expected ":"');
484   - }
485   - ++this._index;
486   - this.getWS();
487   -
488   - const hashItem = new AST.HashItem(key, this.getValue(), defItem);
489   - this.setPosition(hashItem, start, this._index);
490   - return hashItem;
491   - }
492   -
493   - getComment() {
494   - this._index += 2;
495   - const start = this._index;
496   - const end = this._source.indexOf('*/', start);
497   -
498   - if (end === -1) {
499   - throw this.error('Comment without a closing tag');
500   - }
501   -
502   - this._index = end + 2;
503   - const comment = new AST.Comment(this._source.slice(start, end));
504   - this.setPosition(comment, start - 2, this._index);
505   - return comment;
506   - }
507   -
508   - getExpression() {
509   - const start = this._index;
510   - let exp = this.getPrimaryExpression();
511   -
512   - while (true) {
513   - let ch = this._source[this._index];
514   - if (ch === '.' || ch === '[') {
515   - ++this._index;
516   - exp = this.getPropertyExpression(exp, ch === '[', start);
517   - } else if (ch === '(') {
518   - ++this._index;
519   - exp = this.getCallExpression(exp, start);
520   - } else {
521   - break;
522   - }
523   - }
524   -
525   - return exp;
526   - }
527   -
528   - getPropertyExpression(idref, computed, start) {
529   - let exp;
530   -
531   - if (computed) {
532   - this.getWS();
533   - exp = this.getExpression();
534   - this.getWS();
535   - if (this._source[this._index] !== ']') {
536   - throw this.error('Expected "]"');
537   - }
538   - ++this._index;
539   - } else {
540   - exp = this.getIdentifier();
541   - }
542   -
543   - const propExpr = new AST.PropertyExpression(idref, exp, computed);
544   - this.setPosition(propExpr, start, this._index);
545   - return propExpr;
546   - }
547   -
548   - getCallExpression(callee, start) {
549   - this.getWS();
550   -
551   - const callExpr = new AST.CallExpression(callee,
552   - this.getItemList(this.getExpression, ')'));
553   - this.setPosition(callExpr, start, this._index);
554   - return callExpr;
555   - }
556   -
557   - getPrimaryExpression() {
558   - const start = this._index;
559   - const ch = this._source[this._index];
560   -
561   - switch (ch) {
562   - case '$':
563   - ++this._index;
564   - const variable = new AST.Variable(this.getIdentifier());
565   - this.setPosition(variable, start, this._index);
566   - return variable;
567   - case '@':
568   - ++this._index;
569   - const global = new AST.Global(this.getIdentifier());
570   - this.setPosition(global, start, this._index);
571   - return global;
572   - default:
573   - return this.getIdentifier();
574   - }
575   - }
576   -
577   - getItemList(callback, closeChar) {
578   - let items = [];
579   - let closed = false;
580   -
581   - this.getWS();
582   -
583   - if (this._source[this._index] === closeChar) {
584   - ++this._index;
585   - closed = true;
586   - }
587   -
588   - while (!closed) {
589   - items.push(callback.call(this));
590   - this.getWS();
591   - let ch = this._source.charAt(this._index);
592   - switch (ch) {
593   - case ',':
594   - ++this._index;
595   - this.getWS();
596   - break;
597   - case closeChar:
598   - ++this._index;
599   - closed = true;
600   - break;
601   - default:
602   - throw this.error('Expected "," or "' + closeChar + '"');
603   - }
604   - }
605   -
606   - return items;
607   - }
608   -
609   - error(message) {
610   - const pos = this._index;
611   -
612   - let start = this._source.lastIndexOf('<', pos - 1);
613   - let lastClose = this._source.lastIndexOf('>', pos - 1);
614   - start = lastClose > start ? lastClose + 1 : start;
615   - let context = this._source.slice(start, pos + 10);
616   -
617   - let msg = message + ' at pos ' + pos + ': `' + context + '`';
618   -
619   - const err = new L10nError(msg);
620   - err._pos = {start: pos, end: undefined};
621   - err.offset = pos - start;
622   - err.description = message;
623   - err.context = context;
624   - return err;
625   - }
626   -
627   - getJunkEntry() {
628   - const pos = this._index;
629   - let nextEntity = this._source.indexOf('<', pos);
630   - let nextComment = this._source.indexOf('/*', pos);
631   -
632   - if (nextEntity === -1) {
633   - nextEntity = this._length;
634   - }
635   - if (nextComment === -1) {
636   - nextComment = this._length;
637   - }
638   -
639   - let nextEntry = Math.min(nextEntity, nextComment);
640   -
641   - this._index = nextEntry;
642   -
643   - const junk = new AST.JunkEntry(
644   - this._source.slice(this._curEntryStart, nextEntry));
645   -
646   - this.setPosition(junk, this._curEntryStart, nextEntry);
647   - return junk;
648   - }
649   - }
650   -
651   - var parser = {
652   - parseResource: function(string, pos = false) {
653   - const parseContext = new ParseContext(string, pos);
654   - return parseContext.getResource();
655   - },
656   - };
657   -
658   - exports.L20nParser = parser;
659   -
660   -});
661 0 \ No newline at end of file
bower_components/l20n/dist/bundle/bridge/l20n-client.js deleted
1   -(function () { 'use strict';
2   -
3   - /* global bridge, BroadcastChannel */
4   -
5   - const Client = bridge.client;
6   - const channel = new BroadcastChannel('l20n-channel');
7   -
8   - // match the opening angle bracket (<) in HTML tags, and HTML entities like
9   - // &amp;, &#0038;, &#x0026;.
10   - const reOverlay = /<|&#?\w+;/;
11   -
12   - const allowed = {
13   - elements: [
14   - 'a', 'em', 'strong', 'small', 's', 'cite', 'q', 'dfn', 'abbr', 'data',
15   - 'time', 'code', 'var', 'samp', 'kbd', 'sub', 'sup', 'i', 'b', 'u',
16   - 'mark', 'ruby', 'rt', 'rp', 'bdi', 'bdo', 'span', 'br', 'wbr'
17   - ],
18   - attributes: {
19   - global: [ 'title', 'aria-label', 'aria-valuetext', 'aria-moz-hint' ],
20   - a: [ 'download' ],
21   - area: [ 'download', 'alt' ],
22   - // value is special-cased in isAttrAllowed
23   - input: [ 'alt', 'placeholder' ],
24   - menuitem: [ 'label' ],
25   - menu: [ 'label' ],
26   - optgroup: [ 'label' ],
27   - option: [ 'label' ],
28   - track: [ 'label' ],
29   - img: [ 'alt' ],
30   - textarea: [ 'placeholder' ],
31   - th: [ 'abbr']
32   - }
33   - };
34   -
35   - function overlayElement(element, translation) {
36   - const value = translation.value;
37   -
38   - if (typeof value === 'string') {
39   - if (!reOverlay.test(value)) {
40   - element.textContent = value;
41   - } else {
42   - // start with an inert template element and move its children into
43   - // `element` but such that `element`'s own children are not replaced
44   - const tmpl = element.ownerDocument.createElement('template');
45   - tmpl.innerHTML = value;
46   - // overlay the node with the DocumentFragment
47   - overlay(element, tmpl.content);
48   - }
49   - }
50   -
51   - for (let key in translation.attrs) {
52   - const attrName = camelCaseToDashed(key);
53   - if (isAttrAllowed({ name: attrName }, element)) {
54   - element.setAttribute(attrName, translation.attrs[key]);
55   - }
56   - }
57   - }
58   -
59   - // The goal of overlay is to move the children of `translationElement`
60   - // into `sourceElement` such that `sourceElement`'s own children are not
61   - // replaced, but onle have their text nodes and their attributes modified.
62   - //
63   - // We want to make it possible for localizers to apply text-level semantics to
64   - // the translations and make use of HTML entities. At the same time, we
65   - // don't trust translations so we need to filter unsafe elements and
66   - // attribtues out and we don't want to break the Web by replacing elements to
67   - // which third-party code might have created references (e.g. two-way
68   - // bindings in MVC frameworks).
69   - function overlay(sourceElement, translationElement) {
70   - const result = translationElement.ownerDocument.createDocumentFragment();
71   - let k, attr;
72   -
73   - // take one node from translationElement at a time and check it against
74   - // the allowed list or try to match it with a corresponding element
75   - // in the source
76   - let childElement;
77   - while ((childElement = translationElement.childNodes[0])) {
78   - translationElement.removeChild(childElement);
79   -
80   - if (childElement.nodeType === childElement.TEXT_NODE) {
81   - result.appendChild(childElement);
82   - continue;
83   - }
84   -
85   - const index = getIndexOfType(childElement);
86   - const sourceChild = getNthElementOfType(sourceElement, childElement, index);
87   - if (sourceChild) {
88   - // there is a corresponding element in the source, let's use it
89   - overlay(sourceChild, childElement);
90   - result.appendChild(sourceChild);
91   - continue;
92   - }
93   -
94   - if (isElementAllowed(childElement)) {
95   - const sanitizedChild = childElement.ownerDocument.createElement(
96   - childElement.nodeName);
97   - overlay(sanitizedChild, childElement);
98   - result.appendChild(sanitizedChild);
99   - continue;
100   - }
101   -
102   - // otherwise just take this child's textContent
103   - result.appendChild(
104   - translationElement.ownerDocument.createTextNode(
105   - childElement.textContent));
106   - }
107   -
108   - // clear `sourceElement` and append `result` which by this time contains
109   - // `sourceElement`'s original children, overlayed with translation
110   - sourceElement.textContent = '';
111   - sourceElement.appendChild(result);
112   -
113   - // if we're overlaying a nested element, translate the allowed
114   - // attributes; top-level attributes are handled in `translateElement`
115   - // XXX attributes previously set here for another language should be
116   - // cleared if a new language doesn't use them; https://bugzil.la/922577
117   - if (translationElement.attributes) {
118   - for (k = 0, attr; (attr = translationElement.attributes[k]); k++) {
119   - if (isAttrAllowed(attr, sourceElement)) {
120   - sourceElement.setAttribute(attr.name, attr.value);
121   - }
122   - }
123   - }
124   - }
125   -
126   - // XXX the allowed list should be amendable; https://bugzil.la/922573
127   - function isElementAllowed(element) {
128   - return allowed.elements.indexOf(element.tagName.toLowerCase()) !== -1;
129   - }
130   -
131   - function isAttrAllowed(attr, element) {
132   - const attrName = attr.name.toLowerCase();
133   - const tagName = element.tagName.toLowerCase();
134   - // is it a globally safe attribute?
135   - if (allowed.attributes.global.indexOf(attrName) !== -1) {
136   - return true;
137   - }
138   - // are there no allowed attributes for this element?
139   - if (!allowed.attributes[tagName]) {
140   - return false;
141   - }
142   - // is it allowed on this element?
143   - // XXX the allowed list should be amendable; https://bugzil.la/922573
144   - if (allowed.attributes[tagName].indexOf(attrName) !== -1) {
145   - return true;
146   - }
147   - // special case for value on inputs with type button, reset, submit
148   - if (tagName === 'input' && attrName === 'value') {
149   - const type = element.type.toLowerCase();
150   - if (type === 'submit' || type === 'button' || type === 'reset') {
151   - return true;
152   - }
153   - }
154   - return false;
155   - }
156   -
157   - // Get n-th immediate child of context that is of the same type as element.
158   - // XXX Use querySelector(':scope > ELEMENT:nth-of-type(index)'), when:
159   - // 1) :scope is widely supported in more browsers and 2) it works with
160   - // DocumentFragments.
161   - function getNthElementOfType(context, element, index) {
162   - /* jshint boss:true */
163   - let nthOfType = 0;
164   - for (let i = 0, child; child = context.children[i]; i++) {
165   - if (child.nodeType === child.ELEMENT_NODE &&
166   - child.tagName === element.tagName) {
167   - if (nthOfType === index) {
168   - return child;
169   - }
170   - nthOfType++;
171   - }
172   - }
173   - return null;
174   - }
175   -
176   - // Get the index of the element among siblings of the same type.
177   - function getIndexOfType(element) {
178   - let index = 0;
179   - let child;
180   - while ((child = element.previousElementSibling)) {
181   - if (child.tagName === element.tagName) {
182   - index++;
183   - }
184   - }
185   - return index;
186   - }
187   -
188   - function camelCaseToDashed(string) {
189   - // XXX workaround for https://bugzil.la/1141934
190   - if (string === 'ariaValueText') {
191   - return 'aria-valuetext';
192   - }
193   -
194   - return string
195   - .replace(/[A-Z]/g, function (match) {
196   - return '-' + match.toLowerCase();
197   - })
198   - .replace(/^-/, '');
199   - }
200   -
201   - const reHtml = /[&<>]/g;
202   - const htmlEntities = {
203   - '&': '&amp;',
204   - '<': '&lt;',
205   - '>': '&gt;',
206   - };
207   -
208   - function getResourceLinks(head) {
209   - return Array.prototype.map.call(
210   - head.querySelectorAll('link[rel="localization"]'),
211   - el => el.getAttribute('href'));
212   - }
213   -
214   - function setAttributes(element, id, args) {
215   - element.setAttribute('data-l10n-id', id);
216   - if (args) {
217   - element.setAttribute('data-l10n-args', JSON.stringify(args));
218   - }
219   - }
220   -
221   - function getAttributes(element) {
222   - return {
223   - id: element.getAttribute('data-l10n-id'),
224   - args: JSON.parse(element.getAttribute('data-l10n-args'))
225   - };
226   - }
227   -
228   - function getTranslatables(element) {
229   - const nodes = Array.from(element.querySelectorAll('[data-l10n-id]'));
230   -
231   - if (typeof element.hasAttribute === 'function' &&
232   - element.hasAttribute('data-l10n-id')) {
233   - nodes.push(element);
234   - }
235   -
236   - return nodes;
237   - }
238   -
239   - function translateMutations(view, langs, mutations) {
240   - const targets = new Set();
241   -
242   - for (let mutation of mutations) {
243   - switch (mutation.type) {
244   - case 'attributes':
245   - targets.add(mutation.target);
246   - break;
247   - case 'childList':
248   - for (let addedNode of mutation.addedNodes) {
249   - if (addedNode.nodeType === addedNode.ELEMENT_NODE) {
250   - if (addedNode.childElementCount) {
251   - getTranslatables(addedNode).forEach(targets.add.bind(targets));
252   - } else {
253   - if (addedNode.hasAttribute('data-l10n-id')) {
254   - targets.add(addedNode);
255   - }
256   - }
257   - }
258   - }
259   - break;
260   - }
261   - }
262   -
263   - if (targets.size === 0) {
264   - return;
265   - }
266   -
267   - translateElements(view, langs, Array.from(targets));
268   - }
269   -
270   - function translateFragment(view, langs, frag) {
271   - return translateElements(view, langs, getTranslatables(frag));
272   - }
273   -
274   - function getElementsTranslation(view, langs, elems) {
275   - const keys = elems.map(elem => {
276   - const id = elem.getAttribute('data-l10n-id');
277   - const args = elem.getAttribute('data-l10n-args');
278   - return args ? [
279   - id,
280   - JSON.parse(args.replace(reHtml, match => htmlEntities[match]))
281   - ] : id;
282   - });
283   -
284   - return view._resolveEntities(langs, keys);
285   - }
286   -
287   - function translateElements(view, langs, elements) {
288   - return getElementsTranslation(view, langs, elements).then(
289   - translations => applyTranslations(view, elements, translations));
290   - }
291   -
292   - function applyTranslations(view, elems, translations) {
293   - view._disconnect();
294   - for (let i = 0; i < elems.length; i++) {
295   - overlayElement(elems[i], translations[i]);
296   - }
297   - view._observe();
298   - }
299   -
300   - // Polyfill NodeList.prototype[Symbol.iterator] for Chrome.
301   - // See https://code.google.com/p/chromium/issues/detail?id=401699
302   - if (typeof NodeList === 'function' && !NodeList.prototype[Symbol.iterator]) {
303   - NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
304   - }
305   -
306   - // A document.ready shim
307   - // https://github.com/whatwg/html/issues/127
308   - function documentReady() {
309   - if (document.readyState !== 'loading') {
310   - return Promise.resolve();
311   - }
312   -
313   - return new Promise(resolve => {
314   - document.addEventListener('readystatechange', function onrsc() {
315   - document.removeEventListener('readystatechange', onrsc);
316   - resolve();
317   - });
318   - });
319   - }
320   -
321   - // Intl.Locale
322   - function getDirection(code) {
323   - const tag = code.split('-')[0];
324   - return ['ar', 'he', 'fa', 'ps', 'ur'].indexOf(tag) >= 0 ?
325   - 'rtl' : 'ltr';
326   - }
327   -
328   - const observerConfig = {
329   - attributes: true,
330   - characterData: false,
331   - childList: true,
332   - subtree: true,
333   - attributeFilter: ['data-l10n-id', 'data-l10n-args']
334   - };
335   -
336   - const readiness = new WeakMap();
337   -
338   - class View {
339   - constructor(client, doc) {
340   - this._doc = doc;
341   - this.pseudo = {
342   - 'fr-x-psaccent': createPseudo(this, 'fr-x-psaccent'),
343   - 'ar-x-psbidi': createPseudo(this, 'ar-x-psbidi')
344   - };
345   -
346   - this._interactive = documentReady().then(
347   - () => init(this, client));
348   -
349   - const observer = new MutationObserver(onMutations.bind(this));
350   - this._observe = () => observer.observe(doc, observerConfig);
351   - this._disconnect = () => observer.disconnect();
352   -
353   - const translateView = langs => translateDocument(this, langs);
354   - client.on('translateDocument', translateView);
355   - this.ready = this._interactive.then(
356   - client => client.method('resolvedLanguages')).then(
357   - translateView);
358   - }
359   -
360   - requestLanguages(langs, global) {
361   - return this._interactive.then(
362   - client => client.method('requestLanguages', langs, global));
363   - }
364   -
365   - _resolveEntities(langs, keys) {
366   - return this._interactive.then(
367   - client => client.method('resolveEntities', client.id, langs, keys));
368   - }
369   -
370   - formatValue(id, args) {
371   - return this._interactive.then(
372   - client => client.method('formatValues', client.id, [[id, args]])).then(
373   - values => values[0]);
374   - }
375   -
376   - formatValues(...keys) {
377   - return this._interactive.then(
378   - client => client.method('formatValues', client.id, keys));
379   - }
380   -
381   - translateFragment(frag) {
382   - return this._interactive.then(
383   - client => client.method('resolvedLanguages')).then(
384   - langs => translateFragment(this, langs, frag));
385   - }
386   - }
387   -
388   - View.prototype.setAttributes = setAttributes;
389   - View.prototype.getAttributes = getAttributes;
390   -
391   - function createPseudo(view, code) {
392   - return {
393   - getName: () => view._interactive.then(
394   - client => client.method('getName', code)),
395   - processString: str => view._interactive.then(
396   - client => client.method('processString', code, str)),
397   - };
398   - }
399   -
400   - function init(view, client) {
401   - view._observe();
402   - return client.method(
403   - 'registerView', client.id, getResourceLinks(view._doc.head)).then(
404   - () => client);
405   - }
406   -
407   - function onMutations(mutations) {
408   - return this._interactive.then(
409   - client => client.method('resolvedLanguages')).then(
410   - langs => translateMutations(this, langs, mutations));
411   - }
412   -
413   - function translateDocument(view, langs) {
414   - const html = view._doc.documentElement;
415   -
416   - if (readiness.has(html)) {
417   - return translateFragment(view, langs, html).then(
418   - () => setAllAndEmit(html, langs));
419   - }
420   -
421   - const translated =
422   - // has the document been already pre-translated?
423   - langs[0].code === html.getAttribute('lang') ?
424   - Promise.resolve() :
425   - translateFragment(view, langs, html).then(
426   - () => setLangDir(html, langs));
427   -
428   - return translated.then(() => {
429   - setLangs(html, langs);
430   - readiness.set(html, true);
431   - });
432   - }
433   -
434   - function setLangs(html, langs) {
435   - const codes = langs.map(lang => lang.code);
436   - html.setAttribute('langs', codes.join(' '));
437   - }
438   -
439   - function setLangDir(html, langs) {
440   - const code = langs[0].code;
441   - html.setAttribute('lang', code);
442   - html.setAttribute('dir', getDirection(code));
443   - }
444   -
445   - function setAllAndEmit(html, langs) {
446   - setLangDir(html, langs);
447   - setLangs(html, langs);
448   - html.parentNode.dispatchEvent(new CustomEvent('DOMRetranslated', {
449   - bubbles: false,
450   - cancelable: false,
451   - }));
452   - }
453   -
454   - const client = new Client({
455   - service: 'l20n',
456   - endpoint: channel,
457   - timeout: false
458   - });
459   -
460   - window.addEventListener('pageshow', () => client.connect());
461   - window.addEventListener('pagehide', () => client.disconnect());
462   -
463   - document.l10n = new View(client, document);
464   -
465   - //Bug 1204660 - Temporary proxy for shared code. Will be removed once
466   - // l10n.js migration is completed.
467   - navigator.mozL10n = {
468   - setAttributes: document.l10n.setAttributes,
469   - getAttributes: document.l10n.getAttributes,
470   - formatValue: (...args) => document.l10n.formatValue(...args),
471   - translateFragment: (...args) => document.l10n.translateFragment(...args),
472   - once: cb => document.l10n.ready.then(cb),
473   - ready: cb => document.l10n.ready.then(() => {
474   - document.addEventListener('DOMRetranslated', cb);
475   - cb();
476   - }),
477   - };
478   -
479   -})();
480 0 \ No newline at end of file
bower_components/l20n/dist/bundle/bridge/l20n-service.js deleted
1   -(function () { 'use strict';
2   -
3   - const Service = bridge.service;
4   - const channel = new BroadcastChannel('l20n-channel');
5   -
6   - function broadcast(type, data) {
7   - return this.service.broadcast(type, data);
8   - }
9   -
10   - function L10nError(message, id, lang) {
11   - this.name = 'L10nError';
12   - this.message = message;
13   - this.id = id;
14   - this.lang = lang;
15   - }
16   - L10nError.prototype = Object.create(Error.prototype);
17   - L10nError.prototype.constructor = L10nError;
18   -
19   - function load(type, url) {
20   - return new Promise(function(resolve, reject) {
21   - const xhr = new XMLHttpRequest();
22   -
23   - if (xhr.overrideMimeType) {
24   - xhr.overrideMimeType(type);
25   - }
26   -
27   - xhr.open('GET', url, true);
28   -
29   - if (type === 'application/json') {
30   - xhr.responseType = 'json';
31   - }
32   -
33   - xhr.addEventListener('load', function io_onload(e) {
34   - if (e.target.status === 200 || e.target.status === 0) {
35   - // Sinon.JS's FakeXHR doesn't have the response property
36   - resolve(e.target.response || e.target.responseText);
37   - } else {
38   - reject(new L10nError('Not found: ' + url));
39   - }
40   - });
41   - xhr.addEventListener('error', reject);
42   - xhr.addEventListener('timeout', reject);
43   -
44   - // the app: protocol throws on 404, see https://bugzil.la/827243
45   - try {
46   - xhr.send(null);
47   - } catch (e) {
48   - if (e.name === 'NS_ERROR_FILE_NOT_FOUND') {
49   - // the app: protocol throws on 404, see https://bugzil.la/827243
50   - reject(new L10nError('Not found: ' + url));
51   - } else {
52   - throw e;
53   - }
54   - }
55   - });
56   - }
57   -
58   - const io = {
59   - extra: function(code, ver, path, type) {
60   - return navigator.mozApps.getLocalizationResource(
61   - code, ver, path, type);
62   - },
63   - app: function(code, ver, path, type) {
64   - switch (type) {
65   - case 'text':
66   - return load('text/plain', path);
67   - case 'json':
68   - return load('application/json', path);
69   - default:
70   - throw new L10nError('Unknown file type: ' + type);
71   - }
72   - },
73   - };
74   -
75   - function fetchResource(ver, res, lang) {
76   - const url = res.replace('{locale}', lang.code);
77   - const type = res.endsWith('.json') ? 'json' : 'text';
78   - return io[lang.src](lang.code, ver, url, type);
79   - }
80   -
81   - const MAX_PLACEABLES$1 = 100;
82   -
83   - var L20nParser = {
84   - parse: function(emit, string) {
85   - this._source = string;
86   - this._index = 0;
87   - this._length = string.length;
88   - this.entries = Object.create(null);
89   - this.emit = emit;
90   -
91   - return this.getResource();
92   - },
93   -
94   - getResource: function() {
95   - this.getWS();
96   - while (this._index < this._length) {
97   - try {
98   - this.getEntry();
99   - } catch (e) {
100   - if (e instanceof L10nError) {
101   - // we want to recover, but we don't need it in entries
102   - this.getJunkEntry();
103   - if (!this.emit) {
104   - throw e;
105   - }
106   - } else {
107   - throw e;
108   - }
109   - }
110   -
111   - if (this._index < this._length) {
112   - this.getWS();
113   - }
114   - }
115   -
116   - return this.entries;
117   - },
118   -
119   - getEntry: function() {
120   - if (this._source[this._index] === '<') {
121   - ++this._index;
122   - const id = this.getIdentifier();
123   - if (this._source[this._index] === '[') {
124   - ++this._index;
125   - return this.getEntity(id, this.getItemList(this.getExpression, ']'));
126   - }
127   - return this.getEntity(id);
128   - }
129   -
130   - if (this._source.startsWith('/*', this._index)) {
131   - return this.getComment();
132   - }
133   -
134   - throw this.error('Invalid entry');
135   - },
136   -
137   - getEntity: function(id, index) {
138   - if (!this.getRequiredWS()) {
139   - throw this.error('Expected white space');
140   - }
141   -
142   - const ch = this._source[this._index];
143   - const value = this.getValue(ch, index === undefined);
144   - let attrs;
145   -
146   - if (value === undefined) {
147   - if (ch === '>') {
148   - throw this.error('Expected ">"');
149   - }
150   - attrs = this.getAttributes();
151   - } else {
152   - const ws1 = this.getRequiredWS();
153   - if (this._source[this._index] !== '>') {
154   - if (!ws1) {
155   - throw this.error('Expected ">"');
156   - }
157   - attrs = this.getAttributes();
158   - }
159   - }
160   -
161   - // skip '>'
162   - ++this._index;
163   -
164   - if (id in this.entries) {
165   - throw this.error('Duplicate entry ID "' + id, 'duplicateerror');
166   - }
167   - if (!attrs && !index && typeof value === 'string') {
168   - this.entries[id] = value;
169   - } else {
170   - this.entries[id] = {
171   - value,
172   - attrs,
173   - index
174   - };
175   - }
176   - },
177   -
178   - getValue: function(ch = this._source[this._index], optional = false) {
179   - switch (ch) {
180   - case '\'':
181   - case '"':
182   - return this.getString(ch, 1);
183   - case '{':
184   - return this.getHash();
185   - }
186   -
187   - if (!optional) {
188   - throw this.error('Unknown value type');
189   - }
190   -
191   - return;
192   - },
193   -
194   - getWS: function() {
195   - let cc = this._source.charCodeAt(this._index);
196   - // space, \n, \t, \r
197   - while (cc === 32 || cc === 10 || cc === 9 || cc === 13) {
198   - cc = this._source.charCodeAt(++this._index);
199   - }
200   - },
201   -
202   - getRequiredWS: function() {
203   - const pos = this._index;
204   - let cc = this._source.charCodeAt(pos);
205   - // space, \n, \t, \r
206   - while (cc === 32 || cc === 10 || cc === 9 || cc === 13) {
207   - cc = this._source.charCodeAt(++this._index);
208   - }
209   - return this._index !== pos;
210   - },
211   -
212   - getIdentifier: function() {
213   - const start = this._index;
214   - let cc = this._source.charCodeAt(this._index);
215   -
216   - if ((cc >= 97 && cc <= 122) || // a-z
217   - (cc >= 65 && cc <= 90) || // A-Z
218   - cc === 95) { // _
219   - cc = this._source.charCodeAt(++this._index);
220   - } else {
221   - throw this.error('Identifier has to start with [a-zA-Z_]');
222   - }
223   -
224   - while ((cc >= 97 && cc <= 122) || // a-z
225   - (cc >= 65 && cc <= 90) || // A-Z
226   - (cc >= 48 && cc <= 57) || // 0-9
227   - cc === 95) { // _
228   - cc = this._source.charCodeAt(++this._index);
229   - }
230   -
231   - return this._source.slice(start, this._index);
232   - },
233   -
234   - getUnicodeChar: function() {
235   - for (let i = 0; i < 4; i++) {
236   - let cc = this._source.charCodeAt(++this._index);
237   - if ((cc > 96 && cc < 103) || // a-f
238   - (cc > 64 && cc < 71) || // A-F
239   - (cc > 47 && cc < 58)) { // 0-9
240   - continue;
241   - }
242   - throw this.error('Illegal unicode escape sequence');
243   - }
244   - this._index++;
245   - return String.fromCharCode(
246   - parseInt(this._source.slice(this._index - 4, this._index), 16));
247   - },
248   -
249   - stringRe: /"|'|{{|\\/g,
250   - getString: function(opchar, opcharLen) {
251   - const body = [];
252   - let placeables = 0;
253   -
254   - this._index += opcharLen;
255   - const start = this._index;
256   -
257   - let bufStart = start;
258   - let buf = '';
259   -
260   - while (true) {
261   - this.stringRe.lastIndex = this._index;
262   - const match = this.stringRe.exec(this._source);
263   -
264   - if (!match) {
265   - throw this.error('Unclosed string literal');
266   - }
267   -
268   - if (match[0] === '"' || match[0] === '\'') {
269   - if (match[0] !== opchar) {
270   - this._index += opcharLen;
271   - continue;
272   - }
273   - this._index = match.index + opcharLen;
274   - break;
275   - }
276   -
277   - if (match[0] === '{{') {
278   - if (placeables > MAX_PLACEABLES$1 - 1) {
279   - throw this.error('Too many placeables, maximum allowed is ' +
280   - MAX_PLACEABLES$1);
281   - }
282   - placeables++;
283   - if (match.index > bufStart || buf.length > 0) {
284   - body.push(buf + this._source.slice(bufStart, match.index));
285   - buf = '';
286   - }
287   - this._index = match.index + 2;
288   - this.getWS();
289   - body.push(this.getExpression());
290   - this.getWS();
291   - this._index += 2;
292   - bufStart = this._index;
293   - continue;
294   - }
295   -
296   - if (match[0] === '\\') {
297   - this._index = match.index + 1;
298   - const ch2 = this._source[this._index];
299   - if (ch2 === 'u') {
300   - buf += this._source.slice(bufStart, match.index) +
301   - this.getUnicodeChar();
302   - } else if (ch2 === opchar || ch2 === '\\') {
303   - buf += this._source.slice(bufStart, match.index) + ch2;
304   - this._index++;
305   - } else if (this._source.startsWith('{{', this._index)) {
306   - buf += this._source.slice(bufStart, match.index) + '{{';
307   - this._index += 2;
308   - } else {
309   - throw this.error('Illegal escape sequence');
310   - }
311   - bufStart = this._index;
312   - }
313   - }
314   -
315   - if (body.length === 0) {
316   - return buf + this._source.slice(bufStart, this._index - opcharLen);
317   - }
318   -
319   - if (this._index - opcharLen > bufStart || buf.length > 0) {
320   - body.push(buf + this._source.slice(bufStart, this._index - opcharLen));
321   - }
322   -
323   - return body;
324   - },
325   -
326   - getAttributes: function() {
327   - const attrs = Object.create(null);
328   -
329   - while (true) {
330   - this.getAttribute(attrs);
331   - const ws1 = this.getRequiredWS();
332   - const ch = this._source.charAt(this._index);
333   - if (ch === '>') {
334   - break;
335   - } else if (!ws1) {
336   - throw this.error('Expected ">"');
337   - }
338   - }
339   - return attrs;
340   - },
341   -
342   - getAttribute: function(attrs) {
343   - const key = this.getIdentifier();
344   - let index;
345   -
346   - if (this._source[this._index]=== '[') {
347   - ++this._index;
348   - this.getWS();
349   - index = this.getItemList(this.getExpression, ']');
350   - }
351   - this.getWS();
352   - if (this._source[this._index] !== ':') {
353   - throw this.error('Expected ":"');
354   - }
355   - ++this._index;
356   - this.getWS();
357   - const value = this.getValue();
358   -
359   - if (key in attrs) {
360   - throw this.error('Duplicate attribute "' + key, 'duplicateerror');
361   - }
362   -
363   - if (!index && typeof value === 'string') {
364   - attrs[key] = value;
365   - } else {
366   - attrs[key] = {
367   - value,
368   - index
369   - };
370   - }
371   - },
372   -
373   - getHash: function() {
374   - const items = Object.create(null);
375   -
376   - ++this._index;
377   - this.getWS();
378   -
379   - let defKey;
380   -
381   - while (true) {
382   - const [key, value, def] = this.getHashItem();
383   - items[key] = value;
384   -
385   - if (def) {
386   - if (defKey) {
387   - throw this.error('Default item redefinition forbidden');
388   - }
389   - defKey = key;
390   - }
391   - this.getWS();
392   -
393   - const comma = this._source[this._index] === ',';
394   - if (comma) {
395   - ++this._index;
396   - this.getWS();
397   - }
398   - if (this._source[this._index] === '}') {
399   - ++this._index;
400   - break;
401   - }
402   - if (!comma) {
403   - throw this.error('Expected "}"');
404   - }
405   - }
406   -
407   - if (defKey) {
408   - items.__default = defKey;
409   - }
410   -
411   - return items;
412   - },
413   -
414   - getHashItem: function() {
415   - let defItem = false;
416   - if (this._source[this._index] === '*') {
417   - ++this._index;
418   - defItem = true;
419   - }
420   -
421   - const key = this.getIdentifier();
422   - this.getWS();
423   - if (this._source[this._index] !== ':') {
424   - throw this.error('Expected ":"');
425   - }
426   - ++this._index;
427   - this.getWS();
428   -
429   - return [key, this.getValue(), defItem];
430   - },
431   -
432   - getComment: function() {
433   - this._index += 2;
434   - const start = this._index;
435   - const end = this._source.indexOf('*/', start);
436   -
437   - if (end === -1) {
438   - throw this.error('Comment without a closing tag');
439   - }
440   -
441   - this._index = end + 2;
442   - },
443   -
444   - getExpression: function () {
445   - let exp = this.getPrimaryExpression();
446   -
447   - while (true) {
448   - let ch = this._source[this._index];
449   - if (ch === '.' || ch === '[') {
450   - ++this._index;
451   - exp = this.getPropertyExpression(exp, ch === '[');
452   - } else if (ch === '(') {
453   - ++this._index;
454   - exp = this.getCallExpression(exp);
455   - } else {
456   - break;
457   - }
458   - }
459   -
460   - return exp;
461   - },
462   -
463   - getPropertyExpression: function(idref, computed) {
464   - let exp;
465   -
466   - if (computed) {
467   - this.getWS();
468   - exp = this.getExpression();
469   - this.getWS();
470   - if (this._source[this._index] !== ']') {
471   - throw this.error('Expected "]"');
472   - }
473   - ++this._index;
474   - } else {
475   - exp = this.getIdentifier();
476   - }
477   -
478   - return {
479   - type: 'prop',
480   - expr: idref,
481   - prop: exp,
482   - cmpt: computed
483   - };
484   - },
485   -
486   - getCallExpression: function(callee) {
487   - this.getWS();
488   -
489   - return {
490   - type: 'call',
491   - expr: callee,
492   - args: this.getItemList(this.getExpression, ')')
493   - };
494   - },
495   -
496   - getPrimaryExpression: function() {
497   - const ch = this._source[this._index];
498   -
499   - switch (ch) {
500   - case '$':
501   - ++this._index;
502   - return {
503   - type: 'var',
504   - name: this.getIdentifier()
505   - };
506   - case '@':
507   - ++this._index;
508   - return {
509   - type: 'glob',
510   - name: this.getIdentifier()
511   - };
512   - default:
513   - return {
514   - type: 'id',
515   - name: this.getIdentifier()
516   - };
517   - }
518   - },
519   -
520