Skip to content

Commit

Permalink
feat: add .root() to avoid re-parsing inputs when possible (#717)
Browse files Browse the repository at this point in the history
  • Loading branch information
jquense committed Feb 5, 2020
1 parent c09bbaf commit fdb010b
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 20 deletions.
5 changes: 5 additions & 0 deletions packages/processor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
25 changes: 17 additions & 8 deletions packages/processor/processor.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class Processor {
{
cwd : process.cwd(),
map : false,

dupewarn : true,
exportValues : true,
loadFile : defaultLoadFile,
Expand Down Expand Up @@ -123,7 +123,7 @@ class Processor {
this._log("file()", id);

const text = await this._loadFile(id);

return this._add(id, text);
}

Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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 ];

Expand Down Expand Up @@ -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
Expand All @@ -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,
})
Expand All @@ -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;
Expand Down
44 changes: 32 additions & 12 deletions packages/processor/test/__snapshots__/api.test.js.snap
Original file line number Diff line number Diff line change
@@ -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`] = `
Expand Down Expand Up @@ -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 [
Expand Down
16 changes: 16 additions & 0 deletions packages/processor/test/api.test.js
Original file line number Diff line number Diff line change
@@ -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");

Expand All @@ -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(
Expand Down

0 comments on commit fdb010b

Please sign in to comment.