Skip to content

Commit

Permalink
Fixed issue with auto-labelling crashing on $ at runtime (#1451)
Browse files Browse the repository at this point in the history
  • Loading branch information
Andarist authored and emmatown committed Aug 2, 2019
1 parent 2ca4d26 commit 4a3b18a
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 14 deletions.
7 changes: 7 additions & 0 deletions .changeset/hot-flies-rhyme/changes.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"releases": [
{ "name": "babel-plugin-emotion", "type": "patch" },
{ "name": "@emotion/core", "type": "patch" }
],
"dependents": []
}
1 change: 1 addition & 0 deletions .changeset/hot-flies-rhyme/changes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed issue with auto-labelling crashing on $ at runtime
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,9 @@ let Avatar = _styled(\\"img\\", {
`;

exports[`@emotion/babel-plugin-core styled label 1`] = `
"import styled from '@emotion/styled'
"/** @jsx jsx */
import styled from '@emotion/styled'
import { jsx } from '@emotion/core'
class Thing {
static SomeComponent = styled.div\`
Expand All @@ -259,10 +261,19 @@ class Thing {
\`
}
{
// label should get sanitized
const MiniCalWrap$ = styled.div\`
color: red;
\`
const Test = () => <MiniCalWrap$ />
}
↓ ↓ ↓ ↓ ↓ ↓
import _styled from \\"@emotion/styled-base\\";
import { jsx } from '@emotion/core';
class Thing {
static SomeComponent = _styled(\\"div\\", {
Expand All @@ -274,7 +285,7 @@ class Thing {
} : {
name: \\"1lrxbo5\\",
styles: \\"color:hotpink;\\",
map: \\"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxhYmVsLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUdtQyIsImZpbGUiOiJsYWJlbC5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBzdHlsZWQgZnJvbSAnQGVtb3Rpb24vc3R5bGVkJ1xuXG5jbGFzcyBUaGluZyB7XG4gIHN0YXRpYyBTb21lQ29tcG9uZW50ID0gc3R5bGVkLmRpdmBcbiAgICBjb2xvcjogaG90cGluaztcbiAgYFxuICBCYWRJZGVhQ29tcG9uZW50ID0gc3R5bGVkLmRpdmBcbiAgICBiYWNrZ3JvdW5kOiBob3RwaW5rO1xuICBgXG59XG4iXX0= */\\"
map: \\"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxhYmVsLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUttQyIsImZpbGUiOiJsYWJlbC5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qKiBAanN4IGpzeCAqL1xuaW1wb3J0IHN0eWxlZCBmcm9tICdAZW1vdGlvbi9zdHlsZWQnXG5pbXBvcnQgeyBqc3ggfSBmcm9tICdAZW1vdGlvbi9jb3JlJ1xuXG5jbGFzcyBUaGluZyB7XG4gIHN0YXRpYyBTb21lQ29tcG9uZW50ID0gc3R5bGVkLmRpdmBcbiAgICBjb2xvcjogaG90cGluaztcbiAgYFxuICBCYWRJZGVhQ29tcG9uZW50ID0gc3R5bGVkLmRpdmBcbiAgICBiYWNrZ3JvdW5kOiBob3RwaW5rO1xuICBgXG59XG5cbntcbiAgLy8gbGFiZWwgc2hvdWxkIGdldCBzYW5pdGl6ZWRcbiAgY29uc3QgTWluaUNhbFdyYXAkID0gc3R5bGVkLmRpdmBcbiAgICBjb2xvcjogcmVkO1xuICBgXG4gIGNvbnN0IFRlc3QgPSAoKSA9PiA8TWluaUNhbFdyYXAkIC8+XG59XG4iXX0= */\\"
});
BadIdeaComponent = _styled(\\"div\\", {
target: \\"egllku91\\",
Expand All @@ -285,8 +296,25 @@ class Thing {
} : {
name: \\"d1m7sn\\",
styles: \\"background:hotpink;\\",
map: \\"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxhYmVsLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQU0rQiIsImZpbGUiOiJsYWJlbC5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBzdHlsZWQgZnJvbSAnQGVtb3Rpb24vc3R5bGVkJ1xuXG5jbGFzcyBUaGluZyB7XG4gIHN0YXRpYyBTb21lQ29tcG9uZW50ID0gc3R5bGVkLmRpdmBcbiAgICBjb2xvcjogaG90cGluaztcbiAgYFxuICBCYWRJZGVhQ29tcG9uZW50ID0gc3R5bGVkLmRpdmBcbiAgICBiYWNrZ3JvdW5kOiBob3RwaW5rO1xuICBgXG59XG4iXX0= */\\"
map: \\"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxhYmVsLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQVErQiIsImZpbGUiOiJsYWJlbC5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qKiBAanN4IGpzeCAqL1xuaW1wb3J0IHN0eWxlZCBmcm9tICdAZW1vdGlvbi9zdHlsZWQnXG5pbXBvcnQgeyBqc3ggfSBmcm9tICdAZW1vdGlvbi9jb3JlJ1xuXG5jbGFzcyBUaGluZyB7XG4gIHN0YXRpYyBTb21lQ29tcG9uZW50ID0gc3R5bGVkLmRpdmBcbiAgICBjb2xvcjogaG90cGluaztcbiAgYFxuICBCYWRJZGVhQ29tcG9uZW50ID0gc3R5bGVkLmRpdmBcbiAgICBiYWNrZ3JvdW5kOiBob3RwaW5rO1xuICBgXG59XG5cbntcbiAgLy8gbGFiZWwgc2hvdWxkIGdldCBzYW5pdGl6ZWRcbiAgY29uc3QgTWluaUNhbFdyYXAkID0gc3R5bGVkLmRpdmBcbiAgICBjb2xvcjogcmVkO1xuICBgXG4gIGNvbnN0IFRlc3QgPSAoKSA9PiA8TWluaUNhbFdyYXAkIC8+XG59XG4iXX0= */\\"
});
}
{
// label should get sanitized
const MiniCalWrap$ = _styled(\\"div\\", {
target: \\"egllku92\\",
label: \\"MiniCalWrap-\\"
})(process.env.NODE_ENV === \\"production\\" ? {
name: \\"tokvmb\\",
styles: \\"color:red;\\"
} : {
name: \\"tokvmb\\",
styles: \\"color:red;\\",
map: \\"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxhYmVsLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQWVpQyIsImZpbGUiOiJsYWJlbC5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qKiBAanN4IGpzeCAqL1xuaW1wb3J0IHN0eWxlZCBmcm9tICdAZW1vdGlvbi9zdHlsZWQnXG5pbXBvcnQgeyBqc3ggfSBmcm9tICdAZW1vdGlvbi9jb3JlJ1xuXG5jbGFzcyBUaGluZyB7XG4gIHN0YXRpYyBTb21lQ29tcG9uZW50ID0gc3R5bGVkLmRpdmBcbiAgICBjb2xvcjogaG90cGluaztcbiAgYFxuICBCYWRJZGVhQ29tcG9uZW50ID0gc3R5bGVkLmRpdmBcbiAgICBiYWNrZ3JvdW5kOiBob3RwaW5rO1xuICBgXG59XG5cbntcbiAgLy8gbGFiZWwgc2hvdWxkIGdldCBzYW5pdGl6ZWRcbiAgY29uc3QgTWluaUNhbFdyYXAkID0gc3R5bGVkLmRpdmBcbiAgICBjb2xvcjogcmVkO1xuICBgXG4gIGNvbnN0IFRlc3QgPSAoKSA9PiA8TWluaUNhbFdyYXAkIC8+XG59XG4iXX0= */\\"
});
const Test = () => <MiniCalWrap$ />;
}"
`;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/** @jsx jsx */
import styled from '@emotion/styled/macro'
import { jsx } from '@emotion/core'

class Thing {
static SomeComponent = styled.div`
Expand All @@ -8,3 +10,11 @@ class Thing {
background: hotpink;
`
}

{
// label should get sanitized
const MiniCalWrap$ = styled.div`
color: red;
`
const Test = () => <MiniCalWrap$ />
}
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,9 @@ let Avatar = _styled(\\"img\\", {
`;

exports[`@emotion/styled.macro label 1`] = `
"import styled from '@emotion/styled/macro'
"/** @jsx jsx */
import styled from '@emotion/styled/macro'
import { jsx } from '@emotion/core'
class Thing {
static SomeComponent = styled.div\`
Expand All @@ -259,10 +261,19 @@ class Thing {
\`
}
{
// label should get sanitized
const MiniCalWrap$ = styled.div\`
color: red;
\`
const Test = () => <MiniCalWrap$ />
}
↓ ↓ ↓ ↓ ↓ ↓
import _styled from \\"@emotion/styled-base\\";
import { jsx } from '@emotion/core';
class Thing {
static SomeComponent = _styled(\\"div\\", {
Expand All @@ -274,7 +285,7 @@ class Thing {
} : {
name: \\"1lrxbo5\\",
styles: \\"color:hotpink;\\",
map: \\"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxhYmVsLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUdtQyIsImZpbGUiOiJsYWJlbC5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBzdHlsZWQgZnJvbSAnQGVtb3Rpb24vc3R5bGVkL21hY3JvJ1xuXG5jbGFzcyBUaGluZyB7XG4gIHN0YXRpYyBTb21lQ29tcG9uZW50ID0gc3R5bGVkLmRpdmBcbiAgICBjb2xvcjogaG90cGluaztcbiAgYFxuICBCYWRJZGVhQ29tcG9uZW50ID0gc3R5bGVkLmRpdmBcbiAgICBiYWNrZ3JvdW5kOiBob3RwaW5rO1xuICBgXG59XG4iXX0= */\\"
map: \\"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxhYmVsLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUttQyIsImZpbGUiOiJsYWJlbC5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qKiBAanN4IGpzeCAqL1xuaW1wb3J0IHN0eWxlZCBmcm9tICdAZW1vdGlvbi9zdHlsZWQvbWFjcm8nXG5pbXBvcnQgeyBqc3ggfSBmcm9tICdAZW1vdGlvbi9jb3JlJ1xuXG5jbGFzcyBUaGluZyB7XG4gIHN0YXRpYyBTb21lQ29tcG9uZW50ID0gc3R5bGVkLmRpdmBcbiAgICBjb2xvcjogaG90cGluaztcbiAgYFxuICBCYWRJZGVhQ29tcG9uZW50ID0gc3R5bGVkLmRpdmBcbiAgICBiYWNrZ3JvdW5kOiBob3RwaW5rO1xuICBgXG59XG5cbntcbiAgLy8gbGFiZWwgc2hvdWxkIGdldCBzYW5pdGl6ZWRcbiAgY29uc3QgTWluaUNhbFdyYXAkID0gc3R5bGVkLmRpdmBcbiAgICBjb2xvcjogcmVkO1xuICBgXG4gIGNvbnN0IFRlc3QgPSAoKSA9PiA8TWluaUNhbFdyYXAkIC8+XG59XG4iXX0= */\\"
});
BadIdeaComponent = _styled(\\"div\\", {
target: \\"egllku91\\",
Expand All @@ -285,8 +296,25 @@ class Thing {
} : {
name: \\"d1m7sn\\",
styles: \\"background:hotpink;\\",
map: \\"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxhYmVsLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQU0rQiIsImZpbGUiOiJsYWJlbC5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBzdHlsZWQgZnJvbSAnQGVtb3Rpb24vc3R5bGVkL21hY3JvJ1xuXG5jbGFzcyBUaGluZyB7XG4gIHN0YXRpYyBTb21lQ29tcG9uZW50ID0gc3R5bGVkLmRpdmBcbiAgICBjb2xvcjogaG90cGluaztcbiAgYFxuICBCYWRJZGVhQ29tcG9uZW50ID0gc3R5bGVkLmRpdmBcbiAgICBiYWNrZ3JvdW5kOiBob3RwaW5rO1xuICBgXG59XG4iXX0= */\\"
map: \\"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxhYmVsLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQVErQiIsImZpbGUiOiJsYWJlbC5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qKiBAanN4IGpzeCAqL1xuaW1wb3J0IHN0eWxlZCBmcm9tICdAZW1vdGlvbi9zdHlsZWQvbWFjcm8nXG5pbXBvcnQgeyBqc3ggfSBmcm9tICdAZW1vdGlvbi9jb3JlJ1xuXG5jbGFzcyBUaGluZyB7XG4gIHN0YXRpYyBTb21lQ29tcG9uZW50ID0gc3R5bGVkLmRpdmBcbiAgICBjb2xvcjogaG90cGluaztcbiAgYFxuICBCYWRJZGVhQ29tcG9uZW50ID0gc3R5bGVkLmRpdmBcbiAgICBiYWNrZ3JvdW5kOiBob3RwaW5rO1xuICBgXG59XG5cbntcbiAgLy8gbGFiZWwgc2hvdWxkIGdldCBzYW5pdGl6ZWRcbiAgY29uc3QgTWluaUNhbFdyYXAkID0gc3R5bGVkLmRpdmBcbiAgICBjb2xvcjogcmVkO1xuICBgXG4gIGNvbnN0IFRlc3QgPSAoKSA9PiA8TWluaUNhbFdyYXAkIC8+XG59XG4iXX0= */\\"
});
}
{
// label should get sanitized
const MiniCalWrap$ = _styled(\\"div\\", {
target: \\"egllku92\\",
label: \\"MiniCalWrap-\\"
})(process.env.NODE_ENV === \\"production\\" ? {
name: \\"tokvmb\\",
styles: \\"color:red;\\"
} : {
name: \\"tokvmb\\",
styles: \\"color:red;\\",
map: \\"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxhYmVsLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQWVpQyIsImZpbGUiOiJsYWJlbC5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qKiBAanN4IGpzeCAqL1xuaW1wb3J0IHN0eWxlZCBmcm9tICdAZW1vdGlvbi9zdHlsZWQvbWFjcm8nXG5pbXBvcnQgeyBqc3ggfSBmcm9tICdAZW1vdGlvbi9jb3JlJ1xuXG5jbGFzcyBUaGluZyB7XG4gIHN0YXRpYyBTb21lQ29tcG9uZW50ID0gc3R5bGVkLmRpdmBcbiAgICBjb2xvcjogaG90cGluaztcbiAgYFxuICBCYWRJZGVhQ29tcG9uZW50ID0gc3R5bGVkLmRpdmBcbiAgICBiYWNrZ3JvdW5kOiBob3RwaW5rO1xuICBgXG59XG5cbntcbiAgLy8gbGFiZWwgc2hvdWxkIGdldCBzYW5pdGl6ZWRcbiAgY29uc3QgTWluaUNhbFdyYXAkID0gc3R5bGVkLmRpdmBcbiAgICBjb2xvcjogcmVkO1xuICBgXG4gIGNvbnN0IFRlc3QgPSAoKSA9PiA8TWluaUNhbFdyYXAkIC8+XG59XG4iXX0= */\\"
});
const Test = () => <MiniCalWrap$ />;
}"
`;
Expand Down
15 changes: 10 additions & 5 deletions packages/babel-plugin-emotion/src/utils/label.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,32 @@
// @flow
import nodePath from 'path'

const invalidClassNameCharacters = /[!"#$%&'()*+,./:;<=>?@[\]^`|}~{]/g

const sanitizeLabelPart = (labelPart: string) =>
labelPart.trim().replace(invalidClassNameCharacters, '-')

function getLabel(
identifierName?: string,
autoLabel: boolean,
labelFormat?: string,
filename: string
) {
if (!identifierName || !autoLabel) return null
if (!labelFormat) return identifierName.trim()
if (!labelFormat) return sanitizeLabelPart(identifierName)

const parsedPath = nodePath.parse(filename)
let localDirname = nodePath.basename(parsedPath.dir)
let localFilename = parsedPath.name

if (localFilename === 'index') {
localFilename = localDirname
}
localFilename = localFilename.replace('.', '-')

return labelFormat
.replace(/\[local\]/gi, identifierName.trim())
.replace(/\[filename\]/gi, localFilename)
.replace(/\[dirname\]/gi, localDirname)
.replace(/\[local\]/gi, sanitizeLabelPart(identifierName))
.replace(/\[filename\]/gi, sanitizeLabelPart(localFilename))
.replace(/\[dirname\]/gi, sanitizeLabelPart(localDirname))
}

export function getLabelFromPath(path: *, state: *, t: *) {
Expand Down
18 changes: 18 additions & 0 deletions packages/core/__tests__/css.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,24 @@ test('autoLabel without babel', () => {
expect(tree.toJSON().props.className.endsWith('-SomeComp')).toBe(true)
})

test('autoLabel without babel (sanitized)', () => {
let SomeComp$ = props => {
return (
<div
{...props}
css={{
color: 'hotpink'
}}
>
something
</div>
)
}
const tree = renderer.create(<SomeComp$ />)

expect(tree.toJSON().props.className.endsWith('-SomeComp-')).toBe(true)
})

test('overwrite styles from parent', () => {
let SomeComponent = (props: Object) => (
<div
Expand Down
11 changes: 8 additions & 3 deletions packages/core/src/jsx.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ import { getRegisteredStyles, insertStyles } from '@emotion/utils'
import { isBrowser } from './utils'
import { serializeStyles } from '@emotion/serialize'

// those identifiers come from error stacks, so they have to be valid JS identifiers
// thus we only need to replace what is a valid character for JS, but not for CSS
const sanitizeIdentifier = (identifier: string) =>
identifier.replace(/\$/g, '-')

let typePropName = '__EMOTION_TYPE_PLEASE_DO_NOT_USE__'

let labelPropName = '__EMOTION_LABEL_PLEASE_DO_NOT_USE__'
Expand Down Expand Up @@ -149,13 +154,13 @@ export const jsx: typeof React.createElement = function(
let error = new Error()
if (error.stack) {
// chrome
let match = error.stack.match(/at jsx.*\n\s+at ([A-Z][A-Za-z]+) /)
let match = error.stack.match(/at jsx.*\n\s+at ([A-Z][A-Za-z$]+) /)
if (!match) {
// safari and firefox
match = error.stack.match(/^.*\n([A-Z][A-Za-z]+)@/)
match = error.stack.match(/^.*\n([A-Z][A-Za-z$]+)@/)
}
if (match) {
newProps[labelPropName] = match[1]
newProps[labelPropName] = sanitizeIdentifier(match[1])
}
}
}
Expand Down

0 comments on commit 4a3b18a

Please sign in to comment.