Skip to content

Commit 4908367

Browse files
committedOct 29, 2016
some tests, misc
1 parent 6f86829 commit 4908367

File tree

11 files changed

+201
-75
lines changed

11 files changed

+201
-75
lines changed
 

‎examples/css.js

+11-14
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,41 @@
11
// inline css prop
22

33
import React from 'react'
4-
5-
6-
import { cssFor, merge } from '../src'
7-
import { css } from '../src/css'
4+
import { cssFor, merge } from 'glamor'
5+
import { css } from 'glamor/css'
86

97
function log(x) {
108
console.log((x || ''), this) // eslint-disable-line no-console
119
return this
1210
}
1311

14-
12+
1513
let someTag = '.xyz:hover'
1614

1715
let rule = css`
18-
color: yellow; /* 'real' css syntax */
19-
/* pseudo classes */
20-
${css`color: greenish`}
16+
color: yellow;
2117
:hover {
22-
/* just javascript */
18+
/* with interpolations */
2319
color: ${ Math.random() > 0.5 ? 'red' : 'blue' };
2420
}
21+
2522
& > h1 { color: purple }
26-
/* contextual selectors */
2723
html.ie9 & ${someTag} { padding: 300px }
28-
/* compose with objects */
29-
/* or more rules */
30-
/* media queries */
24+
25+
/* and composition */
26+
${css`color: greenish`}
27+
3128
@media (min-width: 300px) {
3229
color: orange;
3330
border: 1px ${'solid'} blue;
3431
${{ color: 'brown' }}
35-
/* increase specificity */
3632
&& {
3733
color: blue;
3834
${{ color: 'browner' }}
3935
}
4036
}
4137
`
38+
4239
export const App = () => <div className={rule}>
4340
...
4441
</div>

‎perf/script.js

+18
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
// hashes per second
2+
3+
// sheet inserts per second
4+
//
5+
6+
7+
// unique rules per second - 1kv
8+
// unique rules per second - complicated objects
9+
// merge( simple / complicated) - small / large batches
10+
// autoprefix rules per second
11+
// - without plugin
12+
// - with plugin, no affected keys
13+
// - with plugin, affected keys
14+
// - browser specific perfs?
15+
16+
// selector performance - growth rate from few to many
17+
18+
119
// /* eslint-disable no-console */
220

321
// import React from 'react'

‎src/autoprefix.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ function includes(obj, search) {
1212
}
1313

1414
function values(obj) {
15-
return Object.keys(obj).map(function (key) {return obj[key] })
15+
return Object.keys(obj).map(key => obj[key])
1616
}
1717

1818
let webkitPrefix = 'Webkit'

‎src/css/README.md

+26-6
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
css
22
---
33

