Skip to content

Commit

Permalink
Extract insertion plugin into stylis-plugin-emotion (#391)
Browse files Browse the repository at this point in the history
* Extract stylis-plugin-emotion from emotion so that other libraries can
use it.

* Update rollup and jest configs

* Fix linting

* Lint fix

* Add tests from stylis to test the plugin.

* Code cleanup

* Add stylis-plugin-emotion snapshots

* Update travis cache.

* Update snapshots after prettier update

* Add another test case
  • Loading branch information
Kye Hohenberger authored Oct 8, 2017
1 parent d2ae53a commit dafab02
Show file tree
Hide file tree
Showing 9 changed files with 852 additions and 92 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@ cache:
- packages/benchmarks/node_modules
- packages/emotion-server/node_modules
- packages/emotion/node_modules
- packages/stylis-plugin-emotion/node_modules
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@
"^emotion-utils$": "<rootDir>/packages/emotion-utils/src",
"^emotion-server$": "<rootDir>/packages/emotion-server/src",
"^emotion-theming$": "<rootDir>/packages/emotion-theming/src",
"^babel-plugin-emotion": "<rootDir>/packages/babel-plugin-emotion/src"
"^babel-plugin-emotion": "<rootDir>/packages/babel-plugin-emotion/src",
"^stylis-plugin-emotion": "<rootDir>/packages/stylis-plugin-emotion/src"
},
"setupTestFrameworkScriptFile": "<rootDir>/test/testSetup.js",
"coveragePathIgnorePatterns": [
Expand Down
3 changes: 2 additions & 1 deletion packages/emotion/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
},
"dependencies": {
"babel-plugin-emotion": "^8.0.4",
"emotion-utils": "^8.0.2-7"
"emotion-utils": "^8.0.2-7",
"stylis-plugin-emotion": "^8.0.4"
},
"devDependencies": {
"babel-cli": "^6.24.1",
Expand Down
103 changes: 14 additions & 89 deletions packages/emotion/src/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { hashString, Stylis, memoize, unitless } from 'emotion-utils'
import stylisPluginEmotion from 'stylis-plugin-emotion'
import StyleSheet from './sheet'

export const sheet = new StyleSheet()
Expand All @@ -16,6 +17,12 @@ const externalStylisPlugins = []

const use = stylis.use

function insertRule(rule) {
sheet.insert(rule, currentSourceMap)
}

const insertionPlugin = stylisPluginEmotion(insertRule)

export const useStylisPlugin = plugin => {
externalStylisPlugins.push(plugin)
use(null)(externalStylisPlugins)(insertionPlugin)
Expand All @@ -25,96 +32,7 @@ export let registered = {}

export let inserted = {}

export function flush() {
sheet.flush()
inserted = {}
registered = {}
sheet.inject()
}

function insertRule(rule) {
sheet.insert(rule, currentSourceMap)
}

let currentSourceMap = ''
let queue = []
let parentQueue = []

function insertionPlugin(
context,
content,
selectors,
parents,
line,
column,
length,
id
) {
switch (context) {
case -2: {
queue.forEach(insertRule)
queue = []
parentQueue = []
break
}

case 2: {
if (id === 0) {
const selector = selectors.join(',')
let parent = parents.join(',')
const rule = `${selector}{${content}}`
let index = parentQueue.indexOf(selector)
if (index === -1) {
index = parentQueue.length
} else {
let length = queue.length
while (length--) {
if (parentQueue[length] === selector) {
parentQueue[length] = undefined
}
}
}
queue.splice(index, 0, rule)
parentQueue.splice(index, 0, parent)
}
break
}
// after an at rule block
case 3: {
let parent = parents.join(',')
parentQueue.push(parent)
let chars = selectors.join('')
const second = chars.charCodeAt(1)
let child = content
switch (second) {
// s upports
case 115:
// d ocument
// eslint-disable-next-line no-fallthrough
case 100:
// m edia
// eslint-disable-next-line no-fallthrough
case 109: {
queue.push(chars + '{' + child + '}')
break
}
// k eyframes
case 107: {
chars = chars.substring(1)
child = chars + '{' + child + '}'
queue.push('@-webkit-' + child)
queue.push('@' + child)
parentQueue.push(parent)
break
}
default: {
queue.push(chars + child)
break
}
}
}
}
}

stylis.use(insertionPlugin)

Expand Down Expand Up @@ -325,3 +243,10 @@ export function hydrate(ids) {
inserted[id] = true
})
}

export function flush() {
sheet.flush()
inserted = {}
registered = {}
sheet.inject()
}
43 changes: 43 additions & 0 deletions packages/stylis-plugin-emotion/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"name": "stylis-plugin-emotion",
"version": "8.0.4",
"description": "stylis plugin to insert parsed rules via insertRule",
"main": "dist/index.cjs.js",
"module": "dist/index.es.js",
"files": [
"src",
"dist"
],
"scripts": {
"build": "npm-run-all clean rollup",
"clean": "rimraf dist",
"watch": "rollup -c ../../rollup.config.js --watch",
"rollup": "rollup -c ../../rollup.config.js"
},
"author": "Mitchell Hamilton",
"homepage": "https://github.com/emotion-js/emotion#readme",
"license": "MIT",
"repository": "https://github.com/emotion-js/emotion/tree/master/packages/stylis-plugin-emotion",
"keywords": [
"styles",
"emotion",
"react",
"css",
"css-in-js",
"insertRule",
"stylis",
"plugin",
"insert rule",
"stylesheet"
],
"bugs": {
"url": "https://github.com/tkh44/emotion/issues"
},
"devDependencies": {
"emotion": "^8.0.4",
"emotion-utils": "^8.0.2-7",
"npm-run-all": "^4.0.2",
"rimraf": "^2.6.1",
"rollup": "^0.47.2"
}
}
79 changes: 79 additions & 0 deletions packages/stylis-plugin-emotion/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
let queue = []
let parentQueue = []

export default insertRule =>
function insertionPlugin(
context,
content,
selectors,
parents,
line,
column,
length,
id
) {
switch (context) {
case -2: {
queue.forEach(insertRule)
queue = []
parentQueue = []
break
}

case 2: {
if (id === 0) {
const selector = selectors.join(',')
let parent = parents.join(',')
const rule = `${selector}{${content}}`
let index = parentQueue.indexOf(selector)
if (index === -1) {
index = parentQueue.length
} else {
let length = queue.length
while (length--) {
if (parentQueue[length] === selector) {
parentQueue[length] = undefined
}
}
}
queue.splice(index, 0, rule)
parentQueue.splice(index, 0, parent)
}
break
}
// after an at rule block
case 3: {
let parent = parents.join(',')
parentQueue.push(parent)
let chars = selectors.join('')
const second = chars.charCodeAt(1)
let child = content
switch (second) {
// s upports
case 115:
// d ocument
// eslint-disable-next-line no-fallthrough
case 100:
// m edia
// eslint-disable-next-line no-fallthrough
case 109: {
queue.push(chars + '{' + child + '}')
break
}
// k eyframes
case 107: {
chars = chars.substring(1)
child = chars + '{' + child + '}'
queue.push('@-webkit-' + child)
queue.push('@' + child)
parentQueue.push(parent)
break
}
default: {
queue.push(chars + child)
break
}
}
}
}
}
Loading

0 comments on commit dafab02

Please sign in to comment.