-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
103 lines (81 loc) · 2.31 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
99
100
101
102
103
const Image = require("@11ty/eleventy-img");
function stripDecl(text) {
return text.replace(/^responsive-bg-img\(/, "").replace(/\)$/, "");
}
function stripUrlFunction(text) {
return text.replace(/^url\(/, "").replace(/\)$/, "");
}
function stripQuotes(text) {
return text.replace(/^\"/g, "").replace(/\"$/g, "").replace(/^\'/g, "").replace(/\'$/g, "");
}
function checkParams(params) {
const [url, ...widths] = params;
if (url === "") {
return "Missed required url and width parameters";
}
if (/^\d+$/.test(url)) {
return "Missed required url parameters";
}
if (widths.length === 0) {
return "Missed required width parameter";
}
return null;
}
function paramsList(params) {
let [url, ...widths] = params;
widths = widths.map((x) => parseInt(x));
url = stripUrlFunction(url);
url = stripQuotes(url);
return {
url,
widths,
};
}
async function processDecl(decl, url, options) {
options.alt = "";
const metadata = await Image(url, options);
const metadataValues = Object.values(metadata.webp);
const defaultData = metadataValues[0];
const mediaQueries = metadataValues
.slice(1)
.map(
(x) =>
`\n@media (min-width: ${x.width}px) { ${decl.parent.selector} { ${decl.prop}: url("${x.url}"); } }`
)
.join("");
decl.value = `url("${defaultData.url}")`;
decl.parent.parent.append(mediaQueries);
}
async function processResponsiveBgImg(decl, opts) {
if (decl.value.includes("responsive-bg-img(")) {
const params = stripDecl(decl.value)
.split(",")
.map((x) => x.trim());
const error = checkParams(params);
if (error) throw decl.error(error);
const { url, widths } = paramsList(params);
try {
await processDecl(decl, url, {
...opts,
widths,
});
} catch (error) {
if (error.message.includes("no such file")) {
const filePathRegex = /stat\s'(.*?)'/;
const filePathMatch = error.message.match(filePathRegex);
throw decl.error(`Invalid filename: ${filePathMatch[1]}`);
}
throw decl.error(error);
}
}
}
/**
* @type {import('postcss').PluginCreator}
*/
module.exports = (opts = {}) => ({
postcssPlugin: "postcss-11ty-responsive-bg-img",
Declaration: {
"*": (decl) => processResponsiveBgImg(decl, opts),
},
});
module.exports.postcss = true;