Skip to content

Commit

Permalink
feat: support configuring linaria with a config
Browse files Browse the repository at this point in the history
file

The babel preset is used in several ways:
- babel config
- webpack loader
- rollup plugin
- stylelint preprocessor

Having a config file makes it possible to configure it in one place instead of configuring separately for each tool.
  • Loading branch information
satya164 committed Jan 7, 2019
1 parent fca503f commit 6c32118
Show file tree
Hide file tree
Showing 14 changed files with 135 additions and 44 deletions.
4 changes: 3 additions & 1 deletion README.md
Expand Up @@ -59,6 +59,8 @@ Optionally, add the `linaria/babel` preset to your Babel configuration at the en
}
```

See [Configuration](/docs/CONFIGURATION.md) to customize how Linaria processes your files.

## Syntax

Linaria can be used with any framework, with additional helpers for React. The basic syntax looks like this:
Expand Down Expand Up @@ -123,7 +125,7 @@ Dynamic styles will be applied using CSS custom properties (aka CSS variables) a
- [API and usage](/docs/API.md)
- [Client APIs](/docs/API.md#client-apis)
- [Server APIs](/docs/API.md#server-apis)
- [Configuring Babel](/docs/BABEL_PRESET.md)
- [Configuration](/docs/CONFIGURATION.md)
- [Dynamic styles with `css` tag](/docs/DYNAMIC_STYLES.md)
- [Theming](/docs/THEMING.md)
- [Critical CSS extraction](/docs/CRITICAL_CSS.md)
Expand Down
23 changes: 0 additions & 23 deletions docs/BABEL_PRESET.md

This file was deleted.

2 changes: 1 addition & 1 deletion docs/BUNDLERS_INTEGRATION.md
Expand Up @@ -86,7 +86,7 @@ The loader accepts the following options:
- `sourceMap: boolean` (default: `false`) - Setting this option to `true` will include source maps for the generated CSS so that you can see where source of the class name in devtools. We recommend to enable this only in development mode because the sourcemap is inlined into the CSS files.
- `cacheDirectory: string` (default: `'.linaria-cache'`) - Path to the directory where the loader will output the intermediate CSS files. You can pass a relative or absolute directory path. Make sure the directory is inside the working directory for things to work properly. **You should add this directory to `.gitignore` so you don't accidentally commit them.**

In addition to the above options, the loader also accepts all the options accepted by the [babel preset](/docs/BABEL_PRESET.md).
In addition to the above options, the loader also accepts all the options supported in the [configuration file](/docs/CONFIGURATION.md).

You can pass options to the loader like so:

Expand Down
51 changes: 51 additions & 0 deletions docs/CONFIGURATION.md
@@ -0,0 +1,51 @@
# Configuration

Linaria can be customized using a JavaScript, JSON or YAML file. This can be in form of:

- `linaria.config.js` JS file exporting the object (recommended).
- `linaria` property in a `package.json` file.
- `.linariarc` file with JSON or YAML syntax.
- `.linariarc.json`, `.linariarc.yaml`, `.linariarc.yml`, or `.linariarc.js` file.

Example `linaria.config.js`:

```js
module.exports = {
evaluate: true,
displayName: false,
}
```

## Options

- `evaluate: boolean` (default: `true`):

Enabling this will evaluate dynamic expressions in the CSS. You need to enable this if you want to use imported variables in the CSS or interpolate other components. Enabling this also ensures that your styled components wrapping other styled components will have the correct specificity and override styles properly.

- `displayName: boolean` (default: `false`):

Enabling this will add a display name to generated class names, e.g. `.Title_abcdef` instead of `.abcdef'. It is disabled by default to generate smaller CSS files.

- `ignore: RegExp` (default: `/node_modules/`):

If you specify a regex here, files matching the regex won't be processed, i.e. the matching files won't be transformed with Babel during evaluation. If you need to compile certain modules under `/node_modules/`, it's recommended to do it on a module by module basis for faster transforms, e.g. `ignore: /node_modules[\/\\](?!some-module|other-module)/`.

## `linaria/babel` preset

The preset pre-processes and evaluates the CSS. The bundler plugins use this preset under the hood. You also might want to use this preset if you import the components outside of the files handled by your bundler, such as on your server or in unit tests.

To use this preset, add `linaria/babel` to your Babel configuration at the end of the presets list:

`.babelrc`:

```diff
{
"presets": [
"@babel/preset-env",
"@babel/preset-react",
+ "linaria/babel"
]
}
```

The babel preset can accept the same options supported by the configuration file, however it's recommended to use the configuration file directly.
2 changes: 2 additions & 0 deletions docs/LINTING.md
Expand Up @@ -29,6 +29,8 @@ Here's the example `.stylelintrc` configuration file:

