forked from small-tech/vite-plugin-sri
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
68 lines (60 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
////////////////////////////////////////////////////////////////////////////////
//
// @small-tech/vite-plugin-sri
//
// Subresource integrity (SRI) plugin for Vite (https://vitejs.dev/)
//
// Adds subresource integrity hashes to script and stylesheet
// imports from your index.html file at build time.
//
// If you’re looking for a generic Rollup plugin that does the same thing,
// see rollup-plugin-sri by Jonas Kruckenberg that this one was inspired by:
// https://github.com/JonasKruckenberg/rollup-plugin-sri
//
// Like this? Fund us!
// https://small-tech.org/fund-us
//
// Copyright ⓒ 2021-present Aral Balkan, Small Technology Foundation
// License: ISC.
//
////////////////////////////////////////////////////////////////////////////////
import { createHash } from 'crypto'
import cheerio from 'cheerio'
import fetch from 'node-fetch'
export default function sri () {
return {
name: 'vite-plugin-sri',
enforce: 'post',
apply: 'build',
async transformIndexHtml(html, context) {
const bundle = context.bundle
const calculateIntegrityHashes = async (element) => {
let source
let attributeName = element.attribs.src ? 'src' : 'href'
const resourcePath = element.attribs[attributeName]
if (resourcePath.startsWith('http')) {
// Load remote source from URL.
source = await (await fetch(resourcePath)).buffer()
} else {
// Load local source from bundle.
const resourcePathWithoutLeadingSlash = element.attribs[attributeName].slice(1)
const bundleItem = bundle[resourcePathWithoutLeadingSlash]
source = bundleItem.code || bundleItem.source
}
element.attribs.integrity = `sha384-${createHash('sha384').update(source).digest().toString('base64')}`
}
const $ = cheerio.load(html)
$.prototype.asyncForEach = async function (callback) {
for (let index = 0; index < this.length; index++) {
await callback(this[index], index, this);
}
}
// Implement SRI for scripts and stylesheets.
const scripts = $('script').filter('[src]')
const stylesheets = $('link[rel=stylesheet]').filter('[href]')
await scripts.asyncForEach(calculateIntegrityHashes)
await stylesheets.asyncForEach(calculateIntegrityHashes)
return $.html()
}
}
}