Skip to content

Commit

Permalink
0.7.0 fixes/cleanup
Browse files Browse the repository at this point in the history
- added flex to popular list
- fixed px detection in firefox for border props
- added z.style to parsestyle without generating class
- removed .style from style object, use z.style instead
- simplified error handling and reduced duplication
- append string helper args automatically (shorthand override essentially)
- removed parser options
- added changelog
- added eslint config
  • Loading branch information
fuzetsu committed Aug 23, 2019
1 parent a355b65 commit 1304088
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 86 deletions.
17 changes: 17 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"env": {
"browser": true,
"es6": true
},
"extends": "eslint:recommended",
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "module"
},
"rules": {
"quotes": ["error", "single", { "avoidEscape": true }],
"semi": ["error", "never"],
"no-console": "off",
"prefer-const": "error"
}
}
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Changelog

## 0.7.0
*2019-08-23*

**Breaking Changes**

- removed parser options (BREAK, OPEN, CLOSE)
- removed `.style` property on style objects returned by `z`, use `z.style` instead

**Enhancements / Bug Fixes**

- string based helpers will automatically have args appended
- added `z.style` to parse style strings without generating classNames
- added `flex` to popular list
- fixed `px` detection for border properties in firefox
73 changes: 43 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ Or download the script and use it locally.

## API

