Skip to content

Commit

Permalink
fix: better interpolation (#300)
Browse files Browse the repository at this point in the history
* better interpolation

* fixup
  • Loading branch information
jquense committed Jul 10, 2019
1 parent 6ea446f commit a7c3b93
Show file tree
Hide file tree
Showing 11 changed files with 388 additions and 486 deletions.
12 changes: 2 additions & 10 deletions src/plugin.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { basename, dirname, extname, join, relative } from 'path';
import { stripIndent } from 'common-tags';
import { outputFileSync } from 'fs-extra';
import camelCase from 'lodash/camelCase';
import defaults from 'lodash/defaults';
import get from 'lodash/get';
import kebabCase from 'lodash/kebabCase';
import generate from '@babel/generator';
import template from '@babel/template';
import * as t from '@babel/types';
Expand All @@ -20,9 +18,7 @@ const buildComponent = template(
`styled(ELEMENTTYPE, OPTIONS, {
displayName: DISPLAYNAME,
styles: IMPORT,
attrs: ATTRS,
kebabName: KEBABNAME,
camelName: CAMELNAME
attrs: ATTRS
})`,
);

Expand Down Expand Up @@ -178,9 +174,7 @@ export default function plugin() {
opts.pluginOptions,
);

const kebabName = kebabCase(displayName);
style.name = kebabName;
style.value = imports + wrapInClass(`.${style.name}`, text);
style.value = imports + wrapInClass(text);

const runtimeNode = buildComponent({
ELEMENTTYPE: elementType,
Expand All @@ -190,8 +184,6 @@ export default function plugin() {
IMPORT: buildImport({
FILENAME: t.StringLiteral(style.relativeFilePath),
}).expression,
KEBABNAME: t.StringLiteral(kebabName),
CAMELNAME: t.StringLiteral(camelCase(kebabName)),
});

if (pluginOptions.generateInterpolations)
Expand Down
6 changes: 3 additions & 3 deletions src/runtime/styled.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ const camelCase = str =>
);

function styled(type, options, settings) {
const { displayName, attrs, styles, kebabName, camelName } = settings;
const { displayName, attrs, styles } = settings;

options = options || { allowAs: typeof type === 'string' };
const componentClassName = styles[kebabName] || styles[camelName];
const componentClassName = styles.cls2 || styles.cls1;

// always passthrough if the type is a styled component
const allowAs = type.isAstroturf ? false : options.allowAs;

const hasModifiers = Object.keys(styles).some(
className => className !== camelName && className !== kebabName,
className => className !== componentClassName,
);

function Styled(rawProps, ref) {
Expand Down
9 changes: 2 additions & 7 deletions src/utils/buildTaggedTemplate.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { dirname, relative } from 'path';
import { stripIndent } from 'common-tags';
import groupBy from 'lodash/groupBy';
import uniq from 'lodash/uniq';

Expand All @@ -18,7 +17,7 @@ function resolveInterpolation(path, nodeMap, localStyle) {
isStyledComponent: style.isStyledComponent,
externalName: !style.isStyledComponent
? path.get('property').node.name
: style.name,
: 'cls1',
importName: relative(
dirname(localStyle.absoluteFilePath),
style.absoluteFilePath,
Expand Down Expand Up @@ -106,11 +105,7 @@ export default (path, nodeMap, localStyle, { tagName }) => {
const { externalName, importName } = interpolations.get(match);
const localName = `a${id++}`;

imports += stripIndent`
:import("${importName}") {
${localName}: ${externalName};
}\n
`;
imports += `@value ${externalName} as ${localName} from "${importName}";\n`;
return `.${localName}`;
});

Expand Down
34 changes: 29 additions & 5 deletions src/utils/wrapInClass.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,41 @@
export default function wrapInClass(className, value) {
import { stripIndents } from 'common-tags';

export default function wrapInClass(text) {
const imports = [];
const composes = [];

let match;
const matcher = /@import.*?(?:$|;)/g;
const rImports = /@import.*?(?:$|;)/g;
const rComposes = /\b(?:composes\s*?:\s*(.*?)(?:from\s(.+?))?(?=[}\n\r]))/gim;

// eslint-disable-next-line no-cond-assign
while ((match = matcher.exec(value))) {
while ((match = rImports.exec(text))) {
imports.push(match[0]);
}
match = null;
// eslint-disable-next-line no-cond-assign
while ((match = rComposes.exec(text))) {
composes.push(match[0]);
}

value = value.replace(matcher, '');
text = text.replace(rImports, '').replace(rComposes, '');

// comment prevents Sass from removing the empty class
let val = stripIndents`
.cls1 {
${text.trim() || '/*!*/'}
}`;

// Components need two css classes, the first being the single root
// class with styles and the second is the exported name used in the Styled helper
// We need both so that that interpolations have a class that is _only_
// the single class, e.g. no additional classes composed in so that it can be used
// as a selecto
if (composes.length) {
composes.unshift(`composes: cls1;`);
val += `\n.cls2 {\n${composes.join('\n')}\n}`;
}

let val = `${className} {\n${value}\n}`;
if (imports.length) val = `${imports.join('\n')}\n${val}`;
return val;
}
41 changes: 23 additions & 18 deletions test/__snapshots__/integration.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,38 @@

exports[`webpack integration should work 1`] = `
"
.index-styles__parent--1oDPf {
.index-styles__parent {
color: red;
}
.index-FancyBox__fancy-box--1DG83 {
color: red;
width: 75px;
.index-FancyBox__cls1 {
color: red;
width: 75px;
}
.index-FancyBox__fancy-box--1DG83.index-FancyBox__primary--3zeTZ {
background: white;
color: palevioletred;
}
.index-FancierBox__fancier-box--3Wzgh {
.index-FancyBox__cls1.index-FancyBox__primary {
background: white;
color: palevioletred;
}
.index-FancyBox__cls2 {
}
.index-FancierBox__cls1 {
color: ultra-red;
}
color: ultra-red;
.index-FancierBox__cls1 > .index-FancyBox__cls1 {
padding: 4em;
}
.index-FancierBox__fancier-box--3Wzgh > .index-FancyBox__fancy-box--1DG83 {
padding: 4em;
}
.index-styles__parent--1oDPf > .index-FancierBox__fancier-box--3Wzgh {
margin: 2em;
}
.index-styles__parent > .index-FancierBox__cls1 {
margin: 2em;
}
.index-Button__cls1 {
/*!*/
}
.index-Button__cls2 {
}
"
`;
Loading

0 comments on commit a7c3b93

Please sign in to comment.