Skip to content

Commit

Permalink
fix: adding quotes when necessary for unquoted sources (#247)
Browse files Browse the repository at this point in the history
  • Loading branch information
evilebottnawi committed Mar 5, 2020
1 parent e3727ab commit d0b0150
Show file tree
Hide file tree
Showing 13 changed files with 788 additions and 180 deletions.
29 changes: 18 additions & 11 deletions src/plugins/attribute-plugin.js
Expand Up @@ -415,15 +415,20 @@ export default (options) =>
{
attributesMeta: {},
onattribute(name, value) {
this.attributesMeta[name] = {
// eslint-disable-next-line no-underscore-dangle
startIndex: parser._tokenizer._index - value.length,
};
// eslint-disable-next-line no-underscore-dangle
const endIndex = parser._tokenizer._index;
const startIndex = endIndex - value.length;
const unquoted = html[endIndex] !== '"' && html[endIndex] !== "'";

this.attributesMeta[name] = { startIndex, unquoted };
},
onopentag(tag, attributes) {
Object.keys(attributes).forEach((attribute) => {
const value = attributes[attribute];
const valueStartIndex = this.attributesMeta[attribute].startIndex;
const {
startIndex: valueStartIndex,
unquoted,
} = this.attributesMeta[attribute];

// TODO use code frame for errors

Expand Down Expand Up @@ -458,7 +463,7 @@ export default (options) =>

const startIndex = valueStartIndex + source.startIndex;

sources.push({ startIndex, value: source.value });
sources.push({ startIndex, value: source.value, unquoted });
});

return;
Expand All @@ -484,7 +489,7 @@ export default (options) =>

const startIndex = valueStartIndex + source.startIndex;

sources.push({ startIndex, value: source.value });
sources.push({ startIndex, value: source.value, unquoted });
});

this.attributesMeta = {};
Expand All @@ -510,7 +515,8 @@ export default (options) =>
let index = 0;

for (const source of sources) {
const uri = parse(source.value);
const { value, startIndex, unquoted } = source;
const uri = parse(value);

if (typeof uri.hash !== 'undefined') {
uri.hash = null;
Expand All @@ -526,16 +532,17 @@ export default (options) =>
type: 'attribute',
replacementName,
source: decodeURIComponent(source.value),
unquoted,
},
});

// eslint-disable-next-line no-param-reassign
html =
html.substr(0, source.startIndex + offset) +
html.substr(0, startIndex + offset) +
replacementName +
html.substr(source.startIndex + source.value.length + offset);
html.substr(startIndex + value.length + offset);

offset += replacementName.length - source.value.length;
offset += replacementName.length - value.length;
index += 1;
}

