Skip to content

Commit

Permalink
feat: scope option for libraries
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisbateman committed Mar 31, 2019
1 parent 5990716 commit 53206bb
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 3 deletions.
4 changes: 4 additions & 0 deletions docs/CONFIGURATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ module.exports = {

If you need to specify custom babel configuration, you can pass them here. These babel options will be used by Linaria when parsing and evaluating modules.

- `scope: boolean or string` (default: `false`):

When set to `true` this option will create unique CSS class names based on your package.json name and version. This may be useful for libraries that want unique class names in different versions. You can alternatively provide a unique string to use (instead of the package.json name and version).

## `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.
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@
"normalize-path": "^3.0.0",
"postcss": "^7.0.14",
"react-is": "^16.8.3",
"read-pkg": "^5.0.0",
"rollup-pluginutils": "^2.4.1",
"source-map": "^0.7.3",
"strip-ansi": "^5.0.0",
Expand Down
31 changes: 31 additions & 0 deletions src/__tests__/transform.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,34 @@ it("doesn't throw due to duplicate preset", async () => {
)
).not.toThrowError('Duplicate plugin/preset detected');
});

it('respects scope option', async () => {
const testFile = dedent`
import { css } from 'linaria';
export const test = css\`
color: red;
\`;
`;

const baseResult = transform(testFile, {
filename: './test.js',
outputFilename: '../.linaria-cache/test.css',
pluginOptions: {
scopeString: '',
},
});

expect(baseResult).toMatchSnapshot();

const customScopeResult = transform(testFile, {
filename: './test.js',
outputFilename: '../.linaria-cache/test.css',
pluginOptions: {
scopeString: 'custom-scope',
},
});

expect(customScopeResult).toMatchSnapshot();
expect(customScopeResult.cssText).not.toBe(baseResult.cssText);
});
1 change: 1 addition & 0 deletions src/babel/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export type StrictOptions = {|
evaluate: boolean,
ignore: RegExp,
babelOptions: Object,
scopeString: string,
|};

export type Location = {
Expand Down
19 changes: 19 additions & 0 deletions src/babel/utils/loadOptions.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* @flow */

import cosmiconfig from 'cosmiconfig';
import readPkg from 'read-pkg';
import type { StrictOptions } from '../types';

export type PluginOptions = $Shape<{
Expand All @@ -14,16 +15,34 @@ export default function loadOptions(
overrides?: PluginOptions = {}
): StrictOptions {
const { configFile, ...rest } = overrides;
let scopeOption;
let scopeString = '';

const result =
configFile !== undefined
? explorer.loadSync(configFile)
: explorer.searchSync();

if (result && result.config) {
scopeOption = result.config.scope;
}

if (scopeOption === true) {
try {
const pkgJson = readPkg.sync();
scopeString = `${pkgJson.name}@${pkgJson.version}`;
} catch (err) {
console.log(`Couldn't retrieve package.json name/version.`);
}
} else if (typeof scopeOption === 'string') {
scopeString = scopeOption;
}

const options = {
displayName: false,
evaluate: true,
ignore: /node_modules/,
scopeString,
...(result ? result.config : null),
...rest,
};
Expand Down
7 changes: 4 additions & 3 deletions src/babel/visitors/TaggedTemplateExpression.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,10 @@ export default function TaggedTemplateExpression(
// Also use append the index of the class to the filename for uniqueness in the file
const slug = toValidCSSIdentifier(
`${displayName.charAt(0).toLowerCase()}${slugify(
`${relative(state.file.opts.root, state.file.opts.filename)}:${
state.index
}`
`${options.scopeString ? `${options.scopeString}:` : ''}${relative(
state.file.opts.root,
state.file.opts.filename
)}:${state.index}`
)}`
);

Expand Down
8 changes: 8 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6261,6 +6261,14 @@ read-pkg@^4.0.1:
parse-json "^4.0.0"
pify "^3.0.0"

read-pkg@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.0.0.tgz#75449907ece8dfb89cbc76adcba2665316e32b94"
integrity sha512-OWufaRc67oJjcgrxckW/qO9q22iYzyiONh8h+GMcnOvSHAmhV1Dr3x+gyRjP+Qxc5jKupkSfoCQLS/98rDPh9A==
dependencies:
normalize-package-data "^2.3.2"
parse-json "^4.0.0"

readable-stream@^2.0.1, readable-stream@^2.1.5:
version "2.3.6"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
Expand Down

0 comments on commit 53206bb

Please sign in to comment.