From 0fa0fa2159bd400d3e67f3b435adee3e6543b420 Mon Sep 17 00:00:00 2001 From: Luigi Poole Date: Mon, 18 Jul 2016 10:40:08 -0700 Subject: [PATCH 01/10] move babel into its own .rc file --- .babelrc | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .babelrc diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..1297a0e --- /dev/null +++ b/.babelrc @@ -0,0 +1,4 @@ +{ + "presets": ["es2015", "react", "stage-0"], + "plugins": ["add-module-exports"] +} From 4e8685f9605f76e87ec5b39c6528ea3cc556b840 Mon Sep 17 00:00:00 2001 From: Luigi Poole Date: Mon, 18 Jul 2016 10:40:50 -0700 Subject: [PATCH 02/10] bring webpack config up to es6 spec --- static/index.html | 11 ---------- webpack.client-watch.js | 34 ----------------------------- webpack.client.js | 32 --------------------------- webpack.config.babel.js | 28 ++++++++++++++++++++++++ webpack.config.devServer.babel.js | 36 +++++++++++++++++++++++++++++++ 5 files changed, 64 insertions(+), 77 deletions(-) delete mode 100644 static/index.html delete mode 100644 webpack.client-watch.js delete mode 100644 webpack.client.js create mode 100644 webpack.config.babel.js create mode 100644 webpack.config.devServer.babel.js diff --git a/static/index.html b/static/index.html deleted file mode 100644 index e80f94b..0000000 --- a/static/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - react-inline-style - - -
- - - diff --git a/webpack.client-watch.js b/webpack.client-watch.js deleted file mode 100644 index 810aef3..0000000 --- a/webpack.client-watch.js +++ /dev/null @@ -1,34 +0,0 @@ -var webpack = require("webpack"); -var config = require("./webpack.client.js"); - -config.cache = true; -config.debug = true; -config.devtool = "eval"; - -config.entry.WDS = "webpack-dev-server/client?http://localhost:8080"; -config.entry.hot = "webpack/hot/only-dev-server"; - -config.module.postLoaders = [ - {test: /\.js$/, loaders: ["react-hot"], exclude: /node_modules/} -]; - -config.output.publicPath = "http://localhost:8080/dist/"; -config.output.hotUpdateMainFilename = "update/[hash]/update.json"; -config.output.hotUpdateChunkFilename = "update/[hash]/[id].update.js"; - -config.plugins = [ - new webpack.HotModuleReplacementPlugin() -]; - -config.devServer = { - publicPath: "http://localhost:8080/dist/", - contentBase: "./static", - hot: true, - inline: true, - quiet: true, - noInfo: true, - headers: {"Access-Control-Allow-Origin": "*"}, - stats: {colors: true} -}; - -module.exports = config; diff --git a/webpack.client.js b/webpack.client.js deleted file mode 100644 index 628b2c6..0000000 --- a/webpack.client.js +++ /dev/null @@ -1,32 +0,0 @@ -var webpack = require("webpack"); -var path = require("path"); - -module.exports = { - target: "web", - cache: false, - context: __dirname, - devtool: false, - entry: {example:"./src/example"}, - output: { - path: path.join(__dirname, "static/dist"), - filename: "[name].js", - chunkFilename: "[name].[id].js", - publicPath: "dist/" - }, - plugins: [ - new webpack.DefinePlugin({"process.env": {NODE_ENV: '"production"'}}), - new webpack.optimize.DedupePlugin(), - new webpack.optimize.OccurenceOrderPlugin(), - new webpack.optimize.UglifyJsPlugin() - ], - module: { - loaders: [ - {test: /\.json$/, loaders: ["json-loader"]}, - {test: /\.js$/, loaders: ["babel-loader?presets[]=es2015&presets[]=react"], exclude: /node_modules/}, - {test: /\.scss$/, loaders: ["raw-loader", "sass-loader"], exclude: /node_modules/} - ] - }, - resolve: { - extensions: ["", ".json", ".jsx", ".js"] - } -}; diff --git a/webpack.config.babel.js b/webpack.config.babel.js new file mode 100644 index 0000000..add1e72 --- /dev/null +++ b/webpack.config.babel.js @@ -0,0 +1,28 @@ +import webpack from 'webpack' +import { join } from 'path' + +export default { + target: 'web', + cache: false, + context: __dirname, + devtool: false, + entry: { example: './src/example' }, + output: { + path: join(__dirname, 'dist'), + filename: 'bundle.js' + }, + plugins: [ + new webpack.DefinePlugin({ 'process.env': { NODE_ENV: 'production' } }), + new webpack.optimize.DedupePlugin(), + new webpack.optimize.OccurenceOrderPlugin(), + new webpack.optimize.UglifyJsPlugin() + ], + module: { + loaders: [ + { test: /\.json$/, loaders: ['json-loader'] }, + { test: /\.js$/, loaders: ['babel-loader'], exclude: /node_modules/ }, + { test: /\.scss$/, loaders: ['raw-loader', 'sass-loader'], exclude: /node_modules/ } + ] + }, + resolve: { extensions: ['', '.json', '.jsx', '.js'] } +} diff --git a/webpack.config.devServer.babel.js b/webpack.config.devServer.babel.js new file mode 100644 index 0000000..8fcde1e --- /dev/null +++ b/webpack.config.devServer.babel.js @@ -0,0 +1,36 @@ +import { HotModuleReplacementPlugin } from 'webpack' +import OpenBrowserPlugin from 'open-browser-webpack-plugin' +import HtmlWebpackPlugin from 'html-webpack-plugin' +import { resolve } from 'path' +import webpackConfig from './webpack.config.babel' + +export default { + devServer: { + historyApiFallback: true, + hot: true, + progress: true, + contentBase: resolve('static'), + port: 8080, + outputPath: resolve('build'), + compress: true + }, + ...webpackConfig, + devtool: 'inline-source-map', + plugins: [ + new HotModuleReplacementPlugin(), + new OpenBrowserPlugin({ url: 'http://localhost:8080' }), + new HtmlWebpackPlugin({ + inject: false, + template: require('html-webpack-template'), + appMountId: 'react-root', + title: 'react-inline-style' + }) + ], + entry: [ + 'webpack/hot/dev-server', + 'webpack-dev-server/client?http://localhost:8080', + './src/example' + ], + debug: true, + cache: true +} From 0cef3dd8000b87dbe0ac7dbf839f60ef92f4d742 Mon Sep 17 00:00:00 2001 From: Luigi Poole Date: Mon, 18 Jul 2016 10:41:46 -0700 Subject: [PATCH 03/10] fix wrapper props containing components props set to invalid also bring component up to es6 spec --- src/react-inline-css.js | 83 +++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 48 deletions(-) diff --git a/src/react-inline-css.js b/src/react-inline-css.js index 570fbc4..6c0bfdb 100644 --- a/src/react-inline-css.js +++ b/src/react-inline-css.js @@ -1,58 +1,45 @@ /** * @copyright © 2015, Rick Wong. All rights reserved. */ -var React = require("react"); -var assign = Object.assign ? Object.assign : React.__spread; -var refCounter = 0; +import React, { PropTypes, Component } from 'react' /** * @module InlineCss */ -var InlineCss = React.createClass({ - displayName: "InlineCss", - propTypes: { - namespace: React.PropTypes.string, - componentName: React.PropTypes.string, - stylesheet: React.PropTypes.string.isRequired, - className: React.PropTypes.string, - wrapper: React.PropTypes.string - }, - _transformSheet: function (stylesheet, componentName, namespace) { - return stylesheet. - // Prettier output. - replace(/}\s*/ig, '\n}\n'). - // Regular rules are namespaced. - replace( - /(^|{|}|;|,)\s*([&a-z0-9\-_\.:#\(\),>*\s]+)\s*(\{)/ig, - function (matched) { - return matched.replace(new RegExp(componentName, "g"), "#" + namespace); - } - ); - }, - render: function () { - var namespace = this.props.namespace || "InlineCss-" + refCounter++; - var componentName = this.props.componentName || "&"; - var stylesheet = this._transformSheet(this.props.stylesheet, componentName, namespace); - var Wrapper = this.props.wrapper || "div"; +export default class InlineCss extends Component { - var wrapperProps = assign({}, this.props, { - namespace: undefined, - componentName: undefined, - stylesheet: undefined, - wrapper: undefined, - id: namespace - }); + static propTypes = { + namespace: PropTypes.string, + componentName: PropTypes.string, + stylesheet: PropTypes.string.isRequired, + wrapper: PropTypes.string + } - return React.createElement( - Wrapper, - wrapperProps, - this.props.children, - React.createElement("style", { - scoped: true, - dangerouslySetInnerHTML: {__html: stylesheet} - }) - ); - } -}); + static defaultProps = { + namespace: `inlineCss`, + componentName: '&', + wrapper: 'div' + } -module.exports = InlineCss; + _transformSheet(stylesheet, componentName, namespace) { + return stylesheet. + replace(/}\s*/ig, '\n}\n'). // Regular rules are namespaced. + replace(/(^|{|}|;|,)\s*([&a-z0-9\-_\.:#\(\),>*\s]+)\s*(\{)/ig, matched => matched.replace(new RegExp(componentName, 'g'), '#' + namespace)) + } + + render() { + const { namespace, componentName, stylesheet, wrapper, ...wrapperProps } = this.props + const id = namespace !== 'inlineCss' ? namespace : `${namespace}-${(Math.random().toString(36) + '00000000000000000').slice(2, 7 + 2)}` + + return React.createElement( + wrapper, { id, ...wrapperProps }, + this.props.children, + React.createElement('style', { + scoped: true, + dangerouslySetInnerHTML: { + __html: ::this._transformSheet(stylesheet, componentName, id) + } + }) + ) + } +} From 35a5703146f6f6afdebc190106484299d9463da1 Mon Sep 17 00:00:00 2001 From: Luigi Poole Date: Mon, 18 Jul 2016 10:41:58 -0700 Subject: [PATCH 04/10] update, change deps --- package.json | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index 7af7f07..a3e34e4 100644 --- a/package.json +++ b/package.json @@ -17,22 +17,25 @@ ], "main": "src/react-inline-css", "scripts": { - "localhost": "sleep 2; which open && open http://localhost:8080", - "build": "webpack --verbose --colors --display-error-details --config webpack.client.js", - "watch-client": "webpack --verbose --colors --display-error-details --config webpack.client-watch.js && webpack-dev-server --config webpack.client-watch.js", - "watch": "concurrent 'npm run watch-client' 'npm run localhost'" + "build": "webpack -p --verbose --colors --display-error-details", + "devserver": "webpack-dev-server --config webpack.config.devServer.babel.js" + }, + "dependencies": { + "react": "^15.2.1", + "react-dom": "^15.2.1" }, "devDependencies": { - "babel-core": "6.7.6", + "babel-core": "^6.10.4", "babel-loader": "6.2.4", - "babel-preset-es2015": "6.6.0", - "babel-preset-react": "6.5.0", - "concurrently": "2.0.0", + "babel-plugin-add-module-exports": "^0.2.1", + "babel-preset-es2015": "^6.9.0", + "babel-preset-react": "^6.11.1", + "babel-preset-stage-0": "^6.5.0", + "html-webpack-plugin": "^2.22.0", + "html-webpack-template": "^5.0.0", "json-loader": "0.5.4", - "react": "15.0.1", - "react-dom": "15.0.1", - "react-hot-loader": "1.3.0", - "webpack": "1.13.0", + "open-browser-webpack-plugin": "0.0.2", + "webpack": "^1.13.1", "webpack-dev-server": "1.14.1" } } From 3d4b19d3ff723d88c0f6b056aed4ae23446344e5 Mon Sep 17 00:00:00 2001 From: Luigi Poole Date: Mon, 18 Jul 2016 10:43:17 -0700 Subject: [PATCH 05/10] update readme accordingly --- README.md | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 0a57737..6bac638 100644 --- a/README.md +++ b/README.md @@ -53,19 +53,19 @@ You get namespaced CSS that works on sub-components (comparable to HTML5 ` @@ -79,7 +79,7 @@ For a cascaded effect, see the `index.html` demo. ## Usage -Run `npm run watch` in your terminal and play with `example/` to get a feel of react-inline-css. +Run `npm run devserver` in your terminal and play with `example/` to get a feel of react-inline-css. ### SASS / LESS @@ -127,11 +127,12 @@ UserComponent { ## Community Let's start one together! After you ★Star this project, follow me [@Rygu](https://twitter.com/rygu) -on Twitter. +on Twitter. ### Contributors - [Danilo Moret](https://github.com/moret) +- [Luigi Poole](https://github.com/luigiplr) ## License From b3123550d3bc56164b9d3fcc56157412e10e3e9a Mon Sep 17 00:00:00 2001 From: Luigi Poole Date: Mon, 18 Jul 2016 10:43:39 -0700 Subject: [PATCH 06/10] LICENSE should not be a .md file, rename it --- LICENSE.md => LICENSE | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename LICENSE.md => LICENSE (100%) diff --git a/LICENSE.md b/LICENSE similarity index 100% rename from LICENSE.md rename to LICENSE From cb1fa1290f66abd9609a1d48c9278afdb35ac69f Mon Sep 17 00:00:00 2001 From: Luigi Poole Date: Mon, 18 Jul 2016 10:48:51 -0700 Subject: [PATCH 07/10] further webpack refinements --- webpack.config.babel.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/webpack.config.babel.js b/webpack.config.babel.js index add1e72..6dc8feb 100644 --- a/webpack.config.babel.js +++ b/webpack.config.babel.js @@ -1,4 +1,4 @@ -import webpack from 'webpack' +import { optimize, DefinePlugin } from 'webpack' import { join } from 'path' export default { @@ -6,16 +6,16 @@ export default { cache: false, context: __dirname, devtool: false, - entry: { example: './src/example' }, + entry: ['./src/react-inline-css', './src/example'], output: { path: join(__dirname, 'dist'), - filename: 'bundle.js' + filename: 'react-inline-css.bundle.js' }, plugins: [ - new webpack.DefinePlugin({ 'process.env': { NODE_ENV: 'production' } }), - new webpack.optimize.DedupePlugin(), - new webpack.optimize.OccurenceOrderPlugin(), - new webpack.optimize.UglifyJsPlugin() + new DefinePlugin({ 'process.env': { NODE_ENV: 'production' } }), + new optimize.DedupePlugin(), + new optimize.OccurenceOrderPlugin(), + new optimize.UglifyJsPlugin({ output: { comments: false } }) ], module: { loaders: [ From b7f763bd450a7fe2333193a68ea165da5c546ba5 Mon Sep 17 00:00:00 2001 From: Luigi Poole Date: Mon, 18 Jul 2016 11:08:01 -0700 Subject: [PATCH 08/10] add pre-publish task to create dist ready build --- .gitignore | 2 ++ .npmignore | 3 +-- package.json | 10 +++++++--- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 947dcde..090ac6f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ .idea/ node_modules/ +build/ dist/ + *.log *.map .DS_Store diff --git a/.npmignore b/.npmignore index c9c2908..620c0a8 100644 --- a/.npmignore +++ b/.npmignore @@ -6,7 +6,6 @@ dist/ .DS_Store static/ -src/example/ -src/example.* +src/ tmp/ webpack.*.js diff --git a/package.json b/package.json index a3e34e4..1386291 100644 --- a/package.json +++ b/package.json @@ -15,16 +15,19 @@ "react-component", "style" ], - "main": "src/react-inline-css", + "main": "build/react-inline-css.js", "scripts": { - "build": "webpack -p --verbose --colors --display-error-details", - "devserver": "webpack-dev-server --config webpack.config.devServer.babel.js" + "babel": "mkdirp build && babel src/react-inline-css.js -o build/react-inline-css.js", + "build": "webpack -p --verbose --colors --display-error-details && npm run babel", + "devserver": "webpack-dev-server --config webpack.config.devServer.babel.js", + "prepublish": "npm run babel" }, "dependencies": { "react": "^15.2.1", "react-dom": "^15.2.1" }, "devDependencies": { + "babel-cli": "^6.10.1", "babel-core": "^6.10.4", "babel-loader": "6.2.4", "babel-plugin-add-module-exports": "^0.2.1", @@ -34,6 +37,7 @@ "html-webpack-plugin": "^2.22.0", "html-webpack-template": "^5.0.0", "json-loader": "0.5.4", + "mkdirp": "^0.5.1", "open-browser-webpack-plugin": "0.0.2", "webpack": "^1.13.1", "webpack-dev-server": "1.14.1" From a8eafd421a2a633cc4c4c1e44b21bf5f78b5f42c Mon Sep 17 00:00:00 2001 From: Luigi Poole Date: Tue, 19 Jul 2016 13:16:40 -0700 Subject: [PATCH 09/10] better regex for matching selectors allows matching of "input[type="checkbox"]" --- src/react-inline-css.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/react-inline-css.js b/src/react-inline-css.js index 6c0bfdb..fb2b858 100644 --- a/src/react-inline-css.js +++ b/src/react-inline-css.js @@ -24,7 +24,7 @@ export default class InlineCss extends Component { _transformSheet(stylesheet, componentName, namespace) { return stylesheet. replace(/}\s*/ig, '\n}\n'). // Regular rules are namespaced. - replace(/(^|{|}|;|,)\s*([&a-z0-9\-_\.:#\(\),>*\s]+)\s*(\{)/ig, matched => matched.replace(new RegExp(componentName, 'g'), '#' + namespace)) + replace(/([^\r\n,{}]+)(,(?=[^}]*{)|\s*{)/ig, matched => matched.replace(new RegExp(componentName, 'g'), '#' + namespace)) } render() { From 74d52706a1a5d2bd007f08672495016cf58775a8 Mon Sep 17 00:00:00 2001 From: Luigi Poole Date: Tue, 19 Jul 2016 13:44:25 -0700 Subject: [PATCH 10/10] add caching to prevent un-needed regexing of stylesheet on re-renders particularly helpful with larger stylesheets. --- src/react-inline-css.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/react-inline-css.js b/src/react-inline-css.js index fb2b858..68b5589 100644 --- a/src/react-inline-css.js +++ b/src/react-inline-css.js @@ -6,25 +6,30 @@ import React, { PropTypes, Component } from 'react' /** * @module InlineCss */ -export default class InlineCss extends Component { +export default class InlineCss extends Component { static propTypes = { namespace: PropTypes.string, componentName: PropTypes.string, stylesheet: PropTypes.string.isRequired, - wrapper: PropTypes.string + wrapper: PropTypes.string, + children: PropTypes.any } static defaultProps = { - namespace: `inlineCss`, + namespace: 'inlineCss', componentName: '&', wrapper: 'div' } _transformSheet(stylesheet, componentName, namespace) { - return stylesheet. - replace(/}\s*/ig, '\n}\n'). // Regular rules are namespaced. - replace(/([^\r\n,{}]+)(,(?=[^}]*{)|\s*{)/ig, matched => matched.replace(new RegExp(componentName, 'g'), '#' + namespace)) + if (this._cachedSheet && this._cachedSheet.formatted && this._cachedSheet.stylesheet === stylesheet) { + return this._cachedSheet.formatted + } + + const formatted = stylesheet.replace(/([^\r\n,{}]+)(,(?=[^}]*{)|\s*{)/ig, matched => matched.replace(new RegExp(componentName, 'g'), '#' + namespace)) + this._cachedSheet = { stylesheet, formatted } + return formatted } render() {