Skip to content

Commit

Permalink
feat: support template literals in object properties and jsx props
Browse files Browse the repository at this point in the history
fixes #134, #138
  • Loading branch information
satya164 committed Oct 21, 2017
1 parent a6297d6 commit 8ce4330
Show file tree
Hide file tree
Showing 29 changed files with 373 additions and 467 deletions.
1 change: 0 additions & 1 deletion babel.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
module.exports = function linariaBabelPreset(context, opts = {}) {
return {
plugins: [
[require('./build/babel/hoist-css').default, opts],
[require('./build/babel/preval-extract').default, opts],
[require('./build/babel/rewire-imports').default, opts],
],
Expand Down
2 changes: 1 addition & 1 deletion src/babel/__integration-tests__/__utils__/transpile.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ function transpile(source, options = { pluginOptions: {}, babelOptions: {} }) {
`,
Object.assign(
{
presets: ['es2015', 'stage-2'],
presets: ['es2015', 'stage-2', 'react'],
plugins: [[PREVAL_PLUGIN_PATH, options.pluginOptions]],
sourceMaps: false,
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,54 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`preval-extract babel plugin errors should throw error if "css" tagged template literal is not assigned to a variable 1`] = `
Command failed: node <<CWD>>/src/babel/__integration-tests__/__utils__/transpile.js '"css\`\\n font-size: 3em;\\n\`;"' '{"pluginOptions":{"cache":false,"extract":false},"babelOptions":{"filename":"test.js"}}'
<<CWD>>/node_modules/babel-core/lib/transformation/file/index.js:590
throw err;
^
SyntaxError: test.js: Couldn't determine the class name for CSS template literal. Ensure that it's either:
- Assigned to a variable
- Is an object property
- Is a prop in a JSX element
1 | import css from '<<CWD>>/build/css.js';
2 |
> 3 | css\`
| ^
4 | font-size: 3em;
5 | \`;
at File.buildCodeFrameError (<<CWD>>/node_modules/babel-core/lib/transformation/file/index.js:427:15)
at NodePath.buildCodeFrameError (<<CWD>>/node_modules/babel-traverse/lib/path/index.js:140:26)
at PluginPass.TaggedTemplateExpression (<<CWD>>/build/babel/preval-extract/index.js:105:26)
at newFn (<<CWD>>/node_modules/babel-traverse/lib/visitors.js:276:21)
at NodePath._call (<<CWD>>/node_modules/babel-traverse/lib/path/context.js:76:18)
at NodePath.call (<<CWD>>/node_modules/babel-traverse/lib/path/context.js:48:17)
at NodePath.visit (<<CWD>>/node_modules/babel-traverse/lib/path/context.js:105:12)
at TraversalContext.visitQueue (<<CWD>>/node_modules/babel-traverse/lib/context.js:150:16)
at TraversalContext.visitSingle (<<CWD>>/node_modules/babel-traverse/lib/context.js:108:19)
at TraversalContext.visit (<<CWD>>/node_modules/babel-traverse/lib/context.js:192:19)
`;
exports[`preval-extract babel plugin errors should throw error if "css.named" is not called with classname 1`] = `
Command failed: node <<CWD>>/src/babel/__integration-tests__/__utils__/transpile.js '"css.named\`\\n font-size: 3em;\\n\`;"' '{"pluginOptions":{"cache":false,"extract":false},"babelOptions":{"filename":"test.js"}}'
<<CWD>>/node_modules/babel-core/lib/transformation/file/index.js:590
throw err;
^
Error: test.js: Linaria's \`css.named\` must be called with a class name
at isLinariaTaggedTemplate (<<CWD>>/build/babel/preval-extract/validators.js:22:11)
at PluginPass.TaggedTemplateExpression (<<CWD>>/build/babel/preval-extract/index.js:88:72)
at newFn (<<CWD>>/node_modules/babel-traverse/lib/visitors.js:276:21)
at NodePath._call (<<CWD>>/node_modules/babel-traverse/lib/path/context.js:76:18)
at NodePath.call (<<CWD>>/node_modules/babel-traverse/lib/path/context.js:48:17)
at NodePath.visit (<<CWD>>/node_modules/babel-traverse/lib/path/context.js:105:12)
at TraversalContext.visitQueue (<<CWD>>/node_modules/babel-traverse/lib/context.js:150:16)
at TraversalContext.visitSingle (<<CWD>>/node_modules/babel-traverse/lib/context.js:108:19)
at TraversalContext.visit (<<CWD>>/node_modules/babel-traverse/lib/context.js:192:19)
at Function.traverse.node (<<CWD>>/node_modules/babel-traverse/lib/index.js:114:17)
`;
exports[`preval-extract babel plugin errors should throw error if the id was not found 1`] = `
Command failed: node <<CWD>>/src/babel/__integration-tests__/__utils__/transpile.js '"const title = css\`\\n width: \${document.width};\\n\`;"' '{"pluginOptions":{"cache":false,"extract":false},"babelOptions":{"filename":"test.js"}}'
<<CWD>>/node_modules/babel-core/lib/transformation/file/index.js:590
Expand All @@ -17,7 +66,7 @@ SyntaxError: test.js: Linaria css evaluation error:
5 | \`;
at File.buildCodeFrameError (<<CWD>>/node_modules/babel-core/lib/transformation/file/index.js:427:15)
at NodePath.buildCodeFrameError (<<CWD>>/node_modules/babel-traverse/lib/path/index.js:140:26)
at resolveSource (<<CWD>>/build/babel/preval-extract/resolveSource.js:33:16)
at resolveSource (<<CWD>>/build/babel/preval-extract/resolveSource.js:31:16)
at Object.Identifier (<<CWD>>/build/babel/preval-extract/index.js:46:48)
at NodePath._call (<<CWD>>/node_modules/babel-traverse/lib/path/context.js:76:18)
at NodePath.call (<<CWD>>/node_modules/babel-traverse/lib/path/context.js:48:17)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import css from '<<CWD>>/build/css.js';
const size = 3;
let color = "#ffffff";
/*linaria-output*/const header = "header__3r30ar";
const header = /*linaria-output*/"header__3r30ar";
`;
exports[`preval-extract babel plugin should preval css with classname from another prevaled css 1`] = `
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ describe('preval-extract babel plugin', () => {
{ filename: path.join(process.cwd(), 'test.js') }
);

const classnameWithSlugFromContent = /header = '(header__[a-z0-9]+)'/g.exec(
const classnameWithSlugFromContent = /header = \/\*.+\*\/'(header__[a-z0-9]+)'/g.exec(
codeWithSlugFromContent
);
const classnameWithSlugFromFilename = /header = '(header__[a-z0-9]+)'/g.exec(
const classnameWithSlugFromFilename = /header = \/\*.+\*\/'(header__[a-z0-9]+)'/g.exec(
codeWithSlugFromFilename
);

Expand Down
4 changes: 2 additions & 2 deletions src/babel/__integration-tests__/preval-extract/errors.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ describe('preval-extract babel plugin errors', () => {
font-size: 3em;
\`;
`);
}).toThrow();
}).toThrowErrorMatchingSnapshot();
});

