Comparing version 0.3.1 to 0.4.0
18
index.js
@@ -17,12 +17,10 @@ /* | ||
var os = require('os'); | ||
var crypto = require('crypto'); | ||
var uuid = require('uuid'); | ||
// promisify fs | ||
// promisify fs and penthouse | ||
Promise.promisifyAll(fs); | ||
var penthouseAsync = Promise.promisify(penthouse); | ||
/** | ||
@@ -35,4 +33,3 @@ * Critical path CSS generation | ||
exports.generate = function (opts, cb) { | ||
var seed = crypto.randomBytes(20); | ||
var TMPCSS = crypto.createHash('md5').update(seed).digest('hex'); | ||
var TMPCSS = '.' + uuid.v4(); | ||
opts = opts || {}; | ||
@@ -75,6 +72,11 @@ cb = cb || function () {}; | ||
var dir = path.dirname(fileName); | ||
var inlined = imageInliner.css(content.toString(), { maxImageFileSize: 10240, cssBasePath: dir, rootImagePath: opts.base }); | ||
var maxFileSize = opts.maxImageFileSize || 10240; | ||
// #40 already inlined background images cause problems with imageinliner | ||
if (opts.inlineImages) { | ||
content = imageInliner.css(content.toString(), { maxImageFileSize: maxFileSize, cssBasePath: dir, rootImagePath: opts.base }); | ||
} | ||
// normalize relative paths | ||
return inlined.toString().replace(/url\(['"]?([^'"\)]+)['"]?\)/g, function (match, filePath) { | ||
return content.toString().replace(/url\(['"]?([^'"\)]+)['"]?\)/g, function (match, filePath) { | ||
// do nothing for absolute paths, urls and data-uris | ||
@@ -81,0 +83,0 @@ if (/^data\:/.test(filePath) || /(?:^\/)|(?:\:\/\/)/.test(filePath)) { |
/* | ||
This is a fork of the inline-styles module by @maxogden | ||
with support for minification. The original module can be | ||
found here: https://github.com/maxogden/inline-styles | ||
*/ | ||
This is a fork of the inline-styles module by @maxogden | ||
with support for minification. The original module can be | ||
found here: https://github.com/maxogden/inline-styles | ||
*/ | ||
"use strict"; | ||
var cheerio = require('cheerio'); | ||
@@ -14,67 +14,75 @@ var path = require('path'); | ||
module.exports = function(html, opts) { | ||
var base = opts.base || process.cwd(); | ||
var minify = opts.minify; | ||
var maxImageSize = opts.maxImageFileSize || 10240; | ||
var dom = cheerio.load(String(html)); | ||
injectStyles(dom); | ||
return new Buffer(dom.html()); | ||
module.exports = function (html, opts) { | ||
var base = opts.base || process.cwd(); | ||
var minify = opts.minify; | ||
var maxImageSize = opts.maxImageFileSize || 10240; | ||
var dom = cheerio.load(String(html)); | ||
injectStyles(dom); | ||
return new Buffer(dom.html()); | ||
function injectStyles(dom) { | ||
var styles = []; | ||
dom('link').each(function(idx, el) { | ||
el = dom(el); | ||
var href = el.attr('href'); | ||
if (el.attr('rel') === 'stylesheet' && isLocal(href)) { | ||
var dir = base + path.dirname(href); | ||
var file = path.join(base, href); | ||
var style = fs.readFileSync(file); | ||
var inlined = inliner.css(style.toString(), { maxImageFileSize: maxImageSize, cssBasePath: dir }); | ||
var inlinedStyles = inlined.toString(); | ||
if (minify) { | ||
inlinedStyles = new CleanCSS().minify(inlinedStyles); | ||
} | ||
function injectStyles(dom) { | ||
dom('link').each(function (idx, el) { | ||
el = dom(el); | ||
var href = el.attr('href'); | ||
if (el.attr('rel') === 'stylesheet' && isLocal(href)) { | ||
var dir = base + path.dirname(href); | ||
var file = path.join(base, href); | ||
var style = fs.readFileSync(file); | ||
var inlinedStyles; | ||
// #40 already inlined background images cause problems with imageinliner | ||
if (opts.inlineImages) { | ||
var inlined = inliner.css(style.toString(), { maxImageFileSize: maxImageSize, cssBasePath: dir }); | ||
inlinedStyles = inlined.toString(); | ||
} else { | ||
inlinedStyles = style.toString() | ||
} | ||
if (minify) { | ||
inlinedStyles = new CleanCSS().minify(inlinedStyles); | ||
} | ||
inlinedStyles = rebaseRelativePaths(base, dir, inlinedStyles); | ||
inlinedStyles = rebaseRelativePaths(base, dir, inlinedStyles); | ||
var inlinedTag = "<style>\n" + inlinedStyles + '\n</style>'; | ||
el.replaceWith(inlinedTag); | ||
} | ||
}) | ||
} | ||
var inlinedTag = "<style>\n" + inlinedStyles + '\n</style>'; | ||
el.replaceWith(inlinedTag); | ||
} | ||
}); | ||
} | ||
function isLocal(href) { | ||
return href && !url.parse(href).hostname; | ||
} | ||
function isLocal(href) { | ||
return href && !url.parse(href).hostname; | ||
} | ||
function rebaseRelativePaths(basePath, cssPath, cssStr){ | ||
var base, | ||
beginsWith, | ||
nests, | ||
newPath; | ||
var paths = cssStr.match(/url\((.+?)\)/g); | ||
var pathDiff = cssPath.replace(basePath).split("/").length; | ||
function rebaseRelativePaths(basePath, cssPath, cssStr) { | ||
var beginsWith, | ||
newPath; | ||
if(paths){ | ||
for(var i=0, j=paths.length; i<j; i++){ | ||
paths[i] = paths[i].match(/url\((.+?)\)/)[1]; | ||
var paths = cssStr.match(/url\((.+?)\)/g); | ||
var pathDiff = cssPath.replace(basePath).split("/").length; | ||
beginsWith = paths[i].split('/')[0].replace(/['"]/, ""); | ||
if (paths) { | ||
for (var i = 0, j = paths.length; i < j; i++) { | ||
paths[i] = paths[i].match(/url\((.+?)\)/)[1]; | ||
if(beginsWith === '..'){ | ||
newPath = paths[i]; | ||
for(var k=0; k < pathDiff; k++){ | ||
newPath = newPath.replace("../", ""); | ||
} | ||
cssStr = cssStr.replace(paths[i], newPath); | ||
}else{ | ||
// the relative path is within the cssPath, so append it | ||
newPath = cssPath.replace(basePath, "") + "/" + paths[i].replace(/['"]/g, ""); | ||
cssStr = cssStr.replace(paths[i], newPath); | ||
// do nothing for absolute paths, urls and data-uris | ||
if (/^data\:/.test(paths[i]) || /(?:^\/)|(?:\:\/\/)/.test(paths[i])) { | ||
continue; | ||
} | ||
beginsWith = paths[i].split('/')[0].replace(/['"]/, ""); | ||
if (beginsWith === '..') { | ||
newPath = paths[i]; | ||
for (var k = 0; k < pathDiff; k++) { | ||
newPath = newPath.replace("../", ""); | ||
} | ||
cssStr = cssStr.replace(paths[i], newPath); | ||
} else { | ||
// the relative path is within the cssPath, so append it | ||
newPath = cssPath.replace(basePath, "") + "/" + paths[i].replace(/['"]/g, ""); | ||
cssStr = cssStr.replace(paths[i], newPath); | ||
} | ||
} | ||
} | ||
} | ||
return cssStr; | ||
} | ||
return cssStr; | ||
} | ||
}; |
{ | ||
"name": "critical", | ||
"version": "0.3.1", | ||
"version": "0.4.0", | ||
"description": "Extract & Inline Critical-path CSS from HTML", | ||
@@ -31,7 +31,9 @@ "author": "Addy Osmani", | ||
"oust": "^0.2.0", | ||
"penthouse": "^0.2.5" | ||
"penthouse": "^0.2.5", | ||
"uuid": "~2.0.1" | ||
}, | ||
"devDependencies": { | ||
"async": "^0.9.0", | ||
"mocha": "*" | ||
} | ||
} |
@@ -13,2 +13,7 @@ # critical [![Build Status](https://travis-ci.org/addyosmani/critical.svg?branch=master)](https://travis-ci.org/addyosmani/critical) | ||
## Build plugins | ||
* [grunt-critical](https://github.com/bezoerb/grunt-critical) | ||
* Gulp users should use Critical directly | ||
## Demo projects | ||
@@ -146,2 +151,3 @@ | ||
| htmlTarget | `string` | (`generateInline` only) Destination for (critical-path CSS) style-inlined HTML | | ||
| inlineImages | `boolean` | Inline images (default: false) | ||
| maxImageFileSize | `integer` | Sets a max file size (in bytes) for base64 inlined images | ||
@@ -148,0 +154,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
17156
264
212
8
2
+ Addeduuid@~2.0.1
+ Addeduuid@2.0.3(transitive)