Expand Down
8 changes: 4 additions & 4 deletions src/runtime/getUrl.js
@@ -1,14 +1,14 @@
module.exports = (url) => {
module.exports = (url, maybeNeedQuotes) => {
// eslint-disable-next-line no-underscore-dangle, no-param-reassign
url = url && url.__esModule ? url.default : url;

if (typeof url !== 'string') {
return url;
}

// if (/[\t\n\f\r "'=<>`]/.test(url)) {
// return `"${url}"`;
// }
if (maybeNeedQuotes && /[\t\n\f\r "'=<>`]/.test(url)) {
return `"${url}"`;
}

return url;
};
7 changes: 5 additions & 2 deletions src/utils.js
Expand Up @@ -71,11 +71,14 @@ export function getExportCode(html, replacers, options) {
}

for (const replacer of replacers) {
const { replacementName } = replacer;
const { replacementName, unquoted } = replacer;

exportCode = exportCode.replace(
new RegExp(replacementName, 'g'),
() => `" + ___HTML_LOADER_GET_URL_IMPORT___(${replacementName}) + "`
() =>
`" + ___HTML_LOADER_GET_URL_IMPORT___(${replacementName}${
unquoted ? ', true' : ''
}) + "`
);
}

Expand Down
386 changes: 312 additions & 74 deletions test/__snapshots__/attributes-option.test.js.snap

Large diffs are not rendered by default.

138 changes: 111 additions & 27 deletions test/__snapshots__/esModule-option.test.js.snap

Large diffs are not rendered by default.

46 changes: 37 additions & 9 deletions test/__snapshots__/loader.test.js.snap

Large diffs are not rendered by default.

200 changes: 166 additions & 34 deletions test/__snapshots__/minimize-option.test.js.snap

Large diffs are not rendered by default.

92 changes: 74 additions & 18 deletions test/__snapshots__/root-option.test.js.snap

Large diffs are not rendered by default.

Binary file removed test/fixtures/alias-image.png
Binary file not shown.
14 changes: 14 additions & 0 deletions test/fixtures/simple.html
Expand Up @@ -210,3 +210,17 @@ <h2>An Ordered HTML List</h2>
<script>
function test() {}
</script>

<img src=image.png />
<img src="image image.png" />
<img src='image image.png' />
<img src=~aliasImageWithSpace />
<img srcset=image.png />
<img srcset="image%20image.png" />
<img srcset='image%20image.png' />
<img srcset=~aliasImageWithSpace />
<img srcset="image.png 480w, image%20image.png 640w, ~aliasImageWithSpace 800w" sizes="(max-width: 600px) 480px, 800px" src="image.png" alt="Elva dressed as a fairy">
<img src = image.png />
<img src = ~aliasImageWithSpace />
<img src = "~aliasImageWithSpace" />
<img src = '~aliasImageWithSpace' />
6 changes: 5 additions & 1 deletion test/helpers/getCompiler.js
Expand Up @@ -54,7 +54,11 @@ export default (fixture, loaderOptions = {}, config = {}) => {
},
resolve: {
alias: {
aliasImg: path.resolve(__dirname, '../fixtures/alias-image.png'),
aliasImg: path.resolve(__dirname, '../fixtures/image.png'),
aliasImageWithSpace: path.resolve(
__dirname,
'../fixtures/image image.png'
),
},
},
plugins: [],
Expand Down
30 changes: 30 additions & 0 deletions test/runtime/__snapshots__/getUrl.test.js.snap
Expand Up @@ -37,3 +37,33 @@ exports[`getUrl should work 14`] = `"image<image.png"`;
exports[`getUrl should work 15`] = `"image\`image.png"`;

exports[`getUrl should work 16`] = `"image.png"`;

exports[`getUrl should work 17`] = `"\\"image image.png\\""`;

exports[`getUrl should work 18`] = `
"\\"image
image.png\\""
`;

exports[`getUrl should work 19`] = `"\\"image image.png\\""`;

exports[`getUrl should work 20`] = `
"\\"image
image.png\\""
`;

exports[`getUrl should work 21`] = `"\\"image image.png\\""`;

exports[`getUrl should work 22`] = `"\\"image\\"image.png\\""`;

exports[`getUrl should work 23`] = `"\\"image'image.png\\""`;

exports[`getUrl should work 24`] = `"\\"image=image.png\\""`;

exports[`getUrl should work 25`] = `"\\"image>image.png\\""`;

exports[`getUrl should work 26`] = `"\\"image<image.png\\""`;

exports[`getUrl should work 27`] = `"\\"image\`image.png\\""`;

exports[`getUrl should work 28`] = `"image.png"`;
12 changes: 12 additions & 0 deletions test/runtime/getUrl.test.js
Expand Up @@ -18,6 +18,18 @@ describe('getUrl', () => {
expect(getUrl('image>image.png')).toMatchSnapshot();
expect(getUrl('image<image.png')).toMatchSnapshot();
expect(getUrl('image`image.png')).toMatchSnapshot();
expect(getUrl('image.png', true)).toMatchSnapshot();
expect(getUrl('image\timage.png', true)).toMatchSnapshot();
expect(getUrl('image\nimage.png', true)).toMatchSnapshot();
expect(getUrl('image\fimage.png', true)).toMatchSnapshot();
expect(getUrl('image\rimage.png', true)).toMatchSnapshot();
expect(getUrl('image image.png', true)).toMatchSnapshot();
expect(getUrl('image"image.png', true)).toMatchSnapshot();
expect(getUrl("image'image.png", true)).toMatchSnapshot();
expect(getUrl('image=image.png', true)).toMatchSnapshot();
expect(getUrl('image>image.png', true)).toMatchSnapshot();
expect(getUrl('image<image.png', true)).toMatchSnapshot();
expect(getUrl('image`image.png', true)).toMatchSnapshot();
expect(
getUrl({ default: 'image.png', __esModule: true })
).toMatchSnapshot();
Expand Down

0 comments on commit d0b0150

Please sign in to comment.