it('should throw error if "css.named" is not called with classname', () => {
Expand All @@ -31,7 +31,7 @@ describe('preval-extract babel plugin errors', () => {
font-size: 3em;
\`;
`);
}).toThrow();
}).toThrowErrorMatchingSnapshot();
});

it('should throw error if the id was not found', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ describe('preval-extract babel plugin', () => {
\`;
`);

const match = /header = '(header__[a-z0-9]+)'/g.exec(code);
const match = /header = \/\*.+\*\/'(header__[a-z0-9]+)'/g.exec(code);
expect(match).not.toBeNull();
const css = getCSSForClassName(match[1]);
expect(css).toMatch('font-size: 3em');
Expand All @@ -62,7 +62,7 @@ describe('preval-extract babel plugin', () => {
\`;
`);

const match = /header = "(my-header__[a-z0-9]+)"/g.exec(code);
const match = /header = \/\*.+\*\/"(my-header__[a-z0-9]+)"/g.exec(code);
expect(match).not.toBeNull();
const css = getCSSForClassName(match[1]);
expect(css).toMatch('font-size: 3em');
Expand All @@ -80,8 +80,8 @@ describe('preval-extract babel plugin', () => {
\`;
`);

const headerMatch = /header = '(header__[a-z0-9]+)'/g.exec(code);
const bodyMatch = /body = '(body__[a-z0-9]+)'/g.exec(code);
const headerMatch = /header = \/\*.+\*\/'(header__[a-z0-9]+)'/g.exec(code);
const bodyMatch = /body = \/\*.+\*\/'(body__[a-z0-9]+)'/g.exec(code);
expect(headerMatch).not.toBeNull();
expect(bodyMatch).not.toBeNull();
const headerStyles = getCSSForClassName(headerMatch[1]);
Expand All @@ -97,15 +97,14 @@ describe('preval-extract babel plugin', () => {
const defaults = {
fontSize: "3em",
};
function render() {
const header = css\`
font-size: ${'${defaults.fontSize}'};
\`;
}
`);

const match = /header = "(header__[a-z0-9]+)"/g.exec(code);
const match = /header = \/\*.+\*\/"(header__[a-z0-9]+)"/g.exec(code);
expect(match).not.toBeNull();
const css = getCSSForClassName(match[1]);
expect(css).toMatch('font-size: 3em');
Expand All @@ -131,7 +130,7 @@ describe('preval-extract babel plugin', () => {
}
);

const match = /header = "(header__[a-z0-9]+)"/g.exec(code);
const match = /header = \/\*.+\*\/"(header__[a-z0-9]+)"/g.exec(code);
expect(match).not.toBeNull();
const css = getCSSForClassName(match[1]);
expect(css).toMatch('font-size: 3em');
Expand All @@ -154,10 +153,12 @@ describe('preval-extract babel plugin', () => {
\`;
`);

const titleMatch = /title = '(title__[a-z0-9]+)'/g.exec(code);
const titleMatch = /title = \/\*.+\*\/'(title__[a-z0-9]+)'/g.exec(code);
expect(titleMatch).not.toBeNull();

const containerMatch = /container = '(container__[a-z0-9]+)'/g.exec(code);
const containerMatch = /container = \/\*.+\*\/'(container__[a-z0-9]+)'/g.exec(
code
);
expect(containerMatch).not.toBeNull();

const css = getCSSForClassName(containerMatch[1]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ describe('preval-extract babel plugin with commonjs imports', () => {

it('should preval imported constants ', () => {
const { code, getCSSForClassName } = transpile(dedent`
const constants = require("./src/babel/__integration-tests__/__fixtures__/commonjs/constants.js");
const constants = require("./src/babel/__integration-tests__/__fixtures__/commonjs/constants.js");
const header = css\`
font-size: ${'${constants.fontSize}'};
\`;
`);
const header = css\`
font-size: ${'${constants.fontSize}'};
\`;
`);

const match = /header = "(header__[a-z0-9]+)"/g.exec(code);
const match = /header = \/\*.+\*\/"(header__[a-z0-9]+)"/g.exec(code);
expect(match).not.toBeNull();
const css = getCSSForClassName(match[1]);
expect(css).toMatch('font-size: 14px');
Expand All @@ -31,14 +31,14 @@ describe('preval-extract babel plugin with commonjs imports', () => {

it('should preval imported constants with destructurization', () => {
const { code, getCSSForClassName } = transpile(dedent`
const { fontSize } = require("./src/babel/__integration-tests__/__fixtures__/commonjs/constants.js");
const { fontSize } = require("./src/babel/__integration-tests__/__fixtures__/commonjs/constants.js");
const header = css\`
font-size: ${'${fontSize}'};
\`;
`);
const header = css\`
font-size: ${'${fontSize}'};
\`;
`);

const match = /header = "(header__[a-z0-9]+)"/g.exec(code);
const match = /header = \/\*.+\*\/"(header__[a-z0-9]+)"/g.exec(code);
expect(match).not.toBeNull();
const css = getCSSForClassName(match[1]);
expect(css).toMatch('font-size: 14px');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ describe('preval-extract babel plugin with ES imports', () => {
\`;
`);

const match = /header = "(header__[a-z0-9]+)"/g.exec(code);
const match = /header = \/\*.+\*\/"(header__[a-z0-9]+)"/g.exec(code);
expect(match).not.toBeNull();
const css = getCSSForClassName(match[1]);
expect(css).toMatch('font-size: 14px');
Expand All @@ -42,8 +42,8 @@ describe('preval-extract babel plugin with ES imports', () => {
\`;
`);

const headerMatch = /header = "(header__[a-z0-9]+)"/g.exec(code);
const bodyMatch = /body = "(body__[a-z0-9]+)"/g.exec(code);
const headerMatch = /header = \/\*.+\*\/"(header__[a-z0-9]+)"/g.exec(code);
const bodyMatch = /body = \/\*.+\*\/"(body__[a-z0-9]+)"/g.exec(code);
expect(headerMatch).not.toBeNull();
expect(bodyMatch).not.toBeNull();
const headerStyles = getCSSForClassName(headerMatch[1]);
Expand All @@ -63,7 +63,7 @@ describe('preval-extract babel plugin with ES imports', () => {
\`;
`);

const match = /header = "(header__[a-z0-9]+)"/g.exec(code);
const match = /header = \/\*.+\*\/"(header__[a-z0-9]+)"/g.exec(code);
expect(match).not.toBeNull();
const css = getCSSForClassName(match[1]);
expect(css).toMatch('font-size: 28px');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ describe('preval-extract babel plugin with function calls', () => {

it('should preval with function call inside an expression', () => {
const { code, getCSSForClassName } = transpile(dedent`
const constants = require("./src/babel/__integration-tests__/__fixtures__/commonjs/constants.js");
const utils = require("./src/babel/__integration-tests__/__fixtures__/commonjs/utils.js");
const constants = require("./src/babel/__integration-tests__/__fixtures__/commonjs/constants.js");
const utils = require("./src/babel/__integration-tests__/__fixtures__/commonjs/utils.js");
const header = css\`
font-size: ${'${utils.multiply(constants.unitless.fontSize)}'}px;
\`;
`);
const header = css\`
font-size: ${'${utils.multiply(constants.unitless.fontSize)}'}px;
\`;
`);

const match = /header = "(header__[a-z0-9]+)"/g.exec(code);
const match = /header = \/\*.+\*\/"(header__[a-z0-9]+)"/g.exec(code);
expect(match).not.toBeNull();
const css = getCSSForClassName(match[1]);
expect(css).toMatch('font-size: 28px');
Expand All @@ -32,21 +32,21 @@ describe('preval-extract babel plugin with function calls', () => {

it('should preval multiple function calls inside an expression', () => {
const { code, getCSSForClassName } = transpile(dedent`
const constants = require("./src/babel/__integration-tests__/__fixtures__/commonjs/constants.js");
const utils = require("./src/babel/__integration-tests__/__fixtures__/commonjs/utils.js");
const constants = require("./src/babel/__integration-tests__/__fixtures__/commonjs/constants.js");
const utils = require("./src/babel/__integration-tests__/__fixtures__/commonjs/utils.js");
function compose(...fns) {
return value => fns.reduce((prev, fn) => {
return fn(prev);
}, value);
}
function compose(...fns) {
return value => fns.reduce((prev, fn) => {
return fn(prev);
}, value);
}
const header = css\`
font-size: ${'${compose(utils.multiply, utils.add5)(constants.unitless.fontSize)}'}px;
\`;
`);
const header = css\`
font-size: ${'${compose(utils.multiply, utils.add5)(constants.unitless.fontSize)}'}px;
\`;
`);

const match = /header = "(header__[a-z0-9]+)"/g.exec(code);
const match = /header = \/\*.+\*\/"(header__[a-z0-9]+)"/g.exec(code);
expect(match).not.toBeNull();
const css = getCSSForClassName(match[1]);
expect(css).toMatch('font-size: 33px');
Expand Down
Loading

0 comments on commit 8ce4330

Please sign in to comment.