4+
[work in progress]
5+
46
tl:dr;
57
- you can now write 'real' css in your javascript
6-
- with syntax highlighting and linting (via [styled components'](https://github.com/styled-components/styled-components) work)
8+
- with syntax highlighting and linting
79
- that can be precompiled / extracted
8-
- all glamor goodies apply
10+
- glamor goodies apply
911

1012
```jsx
13+
import { css } from 'glamor/lib/css'
14+
15+
1116
let rule = css`
1217
color: red;
1318
font-family: helvetica, sans-serif
@@ -61,13 +66,22 @@ let rule = css`
6166
`
6267
```
6368

69+
syntax highlighting
70+
---
71+
atom - via [language-babel](https://github.com/styled-components/styled-components#syntax-highlighting)
72+
sublime text - [open PR](https://github.com/babel/babel-sublime/pull/289)
73+
74+
linting
75+
---
76+
via [stylelint-processor-styled-components](https://github.com/styled-components/stylelint-processor-styled-components)
77+
6478

6579
babel plugin
6680
---
6781

68-
While the css literal syntax is great for developing, it nearly doubles the library size,
69-
and is slower than we'd like for production. By using the babel plugin, we can strip out the tagged literal syntax,
70-
and replaces with a glamor friendly json form. everybody wins! this -
82+
While the css literal syntax is great for DX, it's slower / heavier
83+
than we'd like for runtime. The babel plugin replaces the inline css with a
84+
glamor friendly json form. Everybody wins! This -
7185
```jsx
7286
css` color: red `
7387
```
@@ -77,13 +91,19 @@ css({ color: 'red' })
7791
```
7892
eliminating the need for the css parser in the js bundle. wowzah.
7993

94+
To use, add 'glamor/lib/css/babel' to the `plugins` field in your babel config.
95+
96+
8097

8198
todo
99+
---
82100

101+
- move to [rework](https://github.com/reworkcss/css)/anything else for parsing
83102
- direct selectors `> h1 {...}`
84-
- attribute selectors
85103
- match more of the css spec (currently ~2.1)
104+
- leading comments
86105
- fallback values
87106
- more interpolation points
88107
- better parsing errors
89108
- tests!!!
109+
- guidance for difference types of 'static' css extraction

‎src/css/babel.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// print back, replacing stubs with interpolations
99
// tada?
1010

11-
// let template = require('babel-template')
11+
// todo - custom function instead of merge
1212
let { parse } = require('./spec.js')
1313

1414
function convert(node, ctx, interpolated) {
@@ -79,8 +79,8 @@ let conversions = {
7979
PseudoSelector(node, ctx) {
8080
return ':' + node.value
8181
},
82-
AttributeSelector() {
83-
82+
AttributeSelector(node, ctx) {
83+
return `[${node.attribute}${node.operator ? node.operator + node.value : ''}]`
8484
},
8585
Function() {
8686

‎src/css/index.js

+8-4
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ export const conversions = {
6767
PseudoSelector(node, ctx) {
6868
return ':' + node.value
6969
},
70-
AttributeSelector() {
71-
70+
AttributeSelector(node, ctx) {
71+
return `[${node.attribute}${node.operator ? node.operator + node.value : ''}]`
7272
},
7373
Function() {
7474

@@ -103,8 +103,12 @@ export const conversions = {
103103
}
104104
}
105105

106-
107106
export function css(strings, ...values) {
107+
return merge(_css(strings, ...values))
108+
}
109+
110+
export function _css(strings, ...values) {
111+
108112
let stubs = {}, ctr = 0
109113
strings = strings.reduce((arr, x, i) => {
110114
arr.push(x)
@@ -120,5 +124,5 @@ export function css(strings, ...values) {
120124

121125

122126
let parsed = parse(strings)
123-
return merge(convert(parsed, { stubs }))
127+
return convert(parsed, { stubs })
124128
}

‎src/css/spec.js

+6-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎src/css/spec.pegjs

+6-1
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,12 @@ stubs = stubsHead:stub
167167
};
168168
}
169169

170-
stub = stub_id:(S_ P U R "-" num) S* { return { type:'Stub', id: stub_id.join('').trim() } }
170+
stub = stub_id:(S_ P U R "-" num) S* {
171+
return {
172+
type:'Stub',
173+
id: stub_id.join('').trim()
174+
}
175+
}
171176

172177
contextual
173178
= AMP { return { type: 'Contextual' } }

‎src/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ plugins.keyframes = new PluginSet(prefixes)
2626

2727
// define some constants
2828
const isBrowser = typeof window !== 'undefined'
29-
const isDev = (x => (x === 'development') || !x)(process.env.NODE_ENV)
29+
const isDev = (process.env.NODE_ENV === 'development') || !process.env.NODE_ENV
3030
const isTest = process.env.NODE_ENV === 'test'
3131

3232
/**** simulations ****/

‎src/sheet.js

+43-41
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ styleSheet.flush()
2424
2525
*/
2626

27-
function last() {
28-
return this[this.length -1]
27+
function last(arr) {
28+
return arr[arr.length -1]
2929
}
3030

3131
function sheetForTag(tag) {
@@ -42,7 +42,7 @@ function sheetForTag(tag) {
4242
}
4343

4444
const isBrowser = typeof window !== 'undefined'
45-
const isDev = (x => (x === 'development') || !x)(process.env.NODE_ENV)
45+
const isDev = (process.env.NODE_ENV === 'development') || (!process.env.NODE_ENV) //(x => (x === 'development') || !x)(process.env.NODE_ENV)
4646
const isTest = process.env.NODE_ENV === 'test'
4747

4848
const oldIE = (() => {
@@ -74,7 +74,7 @@ export class StyleSheet {
7474
this.ctr = 0
7575
}
7676
getSheet() {
77-
return sheetForTag(this.tags::last())
77+
return sheetForTag(last(this.tags))
7878
}
7979
inject() {
8080
if(this.injected) {
@@ -129,7 +129,7 @@ export class StyleSheet {
129129
// this.tags::last().styleSheet.cssText+= rule
130130
// }
131131
else{
132-
this.tags::last().appendChild(document.createTextNode(rule))
132+
last(this.tags).appendChild(document.createTextNode(rule))
133133
}
134134
}
135135
else{
@@ -143,42 +143,44 @@ export class StyleSheet {
143143
}
144144
return this.ctr -1
145145
}
146-
_replace(index, rule) {
147-
// this weirdness for perf, and chrome's weird bug
148-
// https://stackoverflow.com/questions/20007992/chrome-suddenly-stopped-accepting-insertrule
149-
try {
150-
let sheet = this.getSheet()
151-
sheet.deleteRule(index) // todo - correct index here
152-
sheet.insertRule(rule, index)
153-
}
154-
catch(e) {
155-
if(isDev) {
156-
// might need beter dx for this
157-
console.warn('whoops, problem replacing rule', rule) //eslint-disable-line no-console
158-
}
159-
}
160-
161-
}
162-
replace(index, rule) {
163-
if(isBrowser) {
164-
if(this.isSpeedy && this.getSheet().insertRule) {
165-
this._replace(index, rule)
166-
}
167-
else {
168-
let _slot = Math.floor((index + this.maxLength) / this.maxLength) - 1
169-
let _index = (index % this.maxLength) + 1
170-
let tag = this.tags[_slot]
171-
tag.replaceChild(document.createTextNode(rule), tag.childNodes[_index])
172-
}
173-
}
174-
else {
175-
this.sheet.cssRules = [ ...this.sheet.cssRules.slice(0, index), { cssText: rule }, ...this.sheet.cssRules.slice(index + 1) ]
176-
}
177-
}
178-
delete(index) {
179-
// we insert a blank rule when 'deleting' so previously returned indexes remain stable
180-
return this.replace(index, '')
181-
}
146+
// commenting this out till we decide on v3's decision
147+
// _replace(index, rule) {
148+
// // this weirdness for perf, and chrome's weird bug
149+
// // https://stackoverflow.com/questions/20007992/chrome-suddenly-stopped-accepting-insertrule
150+
// try {
151+
// let sheet = this.getSheet()
152+
// sheet.deleteRule(index) // todo - correct index here
153+
// sheet.insertRule(rule, index)
154+
// }
155+
// catch(e) {
156+
// if(isDev) {
157+
// // might need beter dx for this
158+
// console.warn('whoops, problem replacing rule', rule) //eslint-disable-line no-console
159+
// }
160+
// }
161+
162+
// }
163+
// replace(index, rule) {
164+
// if(isBrowser) {
165+
// if(this.isSpeedy && this.getSheet().insertRule) {
166+
// this._replace(index, rule)
167+
// }
168+
// else {
169+
// let _slot = Math.floor((index + this.maxLength) / this.maxLength) - 1
170+
// let _index = (index % this.maxLength) + 1
171+
// let tag = this.tags[_slot]
172+
// tag.replaceChild(document.createTextNode(rule), tag.childNodes[_index])
173+
// }
174+
// }
175+
// else {
176+
// let rules = this.sheet.cssRules
177+
// this.sheet.cssRules = [ ...rules.slice(0, index), { cssText: rule }, ...rules.slice(index + 1) ]
178+
// }
179+
// }
180+
// delete(index) {
181+
// // we insert a blank rule when 'deleting' so previously returned indexes remain stable
182+
// return this.replace(index, '')
183+
// }
182184
flush() {
183185
if(isBrowser) {
184186
this.tags.forEach(tag => tag.parentNode.removeChild(tag))

‎tests/index.js

+78-3
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,7 @@ describe('jsxstyle', () => {
735735
})
736736
})
737737

738-
import { css } from '../src/css'
738+
import { _css, css } from '../src/css'
739739
describe('css', () => {
740740
// how to test the plugin?
741741
let node
@@ -750,11 +750,86 @@ describe('css', () => {
750750
flush()
751751
})
752752
it('can parse some css and return a rule', () => {
753-
css` color: red; `
754-
expect(styleSheet.rules().map(x => x.cssText)).toEqual([ '.css-bf70yn, [data-css-bf70yn] { color: red; }' ])
753+
// css` color: red `
754+
let red = 'red'
755+
let rule = _css`
756+
/* 'real' css syntax */
757+
color: yellow;
758+
font-weight: bold;
759+
/* pseudo classes */
760+
:hover {
761+
/* just javascript */
762+
color: ${ red };
763+
}
764+
765+
/* contextual selectors */
766+
& > h1 { color: purple }
767+
html.ie9 & span { padding: 300px }
768+
& [type='checked'] { border: 1px dashed black }
769+
770+
/* compose with objects */
771+
${{ color: 'red' }}
772+
773+
/* or more rules */
774+
${ _css`color: greenish` }
775+
776+
/* media queries */
777+
@media (min-width: 300px) {
778+
color: orange;
779+
border: 1px solid blue;
780+
${{ color: 'brown' }}
781+
/* increase specificity */
782+
&& {
783+
color: blue;
784+
${{ color: 'browner' }}
785+
}
786+
}
787+
`
788+
expect(rule).toEqual([
789+
{ 'color': 'yellow' },
790+
{ 'fontWeight': 'bold' },
791+
{ ':hover': { 'color': 'red' } },
792+
{ '&>h1': { 'color': 'purple' } },
793+
{ 'html.ie9 & span': { 'padding': '300px' } },
794+
{ '& [type=checked]': { 'border': '1px dashed black' } },
795+
[ { 'color': 'red' } ],
796+
[ [ { color: 'greenish' } ] ],
797+
{ '@media (min-width:300px)': [
798+
{ 'color': 'orange' },
799+
{ 'border': '1px solid blue' },
800+
[ { 'color': 'brown' } ],
801+
{ '&&': { 'color': 'browner' } }
802+
] }
803+
])
804+
755805
})
756806
})
757807

808+
// comments everywhere
809+
810+
// declarations -
811+
// color: blue
812+
// fontWeight: 200 vs width: 300 (px)
813+
// multiword - border: 1px solid blue - check units
814+
// !important
815+
// functions???
816+
817+
// non ascii, base 64 encoded data uris, etc
818+
819+
820+
// selectors -
821+
// pseudo
822+
// direct
823+
// element id class attribute pseudo
824+
// contextual
825+
826+
// media queries
827+
828+
829+
// custom vars/props?
830+
831+
// fallbacks
832+
758833

759834
// a useful utility for quickly tapping objects. use with the :: operator
760835
// {x: 1}::log()

0 commit comments

Comments
 (0)
Please sign in to comment.