Skip to content

Commit

Permalink
refactor: make code faster and cleaner
Browse files Browse the repository at this point in the history
  • Loading branch information
bhovhannes committed Nov 29, 2020
1 parent 770c8da commit b5ffa23
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 34 deletions.
61 changes: 36 additions & 25 deletions src/loader.js
Original file line number Diff line number Diff line change
@@ -1,60 +1,71 @@
const { getOptions, parseQuery } = require("loader-utils");

const REGEX_STYLE = /<style[\s\S]*?>[\s\S]*?<\/style>/i;
const REGEX_DECLARATION = /^\s*<\?xml [^>]*>\s*/i;

const REGEX_DOUBLE_QUOTE = /"/g;
const REGEX_XML_DECLARATION = /^\s*<\?xml [^>]*>\s*/i;
const REGEX_MULTIPLE_SPACES = /\s+/g;
const REGEX_DOUBLE_QUOTE = /"/g;
const REGEX_UNSAFE_CHARS = /[{}\|\\\^~\[\]`"<>#%]/g;

module.exports = function (content) {
this.cacheable && this.cacheable();

let query = {
...{
encoding: "none",
},
encoding: "none",
stripdeclarations: true,
...getOptions(this),
...(this.resourceQuery ? parseQuery(this.resourceQuery) : undefined),
};

let limit = query.limit ? parseInt(query.limit, 10) : 0;

if (limit <= 0 || content.length < limit) {
let newContent = content.toString("utf8");
const originalSvgSource = content.toString("utf8");

let hasStyleElement = REGEX_STYLE.test(newContent);

if (!("stripdeclarations" in query) || query.stripdeclarations) {
newContent = newContent.replace(REGEX_DECLARATION, "");
}
newContent = newContent.replace(REGEX_MULTIPLE_SPACES, " ");
const transformedSvgSource = applyGeneralTransforms(
originalSvgSource,
query.stripdeclarations
);

let data;
if (query.encoding === "base64") {
if (typeof newContent === "string") {
newContent = Buffer.from(newContent);
}
data = "data:image/svg+xml;base64," + newContent.toString("base64");
data =
"data:image/svg+xml;base64," +
Buffer.from(transformedSvgSource).toString("base64");
} else {
newContent = newContent.replace(REGEX_DOUBLE_QUOTE, "'");
newContent = newContent.replace(REGEX_UNSAFE_CHARS, function (match) {
return "%" + match[0].charCodeAt(0).toString(16).toUpperCase();
});

data = "data:image/svg+xml," + newContent.trim();
data = "data:image/svg+xml," + uriEncode(transformedSvgSource);
}

if (!(query.iesafe && hasStyleElement && data.length > 4096)) {
if (
!query.iesafe ||
data.length <= 4096 ||
!REGEX_STYLE.test(originalSvgSource)
) {
return "module.exports = " + JSON.stringify(data);
}
}

const fileLoader = require("file-loader");
const childContext = Object.create(this);
childContext.query = Object.assign({}, query);
// childContext.query.esModule = false;
return fileLoader.call(childContext, content);
};

module.exports.raw = true;

function uriEncodeMatch(match) {
return "%" + match[0].charCodeAt(0).toString(16).toLowerCase();
}

function uriEncode(svgSource) {
svgSource = svgSource.replace(REGEX_DOUBLE_QUOTE, "'");
svgSource = svgSource.replace(REGEX_UNSAFE_CHARS, uriEncodeMatch);
return svgSource.trim();
}

function applyGeneralTransforms(svgSource, stripXmlDeclaration) {
if (stripXmlDeclaration) {
svgSource = svgSource.replace(REGEX_XML_DECLARATION, "");
}
svgSource = svgSource.replace(REGEX_MULTIPLE_SPACES, " ");
return svgSource;
}
18 changes: 9 additions & 9 deletions test/loader.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ describe("svg-url-loader", function () {

await runWebpack(config);
const encoded = await evaluateGeneratedBundle();
expect(encoded).toContain("%3C?xml version='1.0' encoding='UTF-8'?%3E");
expect(encoded).toContain("%3c?xml version='1.0' encoding='UTF-8'?%3e");
});

it("if turned on - should do nothing to an SVG that doesn't have an XML declaration", async () => {
Expand All @@ -84,7 +84,7 @@ describe("svg-url-loader", function () {

await runWebpack(config);
const encoded = await evaluateGeneratedBundle();
expect(encoded.startsWith("data:image/svg+xml,%3Csvg")).toBe(true);
expect(encoded.startsWith("data:image/svg+xml,%3csvg")).toBe(true);
});

it("if turned on - should remove XML declaration from a file that has one", async () => {
Expand All @@ -97,9 +97,9 @@ describe("svg-url-loader", function () {
await runWebpack(config);
const encoded = await evaluateGeneratedBundle();
expect(encoded).not.toContain(
'%3C?xml version="1.0" encoding="UTF-8"?%3E'
'%3c?xml version="1.0" encoding="UTF-8"?%3e'
);
expect(encoded.startsWith("data:image/svg+xml,%3Csvg")).toBe(true);
expect(encoded.startsWith("data:image/svg+xml,%3csvg")).toBe(true);
});
});

Expand Down Expand Up @@ -136,7 +136,7 @@ describe("svg-url-loader", function () {
await runWebpack(config);
const encoded = await evaluateGeneratedBundle();
expect(encoded.default.toString()).toContain(
'background-image: url("data:image/svg+xml,%3Csvg'
'background-image: url("data:image/svg+xml,%3csvg'
);
});

Expand All @@ -153,7 +153,7 @@ describe("svg-url-loader", function () {
await runWebpack(config);
const encoded = await evaluateGeneratedBundle();
expect(encoded.default.toString()).toContain(
'background-image: url("data:image/svg+xml,%3Csvg'
'background-image: url("data:image/svg+xml,%3csvg'
);
});

Expand All @@ -170,7 +170,7 @@ describe("svg-url-loader", function () {
await runWebpack(config);
const encoded = await evaluateGeneratedBundle();
expect(encoded.default.toString()).toContain(
'background-image: url("data:image/svg+xml,%3Csvg'
'background-image: url("data:image/svg+xml,%3csvg'
);
});
});
Expand All @@ -185,7 +185,7 @@ describe("svg-url-loader", function () {

await runWebpack(config);
const encoded = await evaluateGeneratedBundle();
expect(encoded.startsWith("data:image/svg+xml,%3Csvg")).toBe(true);
expect(encoded.startsWith("data:image/svg+xml,%3csvg")).toBe(true);
expect(encoded.length).toBeLessThan(4096);
});

Expand All @@ -198,7 +198,7 @@ describe("svg-url-loader", function () {

await runWebpack(config);
const encoded = await evaluateGeneratedBundle();
expect(encoded.startsWith("data:image/svg+xml,%3Csvg")).toBe(true);
expect(encoded.startsWith("data:image/svg+xml,%3csvg")).toBe(true);
expect(encoded.length).toBeGreaterThan(4096);
});

Expand Down

0 comments on commit b5ffa23

Please sign in to comment.