Quick links: [`z`](#css) ~~ [`z.setDebug`](#set-debug) ~~ [`z.global`](#global) ~~ [`z.anim`](#anim) ~~ [`z.helper`](#helper) ~~ [`z.new`](#new)
Quick links: [`z`](#css) ~~ [`z.setDebug`](#set-debug) ~~ [`z.global`](#global) ~~ [`z.style`](#style) ~~ [`z.anim`](#anim) ~~ [`z.helper`](#helper) ~~ [`z.new`](#new)

<hr>

Expand All @@ -99,7 +99,7 @@ Quick links: [`z`](#css) ~~ [`z.setDebug`](#set-debug) ~~ [`z.global`](#global)

Generates a `className` for the given `styleString` and inserts it into a stylesheet in the head of the document.

It returns a `Style` object `{ class, className, style }`.
It returns a `Style` object `{ class, className }`.

When `.toString()` is called on a `Style` object the `className` will be returned.

Expand Down Expand Up @@ -251,6 +251,24 @@ z.global`

<hr>

<a name="style"></a>

### `` z.style`<styleString>` ``

Parses given style string and returns string of css rules. Useful for styles that change frequently to prevent generating too many classNames.
Resulting string can be assigned to the style attribute of a DOM element.

```js
z.style`color ${fgColor};background-color ${bgColor}`

// returns
;('color: #444; background-color: #fff;')
```

Nested selectors will be ignored, only simple styles will be returned.

<hr>

<a name="anim"></a>

### `` z.anim`<styleString>` ``
Expand Down Expand Up @@ -304,6 +322,29 @@ z`
}
```

String based helpers will have any arguments passed automatically appended. This allows you to easily create your own css property shorthands.

```js
z.helper({
bo: 'border',
tra: 'transition'
})

z`
bo 4 solid red
tra 500ms
`
```

```css
/* generated css */

.zx5cc6j6obc9-1 {
border: 4px solid red;
transition: 500ms;
}
```

Helpers can also be used in selectors, mainly useful for media queries.

```js
Expand Down Expand Up @@ -379,36 +420,8 @@ const newZ = z.new({

Creating a new instance is useful when you want to you ensure you get a private/non global version of zaftig, or to render styles into a shadow DOM.

#### Override parser options

You can change how zaftig processes the style string syntax by passing the following options:

```js
const newZ = z.new({
parser: {
OPEN: '{', // block open
CLOSE: '}', // block close
BREAK: ';' // rule separator
}
})
```

```js
import zaftig from 'https://unpkg.com/zaftig?module'
const z = zaftig.new({ parser: { OPEN: '[', CLOSE: ']' } })

z.global`
html [ bc green ]
`
```

[playground][parser-config-playground]

**Warning:** Do not use a character that is valid in a CSS value, such as parentheses, `(` or `)`. Otherwise zaftig will be unable to properly parse css values.

## Credits

Heavily inspired by [bss](https://github.com/porsager/bss) by [Rasmus Porsager](https://github.com/porsager).

[parser-config-playground]: https://flems.io/#0=N4IgZglgNgpgziAXAbVAOwIYFsZJAOgAsAXLKEAGhAGMB7NYmBvEAXwvW10QICsEqdBk2J4IWAA60ATsQAEALwxhiEAOZyw02ljkByEsQlxEAelMBXNBIDWa-HSymlK9QH4stACYXYegDpoQnDyCnIAvIrKqvZoMADuABTAchIY0nAw0ohyKQDyAAoAogByOXrIehRyAMIAMnkAykXlALp6cqydAJSBgQr4alC0AEYYUAAGgXJyJGRyyHIj1HJq0jBMcq2BE5QgmbDUqvQIPACsiACMbBwgmDh4DnACNPSMzDxsraxAA
[example-playground]: https://flems.io/#0=N4IgtglgJlA2CmIBcBWADAOgEwEYA0IAZhAgM7IDaoAdgIZiJIgYAWALmLCAQMYD21NvEHIQAHigQAbgAJoAXgA6IWgAdVygHyLqMmTrEB6SVM3cQpeAh5sIA8kzRIcWEAF88Neo2YArcrwCQiJMhoYyAO58AE4A1qQyvgCupGwytAkRVrCREGwsMgBK8LQ26dRQMnz58NEysBAARtG00RDwpIaELQxRcaQ6EGCqMWlgMt184wDk7GyqpEhhSdSqsQDmGPxghpD5bbAAAlgYmGgAtNE8GAAsAPxgfFBJCNODw6MyAF4T0VMyszY80Wy1WGy2U0MX1ohFs6weTxe8De1B0Xww61gfEatFgAAMdHoACSNNjUc78LF1ADENzpNxghImhBkpFo1FI50sbUITMICRwNyZ4xwaB0BNR1H4HLSpN0Sl0AMaSSBAmmMgA1EyvhK9HpGjEoLUZNQBPAmXpVDJMAB2FDReBgC31CDUeDnFjwCDrdgyHDYB1OxV6SkxGQkskUvhU50G6JGuqYFCs6PQcNyqMx4MyRo8SIsPLm7P8v0ANmdPCS0VIYZGrqE0WdbBaHLydl0zfZpEIMRFaDQYAG2b4KoabpNZudSFKtik8BkwBknY5Pei41IPFx8AAFJgAJwAShkbmdADIMKo2mBWgBPBc5vMR8mh6IAbhkeYiBaEx7PGD+KxGpUi7NDINy-oqEo6NKqQyAAguoMjyDI25HvI2iKmA27TNerrqhq3x4kSwBym497jMmbh4ngMgUM6WFyjR0wAHK9ri0wHng9HbnKmoAheV63v+I4VPAUDTExAAKgnRDeHFcdmDFknxOpEtsIyWDIAGiVA75PpmYbUvA8AoKZKDUQCADqrTUK66zydxvEEapGYvjI6wOsIFnTAAykkPA8B0pAOYpPHKc5RHqXwmmXkMt5aSJQF6a50Zhh5xnUN5fkBUFfHSXFskcUyAC6B46DoYD-sICbblAfCVgwggYAaUA3jRCGqKhZXUOYljWLY9iiCgSBYGg7ieCAdAMKIWykAEIDSsEbCiO4xVuEAA
27 changes: 16 additions & 11 deletions docs/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { h, render, Component } from 'https://unpkg.com/[email protected]beta.3/dist/preact.module.js'
import { h, render, Component } from 'https://unpkg.com/[email protected]rc.1/dist/preact.module.js'
import microh from 'https://unpkg.com/microh?module'
// import _z from '../src/index.js'
import _z from '../src/index.js'
// import _z from '../dist/zaftig.min.js'
import _z from 'https://unpkg.com/zaftig@latest?module'
// import _z from 'https://unpkg.com/zaftig@latest?module'
// const _z = window.z

const m = microh(h)
Expand Down Expand Up @@ -33,13 +33,12 @@ const fakeZ = _z.new({
id: 'sunboy',
style,
unit: 'rem',
helpers: { sun: 'c orange & fs 100' },
parser: { OPEN: '[', CLOSE: ']', BREAK: '&' }
helpers: { sun: 'c orange; fs 100' }
})
fakeZ`sun`
fakeZ`
margin 10 & h 10
h1, h2 [ m 10 ]
margin 10; h 10
h1, h2 { m 10 }
`
p(style.sheet.cssRules)

Expand All @@ -55,7 +54,8 @@ z.helper({
pad: (num, side = '') => `p${side} ${num * 0.25}rem`,
shadow: num => `box-shadow 0 0 ${num} 0 rgba(0,0,0,0.5)`,
'@med': (x, type) => `@media (${type || 'min'}-width: ${breakpoints[x]})`,
'@lg': '@media (min-width: 1024px)'
'@lg': '@media (min-width: 1024px)',
bo: 'border'
})

z.global`
Expand All @@ -76,6 +76,10 @@ z.global`
@lg {
h1 { c yellow }
}
.random {
bo 1 solid white
}
`

window.z = z
Expand Down Expand Up @@ -142,7 +146,6 @@ const spin = z.anim`

class App extends Component {
render(_, { count = 0, exp = '', color = '' }) {
const style = z`${exp}`
return m(
'main' +
z`
Expand All @@ -152,8 +155,10 @@ class App extends Component {
pad 6 b
> * { mar 3 b }
> input { ta center }
bc ${color}
`,
{
style: z.style`bc ${color}`
},
m(
'h1' +
z`
Expand All @@ -179,7 +184,7 @@ class App extends Component {
}),
m(
'div' + z`pad 2;fs 1.5em;ff monospace;ta center`,
m('p', style.valueOf(), ' = ', style.style || m('em', 'type something')),
m('p', z.style(exp) || m('em', 'type something')),
m(
'p',
'zaftig runtime ',
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "zaftig",
"version": "0.6.2",
"version": "0.7.0",
"description": "css for your js",
"source": "src/index.js",
"main": "dist/zaftig.es5.min.js",
Expand Down
86 changes: 42 additions & 44 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ const popular = [
'fontFamily',
'userSelect',
'flexDirection',
'opacity'
'opacity',
'flex'
]

const findStyle = obj => (obj.hasOwnProperty('width') ? obj : findStyle(Object.getPrototypeOf(obj)))
Expand All @@ -64,11 +65,19 @@ for (const prop of Object.keys(findStyle(document.documentElement.style)).concat
}

const testDiv = document.createElement('div')
const needsPx = memo(prop =>
['0', '0 0'].some(val => {
testDiv.style.cssText = `${prop}: ${val};`
return testDiv.style.cssText.slice(-3) == 'px;'
})
const needsPx = memo(
prop =>
['0', '0 0'].some(val => {
testDiv.style.cssText = `${prop}: ${val};`
return testDiv.style.cssText.slice(-3) == 'px;'
}),
{
border: true,
'border-left': true,
'border-right': true,
'border-top': true,
'border-bottom': true
}
)

const selSep = /\s*,\s*/
Expand All @@ -92,10 +101,9 @@ const processSelector = (sel, psel) =>
.join(',\n')

class Style {
constructor(className, style) {
constructor(className) {
this.class = className
this.className = className
this.style = style
}
toString() {
return this.class
Expand All @@ -107,25 +115,18 @@ class Style {

const wrap = (sel, body) => (sel && body ? `\n${sel} {\n${body}}\n` : '')

const handleError = fn => x => {
const handleTemplate = fn => (parts, ...args) => {
try {
return fn(x)
return typeof parts === 'string' ? fn(parts) : Array.isArray(parts) ? fn(zip(parts, args)) : ''
} catch (e) {
console.error('zaftig: error `', x, '`\n', e)
console.error('zaftig: error `', parts, '`', args, '\n', e)
return ''
}
}

const handleTemplate = (parts, args, fn) => {
if (typeof parts === 'string') return fn(parts)
if (Array.isArray(parts)) return fn(zip(parts, args))
return ''
}

const makeZ = (conf = {}) => {
const {
helpers = {},
parser = {},
unit = 'px',
id = 'z' +
Math.random()
Expand Down Expand Up @@ -180,7 +181,9 @@ const makeZ = (conf = {}) => {

const runHelper = (key, value) => {
const helper = helpers[key]
return typeof helper === 'function' ? helper(...(value || '').split(' ')) : helper
return typeof helper === 'function'
? helper(...(value || '').split(' '))
: helper && helper + ' ' + value
}

const assignRule = (ctx, key, value) => {
Expand Down Expand Up @@ -223,26 +226,25 @@ const makeZ = (conf = {}) => {

const PROP = 1
const VALUE = 2
const { OPEN = '{', CLOSE = '}', BREAK = ';' } = parser
const parseRules = memo(str => {
const ctx = [{ rul: '', sub: [] }]
str = str && str.trim()
if (!str) return ctx[0]
str += BREAK // append semi to properly commit last rule
str += ';' // append semi to properly commit last rule
let mode = PROP
let buffer = ''
let depth = 0
let quote = ''
let char, curProp
for (let i = 0; i < str.length; i++) {
char = str[i]
if (char == '\n' || ((char == BREAK || char == CLOSE) && !quote)) {
if (char == '\n' || ((char == ';' || char == '}') && !quote)) {
// end of rule, process key/value
assignRule(ctx[depth], curProp, buffer.trim() + quote)
if (char == CLOSE) ctx[--depth].sub.push(ctx.pop())
if (char == '}') ctx[--depth].sub.push(ctx.pop())
mode = PROP
curProp = buffer = quote = ''
} else if (char == OPEN && !quote) {
} else if (char == '{' && !quote) {
// block open, pre-process helper and create new ctx
ctx[++depth] = {
sel: runHelper(curProp, buffer.trim()) || (curProp + ' ' + buffer).trim(),
Expand Down Expand Up @@ -271,28 +273,24 @@ const makeZ = (conf = {}) => {
return ctx[0]
})

const createKeyframes = handleError(
memo(rules => {
const name = 'anim-' + id + '-' + (idCount += 1)
appendRule('@keyframes ' + name, parseRules(rules))
return name
})
)
const createKeyframes = memo(rules => {
const name = 'anim-' + id + '-' + (idCount += 1)
appendRule('@keyframes ' + name, parseRules(rules))
return name
})

const createStyle = handleError(
memo(rules => {
const parsed = parseRules(rules)
const className =
(parsed.name ? parsed.name.replace(/\s+/, '-') + '-' : '') + id + '-' + (idCount += 1)
appendRule('.' + className, parsed)
return new Style(className + (parsed.cmp ? ' ' + parsed.cmp : ''), parsed.rul)
})
)
const createStyle = memo(rules => {
const parsed = parseRules(rules)
const className =
(parsed.name ? parsed.name.replace(/\s+/, '-') + '-' : '') + id + '-' + (idCount += 1)
appendRule('.' + className, parsed)
return new Style(className + (parsed.cmp ? ' ' + parsed.cmp : ''))
})

const z = (parts, ...args) => handleTemplate(parts, args, createStyle)
z.global = (parts, ...args) =>
handleTemplate(parts, args, handleError(rules => appendRule(':root', parseRules(rules))))
z.anim = (parts, ...args) => handleTemplate(parts, args, createKeyframes)
const z = handleTemplate(createStyle)
z.global = handleTemplate(rules => appendRule(':root', parseRules(rules)))
z.anim = handleTemplate(createKeyframes)
z.style = handleTemplate(rules => parseRules(rules).rul)
z.getSheet = () => style
z.helper = spec => Object.assign(helpers, spec)
z.setDebug = flag => (debug = flag)
Expand Down

0 comments on commit 1304088

Please sign in to comment.