Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@ var yellowLabTools = function(url, options) {

// If a screenshot saveFunction was provided in the options
if (options && typeof options.saveScreenshotFn === 'function') {
const screenshotTmpPath = data.params.options.screenshot;
debug('Now optimizing screenshot...');

// TODO: temporarily set all screenshot sizes to 600px, until we find a solution
ScreenshotHandler.findAndOptimizeScreenshot(data.params.options.screenshot, 600)
ScreenshotHandler.findAndOptimizeScreenshot(screenshotTmpPath, 600)

.then(function(screenshotBuffer) {
debug('Screenshot optimized, now saving...');
Expand Down
89 changes: 9 additions & 80 deletions lib/screenshotHandler.js
Original file line number Diff line number Diff line change
@@ -1,90 +1,19 @@
var debug = require('debug')('ylt:screenshotHandlerAgent');
var Jimp = require('jimp');
var debug = require('debug')('ylt:screenshotHandler');
var sharp = require('sharp');
var Q = require('q');
var fs = require('fs');
var path = require('path');

// Disable sharp cache to reduce the "disk is full" error on Amazon Lambda
sharp.cache(false);

var screenshotHandler = function() {

this.findAndOptimizeScreenshot = function(tmpScreenshotPath, width) {
var that = this;

debug('Starting screenshot transformation');

return this.openImage(tmpScreenshotPath)

.then(function(image) {
that.deleteTmpFile(tmpScreenshotPath);
return that.resizeImage(image, width);
})

.then(this.toBuffer);
};


this.openImage = function(imagePath) {
var deferred = Q.defer();

Jimp.read(imagePath, function(err, image){
if (err) {
debug('Could not open imagePath %s', imagePath);
debug(err);

deferred.reject(err);
} else {
debug('Image correctly open');
deferred.resolve(image);
}
});

return deferred.promise;
};


this.resizeImage = function(image, newWidth) {
var deferred = Q.defer();

var currentWidth = image.bitmap.width;

if (currentWidth > 0) {
var ratio = newWidth / currentWidth;

image.scale(ratio, function(err, image){
if (err) {
debug('Could not resize image');
debug(err);

deferred.reject(err);
} else {
debug('Image correctly resized');
deferred.resolve(image);
}
});
} else {
deferred.reject('Could not resize an empty image');
}

return deferred.promise;
};


this.toBuffer = function(image) {
var deferred = Q.defer();

image.quality(85).getBuffer(Jimp.MIME_JPEG, function(err, buffer){
if (err) {
debug('Could not save image to buffer');
debug(err);

deferred.reject(err);
} else {
debug('Image correctly transformed to buffer');
deferred.resolve(buffer);
}
});

return deferred.promise;
this.findAndOptimizeScreenshot = async function(tmpScreenshotPath, width) {
return sharp(tmpScreenshotPath)
.resize({width: 600})
.jpeg({quality: 85})
.toBuffer();
};


Expand Down
77 changes: 23 additions & 54 deletions lib/tools/redownload/contentTypeChecker.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,12 @@
var debug = require('debug')('ylt:contentTypeChecker');
var Q = require('q');
var isJpg = require('is-jpg');
var isPng = require('is-png');
var isSvg = require('is-svg');
var isGif = require('is-gif');
var isWebp = require('is-webp');
var isWoff = require('is-woff');
var isWoff2 = require('is-woff2');
var isOtf = require('is-otf');
var isTtf = require('is-ttf');
var isEot = require('is-eot');
var isJson = require('is-json');
var debug = require('debug')('ylt:contentTypeChecker');
var Q = require('q');
var FileType = require('file-type');
var isSvg = require('is-svg');
var isJson = require('is-json');

var ContentTypeChecker = function() {

function checkContentType(entry) {
async function checkContentType(entry) {
var deferred = Q.defer();

// Setting isSomething values:
Expand Down Expand Up @@ -55,12 +47,12 @@ var ContentTypeChecker = function() {
var foundType;

try {
foundType = findContentType(entry.weightCheck.bodyBuffer);
foundType = await findContentType(entry.weightCheck.bodyBuffer);

// If it's an image or a font, then rewrite.
if (foundType !== null && (foundType.type === 'image' || foundType.type === 'webfont' || foundType.type === 'json')) {
if (foundType.type !== entry.type) {
debug('Content type %s is wrong for %s. It should be %s.', entry.type, entry.ulr, foundType.type);
debug('Content type %s is wrong for %s. It should be %s.', entry.type, entry.url, foundType.type);
}
rewriteContentType(entry, foundType);
}
Expand All @@ -76,54 +68,23 @@ var ContentTypeChecker = function() {
return deferred.promise;
}

function findContentType(bodyBuffer) {
async function findContentType(bodyBuffer) {
var bodyStr = bodyBuffer.toString();

if (isJpg(bodyBuffer)) {
return contentTypes.jpeg;
}

if (isPng(bodyBuffer)) {
return contentTypes.png;
}

// https://github.com/sindresorhus/is-svg/issues/7
if (/<svg/.test(bodyStr) && isSvg(bodyStr)) {
return contentTypes.svg;
}

if (isGif(bodyBuffer)) {
return contentTypes.gif;
}

if (isWebp(bodyBuffer)) {
return contentTypes.webp;
}

if (isWoff(bodyBuffer)) {
return contentTypes.woff;
}

if (isWoff2(bodyBuffer)) {
return contentTypes.woff2;
}

if (isOtf(bodyBuffer)) {
return contentTypes.otf;
}

if (isTtf(bodyBuffer)) {
return contentTypes.ttf;
}

if (isEot(bodyBuffer)) {
return contentTypes.eot;
}

if (isJson(bodyStr)) {
return contentTypes.json;
}

const type = await FileType.fromBuffer(bodyBuffer);
if (type && type.ext && contentTypes[type.ext]) {
return contentTypes[type.ext];
}

return null;
}

Expand All @@ -146,7 +107,7 @@ var ContentTypeChecker = function() {
}

var contentTypes = {
jpeg: {
jpg: {
type: 'image',
mimes: ['image/jpeg'],
updateFn: function(entry) {
Expand Down Expand Up @@ -187,6 +148,14 @@ var ContentTypeChecker = function() {
entry.isImage = true;
}
},
avif: {
type: 'image',
mimes: ['image/avif'],
updateFn: function(entry) {
entry.type = 'image';
entry.isImage = true;
}
},
woff: {
type: 'webfont',
mimes: ['application/x-font-woff', 'application/font-woff', 'font/woff'],
Expand Down
4 changes: 4 additions & 0 deletions lib/tools/redownload/imageDimensions.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ var ImageDimensions = function() {
return entry.isImage && entry.contentType === 'image/png';
}

function isWebP(entry) {
return entry.isImage && entry.contentType === 'image/webp';
}

return {
getDimensions: getDimensions
};
Expand Down
4 changes: 2 additions & 2 deletions lib/tools/redownload/redownload.js
Original file line number Diff line number Diff line change
Expand Up @@ -819,9 +819,9 @@ var Redownload = function() {

debug('Downloading %s', entry.url);

// Always add compression and webp headers before sending, in case the server listens to them
// Always add compression and webp/avif headers before sending, in case the server listens to them
var reqHeaders = [];
reqHeaders['Accept'] = '*/*,image/webp';
reqHeaders['Accept'] = '*/*,image/webp,image/avif';
reqHeaders['Accept-Encoding'] = 'gzip, deflate, br';
reqHeaders['Connection'] = 'keep-alive';
reqHeaders['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36';
Expand Down
13 changes: 2 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "yellowlabtools",
"version": "3.0.0",
"version": "3.0.1",
"description": "A tool that audits a webpage for performance and front-end quality issues",
"license": "GPL-2.0",
"author": {
Expand All @@ -26,6 +26,7 @@
"css-mq-parser": "0.0.3",
"debug": "4.3.4",
"easyxml": "2.0.1",
"file-type": "16.5.3",
"fontkit": "2.0.2",
"html-minifier": "4.0.0",
"image-size": "1.0.2",
Expand All @@ -34,18 +35,8 @@
"imagemin-jpegtran": "7.0.0",
"imagemin-optipng": "8.0.0",
"imagemin-svgo": "9.0.0",
"is-eot": "1.0.0",
"is-gif": "3.0.0",
"is-jpg": "2.0.0",
"is-json": "2.0.1",
"is-otf": "0.1.2",
"is-png": "1.1.0",
"is-svg": "3.0.0",
"is-ttf": "0.2.2",
"is-webp": "1.0.1",
"is-woff": "1.0.3",
"is-woff2": "1.0.0",
"jimp": "0.22.8",
"md5": "2.3.0",
"meow": "5.0.0",
"parse-color": "1.0.0",
Expand Down