Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow random expressions as long as they result in a className that begins with css #213

Merged
merged 9 commits into from
Aug 2, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/glamor/CSSPropertyOperations/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,13 @@ if (process.env.NODE_ENV !== 'production') {
export function createMarkupForStyles (styles) {
let serialized = ''
for (let styleName in styles) {
// console.log(styleName)
// if (styleName.indexOf('css-') === 0) {
// console.log(styles[styleName])
// serialized += createMarkupForStyles(styles[styleName])
// continue
// }

const isCustomProp = styleName.indexOf('--') === 0
if (!styles.hasOwnProperty(styleName)) {
continue
Expand Down
8 changes: 6 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,8 @@ function deconstruct (style) {
} else if (key.indexOf('@supports') === 0) {
supports = supports || {}
supports[key] = deconstruct(style[key])
} else if (key.indexOf('css-') === 0) {
plain = { ...plain, ...style[key]}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

silly way to get babels object assign

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have an assign util

} else {
plain = plain || {}
plain[key] = style[key]
Expand Down Expand Up @@ -366,7 +368,6 @@ function build (dest, { selector = '', mq = '', supp = '', src = {} }) {
src = [src]
}
src = flatten(src)

forEach(src, _src => {
if (isLikeRule(_src)) {
let reg = _getRegistered(_src)
Expand All @@ -380,7 +381,10 @@ function build (dest, { selector = '', mq = '', supp = '', src = {} }) {
build(dest, { selector, mq, supp, src: _src.composes })
}
forEach(keys(_src || {}), key => {
if (isSelector(key)) {
if (key.indexOf('css-') === 0) {
let _dest = dest
_dest[key] = registered[key.split('css-')[1]].style
} else if (isSelector(key)) {
build(dest, {
selector: joinSelectors(selector, key),
mq,
Expand Down
91 changes: 88 additions & 3 deletions src/parser.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// @flow
import parse from 'postcss-safe-parser'
import SafeParser from 'postcss-safe-parser/lib/safe-parser'
import postcssNested from 'postcss-nested'
import postcssJs from 'postcss-js'
import objParse from 'postcss-js/parser'
Expand Down Expand Up @@ -35,7 +35,7 @@ export function parseCSS (
if (typeof css === 'object') {
root = objParse(css, { from: filename })
} else {
root = parse(css, { from: filename })
root = safeParse(css, { from: filename })
}
let vars = 0
let composes: number = 0
Expand All @@ -56,7 +56,7 @@ export function parseCSS (
}
})

const styles = expandCSSFallbacks(prefixer(postcssJs.objectify(root)))
const styles = expandCSSFallbacks(prefixer(objectifyPostcssRules(root)))

return {
styles,
Expand Down Expand Up @@ -89,3 +89,88 @@ export function expandCSSFallbacks (style: { [string]: any }) {
// flatten arrays which haven't been flattened yet
return flattened
}

var camelcase = require('camelcase-css')

function atRule (node) {
if (typeof node.nodes === 'undefined') {
return true
} else {
return objectifyPostcssRules(node)
}
}

// postcss -> js obj
function objectifyPostcssRules (node) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function needs to be removed.

const result = [{}]
let name
let cursor = 0
node.each(function (child) {
var rules = {}
// console.log(JSON.stringify(child, null, 2))
node.each(function (rule) {
if (rule.type !== 'rule') {
} else if (rules[rule.selector]) {
// console.log(rules[rule.selector])
if (rules[rule.selector].append) {
rules[rule.selector].append(rule.nodes)
rule.remove()
}
} else {
rules[rule.selector] = rule
}
})

if (child.type === 'atrule') {
name = '@' + child.name

if (child.params) name += ' ' + child.params
if (typeof result[cursor][name] === 'undefined') {
result[cursor][name] = atRule(child)
} else if (Array.isArray(result[cursor][name])) {
result[cursor][name].push(atRule(child))
} else {
result[cursor][name] = [result[cursor][name], atRule(child)]
}
} else if (child.type === 'rule') {
result[cursor][child.selector] = objectifyPostcssRules(child)
} else if (child.type === 'decl') {
name = camelcase(child.prop)
child.value = child.important ? child.value + ' !important' : child.value
if (typeof result[cursor][name] === 'undefined') {
result[cursor][name] = child.value
} else if (Array.isArray(result[cursor][name])) {
result[cursor][name].push(child.value)
} else {
result[cursor][name] = [result[cursor][name], child.value]
}
}
})
return result[0]
}

// Parser

import Input from 'postcss/lib/input'

export function safeParse (css, opts) {
let input = new Input(css, opts)

let parser = new EmotionSafeParser(input)
parser.parse()

return parser.root
}

export class EmotionSafeParser extends SafeParser {
unknownWord (tokens) {
if (tokens[0][0] === 'word') {
if (/xxx(\d+)xxx/gm.exec(tokens[0][1])) {
this.decl(tokens)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

giphy 6

return
}
}

this.spaces += tokens.map(i => i[1]).join('')
}
}
19 changes: 19 additions & 0 deletions test/__snapshots__/css.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -222,3 +222,22 @@ exports[`css null rule 1`] = `
className="css-nil"
/>
`;

exports[`css random expression 1`] = `
.glamor-0 {
margin: 12px 48px;
font-size: 32px;
color: #ffffff;
}

@media (min-width: 420px) {
.glamor-0 {
width: 96px;
height: 96px;
}
}

<div
className="glamor-0"
/>
`;
19 changes: 19 additions & 0 deletions test/babel/__snapshots__/css.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,25 @@ exports[`babel css inline css basic 1`] = `
});"
`;

exports[`babel css inline css random expression 1`] = `
"
/*#__PURE__*/css([], [/*#__PURE__*/css([], [], function createEmotionStyledRules() {
return [{
\\"fontSize\\": \\"32px\\"
}];
})], function createEmotionStyledRules(x0) {
return [{
\\"margin\\": \\"12px 48px\\",
[\`\${x0}\`]: \\"\\",
\\"color\\": \\"#ffffff\\",
\\"@media (min-width: 420px)\\": {
\\"width\\": \\"96px\\",
\\"height\\": \\"96px\\"
}
}];
});"
`;

exports[`babel css inline interpolation in selector 1`] = `
"
const cls2 = /*#__PURE__*/css([], [className], function createEmotionStyledRules(x0) {
Expand Down
17 changes: 17 additions & 0 deletions test/babel/css.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,23 @@ describe('babel css', () => {
expect(code).toMatchSnapshot()
})

test('css random expression', () => {
const basic = `
css\`
margin: 12px 48px;
\${css\`font-size: 32px\`};
color: #ffffff;
@media(min-width: 420px) {
width: 96px;
height: 96px;
}
\``
const { code } = babel.transform(basic, {
plugins: [[plugin]]
})
expect(code).toMatchSnapshot()
})

test('nested expanded properties', () => {
const basic = `
css\`
Expand Down
23 changes: 20 additions & 3 deletions test/css.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,19 @@ describe('css', () => {
expect(tree).toMatchSnapshot()
})

test('random expression', () => {
const cls2 = css`
margin: 12px 48px;
${css`font-size: 32px`};
color: #ffffff;
@media(min-width: 420px) {
width: 96px;
height: 96px;
}`
const tree = renderer.create(<div className={cls2} />).toJSON()
expect(tree).toMatchSnapshot()
})

test('composes', () => {
const cls1 = css`
display: flex;
Expand Down Expand Up @@ -118,9 +131,13 @@ describe('css', () => {
expect(tree).toMatchSnapshot()
})
test('nested array', () => {
const cls1 = css([[{
display: 'flex'
}]])
const cls1 = css([
[
{
display: 'flex'
}
]
])
const tree = renderer.create(<div className={cls1} />).toJSON()
expect(tree).toMatchSnapshot()
})
Expand Down