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

More tests, use fns from utils and rework core #191

Merged
merged 18 commits into from
Jul 28, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
"enzyme-to-json": "^1.5.1",
"jest": "^20.0.4",
"jest-cli": "^20.0.4",
"jest-glamor-react": "^3.0.0",
"jest-glamor-react": "^3.1.0",
"npm-run-all": "^4.0.2",
"polished": "^1.2.1",
"prettier-eslint-cli": "^4.0.3",
Expand Down
2 changes: 1 addition & 1 deletion src/glamor/CSSPropertyOperations/CSSProperty.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ let prefixes = ['Webkit', 'ms', 'Moz', 'O']

// Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an
// infinite loop, because it iterates over the newly added props too.
keys(isUnitlessNumber).forEach(function (prop) {
forEach(keys(isUnitlessNumber), function (prop) {
forEach(prefixes, function (prefix) {
isUnitlessNumber[prefixKey(prefix, prop)] = 1
})
Expand Down
7 changes: 5 additions & 2 deletions src/glamor/CSSPropertyOperations/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@
*/

import dangerousStyleValue from './dangerousStyleValue'
import hyphenateStyleName from 'fbjs/lib/hyphenateStyleName'
import memoizeStringOnly from 'fbjs/lib/memoizeStringOnly'

export const processStyleName = memoizeStringOnly(hyphenateStyleName)
const hyphenateRegex = /[A-Z]|^ms/g

export const processStyleName = memoizeStringOnly(styleName =>
styleName.replace(hyphenateRegex, '-$&').toLowerCase()
)

if (process.env.NODE_ENV !== 'production') {
const warning = require('fbjs/lib/warning')
Expand Down
2 changes: 1 addition & 1 deletion src/glamor/clean.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ function cleanObject (object) {

let acc = {}
let hasFalsy = false
forEach(keys(object), (value) => {
forEach(keys(object), value => {
const filteredValue = clean(value)
if (filteredValue === null || filteredValue !== value) {
hasFalsy = true
Expand Down
118 changes: 54 additions & 64 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,16 @@
// @flow
import { StyleSheet } from './sheet'
import { forEach, map, reduce } from './utils'
import { forEach, map, reduce, keys, assign } from './utils'
import { hashString as hash, hashObject } from './hash'
import { createMarkupForStyles } from './glamor/CSSPropertyOperations'
import clean from './glamor/clean.js'

const IS_DEV = process.env.NODE_ENV === 'development' || !process.env.NODE_ENV

export const sheet = new StyleSheet()
// 🚀
sheet.inject()

export let inserted: { [string | number]: boolean | void } = {}

type inputVar = string | number

type vars = Array<inputVar>

export function flush () {
sheet.flush()
inserted = {}
Expand Down Expand Up @@ -45,27 +39,15 @@ function _getRegistered (rule) {
return rule
}

// The idea on how to merge object class names come from glamorous
// 💄
// https://github.com/paypal/glamorous/blob/master/src/get-glamor-classname.js
function getEmotionStylesFromClassName (className) {
const id = className.trim().slice('css-'.length)
if (sheet.registered[id]) {
return sheet.registered[id].style
} else {
return []
}
}

function buildStyles (objs) {
let computedClassName = ''
let objectStyles = []

// This needs to be moved into the core
forEach(objs, (cls): void => {
if (typeof cls === 'string') {
if (cls.trim().indexOf('css-') === 0) {
objectStyles.push(getEmotionStylesFromClassName(cls))
const match = emotionClassRegex.exec(cls)
if (match) {
objectStyles.push(ruleCache[match[1]])
} else {
computedClassName && (computedClassName += ' ')
computedClassName += cls
Expand Down Expand Up @@ -118,7 +100,7 @@ export function injectGlobal (
// injectGlobal is flattened by postcss
// we don't support nested selectors on objects
forEach(combined, obj => {
forEach(Object.keys(obj), selector => {
forEach(keys(obj), selector => {
insertRawRule(`${selector} {${createMarkupForStyles(obj[selector])}}`)
})
})
Expand All @@ -131,7 +113,7 @@ export function fontFace (
) {
const combined = reduce(
content ? objs.concat(content.apply(null, vars)) : objs,
(accum, item, i) => Object.assign(accum, item),
(accum, item, i) => assign(accum, item),
{}
)

Expand All @@ -141,7 +123,7 @@ export function fontFace (
function insertKeyframe (spec) {
if (!inserted[spec.id]) {
const inner = map(
Object.keys(spec.keyframes),
keys(spec.keyframes),
kf => `${kf} {${createMarkupForStyles(spec.keyframes[kf])}}`
).join('')

Expand Down Expand Up @@ -181,16 +163,12 @@ type EmotionRule = { [string]: any }

type CSSRuleList = Array<EmotionRule>

type EmotionClassName = {
[string]: any
}

let cachedCss: (rules: CSSRuleList) => EmotionClassName =
let cachedCss: (rules: CSSRuleList) => EmotionRule =
typeof WeakMap !== 'undefined' ? multiIndexCache(_css) : _css

// 🍩
// https://github.com/threepointone/glamor
export function objStyle (...rules: CSSRuleList): EmotionClassName {
export function objStyle (...rules: CSSRuleList): EmotionRule {
rules = clean(rules)
if (!rules) {
return nullrule
Expand All @@ -211,46 +189,52 @@ function _css (rules) {
return toRule(spec)
}

const emotionClassRegex = /css-([a-zA-Z0-9]+)/

// of shape { 'data-css-<id>': '' }
export function isLikeRule (rule: EmotionRule) {
let keys = Object.keys(rule).filter(x => x !== 'toString')
if (keys.length !== 1) {
const ruleKeys = keys(rule)
if (ruleKeys.length !== 1) {
return false
}
return !!/css-([a-zA-Z0-9]+)/.exec(keys[0])
return !!emotionClassRegex.exec(ruleKeys[0])
}

// extracts id from a { 'css-<id>': ''} like object
export function idFor (rule: EmotionRule) {
let keys = Object.keys(rule).filter(x => x !== 'toString')
if (keys.length !== 1) throw new Error('not a rule')
let regex = /css-([a-zA-Z0-9]+)/
let match = regex.exec(keys[0])
const ruleKeys = keys(rule)
if (ruleKeys.length !== 1) throw new Error('not a rule')
let match = emotionClassRegex.exec(ruleKeys[0])
if (!match) throw new Error('not a rule')
return match[1]
}

const parentSelectorRegex = /&/gm

function selector (id: string, path: string = '') {
if (!id) {
return path.replace(/&/g, '')
return path.replace(parentSelectorRegex, '')
}
if (!path) return `.css-${id}`

let x = path
.split(',')
.map(
x =>
x.indexOf('&') >= 0 ? x.replace(/&/gm, `.css-${id}`) : `.css-${id}${x}`
)
.join(',')
let x = map(
path.split(','),
x =>
x.indexOf('&') >= 0
? x.replace(parentSelectorRegex, `.css-${id}`)
: `.css-${id}${x}`
).join(',')

return x
}

function deconstruct (style) {
// we can be sure it's not infinitely nested here
let plain, selects, medias, supports
Object.keys(style).forEach(key => {
let plain
let selects
let medias
let supports
forEach(keys(style), key => {
if (key.indexOf('&') >= 0) {
selects = selects || {}
selects[key] = style[key]
Expand All @@ -276,17 +260,17 @@ function deconstructedStyleToCSS (id, style) {
css.push(`${selector(id)}{${createMarkupForStyles(plain)}}`)
}
if (selects) {
Object.keys(selects).forEach((key: string) =>
forEach(keys(selects), (key: string) =>
css.push(`${selector(id, key)}{${createMarkupForStyles(selects[key])}}`)
)
}
if (medias) {
Object.keys(medias).forEach(key =>
forEach(keys(medias), key =>
css.push(`${key}{${deconstructedStyleToCSS(id, medias[key]).join('')}}`)
)
}
if (supports) {
Object.keys(supports).forEach(key =>
forEach(keys(supports), key =>
css.push(`${key}{${deconstructedStyleToCSS(id, supports[key]).join('')}}`)
)
}
Expand All @@ -298,7 +282,7 @@ function insert (spec) {
if (!inserted[spec.id]) {
inserted[spec.id] = true
let deconstructed = deconstruct(spec.style)
deconstructedStyleToCSS(spec.id, deconstructed).map(cssRule =>
map(deconstructedStyleToCSS(spec.id, deconstructed), cssRule =>
sheet.insert(cssRule)
)
}
Expand Down Expand Up @@ -342,9 +326,11 @@ function joinSelectors (a, b) {
let as = map(a.split(','), a => (!(a.indexOf('&') >= 0) ? '&' + a : a))
let bs = map(b.split(','), b => (!(b.indexOf('&') >= 0) ? '&' + b : b))

return bs
.reduce((arr, b) => arr.concat(as.map(a => b.replace(/&/g, a))), [])
.join(',')
return reduce(
bs,
(arr, b) => arr.concat(map(as, a => b.replace(parentSelectorRegex, a))),
[]
).join(',')
}

function joinMediaQueries (a, b) {
Expand All @@ -366,10 +352,11 @@ function joinSupports (a, b) {
// flatten a nested array
function flatten (inArr) {
let arr = []
for (let i = 0; i < inArr.length; i++) {
if (Array.isArray(inArr[i])) arr = arr.concat(flatten(inArr[i]))
else arr = arr.concat(inArr[i])
}
forEach(inArr, val => {
if (Array.isArray(val)) arr = arr.concat(flatten(val))
else arr = arr.concat(val)
})

return arr
}

Expand All @@ -380,7 +367,7 @@ function build (dest, { selector = '', mq = '', supp = '', src = {} }) {
}
src = flatten(src)

src.forEach(_src => {
forEach(src, _src => {
if (isLikeRule(_src)) {
let reg = _getRegistered(_src)
if (reg.type !== 'css') {
Expand All @@ -392,7 +379,7 @@ function build (dest, { selector = '', mq = '', supp = '', src = {} }) {
if (_src && _src.composes) {
build(dest, { selector, mq, supp, src: _src.composes })
}
Object.keys(_src || {}).forEach(key => {
forEach(keys(_src || {}), key => {
if (isSelector(key)) {
build(dest, {
selector: joinSelectors(selector, key),
Expand Down Expand Up @@ -478,16 +465,19 @@ function multiIndexCache (fn) {
}
let value = fn(args)
if (inputCaches[args.length]) {
let ctr = 0,
coi = inputCaches[args.length]
let ctr = 0
let coi = inputCaches[args.length]
while (ctr < args.length - 1) {
coi = coi.get(args[ctr])
ctr++
}
try {
coi.set(args[ctr], value)
} catch (err) {
if (IS_DEV && !warnedWeakMapError) {
if (
(process.env.NODE_ENV === 'development' || !process.env.NODE_ENV) &&
!warnedWeakMapError
) {
warnedWeakMapError = true
console.warn('failed setting the WeakMap cache for args:', ...args) // eslint-disable-line no-console
console.warn(
Expand Down
11 changes: 2 additions & 9 deletions src/parser.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
// @flow
import parse from 'postcss-safe-parser'
import postcssNested from 'postcss-nested'
import stringify from 'postcss/lib/stringify'
import postcssJs from 'postcss-js'
import objParse from './obj-parse'
import objParse from 'postcss-js/parser'
import autoprefixer from 'autoprefixer'
import { processStyleName } from './glamor/CSSPropertyOperations'
import { objStyle } from './index'
Expand Down Expand Up @@ -71,13 +70,7 @@ export function parseCSS (
}

function stringifyCSSRoot (root) {
return root.nodes.map((node, i) => {
let str = ''
stringify(node, x => {
str += x
})
return str
})
return root.nodes.map(node => node.toString())
}

export function expandCSSFallbacks (style: { [string]: any }) {
Expand Down
12 changes: 5 additions & 7 deletions src/react/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Component, createElement as h } from 'react'
import PropTypes from 'prop-types'
import { css } from '../index'
import { map, omit, reduce } from '../utils'
import { map, omit, reduce, assign } from '../utils'
import { CHANNEL } from './constants'

export {
Expand Down Expand Up @@ -50,10 +50,9 @@ export default function (tag, objs, vars = [], content) {

render () {
const { props, state, context } = this
const mergedProps = {
...props,
const mergedProps = assign({}, props, {
theme: state.theme
}
})

const getValue = v => {
if (v && typeof v === 'function') {
Expand Down Expand Up @@ -102,11 +101,10 @@ export default function (tag, objs, vars = [], content) {
return h(
tag,
omit(
{
...mergedProps,
assign({}, mergedProps, {
ref: mergedProps.innerRef,
className
},
}),
['innerRef', 'theme']
)
)
Expand Down
Loading