1 | var escodegen = require('escodegen');
|
2 | var falafel = require('falafel');
|
3 | var namedTemplateFn = require('./namedTemplateFn');
|
4 | var bracketedName = require('./bracketedName');
|
5 | var templateName = require('./templateName');
|
6 |
|
7 |
|
8 | function bufDeclartion(name) {
|
9 | return {
|
10 | "type": "VariableDeclarator",
|
11 | "id": {
|
12 | "type": "Identifier",
|
13 | "name": name || "buf"
|
14 | },
|
15 | "init": {
|
16 | "type": "ArrayExpression",
|
17 | "elements": []
|
18 | }
|
19 | };
|
20 | }
|
21 |
|
22 | function returnBuf(name) {
|
23 | return {
|
24 | "type": "ReturnStatement",
|
25 | "argument": {
|
26 | "type": "CallExpression",
|
27 | "callee": {
|
28 | "type": "MemberExpression",
|
29 | "computed": false,
|
30 | "object": {
|
31 | "type": "Identifier",
|
32 | "name": name || "buf"
|
33 | },
|
34 | "property": {
|
35 | "type": "Identifier",
|
36 | "name": "join"
|
37 | }
|
38 | },
|
39 | "arguments": [
|
40 | {
|
41 | "type": "Literal",
|
42 | "value": "",
|
43 | "raw": "\"\""
|
44 | }
|
45 | ]
|
46 | }
|
47 | };
|
48 | }
|
49 |
|
50 | function transformMixinCalls(node, options) {
|
51 | var mixinName;
|
52 | var mixinInvocation;
|
53 | var newCall;
|
54 |
|
55 |
|
56 | if (
|
57 | node.type === 'ExpressionStatement' &&
|
58 | node.expression.type === 'CallExpression' &&
|
59 | node.expression.callee &&
|
60 | node.expression.callee.object &&
|
61 | (
|
62 | node.expression.callee.object.name === 'jade_mixins' ||
|
63 | (
|
64 | node.expression.callee.object.object &&
|
65 | node.expression.callee.object.object.name === 'jade_mixins'
|
66 | )
|
67 | )
|
68 | ) {
|
69 |
|
70 | var callee = node.expression.callee;
|
71 | var calleeProp = callee.property;
|
72 | var calleeObject = callee.object;
|
73 |
|
74 | mixinName = (calleeProp && calleeProp.value) ||
|
75 | (calleeObject && calleeObject.property && calleeObject.property.value);
|
76 |
|
77 | mixinInvocation = options.rootName + bracketedName(options.dir.split('.'));
|
78 |
|
79 | if (mixinName) {
|
80 | mixinInvocation += bracketedName([mixinName]);
|
81 | } else {
|
82 | mixinInvocation += "[" + escodegen.generate(calleeProp) + "]";
|
83 | }
|
84 |
|
85 |
|
86 |
|
87 | newCall = 'buf.push(' + mixinInvocation;
|
88 |
|
89 | newCall = node.source().replace(/^jade_mixins\[.*?\]([\s\S]*);$/gm, newCall + '$1);');
|
90 |
|
91 |
|
92 |
|
93 | newCall = newCall.replace('block: function () {', 'block: function (buf) {');
|
94 |
|
95 | node.update(newCall);
|
96 | }
|
97 | }
|
98 |
|
99 | function findAndReplaceMixin(node, options) {
|
100 | var mixinName;
|
101 | var mixinStatements;
|
102 | var mixin = '';
|
103 |
|
104 |
|
105 | if (
|
106 | node.type === 'ExpressionStatement' &&
|
107 | node.expression.type === 'AssignmentExpression' &&
|
108 | node.expression.left &&
|
109 | node.expression.left.object &&
|
110 | node.expression.left.object.name === 'jade_mixins'
|
111 | ) {
|
112 | mixinName = node.expression.left.property.value;
|
113 | mixinStatements = node.expression.right.right.body.body;
|
114 |
|
115 |
|
116 | mixinStatements[0].declarations.push(bufDeclartion());
|
117 |
|
118 |
|
119 | mixinStatements.push(returnBuf());
|
120 |
|
121 |
|
122 | node.expression.update(escodegen.generate(node.expression));
|
123 |
|
124 |
|
125 | node.expression.right.right.type = 'FunctionDeclaration';
|
126 | node.expression.right.right.id = {
|
127 | "type": "Identifier",
|
128 | "name": templateName(options.dir + '_' + mixinName)
|
129 | };
|
130 |
|
131 |
|
132 | mixin = falafel(escodegen.generate(node.expression.right.right), function (node) {
|
133 | transformMixinCalls(node, options);
|
134 | }).toString();
|
135 |
|
136 |
|
137 |
|
138 | mixin = mixin.replace(/block && block\(\);/g, 'block && block(buf);');
|
139 |
|
140 |
|
141 | mixin = namedTemplateFn({
|
142 | fn: mixin,
|
143 | rootName: options.rootName,
|
144 | dir: options.dir,
|
145 | mixinName: mixinName
|
146 | });
|
147 |
|
148 |
|
149 | node.update('');
|
150 | }
|
151 |
|
152 | return mixin;
|
153 | }
|
154 |
|
155 | module.exports = function (options) {
|
156 | var mixins = [];
|
157 |
|
158 | var template = falafel(options.template, function (node) {
|
159 | var mixin = findAndReplaceMixin(node, options);
|
160 | if (mixin) mixins.push(mixin);
|
161 | transformMixinCalls(node, options);
|
162 | });
|
163 |
|
164 | return {
|
165 | template: template,
|
166 | mixins: mixins
|
167 | };
|
168 | };
|
169 |
|