Skip to content

Commit

Permalink
css enhance & test
Browse files Browse the repository at this point in the history
  • Loading branch information
rehorn committed Mar 27, 2013
1 parent 6bf8a9e commit ceda8d3
Show file tree
Hide file tree
Showing 10 changed files with 220 additions and 30 deletions.
191 changes: 161 additions & 30 deletions lib/cmd/css/index.js
Original file line number Diff line number Diff line change
@@ -1,77 +1,208 @@

var nopo = require('../../core'),
_ = nopo.util._,
file = nopo.file,
logger = nopo.logger,
util = nopo.util,
path = require('path'),
fs = require('fs');
fs = require('fs'),
crypto = require('crypto'),
querystring = require('querystring'),
existsSync = fs.existsSync || path.existsSync;

var urlPattern = /url\(([^\)]+)\)/g;
var isWindows = process.platform === 'win32';
var _opt = {};
var cycleList = [], cycleIndex = 0;

function parseImageUrl(url){
function parseImageUrl(url, rel) {
var tokens = url.replace(/['"]/g, '').split('?');
var query = tokens[1] ? querystring.parse(tokens[1]) : {};
var imagePath = path.normalize(tokens[0]);
var absolutePath = path.join(this.options.rootPath, imagePath);
var absolutePath = path.resolve(path.join(rel, imagePath));
var relPath = path.relative(process.cwd(), absolutePath);

if(isWindows && imagePath.indexOf('data:image') < 0){
if (isWindows && imagePath.indexOf('data:image') < 0) {
imagePath = imagePath.replace(/\\/g, '/');
relPath = relPath.replace(/\\/g, '/');
}

return {
relative: imagePath,
root: rel,
origin: imagePath,
relative: relPath,
absolute: absolutePath,
query: query,
exists: existsSync(absolutePath)
};
}

// enhance-css
function enhanceCss(css){
var data = { original: css };
var embedUrls = {};
function enhanceCss(css, filepath) {
var cssDir = path.dirname(filepath);
var data = {
origin: css
};
var duplicateUrls = {};
var allUrls = [];
var dHost = {};
var md5Mark = '';

// parse all images & duplicate images
(css.match(urlPattern) || []).forEach(function(match) {
var url = match.substring(4, match.length - 1);
var pathInfo = parseImageUrl(url, cssDir);

(css.match(this.urlPattern) || []).forEach(function(url){
var pathInfo = parseImageUrl(url.substring(4, url.length - 1));
if(duplicateUrls[pathInfo.absolute]){
duplicateUrls[pathInfo.absolute]++;
}else{
duplicateUrls[pathInfo.absolute] = 1;
}

if (pathInfo.query.embed !== undefined) {
if (embedUrls[pathInfo.relative])
embedUrls[pathInfo.relative]++;
else
embedUrls[pathInfo.relative] = 1;
}
allUrls.push(pathInfo);

allUrls.push(pathInfo);
if(_opt.addMark){
md5Mark += getFileHex(pathInfo.absolute);
}
});

return css;
data.result = css.replace(urlPattern, function(match, url){
// // data uri
var pathInfo = parseImageUrl(url, cssDir);

// skip remote / not-exists images
if(!pathInfo.exists){
return match;
}

// datauri & !exclude & 跳过重复并且url重复了
if(_opt.dataUri &&
!file.isMatch(_opt.exclude, pathInfo.relative) &&
!(_opt.skipDuplicate && duplicateUrls[pathInfo.absolute] > 1))
{
var type = path.extname(pathInfo.origin).substring(1);
if(type == 'jpg'){
type = 'jpeg';
}
if(type == 'svg'){
type = 'svg+xml';
}

if (!/(jpeg|gif|png|svg\+xml)/.test(type)){
return match;
}

var base64 = fs.readFileSync(pathInfo.absolute).toString('base64');

return "url(data:image/" + type + ";base64," + base64 + ")";
}

// stamp
if(_opt.stamp){
var host = (getNextAssetHost() || '');
if(duplicateUrls[pathInfo.absolute] > 1){
host = dHost[pathInfo.absolute] || host;
dHost[pathInfo.absolute] = host;
}

addFileStamp(pathInfo);

return ['url(', host , pathInfo.stamp, ')'].join('');
}

});

// addMark
if(_opt.addMark){
var encrypted = crypto.createHash('md5');
encrypted.update(md5Mark);
data.result += '\r\n#nopo-build-generate-mark{content: "' + encrypted.digest('hex') + '";}';
}

return data.result;
}

function getFileHex(absolute){
var source = fs.readFileSync(absolute);
var encrypted = crypto.createHash('md5');

encrypted.update(source.toString('utf8'));
var stamp = encrypted.digest('hex');
return stamp;
}

function getNextAssetHost() {
var hosts = _opt.assetHosts;
if(!hosts){
return '';
}

if(hosts.indexOf('[') == -1){
return fixAssetHost(hosts);
}

var start = hosts.indexOf('[');
var end = hosts.indexOf(']');
var pattern = hosts.substring(start + 1, end);

pattern.split(',').forEach(function(version) {
cycleList.push(hosts.replace(/\[([^\]])+\]/, version));
});

if(cycleIndex == cycleList.length){
cycleIndex = 0;
}
return fixAssetHost(cycleList[cycleIndex++]);
};

function fixAssetHost(host){
if(/^http:\/\//.test(host) || /^https:\/\//.test(host) || /^\/\//.test(host)) {
return host;
}
return '//' + host;
};

function addFileStamp(pathInfo){
pathInfo.stamp = pathInfo.relative;
if(_opt.cryptedStamp){
pathInfo.stamp += "?v=" + getFileHex(pathInfo.absolute).substring(0, 8);
} else {
pathInfo.stamp += "?v=" + Date.parse(fs.statSync(pathInfo.absolute).mtime) / 1000;
}
return pathInfo;
};

exports.run = function(cmdConfig, callback) {

var source = cmdConfig.source,
target = cmdConfig.target;

var options = {
stamp: 1, // 是否为图片增加修改时间搓 ?m=
cryptedStamp: 0, // 使用md5作为时间戳
assetHosts: null, // 为图片增加cdn host随机前准 qplus[0,9].idqqimg.com
dataUri: 0, // 把图片资源base64后插入
mhtmlUri: 0, // ie6,7,8 support base64
exclude: [], // dataUri exclude list
addMark: 1 // 是否增加一个nopo-build规则,content为处理时间、图片md5等信息
// 是否为图片增加修改时间搓 ?m=
stamp: 1,
// 使用md5作为时间戳
cryptedStamp: 0,
// 为图片增加cdn host随机前准 qplus[0,9].idqqimg.com
assetHosts: null,
// 把图片资源base64后插入,优先级高于stamp
dataUri: 0,
// ie6,7,8 support base64
// mhtmlUri: 0,
// dataUri exclude list
exclude: [],
// 是否跳过
skipDuplicate: 1,
// 是否增加一个nopo-build规则,content为处理时间、图片md5等信息
addMark: 1
};
_.extend(options, cmdConfig.options);
_opt = options;

var fileMap = file.getFilesSourceTargetMap(source, target);

fileMap.files.forEach(function(item){
fileMap.files.forEach(function(item) {
var from = item,
to = fileMap[from];

var css = file.read(from);
css = enhanceCss(css);
css = enhanceCss(css, from);
file.write(to, css);
});

Expand Down
2 changes: 2 additions & 0 deletions lib/cmd/css/readme
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
add cache buster using timestamp or hash
### base64 datauri
change refer images to base64
todo: mhtml fallback for ie6/7
https://github.com/josephj/dataurize/blob/master/dataurize
### host
cdn host assets, relative -> multi host assets
### mark
Expand Down
1 change: 1 addition & 0 deletions lib/nopo/file.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ var processPatterns = function(patterns, fn) {
};

exports.match = function(patterns, filepaths, options) {
options = options || {};
if (patterns == null || filepaths == null) {
return [];
}
Expand Down
24 changes: 24 additions & 0 deletions test/nopo-test6/css/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@

.test_css{
background-image: url(../img/test.png?v=20120312);
width: 45px;
height: 45px;
}

.test_css2{
background-image: url(../img/test2.png);
width: 45px;
height: 45px;
}

.test_css4{
background-image: url(../img/test2.png);
width: 45px;
height: 45px;
}

.test_css3{
background-image: url(../img/test3.png);
width: 45px;
height: 45px;
}
Binary file added test/nopo-test6/img/test.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/nopo-test6/img/test2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/nopo-test6/img/test3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions test/nopo-test6/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test manifest</title>
<link rel="stylesheet" href="css/style.css?v=20130101" media="all">
</head>
<body>
<script src="js/main.js?v=20130101"></script>
</body>
</html>
5 changes: 5 additions & 0 deletions test/nopo-test6/js/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

// test function
(function(){
return true;
})(window);
16 changes: 16 additions & 0 deletions test/nopo-test6/nopo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module.exports = {
"tasks": {
"enhancecss":{
"cmd": "css",
"source": "css/",
"@css": {
"stamp": 1,
"cryptedStamp": 1,
"assetHosts": "http://qplus[0,1,2,3,4,5,6,7,8,9].idqqimg.com/pub/",
"dataUri": 1,
"exclude": ["img/test3.png"],
"skipDuplicate": 1
}
}
}
}

0 comments on commit ceda8d3

Please sign in to comment.