Skip to content

Commit

Permalink
feat: first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
pjshy committed May 26, 2019
1 parent b8118b8 commit 27b1dd4
Show file tree
Hide file tree
Showing 12 changed files with 247 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .eslintignore
@@ -0,0 +1,5 @@
node_modules

dist

**/*.js
Empty file added .eslintrc.yml
Empty file.
16 changes: 16 additions & 0 deletions .gitignore
@@ -0,0 +1,16 @@
# dependencies
node_modules

# build
dist/

#cache
.eslintcache

# misc
.DS_Store
.env
.cdnUploaderCache
temp
.idea/
*.log
23 changes: 23 additions & 0 deletions README.md
@@ -0,0 +1,23 @@
# keyframes

Many times CSS can works very well. When we need to modify the style sheet at runtime, I tend to operate or style instead of *css in js*. Because such a shema is not zero runtime.

But when I need to use variable in *@keyframes*, use js to generator would be very nice.

This idea is base on [emotion]('https://github.com/emotion-js/emotion'), but sample implementation, if you want to use it in production; It's better to use [emotion]('https://github.com/emotion-js/emotion') directly.

## development

```javascript
git clone git@github.com:pjshy/keyframes.git

cd keyframes

yarn
or
npm install

yarn dev
or
npm run dev
```
24 changes: 24 additions & 0 deletions package.json
@@ -0,0 +1,24 @@
{
"name": "keyframes",
"version": "0.0.1",
"description": "Generate keyframes at runtime",
"main": "index.js",
"scripts": {
"test": "test"
},
"keywords": [
"keyframes",
"runtime",
"css in js"
],
"repository": {
"type": "git",
"url": "git@github.com:pjshy/keyframes.git"
},
"author": "pjshy",
"license": "MIT",
"devDependencies": {
"csstype": "^2.6.4",
"typescript": "^3.4.5"
}
}
16 changes: 16 additions & 0 deletions src/css.ts
@@ -0,0 +1,16 @@
import * as CSS from 'csstype'

export function serializeStyle (style: CSS.Properties) {
const chunks: string[] = ['{']
const properties = Object.keys(style) as Array<keyof CSS.Properties>

properties.forEach((property) => {
const val = `${style[property]}`.trim() + ';'

chunks.push(`${property}: ${val}`)
})

chunks.push('}')

return chunks.join('')
}
19 changes: 19 additions & 0 deletions src/dom.ts
@@ -0,0 +1,19 @@
export const isBrowser = !!document

export function applyStyleRule (rule: string) {
if (isBrowser) {
const style = document.createElement('style')

document.getElementsByTagName('head')[0].appendChild(style)

const styleSheet = document.styleSheets[document.styleSheets.length - 1] as CSSStyleSheet

if (typeof styleSheet.insertRule === 'function') {
styleSheet.insertRule(rule, styleSheet.rules.length)
} else {
/**
* @todo polyfill for IE
*/
}
}
}
69 changes: 69 additions & 0 deletions src/hash.ts
@@ -0,0 +1,69 @@
/**
* JS Implementation of MurmurHash3 (r136) (as of May 20, 2011)
*
* @author <a href="mailto:gary.court@gmail.com">Gary Court</a>
* @see http://github.com/garycourt/murmurhash-js
* @author <a href="mailto:aappleby@gmail.com">Austin Appleby</a>
* @see http://sites.google.com/site/murmurhash/
*
* @param {string} key ASCII only
* @param {number} seed Positive integer only
* @return {number} 32-bit positive integer hash
*/

// murmurhash3 via https://github.com/garycourt/murmurhash-js/blob/master/murmurhash3_gc.js

export function hashString(key: string) {
let remainder, bytes, h1, h1b, c1, c1b, c2, c2b, k1, i

remainder = key.length & 3 // key.length % 4
bytes = key.length - remainder
h1 = 1 * 1
c1 = 0xcc9e2d51
c2 = 0x1b873593
i = 0

while (i < bytes) {
k1 =
((key.charCodeAt(i) & 0xff)) |
((key.charCodeAt(++i) & 0xff) << 8) |
((key.charCodeAt(++i) & 0xff) << 16) |
((key.charCodeAt(++i) & 0xff) << 24)
++i

k1 = ((((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16))) & 0xffffffff
k1 = (k1 << 15) | (k1 >>> 17)
k1 = ((((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16))) & 0xffffffff

h1 ^= k1
h1 = (h1 << 13) | (h1 >>> 19)
h1b = ((((h1 & 0xffff) * 5) + ((((h1 >>> 16) * 5) & 0xffff) << 16))) & 0xffffffff
h1 = (((h1b & 0xffff) + 0x6b64) + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16))
}

k1 = 0

switch (remainder) {
case 3:
k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16
case 2:
k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8
case 1:
k1 ^= (key.charCodeAt(i) & 0xff)

k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff
k1 = (k1 << 15) | (k1 >>> 17)
k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff
h1 ^= k1
}

h1 ^= key.length

h1 ^= h1 >>> 16
h1 = (((h1 & 0xffff) * 0x85ebca6b) + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff
h1 ^= h1 >>> 13
h1 = ((((h1 & 0xffff) * 0xc2b2ae35) + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16))) & 0xffffffff
h1 ^= h1 >>> 16

return h1 >>> 0
}
Empty file added src/index.ts
Empty file.
37 changes: 37 additions & 0 deletions src/keyframes.ts
@@ -0,0 +1,37 @@
import * as CSS from 'csstype'

import { serializeStyle } from './css'
import { hashString } from 'hash'
import { applyStyleRule } from './dom'

type KeyframesRule = {
[key: string]: CSS.Properties,
from: CSS.Properties,
to: CSS.Properties,
}

export function keyframes (rule: KeyframesRule | string) {
const hash = hashString(typeof rule === 'object' ? JSON.stringify(rule) : `${rule}`)
const animationName = `animation-${hash}`
const chunks: string[] = [`@keyframes ${animationName} {`]

if (typeof rule === 'object') {
const selectors = Object.keys(rule)

selectors.forEach((selector) => {
const style = serializeStyle(rule[selector])

chunks.push(`${selector}: ${style}`)
})
} else {
chunks.push(rule)
}

chunks.push('}')

applyStyleRule(chunks.join())
/**
* @todo cache
* @body design a cache for same rule
*/
}
25 changes: 25 additions & 0 deletions tsconfig.json
@@ -0,0 +1,25 @@
{
"compilerOptions": {
"alwaysStrict": true,
"target": "es5",
"module": "esnext",
"moduleResolution": "node",
"baseUrl": "./src",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"dom",
"es5",
"es6",
"es7"
],
"sourceMap": true,
"skipLibCheck": true,
"strictNullChecks": true,
"strict": true
},
"exclude": [
"node_modules"
]
}
13 changes: 13 additions & 0 deletions yarn.lock
@@ -0,0 +1,13 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


csstype@^2.6.4:
version "2.6.4"
resolved "https://registry.npm.taobao.org/csstype/download/csstype-2.6.4.tgz#d585a6062096e324e7187f80e04f92bd0f00e37f"
integrity sha1-1YWmBiCW4yTnGH+A4E+SvQ8A438=

typescript@^3.4.5:
version "3.4.5"
resolved "https://registry.npm.taobao.org/typescript/download/typescript-3.4.5.tgz#2d2618d10bb566572b8d7aad5180d84257d70a99"
integrity sha1-LSYY0Qu1ZlcrjXqtUYDYQlfXCpk=

0 comments on commit 27b1dd4

Please sign in to comment.