Skip to content
Permalink
Browse files

feat: add rollup option to export styles (#453)

  • Loading branch information...
morewry authored and tivac committed Jul 18, 2018
1 parent 6fd18ba commit f0d4e43b77441600f4183102703adbbd8b181bfe
@@ -4,25 +4,41 @@

## Options

### `include`/`exclude`
### `common`

A minimatch pattern, or an array of minimatch patterns, relative to `process.cwd()`.
File name to use in case there are any CSS dependencies that appear in multiple bundles. Defaults to "common.css".

### `common`
### `include`/`exclude`

File path to write any common CSS output to.
A minimatch pattern, or an array of minimatch patterns, relative to `process.cwd()`. `include` defaults to `**/*.css`.

### `json`

File path to write out the JSON mapping file for use in server rendering.
Boolean to determine if JSON files should be output at the end of compilation. Defaults to `false`.

### `map`

Boolean to determine if inline source maps should be included. Defaults to `true`.

To force the creation of external source maps set the value to `{ inline : false }`.

### `namedExports`

Set to `false` to disable named exports, instead only the default export wll be used. This is useful to avoid warnings when your classes aren't valid JS identifiers.
By default this plugin will create both a default export and named `export`s for each class in a CSS file. You can disable this by setting `namedExports` to `false`.

### `styleExport`

By default this plugin will extract and bundle CSS in a separate file. If you would like the styles from each imported CSS file to be exported as a string for use in JS, you can enable this by setting `styleExport` to `true`. If you are using this option the `done` hook **will not run**, you should perform any additional CSS transformations in the `after` hook instead.

```js
import { styles } from "./styles.css";
```

Enable `styleExport` will also disable the plugin from emitting any assets as well as sourcemaps (unless you explicitly opt-in to sourcemaps via the `map` option)

### Shared Options

All other options are passed to the underlying `Processor` instance, see [Options](api.md#options).
All other options are passed to the underlying `Processor` instance, see [Options](https://github.com/tivac/modular-css/blob/master/docs/api.md#options).

## API

@@ -66,6 +66,16 @@ To force the creation of external source maps set the value to `{ inline : false

By default this plugin will create both a default export and named `export`s for each class in a CSS file. You can disable this by setting `namedExports` to `false`.

### `styleExport`

By default this plugin will extract and bundle CSS in a separate file. If you would like the styles from each imported CSS file to be exported as a string for use in JS, you can enable this by setting `styleExport` to `true`. If you are using this option the `done` hook **will not run**, you should perform any additional CSS transformations in the `after` hook instead.

```js
import { styles } from "./styles.css";
```

Enable `styleExport` will also disable the plugin from emitting any assets as well as sourcemaps (unless you explicitly opt-in to sourcemaps via the `map` option)

### Shared Options

All other options are passed to the underlying `Processor` instance, see [Options](https://github.com/tivac/modular-css/blob/master/docs/api.md#options).
@@ -12,7 +12,7 @@ const output = require("modular-css-core/lib/output.js");

// sourcemaps for css-to-js don't make much sense, so always return nothing
// https://github.com/rollup/rollup/wiki/Plugins#conventions
const map = {
const emptyMappings = {
mappings : "",
};

@@ -25,22 +25,42 @@ module.exports = function(opts) {
common : "common.css",

json : false,
map : true,

include : "**/*.css",

namedExports : true,

styleExport : false,
}, opts);

const filter = utils.createFilter(options.include, options.exclude);


const { styleExport, done, map } = options;

if(typeof map === "undefined") {
// Sourcemaps don't make much sense in styleExport mode
// But default to true otherwise
options.map = !styleExport;
}

const processor = options.processor || new Processor(options);

let runs = 0;

return {
name : "modular-css-rollup",

buildStart() {
// 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
if(styleExport && done) {
this.warn(
`Any plugins defined during the "done" lifecycle won't run when "styleExport" is set!`
);
}
},

async transform(code, id) {
if(!filter(id)) {
return null;
@@ -98,11 +118,15 @@ module.exports = function(opts) {
});
}

if(options.styleExport) {
out.push(`export var styles = ${JSON.stringify(result.details.result.css)};`);
}

const dependencies = processor.dependencies(id);

return {
code : out.join("\n"),
map,
map : emptyMappings,
dependencies,
};
},
@@ -113,6 +137,11 @@ module.exports = function(opts) {
},

async generateBundle(outputOptions, bundles) {
// styleExport disables all output file generation
if(styleExport) {
return;
}

const usage = new Map();
const common = new Map();
const files = [];
@@ -199,7 +228,7 @@ module.exports = function(opts) {
});
}
}

await Promise.all(
files
.filter(({ css }) => css.length)
@@ -190,6 +190,13 @@ console.log(a, str, num, dim, mix);
"
`;

exports[`/rollup.js should provide style export 1`] = `
"var styles = \\".ooh {\\\\n content: \\\\\\"string\\\\\\";\\\\n}\\\\n\\";

console.log(styles);
"
`;

exports[`/rollup.js should respect the CSS dependency tree 1`] = `
"var css = {
\\"wooga\\": \\"fooga wooga\\"
@@ -233,6 +240,14 @@ console.log(css, fooga);
"
`;

exports[`/rollup.js should warn that styleExport and done aren't compatible 1`] = `
Array [
Array [
"Any plugins defined during the \\"done\\" lifecycle won't run when \\"styleExport\\" is set!",
],
]
`;

exports[`/rollup.js shouldn't disable sourcemap generation 1`] = `
SourceMap {
"file": "simple.js",
@@ -178,6 +178,44 @@ describe("/rollup.js", () => {
expect(result.code).toMatchSnapshot();
});

it("should provide style export", async () => {
const bundle = await rollup({
input : require.resolve("./specimens/style-export.js"),
plugins : [
plugin({
namer,
styleExport : true,
}),
],
});

const result = await bundle.generate({ format });

expect(result.code).toMatchSnapshot();
});

it("should warn that styleExport and done aren't compatible", async () => {
const spy = jest.spyOn(global.console, "warn");

spy.mockImplementation(() => { /* NO-OP */ });

await rollup({
input : require.resolve("./specimens/style-export.js"),
plugins : [
plugin({
namer,
styleExport : true,
done : [
() => { /* NO OP */ },
],
}),
],
});

expect(spy).toHaveBeenCalled();
expect(spy.mock.calls).toMatchSnapshot();
});

it("should generate external source maps", async () => {
const bundle = await rollup({
input : require.resolve("./specimens/simple.js"),
@@ -0,0 +1,5 @@
@value str: "string";

.ooh {
content: str;
}
@@ -0,0 +1,3 @@
import { styles } from "./style-export.css";

console.log(styles);

0 comments on commit f0d4e43

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