From d2c7eec25711c85ed6f9ad5507402851e3435d24 Mon Sep 17 00:00:00 2001 From: John Gozde Date: Fri, 5 Dec 2014 15:05:40 -0700 Subject: [PATCH] Add 'cache' option for caching parsed output. Stores the stylesheet rules for a given absolute path if provided a 'cache' object. After resolving an import path, checks for cached output and returns that if available. - Added tests - Updated docs --- README.md | 27 +++++++++++++++++++++++++++ index.js | 12 +++++++++++- test.js | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a54e5ce..e919ff9 100644 --- a/README.md +++ b/README.md @@ -137,3 +137,30 @@ function compile(src, file) { return src; } ``` + +### cache +An object that will be used as a cache for parsed output of import files, indexed by absolute file path. +This option may be useful when integrating rework with a watcher by avoiding unnecessary parsing of unchanged files. + +Example: + +```js +var cache = {}; + +function buildCss() { + // When './abc' is resolved, the cache will be checked + // first. If not cached, the parsed output will be added + // to the cache. + rework('@import "./abc";', { source: 'index.css' }) + .use(reworkNPM({ cache: cache })) + .toString(); +} + +// Triggered by a watcher, perhaps +function onCssFileChanged(file) { + // A css file has changed, so remove it from the cache + // and run rework again. + delete cache[path.resolve(file)]; + buildCss(); +} +``` diff --git a/index.js b/index.js index 66b9d73..f88f272 100644 --- a/index.js +++ b/index.js @@ -18,6 +18,7 @@ function reworkNPM(opts) { var prefilter = opts.prefilter || identity; var shim = opts.shim || {}; var alias = opts.alias || {}; + var cache = opts.cache || null; function inline(scope, style) { style.rules = concatMap(style.rules, function(rule) { @@ -41,10 +42,19 @@ function reworkNPM(opts) { } scope.push(file); + if (cache && cache.hasOwnProperty(file)) { + return cache[file]; + } + var contents = fs.readFileSync(file, 'utf8'); contents = prefilter(contents, file); contents = parse(contents, { source: path.relative(root, file) }); - return inline(scope, contents.stylesheet).rules; + + var rules = inline(scope, contents.stylesheet).rules; + if (cache) { + cache[file] = rules; + } + return rules; } function resolveImport(rule) { diff --git a/test.js b/test.js index 940119c..a2513f6 100644 --- a/test.js +++ b/test.js @@ -3,6 +3,7 @@ var reworkNPM = require('./'); var fs = require('fs'); var path = require('path'); var rework = require('rework'); +var parse = require('css').parse; var sass = require('node-sass'); var convertSourceMap = require('convert-source-map'); var SourceMapConsumer = require('source-map').SourceMapConsumer; @@ -254,3 +255,34 @@ test('Provide filename as second arg to prefilter', function(t) { : code; } }); + +test('Use cached rules if cache provided', function(t) { + var cachedContents = '.test {\n content: "Cached package";\n}'; + + var cache = {}; + cache[path.resolve('test/node_modules/test/index.css')] = parse(cachedContents, { source: 'test/index.css' }).stylesheet.rules; + + var input = '@import "test";'; + var output = rework(input, { source: 'test/index.css' }) + .use(reworkNPM({ cache: cache })) + .toString(); + t.equal(output, cachedContents); + + t.end(); +}); + +test('Caches parsed output if cache provided', function(t) { + var cache = {}; + var input = '@import "test";'; + var output = rework(input, { source: 'test/index.css' }) + .use(reworkNPM({ cache: cache })) + .toString(); + + t.equal(output, '.test {\n content: "Test package";\n}'); + + var resolvedPath = path.resolve('test/node_modules/test/index.css'); + t.ok(cache[resolvedPath]); + t.type(cache[resolvedPath], "object"); + + t.end(); +});