UNPKG

4.32 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
43 args.map(function (w) {
44 if (w.k) w_args[w.k] = w.v;
45 });
46 // 处理_VAR_:标记,将其转变为获取ctx变量
47 var w_args_str = JSON.stringify(w_args).replace(/"<<VAR:(.*?)>>"/g, "_ctx.$1");
48 return (ignore ? ' try {\n' : '') +
49 '_output += _swig._w(_ctx._yog, ' + file + ',' + w_args_str + ', {' +
50 'resolveFrom: "' + parentFile + '"' +
51 '})(' +
52 ((onlyCtx && w) ? w : (!w ? '_ctx' : '_utils.extend({}, _ctx, ' + w + ')')) +
53 ');\n' +
54 (ignore ? '} catch (e) {}\n' : '');
55};
56
57exports.parse = function (str, line, parser, types, stack, opts) {
58 var file, w, k;
59
60 parser.on(types.STRING, function (token) {
61
62 if (!file) {
63 file = token.match;
64 this.out.push(file);
65 return;
66 }
67
68 var out = {
69 v: '',
70 k: ''
71 };
72
73 if (~attrs.indexOf(k)) {
74 out.v = token.match.replace(/^("|')?(.*)\1$/g, '$2');
75 out.k = k;
76 this.out.push(out);
77 k = ''; //reset
78 }
79
80 });
81
82 parser.on(types.VAR, function (token) {
83 if (!file) {
84 k = '';
85 file = token.match;
86 return true;
87 }
88
89 if (~attrs.indexOf(k)) {
90 var out = {
91 v: '',
92 k: ''
93 };
94 out.v = '<<VAR:' + token.match + '>>';
95 out.k = k;
96 this.out.push(out);
97 k = '';
98 }
99
100 if (~attrs.indexOf(token.match)) {
101 k = token.match;
102 return false;
103 }
104
105 if (!w && token.match === 'with') {
106 w = true;
107 return;
108 }
109
110 if (w && token.match === only && this.prevToken.match !== 'with') {
111 this.out.push(token.match);
112 return;
113 }
114
115 if (token.match === ignore) {
116 return false;
117 }
118
119 if (token.match === missing) {
120 if (this.prevToken.match !== ignore) {
121 throw new Error('Unexpected token "' + missing + '" on line ' + line + '.');
122 }
123 this.out.push(token.match);
124 return false;
125 }
126
127 if (this.prevToken.match === ignore) {
128 throw new Error('Expected "' + missing + '" on line ' + line + ' but found "' + token.match + '".');
129 }
130
131 return true;
132 });
133
134 parser.on('end', function () {
135 this.out.push(opts.filename || null);
136 });
137
138 return true;
139};
140
141exports.ends = false;