UNPKG

2.67 kBJavaScriptView Raw
1import {createFilter} from "rollup-pluginutils"
2import mime from "mime"
3import crypto from "crypto"
4import path from "path"
5import fs from "fs"
6
7const defaultInclude = [
8 "**/*.svg",
9 "**/*.png",
10 "**/*.jpg",
11 "**/*.gif",
12]
13
14export default function url(options = {}) {
15 const {
16 limit = 14 * 1024,
17 include = defaultInclude,
18 exclude,
19 publicPath = "",
20 emitFiles = true
21 } = options
22 const filter = createFilter(include, exclude)
23
24 const copies = Object.create(null)
25
26 return {
27 load(id) {
28 if (!filter(id)) {
29 return null
30 }
31 return Promise.all([
32 promise(fs.stat, id),
33 promise(fs.readFile, id),
34 ]).then(([stats, buffer]) => {
35 let data
36 if ((limit && stats.size > limit) || limit === 0) {
37 const hash = crypto.createHash("sha1")
38 .update(buffer)
39 .digest("hex")
40 .substr(0, 16)
41 const filename = hash + path.extname(id)
42 data = `${publicPath}${filename}`
43 copies[id] = filename
44 } else {
45 const mimetype = mime.lookup(id)
46 const isSVG = mimetype === "image/svg+xml"
47 data = isSVG
48 ? encodeSVG(buffer)
49 : buffer.toString("base64")
50 const encoding = isSVG ? "" : ";base64"
51 data = `data:${mimetype}${encoding},${data}`
52 }
53 return `export default "${data}"`
54 })
55 },
56 onwrite: function write(options) {
57 // Allow skipping saving files for server side builds.
58 if (!emitFiles) return
59
60 const base = path.dirname(options.dest)
61 return Promise.all(Object.keys(copies).map(name => {
62 const output = copies[name]
63 return copy(name, path.join(base, output))
64 }))
65 }
66 }
67}
68
69function promise(fn, ...args) {
70 return new Promise((resolve, reject) =>
71 fn(...args, (err, res) =>
72 err ? reject(err) : resolve(res)))
73}
74
75function copy(src, dest) {
76 return new Promise((resolve, reject) => {
77 const read = fs.createReadStream(src)
78 read.on("error", reject)
79 const write = fs.createWriteStream(dest)
80 write.on("error", reject)
81 write.on("finish", resolve)
82 read.pipe(write)
83 })
84}
85
86// https://github.com/filamentgroup/directory-encoder/blob/master/lib/svg-uri-encoder.js
87function encodeSVG(buffer) {
88 return encodeURIComponent(buffer.toString("utf-8")
89 // strip newlines and tabs
90 .replace(/[\n\r]/gmi, "")
91 .replace(/\t/gmi, " ")
92 // strip comments
93 .replace(/<!\-\-(.*(?=\-\->))\-\->/gmi, "")
94 // replace
95 .replace(/'/gmi, "\\i"))
96 // encode brackets
97 .replace(/\(/g, "%28").replace(/\)/g, "%29")
98}