Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix handling of SVG #390

Merged
merged 2 commits into from
Aug 11, 2021
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 9 additions & 7 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import {promisify} from 'util';
import path from 'path';
import {Buffer} from 'node:buffer';
import {promises as fsPromises} from 'node:fs';
import {promisify} from 'node:util';
import path from 'node:path';
import fs from 'graceful-fs';
import {promises as fsPromises} from 'fs';
import FileType from 'file-type';
import globby from 'globby';
import {globby} from 'globby';
import pPipe from 'p-pipe';
import replaceExt from 'replace-ext';
import junk from 'junk';
Expand All @@ -19,14 +20,15 @@ const handleFile = async (sourcePath, {destination, plugins = []}) => {
let data = await readFile(sourcePath);
data = await (plugins.length > 0 ? pPipe(...plugins)(data) : data);

const {ext} = await FileType.fromBuffer(data);
// NOTE FT may not detect some extensions like `svg`
const {ext} = await FileType.fromBuffer(data) || {ext: path.extname(sourcePath)};
let destinationPath = destination ? path.join(destination, path.basename(sourcePath)) : undefined;
destinationPath = ext === 'webp' ? replaceExt(destinationPath, '.webp') : destinationPath;

const returnValue = {
data,
sourcePath,
destinationPath
destinationPath,
};

if (!destinationPath) {
Expand Down Expand Up @@ -56,7 +58,7 @@ export default async function imagemin(input, {glob = true, ...options} = {}) {
error.message = `Error occurred when handling file: ${input}\n\n${error.stack}`;
throw error;
}
})
}),
);
}

Expand Down
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@
"svg"
],
"dependencies": {
"file-type": "^14.6.0",
"globby": "^11.0.3",
"graceful-fs": "^4.2.6",
"file-type": "^16.5.3",
"globby": "^12.0.0",
"graceful-fs": "^4.2.8",
"junk": "^3.1.0",
"p-pipe": "^4.0.0",
"replace-ext": "^2.0.0"
Expand All @@ -42,6 +42,6 @@
"imagemin-webp": "^6.0.0",
"is-jpg": "^2.0.0",
"tempy": "^1.0.1",
"xo": "^0.39.1"
"xo": "^0.43.0"
}
}
43 changes: 27 additions & 16 deletions test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import fs, {promises as fsPromises} from 'fs';
import path from 'path';
import {fileURLToPath} from 'url';
import fs, {promises as fsPromises} from 'node:fs';
import path from 'node:path';
import {fileURLToPath} from 'node:url';
import del from 'del';
import imageminJpegtran from 'imagemin-jpegtran';
import imageminWebp from 'imagemin-webp';
Expand All @@ -15,7 +15,7 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
test('optimize a file', async t => {
const buffer = await fsPromises.readFile(path.join(__dirname, 'fixture.jpg'));
const files = await imagemin(['fixture.jpg'], {
plugins: [imageminJpegtran()]
plugins: [imageminJpegtran()],
});

t.is(files[0].destinationPath, undefined);
Expand All @@ -26,7 +26,7 @@ test('optimize a file', async t => {
test('optimize a buffer', async t => {
const buffer = await fsPromises.readFile(path.join(__dirname, 'fixture.jpg'));
const data = await imagemin.buffer(buffer, {
plugins: [imageminJpegtran()]
plugins: [imageminJpegtran()],
});

t.true(data.length < buffer.length);
Expand All @@ -35,7 +35,7 @@ test('optimize a buffer', async t => {

test('output error on corrupt images', async t => {
await t.throwsAsync(imagemin(['fixture-corrupt.jpg'], {
plugins: [imageminJpegtran()]
plugins: [imageminJpegtran()],
}), {message: /Corrupt JPEG data/});
});

Expand Down Expand Up @@ -72,12 +72,12 @@ test.failing('return processed buffer even it is a bad optimization', async t =>
plugins: [{
addAttributesToSVGElement: {
attributes: [{
xmlns: 'http://www.w3.org/2000/svg'
}]
}
}]
})
]
xmlns: 'http://www.w3.org/2000/svg',
}],
},
}],
}),
],
});

t.true(data.includes('xmlns="http://www.w3.org/2000/svg"'));
Expand All @@ -94,7 +94,7 @@ test('output at the specified location', async t => {

const files = await imagemin(['fixture.jpg', `${temporary}/*.jpg`], {
destination: destinationTemporary,
plugins: [imageminJpegtran()]
plugins: [imageminJpegtran()],
});

t.true(fs.existsSync(files[0].destinationPath));
Expand All @@ -107,13 +107,24 @@ test('set webp ext', async t => {
const temporary = tempy.file();
const files = await imagemin(['fixture.jpg'], {
destination: temporary,
plugins: [imageminWebp()]
plugins: [imageminWebp()],
});

t.is(path.extname(files[0].destinationPath), '.webp');
await del(temporary, {force: true});
});

test('set svg ext', async t => {
const temporary = tempy.file();
const files = await imagemin(['fixture.svg'], {
destination: temporary,
plugins: [imageminSvgo()],
});

t.is(path.extname(files[0].destinationPath), '.svg');
await del(temporary, {force: true});
});

test('ignores junk files', async t => {
const temporary = tempy.directory();
const destinationTemporary = tempy.directory();
Expand All @@ -126,7 +137,7 @@ test('ignores junk files', async t => {

await t.notThrowsAsync(imagemin([`${temporary}/*`], {
destination: destinationTemporary,
plugins: [imageminJpegtran()]
plugins: [imageminJpegtran()],
}));

t.true(fs.existsSync(path.join(destinationTemporary, 'fixture.jpg')));
Expand All @@ -139,7 +150,7 @@ test('ignores junk files', async t => {
test('glob option', async t => {
const files = await imagemin(['fixture.jpg'], {
glob: false,
plugins: [imageminJpegtran()]
plugins: [imageminJpegtran()],
});

t.true(isJpg(files[0].data));
Expand Down