diff --git a/packages/processor/README.md b/packages/processor/README.md index aafc83043..30b7634f7 100644 --- a/packages/processor/README.md +++ b/packages/processor/README.md @@ -56,6 +56,11 @@ Returns a promise. Add `file` to the `Processor` instance with `css` contents. Returns a promise. Add `file` to the `Processor` instance, reads contents from disk using `fs`. +### `.root(file, Root)` + +Returns a promise. Add `file` to the `Processor` instance, re-uses a Postcss `Root` object, avoiding +unnecessarily parsing an AST again. + ### `.output({ args })` Returns a promise. Finalize processing of all added CSS and create combined CSS output file. diff --git a/packages/processor/processor.js b/packages/processor/processor.js index 395be58b0..3fddc0b6f 100644 --- a/packages/processor/processor.js +++ b/packages/processor/processor.js @@ -41,7 +41,7 @@ class Processor { { cwd : process.cwd(), map : false, - + dupewarn : true, exportValues : true, loadFile : defaultLoadFile, @@ -123,7 +123,7 @@ class Processor { this._log("file()", id); const text = await this._loadFile(id); - + return this._add(id, text); } @@ -136,6 +136,15 @@ class Processor { return this._add(id, text); } + // Add an existing postcss Root object by name + root(file, root) { + const id = this._normalize(file); + + this._log("root()", id); + + return this._add(id, root); + } + // Remove a file from the dependency graph remove(input) { // Only want files actually in the array @@ -351,7 +360,7 @@ class Processor { // Take a file id and some text, walk it for dependencies, then // process and return details - async _add(id, text) { + async _add(id, src) { const check = id.toLowerCase(); // Warn about potential dupes if an ID goes past we've seen before @@ -368,7 +377,7 @@ class Processor { this._log("_add()", id); - await this._walk(id, text); + await this._walk(id, src); const deps = [ ...this._graph.dependenciesOf(id), id ]; @@ -424,7 +433,7 @@ class Processor { // Process files and walk their composition/value dependency tree to find // new files we need to process - async _walk(name, text) { + async _walk(name, src) { // No need to re-process files unless they've been marked invalid if(this._files[name] && this._files[name].valid) { // Do want to wait until they're done being processed though @@ -440,12 +449,12 @@ class Processor { let walked; const file = this._files[name] = { - text, + text : typeof src === "string" ? src : src.source.input.css, exports : false, values : false, valid : true, before : this._before.process( - text, + src, params(this, { from : name, }) @@ -471,7 +480,7 @@ class Processor { await Promise.all( this._graph.dependenciesOf(name).map((dependency) => { const { valid, walked : complete } = this._files[dependency] || false; - + // If the file hasn't been invalidated wait for it to be done processing if(valid) { return complete; diff --git a/packages/processor/test/__snapshots__/api.test.js.snap b/packages/processor/test/__snapshots__/api.test.js.snap index d46b0e4a3..c93a4f79b 100644 --- a/packages/processor/test/__snapshots__/api.test.js.snap +++ b/packages/processor/test/__snapshots__/api.test.js.snap @@ -1,17 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`/processor.js API .resolve() should fall back to a default resolver 1`] = ` -Array [ - "packages/processor/test/specimens/local.css", -] -`; - -exports[`/processor.js API .resolve() should run resolvers until a match is found 1`] = ` -Array [ - "packages/processor/test/specimens/local.css", -] -`; - exports[`/processor.js API .compositions should return compositions for loaded files 1`] = `Promise {}`; exports[`/processor.js API .dependencies() should return the dependencies of the specified file 1`] = ` @@ -310,6 +298,38 @@ Array [ ] `; +exports[`/processor.js API .resolve() should fall back to a default resolver 1`] = ` +Array [ + "packages/processor/test/specimens/local.css", +] +`; + +exports[`/processor.js API .resolve() should run resolvers until a match is found 1`] = ` +Array [ + "packages/processor/test/specimens/local.css", +] +`; + +exports[`/processor.js API .root() should process a postcss Root 1`] = ` +Object { + "wooga": Array [ + "wooga", + ], +} +`; + +exports[`/processor.js API .root() should process a postcss Root 2`] = ` +Object { + "wooga": Array [ + "wooga", + ], +} +`; + +exports[`/processor.js API .root() should process a postcss Root 3`] = `".wooga { }"`; + +exports[`/processor.js API .root() should process a postcss Root 4`] = `".wooga { }"`; + exports[`/processor.js API .string() should process a string 1`] = ` Object { "wooga": Array [ diff --git a/packages/processor/test/api.test.js b/packages/processor/test/api.test.js index 3dd126386..db25f290b 100644 --- a/packages/processor/test/api.test.js +++ b/packages/processor/test/api.test.js @@ -1,5 +1,6 @@ "use strict"; +const postcss = require("postcss"); const namer = require("@modular-css/test-utils/namer.js"); const relative = require("@modular-css/test-utils/relative.js"); @@ -19,6 +20,21 @@ describe("/processor.js", () => { expect(typeof Processor).toBe("function"); }); + describe(".root()", () => { + it("should process a postcss Root", async () => { + const file = "./simple.css"; + const root = postcss.parse(".wooga { }", { from : file }); + const result = await processor.root( + file, root + ); + + expect(result.exports).toMatchSnapshot(); + expect(result.details.exports).toMatchSnapshot(); + expect(result.details.text).toMatchSnapshot(); + expect(result.details.processed.root.toResult().css).toMatchSnapshot(); + }); + }); + describe(".string()", () => { it("should process a string", async () => { const result = await processor.string(