Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
adamwathan committed Mar 7, 2018
1 parent f00e1df commit 6450748
Show file tree
Hide file tree
Showing 4 changed files with 210 additions and 0 deletions.
136 changes: 136 additions & 0 deletions __tests__/parseObjectStyles.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import _ from 'lodash'
import parseObjectStyles from '../src/util/parseObjectStyles'
import cxs from 'cxs'
import postcss from 'postcss'

function css(nodes) {
return postcss.root({ nodes }).toString()
}

test('it parses simple single class definitions', () => {
const result = parseObjectStyles({
'.foobar': {
backgroundColor: 'red',
color: 'white',
padding: '1rem',
},
})

expect(result).toMatchCss(`
.foobar {
background-color: red;
color: white;
padding: 1rem
}
`)
})

test('it parses multiple class definitions', () => {
const result = parseObjectStyles({
'.foo': {
backgroundColor: 'red',
color: 'white',
padding: '1rem',
},
'.bar': {
width: '200px',
height: '100px',
},
})

expect(result).toMatchCss(`
.foo {
background-color: red;
color: white;
padding: 1rem
}
.bar {
width: 200px;
height: 100px
}
`)
})

test('it parses nested pseudo-selectors', () => {
const result = parseObjectStyles({
'.foo': {
backgroundColor: 'red',
color: 'white',
padding: '1rem',
':hover': {
backgroundColor: 'orange',
},
':focus': {
backgroundColor: 'blue',
},
},
})

expect(result).toMatchCss(`
.foo {
background-color: red;
color: white;
padding: 1rem
}
.foo:hover {
background-color: orange
}
.foo:focus {
background-color: blue
}
`)
})

test('it parses nested media queries', () => {
const result = parseObjectStyles({
'.foo': {
backgroundColor: 'red',
color: 'white',
padding: '1rem',
'@media (min-width: 200px)': {
backgroundColor: 'orange',
},
},
})

expect(result).toMatchCss(`
.foo {
background-color: red;
color: white;
padding: 1rem
}
@media (min-width: 200px) {
.foo {
background-color: orange
}
}
`)
})

// test('it parses pseudo-selectors in nested media queries', () => {
// const result = parseObjectStyles({
// '.foo': {
// backgroundColor: 'red',
// color: 'white',
// padding: '1rem',
// ':hover': {
// '@media (min-width: 200px)': {
// backgroundColor: 'orange',
// }
// },
// },
// })

// expect(result).toMatchCss(`
// .foo {
// background-color: red;
// color: white;
// padding: 1rem
// }
// @media (min-width: 200px) {
// .foo:hover {
// background-color: orange
// }
// }
// `)
// })
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
},
"dependencies": {
"commander": "^2.11.0",
"cxs": "^6.2.0",
"fs-extra": "^4.0.2",
"lodash": "^4.17.4",
"nodemon": "^1.11.0",
Expand Down
69 changes: 69 additions & 0 deletions src/util/parseObjectStyles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import _ from 'lodash'
import postcss from 'postcss'

const hyph = s => s.replace(/[A-Z]|^ms/g, '-$&').toLowerCase()
const mx = (rule, media) => media ? `${media}{${rule}}` : rule
const noAnd = s => s.replace(/&/g, '')
const createDeclaration = (key, value) => hyph(key) + ':' + value
const createRule = ({
className,
child,
media,
declarations
}) => mx(`${className + child}{${declarations.join(';')}}`, media)

const parseRules = (obj, child = '', media) => {
const rules = []
const declarations = []

for (let key in obj) {
const value = obj[key]

if (value === null) continue

if (typeof value === 'object') {
const _media = /^@/.test(key) ? key : null
const _child = _media ? child : child + noAnd(key)
parseRules(value, _child, _media)
.forEach(r => rules.push(r))
continue
}

const dec = createDeclaration(key, value)
declarations.push(dec)
}

rules.unshift({
media,
child,
declarations
})

return rules
}

const parse = (selector, obj) => {
const rules = parseRules(obj)

console.log(rules)

return rules.map(rule => {
const className = selector
const ruleset = createRule(Object.assign(rule, { className }))
return ruleset
})
}

function parseObjectStyles(styles) {
if (!Array.isArray(styles)) {
return parseObjectStyles([styles])
}

return _.flatMap(styles, (style) => {
return _.flatMap(style, (declarations, selector) => {
return parse(selector, declarations)
})
}).join('')
}

export default parseObjectStyles
4 changes: 4 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1212,6 +1212,10 @@ [email protected], "cssom@>= 0.3.2 < 0.4.0":
dependencies:
cssom "0.3.x"

cxs@^6.2.0:
version "6.2.0"
resolved "https://registry.yarnpkg.com/cxs/-/cxs-6.2.0.tgz#f11ca3bdaef154b93bdadca5df70f2cb3e37ca24"

dashdash@^1.12.0:
version "1.14.1"
resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
Expand Down

0 comments on commit 6450748

Please sign in to comment.