-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparseSCSS.js
More file actions
88 lines (73 loc) · 2.37 KB
/
parseSCSS.js
File metadata and controls
88 lines (73 loc) · 2.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
'use strict';
const postcss = require('postcss');
const syntax = require('postcss-scss');
const nest = require('postcss-nested');
const vars = require('postcss-nested-vars');
let params = {};
const parser = (css) => {
const splits = [];
/**
* @param {object} at - an at rule, e.g. @media
*/
const parseAtRule = (at) => {
const regex = new RegExp(params.keyword);
if (regex.test(at.params)) {
if (at.parent.type === 'atrule') {
if (!regex.test(at.parent.params)) {
splits.push(`@${at.parent.name} ${at.parent.params} {`);
splits.push(at.toString());
splits.push('}');
}
} else {
splits.push(`${at.parent.selector} {`);
splits.push(at.toString());
splits.push('}');
}
at.remove();
}
};
/**
* @param {object} rule - a CSS rule: a selector followed by a declaration block
*/
const parseDecl = (rule) => {
rule.walkDecls(decl => {
const regex = new RegExp(`${params.keyword}-`);
if (regex.test(decl.value)) {
if (rule.parent.type === 'atrule') {
splits.push(`@${rule.parent.name} ${rule.parent.params} {`);
splits.push(`${rule.selector} { ${decl.toString()}; }`);
splits.push('}');
} else {
splits.push(`${rule.selector} { ${decl.toString()}; }`);
}
decl.remove();
}
});
};
/**
* @returns {Function} - PostCSS function
*/
const brandParse = postcss.plugin('brand-parse', (options) => {
return (global, result) => {
global.walkAtRules(x => parseAtRule(x));
global.walkRules(x => parseDecl(x));
};
});
/**
* @param {object} config - contains the css string and an optional keyword to search for.
* @returns {Promise} object - containing the global css and the split code
*/
const parseSCSS = (config) => {
params = config;
params.keyword = config.keyword || 'brand';
// remove any line where the first non-space character is `//`
css = params.css.replace(/^\s*\/\/.*/gm, '');
//https://github.com/postcss/postcss-nested#options
//use the bubble option to specify mixins to unwrap
const processor = postcss([vars(), nest({bubble: [params.keyword]}), brandParse()]);
return processor.process(css, { syntax })
.then(x => ({ css: x.css, splits: splits }));
};
return parseSCSS(css);
};
module.exports = parser;