diff --git a/packages/processor/processor.js b/packages/processor/processor.js index a547cdc1d..9a31d75cf 100644 --- a/packages/processor/processor.js +++ b/packages/processor/processor.js @@ -33,50 +33,49 @@ function params(processor, args) { class Processor { constructor(opts) { - /* eslint max-statements: [ "warn", 20 ] */ - this._options = Object.assign( + /* eslint max-statements: [ "warn", 25 ] */ + const options = Object.assign( Object.create(null), { - cwd : process.cwd(), - map : false, - rewrite : true, - verbose : false, + cwd : process.cwd(), + map : false, + rewrite : true, + verbose : false, + resolvers : [], }, opts ); - if(!path.isAbsolute(this._options.cwd)) { - this._options.cwd = path.resolve(this._options.cwd); - } + this._options = options; - if(typeof this._options.namer === "string") { - this._options.namer = require(this._options.namer)(); + if(!path.isAbsolute(options.cwd)) { + options.cwd = path.resolve(options.cwd); } - if(typeof this._options.namer !== "function") { - this._options.namer = (file, selector) => - `mc${slug(relative(this._options.cwd, file))}_${selector}`; + if(typeof options.namer === "string") { + options.namer = require(options.namer)(); } - if(!Array.isArray(this._options.resolvers)) { - this._options.resolvers = []; + if(typeof options.namer !== "function") { + options.namer = (file, selector) => + `mc${slug(relative(options.cwd, file))}_${selector}`; } - this._log = this._options.verbose ? + this._log = options.verbose ? // eslint-disable-next-line no-console console.log.bind(console, "[processor]") : // eslint-disable-next-line no-empty-function () => {}; - this._resolve = resolve.resolvers(this._options.resolvers); + this._resolve = resolve.resolvers(options.resolvers); - this._absolute = (file) => (path.isAbsolute(file) ? file : path.join(this._options.cwd, file)); + this._absolute = (file) => (path.isAbsolute(file) ? file : path.join(options.cwd, file)); this._files = Object.create(null); this._graph = new Graph(); this._before = postcss([ - ...(this._options.before || []), + ...(options.before || []), require("./plugins/values-local.js"), require("./plugins/values-export.js"), require("./plugins/values-replace.js"), @@ -93,17 +92,17 @@ class Processor { require("./plugins/externals.js"), require("./plugins/composition.js"), require("./plugins/keyframes.js"), - ...(this._options.processing || []), + ...(options.processing || []), ]); - this._after = postcss(this._options.after || [ noop ]); + this._after = postcss(options.after || [ noop ]); // Add postcss-url to the afters if requested - if(this._options.rewrite) { - this._after.use(require("postcss-url")(this._options.rewrite)); + if(options.rewrite) { + this._after.use(require("postcss-url")(options.rewrite)); } - this._done = postcss(this._options.done || [ noop ]); + this._done = postcss(options.done || [ noop ]); } // Add a file on disk to the dependency graph diff --git a/packages/processor/test/__snapshots__/options.test.js.snap b/packages/processor/test/__snapshots__/options.test.js.snap index c7565399b..fdc00ee0c 100644 --- a/packages/processor/test/__snapshots__/options.test.js.snap +++ b/packages/processor/test/__snapshots__/options.test.js.snap @@ -74,6 +74,76 @@ exports[`/processor.js options lifecycle options processing should run sync post a {}" `; +exports[`/processor.js options lifecycle options verbose should output debugging messages when verbose mode is enabled 1`] = ` +Array [ + Array [ + "[processor]", + "file()", + "packages/processor/test/specimens/start.css", + ], + Array [ + "[processor]", + "string()", + "packages/processor/test/specimens/start.css", + ], + Array [ + "[processor]", + "processing", + "packages/processor/test/specimens/folder/folder.css", + ], + Array [ + "[processor]", + "processed", + "packages/processor/test/specimens/folder/folder.css", + ], + Array [ + "[processor]", + "processing", + "packages/processor/test/specimens/local.css", + ], + Array [ + "[processor]", + "processed", + "packages/processor/test/specimens/local.css", + ], + Array [ + "[processor]", + "processing", + "packages/processor/test/specimens/start.css", + ], + Array [ + "[processor]", + "processed", + "packages/processor/test/specimens/start.css", + ], + Array [ + "[processor]", + "string() done", + "packages/processor/test/specimens/start.css", + ], + Array [ + "[processor]", + "string()", + "packages/processor/test/specimens/string.css", + ], + Array [ + "[processor]", + "processing", + "packages/processor/test/specimens/string.css", + ], + Array [ + "[processor]", + "processed", + "packages/processor/test/specimens/string.css", + ], + Array [ + "[processor]", + "string() done", + "packages/processor/test/specimens/string.css", + ], +] +`; + exports[`/processor.js options map should generate external source maps 1`] = ` "/* packages/processor/test/specimens/folder/folder.css */ .folder { margin: 2px; } diff --git a/packages/processor/test/options.test.js b/packages/processor/test/options.test.js index 5f69ac0bb..f359c956d 100644 --- a/packages/processor/test/options.test.js +++ b/packages/processor/test/options.test.js @@ -5,6 +5,7 @@ const path = require("path"); const dedent = require("dedent"); const namer = require("@modular-css/test-utils/namer.js"); const relative = require("@modular-css/test-utils/relative.js"); +const logs = require("@modular-css/test-utils/logs.js"); const Processor = require("../processor.js"); @@ -370,6 +371,27 @@ describe("/processor.js", () => { .then((result) => expect(result.css).toMatchSnapshot()); }); }); + + describe("verbose", () => { + it("should output debugging messages when verbose mode is enabled", async () => { + const { logSnapshot } = logs(); + + const processor = new Processor({ + namer, + verbose : true, + }); + + await processor.file("./packages/processor/test/specimens/start.css"); + await processor.string( + "packages/processor/test/specimens/string.css", + ".foo { color: fuschia; }" + ); + + await processor.output(); + + logSnapshot(); + }); + }); }); }); }); diff --git a/packages/rollup/rollup.js b/packages/rollup/rollup.js index 4cde5c8b6..8eadd4fca 100644 --- a/packages/rollup/rollup.js +++ b/packages/rollup/rollup.js @@ -35,11 +35,15 @@ module.exports = function(opts) { namedExports : true, styleExport : false, dev : false, + verbose : false, }, opts); const filter = utils.createFilter(options.include, options.exclude); - const { styleExport, done, map, dev } = options; + const { styleExport, done, map, dev, verbose } = options; + + // eslint-disable-next-line no-console, no-empty-function + const log = verbose ? console.log.bind(console, "[rollup]") : () => {}; if(typeof map === "undefined") { // Sourcemaps don't make much sense in styleExport mode @@ -53,6 +57,8 @@ module.exports = function(opts) { name : "@modular-css/rollup", buildStart() { + log("build start"); + // done lifecycle won't ever be called on per-component styles since // it only happens at bundle compilation time // Need to do this on buildStart so it has access to this.warn() o_O @@ -68,6 +74,8 @@ module.exports = function(opts) { return; } + log("file changed", file); + processor.dependents(file).forEach((dep) => processor.remove(dep) ); @@ -80,6 +88,8 @@ module.exports = function(opts) { return null; } + log("transform", id); + const { details, exports } = await processor.string(id, code); const exported = output.join(exports); @@ -226,6 +236,8 @@ module.exports = function(opts) { .map(async ({ base, name, css }, idx) => { const id = this.emitAsset(`${base}.css`); + log("css output", id); + const result = await processor.output({ to : to.replace(/\[(name|extname)\]/g, (match, field) => (field === "name" ? name : ".css") @@ -240,11 +252,17 @@ module.exports = function(opts) { if(options.json && idx === 0) { const file = typeof options.json === "string" ? options.json : "exports.json"; + log("json output", file); + this.emitAsset(file, JSON.stringify(result.compositions, null, 4)); } if(result.map) { - this.emitAsset(`${base}.css.map`, result.map.toString()); + const file = `${base}.css.map`; + + log("map output", file); + + this.emitAsset(file, result.map.toString()); } }) ); diff --git a/packages/rollup/test/__snapshots__/rollup.test.js.snap b/packages/rollup/test/__snapshots__/rollup.test.js.snap index b8c5d5feb..542a85e45 100644 --- a/packages/rollup/test/__snapshots__/rollup.test.js.snap +++ b/packages/rollup/test/__snapshots__/rollup.test.js.snap @@ -110,6 +110,110 @@ exports[`/rollup.js should handle assetFileNames being undefined 1`] = ` " `; +exports[`/rollup.js should log in verbose mode 1`] = ` +Array [ + Array [ + "[rollup]", + "build start", + ], + Array [ + "[rollup]", + "transform", + "packages/rollup/test/specimens/simple.css", + ], + Array [ + "[processor]", + "string()", + "packages/rollup/test/specimens/simple.css", + ], + Array [ + "[processor]", + "processing", + "packages/rollup/test/specimens/simple.css", + ], + Array [ + "[processor]", + "processed", + "packages/rollup/test/specimens/simple.css", + ], + Array [ + "[processor]", + "string() done", + "packages/rollup/test/specimens/simple.css", + ], + Array [ + "[rollup]", + "css output", + "40a365e7", + ], + Array [ + "[processor]", + "file()", + "packages/processor/test/specimens/start.css", + ], + Array [ + "[processor]", + "string()", + "packages/processor/test/specimens/start.css", + ], + Array [ + "[processor]", + "processing", + "packages/processor/test/specimens/folder/folder.css", + ], + Array [ + "[processor]", + "processed", + "packages/processor/test/specimens/folder/folder.css", + ], + Array [ + "[processor]", + "processing", + "packages/processor/test/specimens/local.css", + ], + Array [ + "[processor]", + "processed", + "packages/processor/test/specimens/local.css", + ], + Array [ + "[processor]", + "processing", + "packages/processor/test/specimens/start.css", + ], + Array [ + "[processor]", + "processed", + "packages/processor/test/specimens/start.css", + ], + Array [ + "[processor]", + "string() done", + "packages/processor/test/specimens/start.css", + ], + Array [ + "[processor]", + "string()", + "packages/processor/test/specimens/string.css", + ], + Array [ + "[processor]", + "processing", + "packages/processor/test/specimens/string.css", + ], + Array [ + "[processor]", + "processed", + "packages/processor/test/specimens/string.css", + ], + Array [ + "[processor]", + "string() done", + "packages/processor/test/specimens/string.css", + ], +] +`; + exports[`/rollup.js should not output sourcemaps when they are disabled 1`] = ` "/* packages/rollup/test/specimens/simple.css */ .fooga { diff --git a/packages/rollup/test/rollup.test.js b/packages/rollup/test/rollup.test.js index 995cc08f4..8874b3ed9 100644 --- a/packages/rollup/test/rollup.test.js +++ b/packages/rollup/test/rollup.test.js @@ -6,10 +6,11 @@ const { rollup } = require("rollup"); const dedent = require("dedent"); const shell = require("shelljs"); -const read = require("@modular-css/test-utils/read.js")(__dirname); +const read = require("@modular-css/test-utils/read.js")(__dirname); const exists = require("@modular-css/test-utils/exists.js")(__dirname); const prefix = require("@modular-css/test-utils/prefix.js")(__dirname); -const namer = require("@modular-css/test-utils/namer.js"); +const namer = require("@modular-css/test-utils/namer.js"); +const logs = require("@modular-css/test-utils/logs.js"); const Processor = require("@modular-css/processor"); @@ -215,9 +216,7 @@ describe("/rollup.js", () => { }); it("should warn that styleExport and done aren't compatible", async () => { - const spy = jest.spyOn(global.console, "warn"); - - spy.mockImplementation(() => { /* NO-OP */ }); + const { logSnapshot } = logs("warn"); await rollup({ input : require.resolve("./specimens/style-export.js"), @@ -232,8 +231,7 @@ describe("/rollup.js", () => { ], }); - expect(spy).toHaveBeenCalled(); - expect(spy.mock.calls).toMatchSnapshot(); + logSnapshot(); }); it("should generate external source maps", async () => { @@ -453,6 +451,40 @@ describe("/rollup.js", () => { expect(result.code).toMatchSnapshot(); }); + it("should log in verbose mode", async () => { + const { logSnapshot } = logs(); + + const bundle = await rollup({ + input : require.resolve("./specimens/simple.js"), + plugins : [ + plugin({ + namer, + verbose : true, + }), + ], + }); + + await bundle.generate({ + format, + assetFileNames, + }); + + const processor = new Processor({ + namer, + verbose : true, + }); + + await processor.file("./packages/processor/test/specimens/start.css"); + await processor.string( + "packages/processor/test/specimens/string.css", + ".foo { color: fuschia; }" + ); + + await processor.output(); + + logSnapshot(); + }); + describe("errors", () => { function checkError(err) { expect(err.toString()).toMatch("error-plugin:"); diff --git a/packages/svelte/src/markup.js b/packages/svelte/src/markup.js index 89f00d36e..afe5262e5 100644 --- a/packages/svelte/src/markup.js +++ b/packages/svelte/src/markup.js @@ -10,11 +10,13 @@ const scriptRegex = /([\S\s]*?)<\/script>/im; const linkRegex = /]*?\bhref=\s*(?:"([^"]+)"|'([^']+)'|([^>\s]+))[^>]*>/im; const missedRegex = /css\.\w+/gim; -function updateCss({ processor, content, result, filename }) { +function updateCss({ processor, log, content, result, filename }) { const exported = result.files[result.file].exports; const keys = Object.keys(exported); let code = content; + log("updating css references", filename, JSON.stringify(keys)); + if(keys.length) { const selectors = keys.join("|"); @@ -54,12 +56,14 @@ function updateCss({ processor, content, result, filename }) { }; } -async function extractLink({ processor, content, filename, link }) { +async function extractLink({ processor, log, content, filename, link }) { // This looks weird, but it's to support multiple types of quotation marks const href = link[1] || link[2] || link[3]; const external = resolve(path.dirname(filename), href); + log("extract ", filename, external); + // Remove any files that've already been encountered, they should be re-processed if(external in processor.files) { [ ...processor.dependents(external), external ].forEach((file) => processor.remove(file)); @@ -94,13 +98,16 @@ async function extractLink({ processor, content, filename, link }) { return updateCss({ processor, + log, content, result, filename : href, }); } -async function extractStyle({ processor, content, filename, style }) { +async function extractStyle({ processor, log, content, filename, style }) { + log("extract