vite-plugin-html-security
Version:
vite plugin for html security
59 lines (58 loc) • 2.86 kB
JavaScript
import * as __WEBPACK_EXTERNAL_MODULE_crypto__ from "crypto";
import * as __WEBPACK_EXTERNAL_MODULE_fs__ from "fs";
import * as __WEBPACK_EXTERNAL_MODULE_path__ from "path";
import * as __WEBPACK_EXTERNAL_MODULE_lodash__ from "lodash";
const sriAssetsMap = [];
const integrityAttrValueShaKey = "integrityAttrValueSha";
function getSRIHash(filePath) {
try {
const fileContent = (0, __WEBPACK_EXTERNAL_MODULE_fs__.readFileSync)(filePath);
const hash = (0, __WEBPACK_EXTERNAL_MODULE_crypto__.createHash)("sha384");
hash.update(fileContent);
return `sha384-${hash.digest("base64")}`;
} catch (e) {
return null;
}
}
function src(options) {
const config = (0, __WEBPACK_EXTERNAL_MODULE_lodash__.merge)({
outputDir: "dist"
}, options);
return {
name: "vite-plugin-sri",
apply: "build",
enforce: "post",
closeBundle () {
sriAssetsMap.forEach((item)=>{
const htmlPath = (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(process.cwd(), config.outputDir, item.path);
const sriHash = getSRIHash(/node_modules/.test(item.filePath) ? (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(process.cwd(), "node_modules", item.filePath.replace(/.*?node_modules/, "")) : item.filePath);
let newHtml = (0, __WEBPACK_EXTERNAL_MODULE_fs__.readFileSync)(htmlPath, "utf-8");
if (sriHash) newHtml = newHtml.replace(item.match, (0, __WEBPACK_EXTERNAL_MODULE_lodash__.template)(item.matchTag)({
[integrityAttrValueShaKey]: sriHash
}));
(0, __WEBPACK_EXTERNAL_MODULE_fs__.writeFileSync)(htmlPath, newHtml);
});
},
transformIndexHtml: {
enforce: "post",
transform (html, { bundle, path }) {
if (!bundle) return html;
const newHtml = html.replace(/<(link|script) ([^>]*?)(href|src)=("([^"]+)"|'([^']+)')([^>]*?)>/g, (match, tag, before, attr, quoteWrappedUrl, url1, url2)=>{
const url = (url1 || url2 || "").replace(/^(\.|\/)+/, "");
const asset = Object.values(bundle).find((b)=>b.fileName === url);
const filePath = (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(process.cwd(), config.outputDir, url);
sriAssetsMap.push({
filePath,
asset: !!asset,
path,
match,
matchTag: `<${tag} ${before}${attr}=${quoteWrappedUrl} integrity="<%=${integrityAttrValueShaKey}%>" crossorigin="anonymous"${match.endsWith("/>") ? "/" : ""}>`
});
return match;
});
return newHtml;
}
}
};
}
export { src as default };