UNPKG

10.4 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6
7var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
8
9var _comment = require('postcss/lib/comment');
10
11var _comment2 = _interopRequireDefault(_comment);
12
13var _parser = require('postcss/lib/parser');
14
15var _parser2 = _interopRequireDefault(_parser);
16
17var _rule = require('./rule');
18
19var _rule2 = _interopRequireDefault(_rule);
20
21var _findExtendRule = require('./find-extend-rule');
22
23var _findExtendRule2 = _interopRequireDefault(_findExtendRule);
24
25var _isMixinToken = require('./is-mixin-token');
26
27var _isMixinToken2 = _interopRequireDefault(_isMixinToken);
28
29var _lessTokenize = require('./less-tokenize');
30
31var _lessTokenize2 = _interopRequireDefault(_lessTokenize);
32
33function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
34
35function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
36
37function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
38
39function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
40
41var blockCommentEndPattern = /\*\/$/;
42
43var LessParser = function (_Parser) {
44 _inherits(LessParser, _Parser);
45
46 function LessParser() {
47 _classCallCheck(this, LessParser);
48
49 return _possibleConstructorReturn(this, (LessParser.__proto__ || Object.getPrototypeOf(LessParser)).apply(this, arguments));
50 }
51
52 _createClass(LessParser, [{
53 key: 'tokenize',
54 value: function tokenize() {
55 this.tokens = (0, _lessTokenize2.default)(this.input);
56 }
57 }, {
58 key: 'rule',
59 value: function rule(tokens) {
60 tokens.pop();
61
62 var node = new _rule2.default();
63
64 this.init(node, tokens[0][2], tokens[0][3]);
65 node.raws.between = this.spacesFromEnd(tokens);
66 this.raw(node, 'selector', tokens);
67 this.current = node;
68 }
69 }, {
70 key: 'comment',
71 value: function comment(token) {
72 var node = new _comment2.default();
73 var content = token[1];
74 var text = content.slice(2).replace(blockCommentEndPattern, '');
75
76 this.init(node, token[2], token[3]);
77 node.source.end = {
78 line: token[4],
79 column: token[5]
80 };
81
82 node.raws.content = content;
83 node.raws.begin = content[0] + content[1];
84 node.inline = token[6] === 'inline';
85 node.block = !node.inline;
86
87 if (/^\s*$/.test(text)) {
88 node.text = '';
89 node.raws.left = text;
90 node.raws.right = '';
91 } else {
92 var match = text.match(/^(\s*)([^]*[^\s])(\s*)$/);
93
94 node.text = match[2];
95
96 // Add extra spaces to generate a comment in a common style /*[space][text][space]*/
97 node.raws.left = match[1] || ' ';
98 node.raws.right = match[3] || ' ';
99 }
100 }
101
102 /**
103 * @description Create a Rule node
104 * @param options {{start: number, params: Array}}
105 */
106
107 }, {
108 key: 'createRule',
109 value: function createRule(options) {
110 this.rule(this.tokens.slice(options.start, this.pos + 1));
111
112 /**
113 * By default in PostCSS `Rule.params` is `undefined`. There are rules to save the compability with PostCSS:
114 * - Don't set empty params for Rule node.
115 * - Set params fro Rule node only if it can be a mixin or &:extend rule.
116 */
117 if (options.params[0] && (options.isMixin || options.isExtendRule)) {
118 this.raw(this.current, 'params', options.params);
119 }
120 }
121
122 /**
123 * @description Create a Declaration
124 * @param options {{start: number}}
125 */
126
127 }, {
128 key: 'createDeclaration',
129 value: function createDeclaration(options) {
130 this.decl(this.tokens.slice(options.start, this.pos + 1));
131 }
132
133 /**
134 * @description Create a Rule block and close it, because this mixin doesn't have a body
135 * @param options
136 */
137
138 }, {
139 key: 'ruleWithoutBody',
140 value: function ruleWithoutBody(options) {
141 this.createRule(options);
142
143 /**
144 * @description Mark mixin without body.
145 * @type {boolean}
146 */
147 this.current.ruleWithoutBody = true;
148
149 // remove `nodes` property from rules without body
150 // eslint-disable-next-line
151 delete this.current.nodes;
152 this.current.extendRule = this.current.selector.indexOf('&:extend') >= 0;
153 this.current.important = this.current.selector.indexOf('!important') >= 0;
154
155 this.pos--;
156
157 this.end(this.tokens[this.pos]);
158 }
159
160 /**
161 * @description
162 * @param options
163 * @returns {boolean}
164 */
165
166 }, {
167 key: 'processEndOfRule',
168 value: function processEndOfRule(options) {
169 var start = options.start;
170
171
172 if (options.isExtendRule || options.isMixin) {
173 this.ruleWithoutBody(options);
174 return true;
175 }
176
177 if (options.colon) {
178 if (options.isEndOfBlock) {
179 while (this.pos > start) {
180 var token = this.tokens[this.pos][0];
181
182 if (token !== 'space' && token !== 'comment') {
183 break;
184 }
185
186 this.pos -= 1;
187 }
188 }
189
190 this.createDeclaration({ start: start });
191 return true;
192 }
193
194 return false;
195 }
196
197 /* eslint-disable max-statements, complexity */
198
199 }, {
200 key: 'other',
201 value: function other() {
202 var end = false;
203 var colon = false;
204 var bracket = null;
205 var brackets = [];
206 var start = this.pos;
207
208 // we need pass "()" as spaces
209 // However we can override method Parser.loop, but it seems less maintainable
210 if (this.tokens[start][0] === 'brackets') {
211 this.spaces += this.tokens[start][1];
212 return;
213 }
214 var isMixin = (0, _isMixinToken2.default)(this.tokens[start]);
215 var isExtendRule = Boolean((0, _findExtendRule2.default)(this.tokens, start));
216 var params = [];
217
218 this.pos += 1;
219 while (this.pos < this.tokens.length) {
220 var token = this.tokens[this.pos];
221 var type = token[0];
222
223 if (type === '(' || type === '[') {
224 if (!bracket) {
225 bracket = token;
226 }
227
228 brackets.push(type === '(' ? ')' : ']');
229 } else if (brackets.length === 0) {
230 if (type === ';') {
231 var foundEndOfRule = this.processEndOfRule({
232 start: start,
233 params: params,
234 colon: colon,
235 isMixin: isMixin,
236 isExtendRule: isExtendRule
237 });
238
239 if (foundEndOfRule) {
240 return;
241 }
242
243 break;
244 } else if (type === '{') {
245 this.createRule({ start: start, params: params, isMixin: isMixin });
246 return;
247 } else if (type === '}') {
248 this.pos -= 1;
249 end = true;
250 break;
251 } else if (type === ':') {
252 colon = true;
253 }
254 } else if (type === brackets[brackets.length - 1]) {
255 brackets.pop();
256 if (brackets.length === 0) {
257 bracket = null;
258 }
259 }
260
261 if (brackets.length > 0 || type === 'brackets' || params[0]) {
262 params.push(token);
263 }
264
265 this.pos += 1;
266 }
267
268 if (this.pos === this.tokens.length) {
269 this.pos -= 1;
270 end = true;
271 }
272
273 if (brackets.length > 0) {
274 this.unclosedBracket(bracket);
275 }
276
277 if (end) {
278 var _foundEndOfRule = this.processEndOfRule({
279 start: start,
280 params: params,
281 colon: colon,
282 isMixin: isMixin,
283 isExtendRule: isExtendRule,
284 isEndOfBlock: true
285 });
286
287 if (_foundEndOfRule) {
288 return;
289 }
290 }
291
292 this.unknownWord(start);
293 }
294
295 /* eslint-enable max-statements, complexity */
296
297 }]);
298
299 return LessParser;
300}(_parser2.default);
301
302exports.default = LessParser;
303module.exports = exports['default'];
\No newline at end of file