Skip to content
Permalink
Browse files

feat: replacing missing css.fooga with stringified version (#574)

* feat: missing classes replaced with strings

So that there's less JS errors and it's easier to fix up the broken things.

BREAKING CHANGE: Previously missing css.fooga references would be left as-is, now they're wrapped in quotes to prevent them from causing JS errors. If you want missing classes to break things you should enable strict mode. Also no longer injecting a `<script>` block just to import css if there isn't already a `<script>` block defined in the module.
  • Loading branch information...
tivac committed Mar 28, 2019
1 parent 89b0398 commit 2084b6254620469a1da7684d0d2a1e1e2fba9f96
@@ -4,7 +4,7 @@ const parser = require("../parsers/parser.js");

const plugin = "modular-css-values-composed";

// Find @value fooga: wooga entries & catalog/remove them
// Find @value fooga from "./wooga.css" entries & catalog/remove them
module.exports = (css, { opts, messages }) => {
const { files, resolve, from } = opts;

@@ -25,7 +25,7 @@ module.exports = (css, { opts, messages }) => {

rule.remove();
});

if(Object.keys(values).length > 0) {
messages.push({
type : "modular-css",
@@ -3,7 +3,6 @@
const path = require("path");

const resolve = require("resolve-from");
const dedent = require("dedent");
const isUrl = require("is-url");
const escape = require("escape-string-regexp");

@@ -23,12 +22,41 @@ module.exports = (config = false) => {
// eslint-disable-next-line no-console, no-empty-function
const log = config.verbose ? console.log.bind(console, "[svelte]") : () => {};

// Check for and stringify any values in the template we couldn't convert
const missing = ({ source, file }) => {
const missed = source.match(missedRegex);

if(!missed) {
return source;
}

const { strict } = processor.options;

const classes = missed.map((reference) => reference.replace("css.", ""));

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

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

// Turn all missing values into strings so nothing explodes
return source.replace(
new RegExp(`(${missed.map((ref) => escape(ref)).join("|")})`),
(match) => JSON.stringify(match)
);
};

// This function is hilariously large but it's actually simpler this way
// Mostly because markup() is async so tracking state is painful w/o inlining
// the whole damn thing
// eslint-disable-next-line max-statements, complexity
const markup = async ({ content, filename: html }) => {
const markup = async ({ content, filename : html }) => {
let source = content;
let dependencies = [];

const links = source.match(linkRegex);
const style = source.match(styleRegex);
@@ -40,7 +68,10 @@ module.exports = (config = false) => {
// No-op
if(!links && !style) {
return {
code : source,
code : missing({
source,
file : html,
}),
};
}

@@ -89,7 +120,10 @@ module.exports = (config = false) => {
// No-op
if(!valid.length) {
return {
code : source,
code : missing({
source,
file : html,
}),
};
}

@@ -117,8 +151,7 @@ module.exports = (config = false) => {
// Remove the <link> element from the component to avoid double-loading
source = source.replace(new RegExp(`${escape(link)}\r?\n?`), "");

// To get rollup to watch the CSS file we need to inject an import statement
// if a <script> block already exists hijack it otherwise inject a simple one
// Inject the link into the <script> block if it exists for JS referencing
const script = source.match(scriptRegex);

if(script) {
@@ -128,13 +161,9 @@ module.exports = (config = false) => {
tag,
tag.replace(contents, `\nimport css from ${JSON.stringify(css)};\n\n${contents}`)
);
} else {
source += dedent(`
<script>
import css from ${JSON.stringify(css)};
</script>
`);
}

dependencies = processor.dependencies(external);
}

log("processed styles", html);
@@ -171,26 +200,12 @@ module.exports = (config = false) => {
);
}

// Check for any values in the template we couldn't convert
const missed = source.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 .${classes.join(", .")} in "${css}"`);
}

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

return {
code : source,
code : missing({
source,
file : css
}),
dependencies,
};
};

@@ -0,0 +1,32 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`/svelte.js rollup watching should generate updated output 1`] = `
Snapshot Diff:
- First value
+ Second value

@@ -1,6 +1,10 @@
Object {
+ "assets/app.css": "/* packages/svelte/test/output/rollup/input/app.css */
+ .mc043115d5_nope {
+ color: blue;
+ }",
"output.js": "function noop() {}

function assign(tar, src) {
for (var k in src) tar[k] = src[k];
return tar;
@@ -158,11 +162,11 @@

return {
c() {
div = createElement(\\"div\\");
div.textContent = \\"Hi\\";
- div.className = \\"css.nope\\";
+ div.className = \\"mc043115d5_nope\\";
},

m(target, anchor) {
insert(target, div, anchor);
},
`;
@@ -60,9 +60,7 @@ exports[`/svelte.js should extract CSS from a <link> tag (no script) 1`] = `
<p class=\\"{bool ? \\"text\\" : \\"active\\" }\\">Text</p>
</div>
</div>
<script>
import css from \\"./external.css\\";
</script>"
"
`;

exports[`/svelte.js should extract CSS from a <link> tag (no script) 2`] = `
@@ -95,9 +93,7 @@ exports[`/svelte.js should extract CSS from a <link> tag (single quotes) 1`] = `
<p class=\\"{bool ? \\"text\\" : \\"active\\" }\\">Text</p>
</div>
</div>
<script>
import css from \\"./external.css\\";
</script>"
"
`;

exports[`/svelte.js should extract CSS from a <link> tag (single quotes) 2`] = `
@@ -130,9 +126,7 @@ exports[`/svelte.js should extract CSS from a <link> tag (unquoted) 1`] = `
<p class=\\"{bool ? \\"text\\" : \\"active\\" }\\">Text</p>
</div>
</div>
<script>
import css from \\"./external.css\\";
</script>"
"
`;

exports[`/svelte.js should extract CSS from a <link> tag (unquoted) 2`] = `
@@ -259,11 +253,9 @@ Array [

exports[`/svelte.js should handle errors: empty css file - <link> 3`] = `
"
<div class=\\"{css.nope}\\">NOPE</div>
<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>\\""`;
@@ -280,7 +272,7 @@ Array [
`;

exports[`/svelte.js should handle errors: empty css file - <style> 3`] = `
"<div class=\\"{css.nope}\\">NOPE</div>
"<div class=\\"{\\"css.nope\\"}\\">NOPE</div>
<div class=\\"{css.alsonope}\\">STILL NOPE</div>

<style>/* replaced by modular-css */</style>
@@ -305,7 +297,7 @@ exports[`/svelte.js should handle errors: invalid reference <script> - <link> 3`
import css from \\"./invalid.css\\";


console.log(css.nuhuh);
console.log(\\"css.nuhuh\\");
</script>
"
`;
@@ -326,7 +318,7 @@ exports[`/svelte.js should handle errors: invalid reference <script> - <style> 3
<style>/* replaced by modular-css */</style>

<script>
console.log(css.nuhuh);
console.log(\\"css.nuhuh\\");
</script>
"
`;
@@ -343,11 +335,9 @@ Array [

exports[`/svelte.js should handle errors: invalid reference template - <link> 3`] = `
"
<h1 class=\\"{css.nope}\\">Nope</h1>
<h1 class=\\"{\\"css.nope\\"}\\">Nope</h1>
<h2 class=\\"yup\\">Yup</h2>
<script>
import css from \\"./invalid.css\\";
</script>"
"
`;

exports[`/svelte.js should handle errors: invalid reference template - <style> 1`] = `"@modular-css/svelte: Unable to find .nope in \\"<style>\\""`;
@@ -361,7 +351,7 @@ Array [
`;

exports[`/svelte.js should handle errors: invalid reference template - <style> 3`] = `
"<h1 class=\\"{css.nope}\\">Nope</h1>
"<h1 class=\\"{\\"css.nope\\"}\\">Nope</h1>
<h2 class=\\"yup\\">Yup</h2>

<style>/* replaced by modular-css */</style>
@@ -372,9 +362,7 @@ exports[`/svelte.js should ignore <links> that reference a URL 1`] = `
"<link rel=\\"stylesheet\\" href=\\"http://example.com/styles.css\\" />

<div class=\\"fooga\\">fooga</div>
<script>
import css from \\"./simple.css\\";
</script>"
"
`;

exports[`/svelte.js should ignore <links> that reference a URL 2`] = `
@@ -392,11 +380,7 @@ exports[`/svelte.js should ignore files without <style> blocks 1`] = `

exports[`/svelte.js should ignore files without <style> blocks 2`] = `""`;

exports[`/svelte.js should invalidate files before reprocessing (<link>) 1`] = `
"<div class=\\"source\\">Source</div><script>
import css from \\"./source.css\\";
</script>"
`;
exports[`/svelte.js should invalidate files before reprocessing (<link>) 1`] = `"<div class=\\"source\\">Source</div>"`;

exports[`/svelte.js should invalidate files before reprocessing (<link>) 2`] = `
"/* packages/svelte/test/output/source.css */
@@ -405,11 +389,7 @@ exports[`/svelte.js should invalidate files before reprocessing (<link>) 2`] = `
}"
`;

exports[`/svelte.js should invalidate files before reprocessing (<link>) 3`] = `
"<div class=\\"source\\">Source</div><script>
import css from \\"./source.css\\";
</script>"
`;
exports[`/svelte.js should invalidate files before reprocessing (<link>) 3`] = `"<div class=\\"source\\">Source</div>"`;

exports[`/svelte.js should invalidate files before reprocessing (<link>) 4`] = `
"/* packages/svelte/test/output/source.css */
@@ -660,9 +640,7 @@ exports[`/svelte.js should use an already-created processor 1`] = `
"<link rel=\\"stylesheet\\" href=\\"http://example.com/styles.css\\" />

<div class=\\"fooga\\">fooga</div>
<script>
import css from \\"./simple.css\\";
</script>"
"
`;

exports[`/svelte.js should use an already-created processor 2`] = `
@@ -689,10 +667,8 @@ exports[`/svelte.js should warn when multiple <link> elements are in the html 1`
"<link rel=\\"stylesheet\\" href=\\"./simple2.css\\" />

<div class=\\"fooga\\">fooga</div>
<div class=\\"{css.booga}\\">booga</div>
<script>
import css from \\"./simple.css\\";
</script>"
<div class=\\"{\\"css.booga\\"}\\">booga</div>
"
`;

exports[`/svelte.js should warn when multiple <link> elements are in the html 2`] = `
Oops, something went wrong.

0 comments on commit 2084b62

Please sign in to comment.
You can’t perform that action at this time.