-
Notifications
You must be signed in to change notification settings - Fork 9
/
css-b64-images.js
113 lines (105 loc) · 2.99 KB
/
css-b64-images.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
104
105
106
107
108
109
110
111
112
113
'use strict';
var fs = require('fs'),
Path = require('path'),
MAX_SIZE = 4096,
/* Adapted from https://gist.github.com/2594980 */
imgRegex = /url\s?\(['"]?(.*?)(?=['"]?\))/gi,
absoluteUrlRegex = /^\//,
externalUrlRegex = /http/,
mediatypes = {
'.eot' : 'application/vnd.ms-fontobject',
'.gif' : 'image/gif',
'.ico' : 'image/vnd.microsoft.icon',
'.jpg' : 'image/jpeg',
'.jpeg' : 'image/jpeg',
'.otf' : 'application/x-font-opentype',
'.png' : 'image/png',
'.svg' : 'image/svg+xml',
'.ttf' : 'application/x-font-ttf',
'.webp' : 'image/webp',
'.woff' : 'application/x-font-woff'
};
module.exports = {
fromFile: fromFile,
fromString: fromString
};
function fromString(css, relativePath, rootPath , options, cb) {
if(!cb) {
cb = options;
options = {maxSize: MAX_SIZE};
}
if(!css.replace && css.toString) css = css.toString();
var urls = [], match;
while (match = imgRegex.exec(css)) {
urls.push(match[1]);
}
forEachSeries(urls, base64img, function(err){
if(err) return cb(err, css);
cb(null, css);
});
function base64img(imageUrl, cb){
if(externalUrlRegex.test(imageUrl)) {
return cb(new Error('Skip ' + imageUrl + ' External file.'), css);
}
var imagePath;
if(absoluteUrlRegex.test(imageUrl)) {
imagePath = Path.join(rootPath, imageUrl.substr(1));
}else{
imagePath = Path.join(relativePath, imageUrl);
}
replaceUrlByB64(imageUrl, imagePath, css, options, function (err, newCss){
if(err) return cb(err, css);
css = newCss;
cb();
});
}
}
function fromFile(cssFile, root, options, cb) {
if(!cb) {
cb = options;
options = {maxSize: MAX_SIZE};
}
fs.readFile(cssFile, function(err, css){
if(err) return cb(err, css);
fromString(css.toString(), Path.dirname(cssFile), root, options, cb);
});
}
function replaceUrlByB64(imageUrl, imagePath, css, options, cb){
imagePath = imagePath.replace(/[?#].*/g, '');
fs.stat(imagePath, function(err, stat){
if(err) return cb(err, css);
if (stat.size > options.maxSize){
return cb(new Error('Skip ' + imageUrl + ' Exceed max size'), css);
}
fs.readFile(imagePath, 'base64', function(err, img){
if(err) return cb(err, css);
var ext = Path.extname(imagePath);
var newCss = css.replace(imageUrl, 'data:' + mediatypes[ext] + ';base64,' + img);
cb(null, newCss);
});
});
}
/* Adapted from async. Continue on error. */
function forEachSeries(arr, iterator, callback) {
callback = callback || function () {};
if (!arr.length) {
return callback();
}
var completed = 0, errs = [];
var iterate = function () {
iterator(arr[completed], function (err) {
if (err) {
errs.push(err);
}
completed += 1;
if (completed === arr.length) {
if(errs.length) return callback(errs);
callback(null);
}
else {
iterate();
}
});
};
iterate();
}