-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
98 lines (82 loc) · 2.44 KB
/
index.js
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
"use strict";
const postcss = require("postcss");
const objectAssign = require("object-assign");
const defaults = {
revertMediaPoint: 1281,
banNames: ["_ban"],
onlyPX: false,
exclude: false
};
module.exports = options => {
const opts = objectAssign({}, defaults, options);
return {
postcssPlugin: "postcss-reverse-media",
Once(css) {
const filePath = css.source.input.file;
const fileName = filePath.substr(filePath.lastIndexOf("/") + 1);
// Проверка на ban name
if (
checkBanFiles(opts.banNames, fileName) ||
isFileExcluded(opts.exclude, filePath)
) {
return;
}
css.walkRules(rule => {
// Добавляем только декларации со значениями в 'px'
if (ruleContainsPxValue(rule)) {
const ruleClone = opts.onlyPX
? cloneRuleWithPxDeclarations(rule)
: rule;
// Добавляем клонированное правило с декларациями 'px' в медиа-запрос и в начало файла
afterRuleInMediaQuery(css, ruleClone, opts.revertMediaPoint, rule);
}
});
}
};
};
function afterRuleInMediaQuery(css, ruleClone, revertMediaPoint, rule) {
css.insertAfter(
rule,
postcss.atRule({
params: `(min-width: ${revertMediaPoint}px)`,
name: "media",
nodes: [ruleClone]
})
);
}
function ruleContainsPxValue(rule) {
if (rule.parent.type === "atrule") return;
let containsPx = false;
rule.walkDecls(decl => {
if (decl.value.includes("px")) {
containsPx = true;
}
});
return containsPx;
}
function cloneRuleWithPxDeclarations(rule) {
const ruleClone = rule.clone();
ruleClone.removeAll();
rule.walkDecls(decl => {
if (decl.value.includes("px")) {
ruleClone.append(decl.clone());
}
});
return ruleClone;
}
function checkBanFiles(banNames, fileName) {
return banNames.some(banName => fileName.includes(banName));
}
function isFileExcluded(excludeOption, file) {
if (!excludeOption) return false;
const isRegExp =
Object.prototype.toString.call(excludeOption) === "[object RegExp]";
const isArray = Array.isArray(excludeOption);
if (isRegExp) {
return excludeOption.test(file);
} else if (isArray) {
return excludeOption.some(exclude => isFileExcluded(exclude, file));
} else {
throw new Error("options.exclude should be RegExp or Array.");
}
}