-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathindex.js
More file actions
138 lines (118 loc) · 4.07 KB
/
Copy pathindex.js
File metadata and controls
138 lines (118 loc) · 4.07 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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
const fs = require('fs');
const path = require('path');
const nodeResolve = require('resolve');
const postcss = require('postcss');
const selectorTokenizer = require('css-selector-tokenizer');
function globalizeSelectors (selector) {
const selectors = selectorTokenizer.parse(selector);
const wrapToGlobal = (classNode) => {
return {
type: 'nested-pseudo-class',
name: 'global',
nodes: [
{
type: 'selector',
nodes: [ classNode ]
}
]
}
};
const walkNodes = (nodes) => {
return nodes.map(node => {
if (node.type === 'class' || node.type === 'id') {
return wrapToGlobal(node);
} else if (node.type === 'selector' || (node.type === 'nested-pseudo-class' && node.name !== 'global')) {
return Object.assign({}, node, {
nodes: walkNodes(node.nodes)
});
}
return node;
});
};
return selectorTokenizer.stringify({
type: 'selectors',
nodes: walkNodes(selectors.nodes)
});
}
/**
* Plugin for PostCSS, which can do global import in Css.
* Global import don't modify class names inside file, where he imports,
* for example, for import Leaflet or Bootstrap css files.
*
* @example:
* @global-import './some-file.css';
*/
module.exports = postcss.plugin('postcss-global-import', function (options) {
const sync = options && options.sync;
const globalizeKeyframes = options && options.globalizeKeyframes;
return function (root, result) {
const processCss = (str, modulePath, atRule) => {
const css = postcss.parse(str, {
from: modulePath
});
// Выставляем названия директив @keyframes в global
// @TODO: данная логика работает только для плагина postcss-modules-local-by-default
// В будущем, когда postcss-modules перейдет на postcss-icss-selectors и postcss-icss-keyframes
// последний не будет поддерживать именно такую семантику
if (globalizeKeyframes) {
css.walkAtRules(rule => {
if (rule.name.indexOf('keyframes') !== -1) {
rule.params = `:global(${rule.params})`;
}
});
}
css.walkRules(rule => {
const outer = rule.parent;
const inKeyframes = outer.name && outer.name.indexOf('keyframes') !== -1;
if (!inKeyframes) {
rule.replaceWith(rule.clone({
selector: globalizeSelectors(rule.selector)
}));
}
});
atRule.replaceWith(css);
};
let promises = [];
root.walkAtRules('global-import', atRule => {
const moduleDirname = path.dirname(root.source.input.file);
const modulePath = atRule.params.replace(/'?"?/g, '');
let resolvedModulePath;
if (sync) {
resolvedModulePath = resolvePathSync(modulePath, { basedir: moduleDirname });
processCss(readModuleSync(resolvedModulePath), resolvedModulePath, atRule);
} else {
const task = resolvePath(modulePath, { basedir: moduleDirname })
.then(modulepath => {
resolvedModulePath = modulepath;
return modulepath;
})
.then(modulepath => readModule(modulepath))
.then((res) => {
processCss(res, resolvedModulePath, atRule);
})
.catch(err => {
console.error(err);
process.exit(1);
});
promises.push(task);
}
});
return promises.length ? Promise.all(promises) : result;
};
});
function resolvePath (filepath, options) {
return new Promise(function (resolve, reject) {
nodeResolve(filepath, options, (e, res) => (e) ? reject(e) : resolve(res));
});
}
function readModule (filepath) {
return new Promise(function (resolve, reject) {
fs.readFile(filepath, 'utf8', (e, res) => (e) ? reject(e) : resolve(res));
});
}
function resolvePathSync (filepath, options) {
return nodeResolve.sync(filepath, options);
}
function readModuleSync (filepath) {
return fs.readFileSync(filepath, 'utf8');
}