Please refer to the [official stylelint documentation](https://stylelint.io/user-guide/configuration/) for more info about configuration.

The preprocessor will use the [options from the configuration file](/docs/CONFIGURATION.md) for processing your files.

### Linting your files

Add the following to your `package.json` scripts:
Expand Down
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -82,6 +82,7 @@
"@babel/plugin-syntax-dynamic-import": "^7.0.0",
"@babel/plugin-transform-modules-commonjs": "^7.1.0",
"@babel/register": "^7.0.0",
"cosmiconfig": "^5.0.7",
"loader-utils": "^1.1.0",
"mkdirp": "^0.5.1",
"postcss": "^7.0.5",
Expand Down
6 changes: 4 additions & 2 deletions src/babel/evaluate.js
@@ -1,5 +1,7 @@
/* @flow */

import type { Options as PluginOptions } from './extract';

const generator = require('@babel/generator').default;
const babel = require('@babel/core');
const Module = require('./module');
Expand Down Expand Up @@ -59,7 +61,7 @@ module.exports = function evaluate(
t: any,
filename: string,
transformer?: (text: string) => { code: string },
options?: { ignore?: RegExp }
options?: PluginOptions
) {
const requirements = [];

Expand Down Expand Up @@ -159,14 +161,14 @@ module.exports = function evaluate(
return babel.transformSync(text, {
caller: { name: 'linaria', evaluate: true },
filename: this.filename,
presets: [[require.resolve('./index'), options]],
plugins: [
// Include this plugin to avoid extra config when using { module: false } for webpack
'@babel/plugin-transform-modules-commonjs',
'@babel/plugin-proposal-export-namespace-from',
// We don't support dynamic imports when evaluating, but don't wanna syntax error
// This will replace dynamic imports with an object that does nothing
require.resolve('./dynamic-import-noop'),
[require.resolve('./extract'), { evaluate: true }],
],
});
};
Expand Down
16 changes: 4 additions & 12 deletions src/babel/extract.js
Expand Up @@ -168,20 +168,12 @@ type State = {|
|};

export type Options = {
displayName?: boolean,
evaluate?: boolean,
ignore?: RegExp,
displayName: boolean,
evaluate: boolean,
ignore: RegExp,
};

module.exports = function extract(babel: any, options: Options = {}) {
// Set some defaults for options
options = {
displayName: false,
evaluate: true,
ignore: /node_modules/,
...options,
};

module.exports = function extract(babel: any, options: Options) {
const { types: t } = babel;

return {
Expand Down
17 changes: 17 additions & 0 deletions src/babel/index.js
@@ -1,4 +1,21 @@
const cosmiconfig = require('cosmiconfig');

const explorer = cosmiconfig('linaria');

module.exports = function linaria(context, options) {
// Load configuration file
const result = explorer.searchSync();

// Set some defaults for options
// eslint-disable-next-line no-param-reassign
options = {
displayName: false,
evaluate: true,
ignore: /node_modules/,
...(result ? result.config : null),
...options,
};

return {
plugins: [[require('./extract'), options]],
};
Expand Down
3 changes: 2 additions & 1 deletion src/rollup.js
Expand Up @@ -6,10 +6,11 @@ const { createFilter } = require('rollup-pluginutils');
const transform = require('./transform');
const slugify = require('./slugify');

type RollupPluginOptions = PluginOptions & {
type RollupPluginOptions = {
include?: string | string[],
exclude?: string | string[],
sourceMap?: boolean,
...$Shape<PluginOptions>,
};

module.exports = function linaria({
Expand Down
4 changes: 1 addition & 3 deletions src/stylelint/preprocessor.js
Expand Up @@ -16,9 +16,7 @@ function preprocessor() {
let result;

try {
result = transform(filename, input, {
evaluate: true,
});
result = transform(filename, input);
} catch (e) {
// Ignore parse errors
return '';
Expand Down
2 changes: 1 addition & 1 deletion src/transform.js
Expand Up @@ -36,7 +36,7 @@ const STYLIS_DECLARATION = 1;
module.exports = function transform(
filename: string,
content: string,
options: PluginOptions,
options: $Shape<PluginOptions>,
inputSourceMap?: Object,
outputFilename?: string
): Result {
Expand Down
3 changes: 3 additions & 0 deletions website/linaria.config.js
@@ -0,0 +1,3 @@
module.exports = {
displayName: process.env.NODE_ENV !== 'production',
};
45 changes: 45 additions & 0 deletions yarn.lock
Expand Up @@ -2040,13 +2040,27 @@ call-me-maybe@^1.0.1:
resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b"
integrity sha1-JtII6onje1y95gJQoV8DHBak1ms=

caller-callsite@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134"
integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=
dependencies:
callsites "^2.0.0"

caller-path@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f"
integrity sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=
dependencies:
callsites "^0.2.0"

caller-path@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4"
integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=
dependencies:
caller-callsite "^2.0.0"

callsites@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca"
Expand Down Expand Up @@ -2586,6 +2600,16 @@ core-util-is@1.0.2, core-util-is@~1.0.0:
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=

cosmiconfig@^5.0.7:
version "5.0.7"
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.0.7.tgz#39826b292ee0d78eda137dfa3173bd1c21a43b04"
integrity sha512-PcLqxTKiDmNT6pSpy4N6KtuPwb53W+2tzNvwOZw0WH9N6O0vLIBq0x8aj8Oj75ere4YcGi48bDFCL+3fRJdlNA==
dependencies:
import-fresh "^2.0.0"
is-directory "^0.3.1"
js-yaml "^3.9.0"
parse-json "^4.0.0"

cp-file@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/cp-file/-/cp-file-6.0.0.tgz#f38477ece100b403fcf780fd34d030486beb693e"
Expand Down Expand Up @@ -4243,6 +4267,14 @@ ignore@^4.0.6:
resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==

import-fresh@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546"
integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY=
dependencies:
caller-path "^2.0.0"
resolve-from "^3.0.0"

import-lazy@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43"
Expand Down Expand Up @@ -4466,6 +4498,11 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2:
is-data-descriptor "^1.0.0"
kind-of "^6.0.2"

is-directory@^0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1"
integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=

is-dotfile@^1.0.0:
version "1.0.3"
resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1"
Expand Down Expand Up @@ -5172,6 +5209,14 @@ js-yaml@^3.7.0:
argparse "^1.0.7"
esprima "^4.0.0"

js-yaml@^3.9.0:
version "3.12.1"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.1.tgz#295c8632a18a23e054cf5c9d3cecafe678167600"
integrity sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==
dependencies:
argparse "^1.0.7"
esprima "^4.0.0"

jsbn@~0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
Expand Down

0 comments on commit 6c32118

Please sign in to comment.