Skip to content

Commit

Permalink
fix: modular-css-svelte handles empty CSS files (#513)
Browse files Browse the repository at this point in the history
Fixes #512
  • Loading branch information
tivac authored Aug 29, 2018
1 parent 6e5d2b6 commit 78ba84b
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 56 deletions.
38 changes: 23 additions & 15 deletions packages/svelte/src/markup.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,32 +12,40 @@ const missedRegex = /css\.\w+/gim;

function updateCss({ processor, content, result, filename }) {
const exported = result.files[result.file].exports;

const code = content
// Replace simple {css.<key>} values first
.replace(
new RegExp(`{css\\.(${Object.keys(exported).join("|")})}`, "gm"),
(match, key) => exported[key].join(" ")
)
// Then any remaining bare css.<key> values
.replace(
new RegExp(`(\\b)css\\.(${Object.keys(exported).join("|")})(\\b)`, "gm"),
(match, prefix, key, suffix) => `${prefix}"${exported[key].join(" ")}"${suffix}`
);
const keys = Object.keys(exported);
let code = content;

if(keys.length) {
const selectors = keys.join("|");

code = code
// Replace simple {css.<key>} values first
.replace(
new RegExp(`{css\\.(${selectors})}`, "gm"),
(match, key) => exported[key].join(" ")
)
// Then any remaining bare css.<key> values
.replace(
new RegExp(`(\\b)css\\.(${selectors})(\\b)`, "gm"),
(match, prefix, key, suffix) => `${prefix}"${exported[key].join(" ")}"${suffix}`
);
}

// Check for any values in the template we couldn't convert
const missed = code.match(missedRegex);

if(missed) {
const { strict } = processor.options;

const classes = missed.map((reference) => reference.split("css.")[1]);

if(strict) {
throw new Error(`modular-css-svelte: Unable to find "${missed.join(", ")}" in ${filename}`);
throw new Error(`modular-css-svelte: Unable to find .${classes.join(", .")} in "${filename}"`);
}

missed.forEach((key) =>
classes.forEach((key) =>
// eslint-disable-next-line no-console
console.warn(`modular-css-svelte: Unable to find "${key}" in ${filename}`)
console.warn(`modular-css-svelte: Unable to find .${key} in "${filename}"`)
);
}

Expand Down
78 changes: 61 additions & 17 deletions packages/svelte/test/__snapshots__/svelte.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -205,15 +205,61 @@ exports[`/svelte.js should extract CSS from a <style> tag 2`] = `
"
`;
exports[`/svelte.js should handle invalid references in "<script>" (inline: false, strict: false) 1`] = `
exports[`/svelte.js should handle errors: "empty css file - <link>" 1`] = `"modular-css-svelte: Unable to find .nope, .alsonope in \\"./empty.css\\""`;
exports[`/svelte.js should handle errors: "empty css file - <link>" 2`] = `
Array [
Array [
"modular-css-svelte: Unable to find \\"css.nuhuh\\" in ./invalid.css",
"modular-css-svelte: Unable to find .nope in \\"./empty.css\\"",
],
Array [
"modular-css-svelte: Unable to find .alsonope in \\"./empty.css\\"",
],
]
`;
exports[`/svelte.js should handle invalid references in "<script>" (inline: false, strict: false) 2`] = `
exports[`/svelte.js should handle errors: "empty css file - <link>" 3`] = `
"
<div class=\\"{css.nope}\\">NOPE</div>
<div class=\\"{css.alsonope}\\">STILL NOPE</div>
<script>
import css from \\"./empty.css\\";
</script>"
`;
exports[`/svelte.js should handle errors: "empty css file - <style>" 1`] = `"modular-css-svelte: Unable to find .nope, .alsonope in \\"<style>\\""`;
exports[`/svelte.js should handle errors: "empty css file - <style>" 2`] = `
Array [
Array [
"modular-css-svelte: Unable to find .nope in \\"<style>\\"",
],
Array [
"modular-css-svelte: Unable to find .alsonope in \\"<style>\\"",
],
]
`;
exports[`/svelte.js should handle errors: "empty css file - <style>" 3`] = `
"<div class=\\"{css.nope}\\">NOPE</div>
<div class=\\"{css.alsonope}\\">STILL NOPE</div>
<style>/* replaced by modular-css */</style>
"
`;
exports[`/svelte.js should handle errors: "invalid reference <script> - <link>" 1`] = `"modular-css-svelte: Unable to find .nuhuh in \\"./invalid.css\\""`;
exports[`/svelte.js should handle errors: "invalid reference <script> - <link>" 2`] = `
Array [
Array [
"modular-css-svelte: Unable to find .nuhuh in \\"./invalid.css\\"",
],
]
`;
exports[`/svelte.js should handle errors: "invalid reference <script> - <link>" 3`] = `
"
<h2 class=\\"yup\\">Yup</h2>
Expand All @@ -224,17 +270,17 @@ console.log(css.nuhuh);</script>
"
`;
exports[`/svelte.js should handle invalid references in "<script>" (inline: false, strict: true) 1`] = `"modular-css-svelte: Unable to find \\"css.nuhuh\\" in ./invalid.css"`;
exports[`/svelte.js should handle errors: "invalid reference <script> - <style>" 1`] = `"modular-css-svelte: Unable to find .nuhuh in \\"<style>\\""`;
exports[`/svelte.js should handle invalid references in "<script>" (inline: true, strict: false) 1`] = `
exports[`/svelte.js should handle errors: "invalid reference <script> - <style>" 2`] = `
Array [
Array [
"modular-css-svelte: Unable to find \\"css.nuhuh\\" in <style>",
"modular-css-svelte: Unable to find .nuhuh in \\"<style>\\"",
],
]
`;
exports[`/svelte.js should handle invalid references in "<script>" (inline: true, strict: false) 2`] = `
exports[`/svelte.js should handle errors: "invalid reference <script> - <style>" 3`] = `
"<h2 class=\\"yup\\">Yup</h2>
<style>/* replaced by modular-css */</style>
Expand All @@ -245,17 +291,17 @@ exports[`/svelte.js should handle invalid references in "<script>" (inline: true
"
`;
exports[`/svelte.js should handle invalid references in "<script>" (inline: true, strict: true) 1`] = `"modular-css-svelte: Unable to find \\"css.nuhuh\\" in <style>"`;
exports[`/svelte.js should handle errors: "invalid reference template - <link>" 1`] = `"modular-css-svelte: Unable to find .nope in \\"./invalid.css\\""`;
exports[`/svelte.js should handle invalid references in "template" (inline: false, strict: false) 1`] = `
exports[`/svelte.js should handle errors: "invalid reference template - <link>" 2`] = `
Array [
Array [
"modular-css-svelte: Unable to find \\"css.nope\\" in ./invalid.css",
"modular-css-svelte: Unable to find .nope in \\"./invalid.css\\"",
],
]
`;
exports[`/svelte.js should handle invalid references in "template" (inline: false, strict: false) 2`] = `
exports[`/svelte.js should handle errors: "invalid reference template - <link>" 3`] = `
"
<h1 class=\\"{css.nope}\\">Nope</h1>
Expand All @@ -265,26 +311,24 @@ exports[`/svelte.js should handle invalid references in "template" (inline: fals
</script>"
`;
exports[`/svelte.js should handle invalid references in "template" (inline: false, strict: true) 1`] = `"modular-css-svelte: Unable to find \\"css.nope\\" in ./invalid.css"`;
exports[`/svelte.js should handle errors: "invalid reference template - <style>" 1`] = `"modular-css-svelte: Unable to find .nope in \\"<style>\\""`;
exports[`/svelte.js should handle invalid references in "template" (inline: true, strict: false) 1`] = `
exports[`/svelte.js should handle errors: "invalid reference template - <style>" 2`] = `
Array [
Array [
"modular-css-svelte: Unable to find \\"css.nope\\" in <style>",
"modular-css-svelte: Unable to find .nope in \\"<style>\\"",
],
]
`;
exports[`/svelte.js should handle invalid references in "template" (inline: true, strict: false) 2`] = `
exports[`/svelte.js should handle errors: "invalid reference template - <style>" 3`] = `
"<h1 class=\\"{css.nope}\\">Nope</h1>
<h2 class=\\"yup\\">Yup</h2>
<style>/* replaced by modular-css */</style>
"
`;
exports[`/svelte.js should handle invalid references in "template" (inline: true, strict: true) 1`] = `"modular-css-svelte: Unable to find \\"css.nope\\" in <style>"`;
exports[`/svelte.js should ignore files without <style> blocks 1`] = `
"<h1>Hello</h1>
<script>console.log(\\"output\\")</script>"
Expand Down
Empty file.
4 changes: 4 additions & 0 deletions packages/svelte/test/specimens/invalid-external-empty.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<link rel="stylesheet" href="./empty.css" />

<div class="{css.nope}">NOPE</div>
<div class="{css.alsonope}">STILL NOPE</div>
5 changes: 5 additions & 0 deletions packages/svelte/test/specimens/invalid-inline-empty.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<div class="{css.nope}">NOPE</div>
<div class="{css.alsonope}">STILL NOPE</div>

<style>
</style>
48 changes: 24 additions & 24 deletions packages/svelte/test/svelte.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,41 +74,41 @@ describe("/svelte.js", () => {
});

it.each`
title | inline | strict | specimen
${"<script>"} | ${true} | ${true} | ${"invalid-inline-script.html"}
${"template"} | ${true} | ${true} | ${"invalid-inline-template.html"}
${"<script>"} | ${true} | ${false} | ${"invalid-inline-script.html"}
${"template"} | ${true} | ${false} | ${"invalid-inline-template.html"}
${"<script>"} | ${false} | ${false} | ${"invalid-external-script.html"}
${"template"} | ${false} | ${false} | ${"invalid-external-template.html"}
${"<script>"} | ${false} | ${true} | ${"invalid-external-script.html"}
${"template"} | ${false} | ${true} | ${"invalid-external-template.html"}
`("should handle invalid references in $title (inline: $inline, strict: $strict)", async ({ strict, specimen }) => {
title | specimen
${"invalid reference <script> - <style>"} | ${"invalid-inline-script.html"}
${"invalid reference template - <style>"} | ${"invalid-inline-template.html"}
${"invalid reference <script> - <link>"} | ${"invalid-external-script.html"}
${"invalid reference template - <link>"} | ${"invalid-external-template.html"}
${"empty css file - <style>"} | ${"invalid-inline-empty.html"}
${"empty css file - <link>"} | ${"invalid-external-empty.html"}
`("should handle errors: $title", async ({ specimen }) => {
const spy = jest.spyOn(global.console, "warn");

spy.mockImplementation(() => { /* NO-OP */ });

const filename = require.resolve(`./specimens/${specimen}`);

const { preprocess } = plugin({

// Set up strict plugin
const { preprocess : strict } = plugin({
namer,
strict,
strict : true,
});

if(strict) {
await expect(
svelte.preprocess(
fs.readFileSync(filename, "utf8"),
Object.assign({}, preprocess, { filename })
)
).rejects.toThrowErrorMatchingSnapshot();

return;
}
await expect(
svelte.preprocess(
fs.readFileSync(filename, "utf8"),
Object.assign({}, strict, { filename })
)
).rejects.toThrowErrorMatchingSnapshot();

// Now the loose plugin
const { preprocess : loose } = plugin({
namer,
});

const processed = await svelte.preprocess(
fs.readFileSync(filename, "utf8"),
Object.assign({}, preprocess, { filename })
Object.assign({}, loose, { filename })
);

expect(spy).toHaveBeenCalled();
Expand Down

0 comments on commit 78ba84b

Please sign in to comment.