UNPKG

4.49 kBJavaScriptView Raw
1var ignore = 'ignore',
2 missing = 'missing',
3 only = 'only',
4 attrs = ["id", "mode", "group", "for", "model", "lazy", "cache"];
5
6/**
7 * Includes a template partial in place. The template is rendered within the current locals variable context.
8 *
9 * @alias widget
10 *
11 * @example
12 * // food = 'burritos';
13 * // drink = 'lemonade';
14 * {% widget "./partial.html" %}
15 * // => I like burritos and lemonade.
16 *
17 * @example
18 * // my_obj = { food: 'tacos', drink: 'horchata' };
19 * {% widget "./partial.html" id="pagelet_id" mode="async" with my_obj%}
20 * // => I like tacos and horchata.
21 *
22 * @example
23 * {% widget "/this/file/does/not/exist" ignore missing %}
24 * // => (Nothing! empty string)
25 *
26 * @param {string|var} file The path, relative to the template root, to render into the current context.
27 * @param {literal} [with] Literally, "with".
28 * @param {object} [context] Local variable key-value object context to provide to the included file.
29 * @param {literal} [only] Restricts to <strong>only</strong> passing the <code>with context</code> as local variables–the included template will not be aware of any other local variables in the parent template. For best performance, usage of this option is recommended if possible.
30 * @param {literal} [ignore missing] Will output empty string if not found instead of throwing an error.
31 */
32exports.compile = function (compiler, args) {
33 var file = args.shift(),
34 onlyIdx = args.indexOf(only),
35 onlyCtx = onlyIdx !== -1 ? args.splice(onlyIdx, 1) : false,
36 parentFile = (args.pop() || '').replace(/\\/g, '\\\\'),
37 ignore = args[args.length - 1] === missing ? (args.pop()) : false,
38 w = args.filter(function (o) {
39 return !o.k;
40 }).join(','),
41 w_args = {
42 id: "spage",
43 mode: "async"
44 };
45
46 args.map(function (w) {
47 if (w.k) w_args[w.k] = w.v;
48 });
49
50 // 处理_VAR_:标记,将其转变为获取ctx变量
51 var w_args_str = JSON.stringify(w_args).replace(/"<<VAR:(.*?)>>"/g, "_ctx.$1");
52
53 return (ignore ? ' try {\n' : '') +
54 'var w_args = ' + JSON.stringify(w_args) + ';' +
55 'if (_ctx.isQuickingMode){w_args.mode="quickling"}' +
56 '_output += _swig._w(_ctx._yog, ' + file + ', w_args, {' +
57 'resolveFrom: "' + parentFile + '"' +
58 '})(' +
59 ((onlyCtx && w) ? w : (!w ? '_ctx' : '_utils.extend({}, _ctx, ' + w + ')')) +
60 ');\n' +
61 (ignore ? '} catch (e) {}\n' : '');
62};
63
64exports.parse = function (str, line, parser, types, stack, opts) {
65 var file, w, k;
66
67 parser.on(types.STRING, function (token) {
68
69 if (!file) {
70 file = token.match;
71 this.out.push(file);
72 return;
73 }
74
75 var out = {
76 v: '',
77 k: ''
78 };
79
80 if (~attrs.indexOf(k)) {
81 out.v = token.match.replace(/^("|')?(.*)\1$/g, '$2');
82 out.k = k;
83 this.out.push(out);
84 k = ''; //reset
85 }
86
87 });
88
89 parser.on(types.VAR, function (token) {
90 if (!file) {
91 k = '';
92 file = token.match;
93 return true;
94 }
95
96 if (~attrs.indexOf(k)) {
97 var out = {
98 v: '',
99 k: ''
100 };
101 out.v = '<<VAR:' + token.match + '>>';
102 out.k = k;
103 this.out.push(out);
104 k = '';
105 }
106
107 if (~attrs.indexOf(token.match)) {
108 k = token.match;
109 return false;
110 }
111
112 if (!w && token.match === 'with') {
113 w = true;
114 return;
115 }
116
117 if (w && token.match === only && this.prevToken.match !== 'with') {
118 this.out.push(token.match);
119 return;
120 }
121
122 if (token.match === ignore) {
123 return false;
124 }
125
126 if (token.match === missing) {
127 if (this.prevToken.match !== ignore) {
128 throw new Error('Unexpected token "' + missing + '" on line ' + line + '.');
129 }
130 this.out.push(token.match);
131 return false;
132 }
133
134 if (this.prevToken.match === ignore) {
135 throw new Error('Expected "' + missing + '" on line ' + line + ' but found "' + token.match + '".');
136 }
137
138 return true;
139 });
140
141 parser.on('end', function () {
142 this.out.push(opts.filename || null);
143 });
144
145 return true;
146};
147
148exports.ends = false;