diff --git a/.babelrc b/.babelrc
new file mode 100644
index 0000000..b0b9a96
--- /dev/null
+++ b/.babelrc
@@ -0,0 +1,3 @@
+{
+ "stage": 0
+}
diff --git a/.eslintrc b/.eslintrc
index 22537cf..0233e9e 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -1,12 +1,30 @@
---
+# babel support more syntax stuff than eslint for now
+parser: babel-eslint
+
ecmaFeatures:
modules: true
+ jsx: true
env:
es6: true
browser: true
node: true
+globals:
+ # for docs
+ __DEV__: true
+ __PROD__: true
+ __SERVER_PROTOCOL__: true
+ __SERVER_HOSTNAME__: true
+ __SERVER_PORT__: true
+ __SERVER_HOST__: true
+ __SERVER_URL__: true
+ __LR_SERVER_PORT__: true
+
+plugins:
+ - react
+
# 0: off, 1: warning, 2: error
rules:
# max 80 chars per line
@@ -50,3 +68,16 @@ rules:
# enforce comma at eol (never before)
comma-style: [2, "last"]
+
+ # see globals
+ no-underscore-dangle: 0
+
+ # eslint-plugin-react rules
+ react/no-multi-comp: 2
+ react/prop-types: 2
+ react/wrap-multilines: 2
+ react/self-closing-comp: 2
+ react/no-did-mount-set-state: 2
+ react/no-did-update-set-state: 2
+ react/jsx-uses-react: 2
+ react/jsx-uses-vars: 2
diff --git a/.gitignore b/.gitignore
index d2eef5e..4da1288 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@ node_modules
# standalone build
dist
+docs/dist
# fixtures
test/**/*.actual.css
diff --git a/.travis.yml b/.travis.yml
index ec26778..d712cdd 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -14,3 +14,8 @@ notifications:
on_failure: always
use_notice: true
skip_join: true
+
+script:
+ - npm run test
+ # travis take is weird, disabled for now
+ #- if [[ $(node --version) != v0.* ]]; then; npm run docs-test; fi
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..9446f6e
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,29 @@
+## Contributing
+
+_cssnext uses a lot of [postcss](https://github.com/postcss) plugins,
+so you might need to take a look at them if you find an issue or want to create
+or enhance a feature._
+
+Otherwise, fork, work on a branch, install dev-dependencies,
+respect coding style & run tests before submitting a bug fix or a feature.
+
+```console
+$ git clone https://github.com/YOU/cssnext.git
+$ npm install
+$ npm test
+$ git checkout -b fix.bug423
+```
+
+### Add a feature
+
+1. Add test files (input + expected output) in [`test/fixtures/features`](test/features)
+- If the feature can affect some others, update [`test/fixtures/cases/example.css`](test/cases/example.css) to test integration with other features
+- Run test, & check tests are broken (otherwise feature is useless)
+- Choose a pretty simple and clear name (that match the specs)
+- Add the feature in the [README features list](#features) (title, link to spec, link of the plugin, short desc)
+- Add the feature in the [README node.js options list](#features-default-all-features) (camelCaseName)
+- Add the dependency in the [`package.json`](package.json)
+- Add the feature in the source (in [`index.js`](index.js)), in the appropriate place (order matter)
+- Run test and be happy
+- Add feature in [the docs](docs/content)
+- Add feature on [the playground](https://github.com/cssnext/playground) example
diff --git a/README.md b/README.md
index 04c86dc..5c1276f 100644
--- a/README.md
+++ b/README.md
@@ -1,414 +1,33 @@
-# cssnext [](https://www.npmjs.org/package/cssnext) [](https://travis-ci.org/cssnext/cssnext) [](https://ci.appveyor.com/project/MoOx/cssnext) [](https://gitter.im/cssnext/cssnext)
+# cssnext
+[](https://www.npmjs.org/package/cssnext)
+[](https://travis-ci.org/cssnext/cssnext)
+[](https://ci.appveyor.com/project/MoOx/cssnext)
+[](https://gitter.im/cssnext/cssnext)
-> Use tomorrow's CSS syntax, today.
+> Use tomorrow's CSS syntax, today.
This is a CSS transpiler (CSS4+ to CSS3) that allows you to use tomorrow's CSS syntax today.
It transforms CSS specs that are not already implemented in popular browsers into more compatible CSS.
-_This is not a classic CSS preprocessor, but can totally replace one._
-
-Check out [the website](https://cssnext.github.io/) or [try cssnext](https://cssnext.github.io/cssnext-playground) in your browser.
-
-**Is it cssnext or CSSNext or CSSnext?**
-The official name is **cssnext**, which should never be capitalized, especially not at the start of a sentence, unless it is being displayed in a location that is customarily all-caps (such as the title of man pages).
+## Check out [cssnext website](https://cssnext.io/)
----
+- [Features](https://cssnext.io/features/)
+- [Setup](https://cssnext.io/setup/)
+- [Usage](https://cssnext.io/usage/)
+- [Playground](https://cssnext.io/playground/)
-[Why](#why) | [Features](#features) | [Limitations](#limitations) | [Installation](#installation)| [CLI Usage](#cli) | [Node.js API](#nodejs-api) | [Contribute](#contributing)
---- | --- | --- | --- | --- | --- | ---
+For questions and support please visit the
+[gitter room](https://gitter.im/cssnext/cssnext).
---
-## Why
-
-Prior 2015, CSS was frustrating by not having any specification for features we were looking for. No variables, no math, no color manipulation & no customization. Things are going to change soon since a lot of work has been made by the W3C to write new specs to make our life easier.
-
-**This project aims to allow you to use future CSS syntax, today.**
-
-It is similar to [Myth](http://myth.io/) or [SUIT CSS preprocessor](https://github.com/suitcss/preprocessor) but pushes the concept to the next level by supporting more features. It works great with [cssrecipes](https://cssrecipes.github.io/) or [SUIT CSS](https://suitcss.github.io/).
-
-_It's not planned for now to provide polyfills for future CSS APIs that depend on the client browser._
-
-Follow [@cssnext on Twitter](https://twitter.com/cssnext) to get the latest news & join [#cssnext on irc.freenode.net](http://webchat.freenode.net/?channels=cssnext) if you have any questions.
-
-## Features
-
-You can safely use the following features:
-
-* automatic vendor prefixes
-(via [autoprefixer](https://github.com/postcss/autoprefixer)),
-* [custom properties & `var()`](http://www.w3.org/TR/css-variables/)
-limited to `:root`
-([⇗](https://github.com/postcss/postcss-custom-properties)),
-* [reduced `calc()`](https://github.com/MoOx/reduce-css-calc#readme)
-to optimize previously parsed `var()` references
-([⇗](https://github.com/postcss/postcss-calc)),
-* [custom media queries](http://dev.w3.org/csswg/mediaqueries/#custom-mq)
-a nice way to have semantic media queries
-([⇗](https://github.com/postcss/postcss-custom-media)),
-* [media queries ranges](http://dev.w3.org/csswg/mediaqueries/#mq-ranges)
-that allows to replace min-/max- with `<=` & `>=` (syntax easier to read)
-([⇗](https://github.com/postcss/postcss-media-minmax)),
-* [custom selectors](http://dev.w3.org/csswg/css-extensions/#custom-selectors)
-to create your own selectors
-([⇗](https://github.com/postcss/postcss-custom-selector)),
-* [`color()`](http://dev.w3.org/csswg/css-color/#modifying-colors)
-a color function to modify colors
-(transpiled to: `rgba()`)
-([⇗](https://github.com/postcss/postcss-color-function)),
-* [`hwb()`](http://dev.w3.org/csswg/css-color/#the-hwb-notation)
-similar to `hsl()` but easier for humans to work with
-(transpiled to: `rgba()`)
-([⇗](https://github.com/postcss/postcss-color-hwb)) ,
-* [`gray()`](http://dev.w3.org/csswg/css-color/#grays)
-(transpiled to: `rgba()`)
-([⇗](https://github.com/postcss/postcss-color-gray)),
-* [#rrggbbaa](http://dev.w3.org/csswg/css-color/#hex-notation)
-(transpiled to: `rgba()`)
-([⇗](https://github.com/postcss/postcss-color-hex-alpha)),
-* [`rebeccapurple`](http://dev.w3.org/csswg/css-color/#valdef-color-rebeccapurple)
-([⇗](https://github.com/postcss/postcss-color-rebeccapurple)),
-* [font-variant](http://dev.w3.org/csswg/css-fonts/#propdef-font-variant)
-properties (fallback: `font-feature-settings`)
-([⇗](https://github.com/postcss/postcss-font-variant)),
-* [filter](http://www.w3.org/TR/filter-effects/)
-properties (fallback: inlined `` filter)
-([⇗](https://github.com/iamvdo/pleeease-filters))
-* [`rem` units](http://www.w3.org/TR/css3-values/#rem-unit)
-(fallback: `px`)
-([⇗](https://github.com/robwierzbowski/node-pixrem))
-* [pseudo-elements](http://www.w3.org/TR/css3-selectors/#pseudo-elements)
-(adjust `::` to `:`)
-([⇗](https://github.com/axa-ch/postcss-pseudoelements))
-* [`:matches` pseudo-class](http://dev.w3.org/csswg/selectors-4/#matches)
-([⇗](https://github.com/postcss/postcss-selector-matches))
-* [`:not` pseudo-class](http://dev.w3.org/csswg/selectors-4/#negation)
-([⇗](https://github.com/postcss/postcss-selector-NOT))
-* alpha colors for browser that don't understand [css 3 colors](http://www.w3.org/TR/css3-color/)
-(fallback: solid hexa colors)
-([⇗](https://github.com/postcss/postcss-color-rgba-fallback))
-
-_Note that according to your [browser scope](#nodejs-options) some might be not transpiled to avoid extra useless output._
-
-### Bonus features
-
-_The features below are considered as bonus since it's totally not related to CSS specs ._
-
-* `@import` inline local files and modules - `node_modules` or `web_modules` ([⇗](https://github.com/postcss/postcss-import)) to output a bundled CSS file. `url()` referenced are also rebased.
-* minification is available ([⇗](https://github.com/hail2u/node-csswring)) if you want to compress the output for production.
-
-
-### @todo
-
-Any omissions of the CSS specifications (even in draft) that are subject to be handled by cssnext are not intentional.
-You can take a look at the [list of features that are waiting to be implemented](https://github.com/cssnext/cssnext/issues?q=is%3Aopen+is%3Aissue+label%3Afeature+label%3Aready).
-Feel free to work on a feature ready to be added, or [open a new issue](https://github.com/cssnext/cssnext/issues/new) if you find something that should be handled.
-Keep in mind that, as of right now, this project is intended to support new CSS *syntax* only.
-
-## Limitations
-
-### Custom properties
-
-The current transformation for custom properties just aims to provide a future-proof way of using a **limited subset (to top-level `:root` selector)** of the features provided by native CSS custom properties.
-The transformation is not complete and can't be properly. By injecting selectors with new computed rules, we will break original cascade & unexpected results might happen.
-
-### Font variant
-
-`font-variant` are transformed to `font-feature-settings`. You might take a look at the support of [font feature settings](http://caniuse.com/#feat=font-feature).
-
-### Filter
-
-The W3C filters are only transformed as svg filter using the `url(data:*)` trick for Firefox < 35.
+_The [issue tracker](https://github.com/cssnext/cssnext/issues) is exclusively for bug reports and feature requests._
---
-## Installation
-
-```console
-$ npm install cssnext
-```
-
-You can install it
-
-- locally (`--save` or `--save-dev`), to use it through [npm scripts](https://www.npmjs.org/doc/misc/npm-scripts.html) (`npm run`) or via `.node_modules/.bin/cssnext`
-- globally (`-g`), to use it through the [CLI](cli) (not recommanded)
-- by using [other plugins & tools](#usage-with-other-tools) like [gulp-cssnext](https://github.com/cssnext/gulp-cssnext)
-
-## Usage
-
-You can use cssnext using [CLI](#cli),
-as [a JavaScript library](#nodejs-api),
-as a [PostCSS](https://github.com/postcss/postcss) plugin
-or through [others tools](#usage-with-other-tools).
-
-### CLI
-
-cssnext offers a command-line interface.
-Here's how to compile a file and print it to stdout:
-
-```console
-$ cssnext index.css
-```
-
-To create an output file, you can just add a second argument
-
-```console
-$ cssnext index.css output.css
-```
-
-Or use CLI std(in|out) redirection(s)
-
-```console
-$ cat input.css | cssnext > output.css
-```
-
-### CLI options
-
-If you don't care about a certain feature, such as custom media queries, you can omit support for them like so:
-
-```console
-$ cssnext --no-custom-media index.css
-```
-
-To enable source maps for these files, add the `--sourcemap` flag.
-
-**To see all CLI options**
-
-```console
-$ cssnext --help
-```
-
-### Node.js API
-
-cssnext can be used with its own API or as a PostCSS plugin.
-
-#### `var string = cssnext(string, options)`
-
-cssnext accepts 2 arguments: a css string and an object of options.
-
-```js
-var fs = require("fs")
-var cssnext = require("cssnext")
-
-var input = fs.readFileSync("index.css", "utf8")
-
-var output = cssnext(input)
-fs.writeFileSync("dist/index.css", output)
-```
-
-**`/!\` Note: if you are using non inlined sourcemaps, cssnext will return an object: `{css: string, map: sourcemap}`**
-
-See [sourcemap](#sourcemap-default-false) & [map](#map-default-depends-on-sourcemap) options for more informations.
-
-#### `var postcssPlugin = cssnext(options)`
-
-cssnext can be used as a postcss plugin:
-
-```js
-var fs = require("fs")
-var postcss = require("postcss")
-var cssnext = require("cssnext")
-
-var input = fs.readFileSync("index.css", "utf8")
-
-var output = postcss()
- .use(cssnext())
- .use(/* your other postcss plugin */)
- .process(input)
-fs.writeFileSync("dist/index.css", output)
-```
-
-#### Node.js options
-
-##### `browsers` (default: [browserslist default](https://github.com/ai/browserslist#readme) - `> 1%, last 2 versions, Firefox ESR, Opera 12.1`)
-
-Allows you to specify your browser scope.
-**This option enables or disables `features` according to [caniuse](http://caniuse.com/) database.**
-This is the exact same option that you might know from Autoprefixer.
-Since cssnext includes Autoprefixer, the option is propagated.
-
-See [Browserslist](https://github.com/ai/browserslist#queries) queries syntax to adjust this option to your needs.
-
-_Note: if you don't specify this option, Browserslist will automatically try to find a `browserslist`
-config file or use its default value._
-
-##### `features` (default: all features)
-
-**You should probably use `browsers` option instead of this one.**
-
-Object containing key of features to enable/disable.
-_Features are enabled by default: no key means feature is enabled_.
-
-```js
-//eg: disable custom properties support
-var output = cssnext(input, {
- features: {
- customProperties: false
- }
-})
-```
-
-Each feature is based on PostCSS plugins & can get its own options.
-To pass options to a feature, you can just pass an object to the feature:
-
-```js
-//eg: preserve custom properties
-var output = cssnext(input, {
- features: {
- customProperties: {
- preserve: true
- }
- }
-})
-```
-
-To know all available options, please check the [available features](#available) list where you will find references to all the plugins used.
-
-Here are all the available features:
-
-- `customProperties`
-- `calc`
-- `customMedia`
-- `mediaQueriesRange`
-- `customSelectors`
-- `colorFunction`
-- `colorHexAlpha`
-- `colorHwb`
-- `colorRebeccapurple`
-- `fontVariant`
-- `filter`
-- `rem`
-- `pseudoElements`
-- `pseudoClassMatches`
-- `pseudoClassNot`
-- `colorRgba`
-- `autoprefixer`
-
-_Note: order is important to get everything working correctly._
-
-##### `import` (default: `true`)
-
-Allows you to inline local `@import` files (thanks to [postcss-import](https://github.com/postcss/postcss-import#readme)):
-
-* you can refer to `node_modules` and `web_modules` packages
-* you can omit .css extension
-
-_Note: you can pass [postcss-import options](https://github.com/postcss/postcss-import#readme) directly._
-
-##### `url` (default: `true`)
-
-By default, `url()` are rebased according to `from` (and `to`) option(s). This is convenient especially for `@import`ed files.
-
-_Note: you can pass [postcss-url options](https://github.com/postcss/postcss-url#options) directly in order to inline or have more control over urls._
-
-##### `compress` (default: `false`)
-
-Allows you to compress the output (using [cssnano](https://github.com/ben-eb/cssnano)).
-You can enable minification by passing `true` or by providing an object containing [cssnano options](https://github.com/ben-eb/cssnano#options).
-
-##### `sourcemap` (default: `false`)
-
-This option is a shortcut to enable inlined sourcemap in the output.
-Just pass `true` to get the sourcemap at the end of the output.
-
-- _If you want an accurate sourcemap, please also use the `from` option._
-- _If you want more control on the sourcemap, please use the `map` option instead._
-
-##### `map` (default: _depends on `sourcemap`_)
-
-_(default: `undefined` if `sourcemap` is `false`, `inline` if `sourcemap` it true)_
-
-If you want better control on sourcemap, you are at the right place.
-This is the [postcss `map` option](https://github.com/postcss/postcss#source-map-1), so checkout the related documentation directly.
-
-_If you specify this option, `sourcemap` value will be ignored._
-
-**`/!\` Using this option might change the return value of `cssnext()` (`object` instead of css `string` if map is not inlined. The object will be like {css: "{css string}", map: {sourcemap object}})**
-
-##### `from` (default: `null`)
-
-Source of the file. Required for accurate sourcemap.
-
-```js
-var cssnext = require("cssnext")
-var fs = require("fs")
-
-var source = "./index.css"
-var output = cssnext(
- fs.readFileSync(source, "utf8"),
- {from: source}
-)
-fs.writeFileSync("dist/index.css", output)
-```
-
-### Usage with other tools
-
-Here are some tools that will help you use cssnext in your current workflow:
-
-* [gulp-cssnext](https://github.com/cssnext/gulp-cssnext)
-* [grunt-cssnext](https://github.com/cssnext/grunt-cssnext)
-* [cssnext-loader (webpack)](https://github.com/cssnext/cssnext-loader)
-* [duo-cssnext](https://github.com/cssnext/duo-cssnext)
-* [cssnext-brunch](https://github.com/cssnext/cssnext-brunch)
-* [broccoli-cssnext](https://github.com/cssnext/broccoli-cssnext)
-* [Prepros 5](https://prepros.io/) (_More options_ (dropdown) > _Project options_ (item) > _Compilers_ (tab) > _Enable cssnext_ (checkbox at the bottom))
-* @todo component-builder package
-* @todo meteor package
-
-_Note that you can also use cssnext as a PostCSS plugin._
-
----
-
-## Contributing
-
-_cssnext uses a lot of [postcss](https://github.com/postcss) plugins, so you might need to take a look at them if you find an issue or want to create or enhance a feature._
-
-Otherwise, work on a branch, install dev-dependencies, respect coding style & run tests before submitting a bug fix or a feature.
-
-```console
-$ git clone https://github.com/cssnext/cssnext.git
-$ git checkout -b patch-1
-$ npm install
-$ npm test
-```
-
-### Add a feature
-
-1. Add test files (input + expected output) in [`test/fixtures/features`](test/features)
-- If the feature can affect some others, update [`test/fixtures/cases/example.css`](test/cases/example.css) to test integration with other features
-- Run test, & check tests are broken (otherwise feature is useless)
-- Choose a pretty simple and clear name (that match the specs)
-- Add the feature in the [README features list](#features) (title, link to spec, link of the plugin, short desc)
-- Add the feature in the [README node.js options list](#features-default-all-features) (camelCaseName)
-- Add the dependency in the [`package.json`](package.json)
-- Add the feature in the source (in [`index.js`](index.js)), in the appropriate place (order matter)
-- Run test and be happy
-- Add feature on [the playground](https://github.com/cssnext/cssnext-playground) example
-- Add feature on [the website](https://github.com/cssnext/cssnext.github.io)
-
## [Changelog](CHANGELOG.md)
## [License](LICENSE)
-
----
-
-## People
-
-The current lead maintainer is [Maxime Thirouin](http://moox.io/). [](https://gratipay.com/MoOx/)
-
-See [all contributors](https://github.com/cssnext/cssnext/graphs/contributors).
-
-## Acknowledgements
-
-Huge thanks to all the people that where involved in:
-
-- [rework](https://github.com/reworkcss/rework/graphs/contributors)
-- [rework css parser](https://github.com/reworkcss/css/graphs/contributors)
-- [myth](https://github.com/segmentio/myth/graphs/contributors)
-- [autoprefixer](https://github.com/postcss/autoprefixer/graphs/contributors)
-- [postcss](https://github.com/postcss/postcss/graphs/contributors)
-
-Without all those people, this project would not exist.
diff --git a/docs/content/CNAME b/docs/content/CNAME
new file mode 100644
index 0000000..3f8074d
--- /dev/null
+++ b/docs/content/CNAME
@@ -0,0 +1 @@
+cssnext.io
diff --git a/docs/content/credits.md b/docs/content/credits.md
new file mode 100644
index 0000000..1291a2b
--- /dev/null
+++ b/docs/content/credits.md
@@ -0,0 +1,9 @@
+---
+title: Credits
+footer: false
+---
+
+* [delorean back](https://www.flickr.com/photos/jasoncipriani/11866004734)
+* [delorean with blue trails](https://www.flickr.com/photos/wizzer/9295055565)
+* [bttf legos](https://www.flickr.com/photos/brianneudorff/10047726604)
+* [delorean side](https://www.flickr.com/photos/mooshuu/5963681346)
diff --git a/docs/content/features.md b/docs/content/features.md
new file mode 100644
index 0000000..4fe35bc
--- /dev/null
+++ b/docs/content/features.md
@@ -0,0 +1,126 @@
+---
+title: Discover cssnext features
+backgroundModifier: darkRoad
+incomplete: true
+---
+
+## automatic vendor prefixes
+
+(via [autoprefixer](https://github.com/postcss/autoprefixer)),
+
+
+## [custom properties & `var()`](http://www.w3.org/TR/css-variables/)
+
+limited to `:root`
+([⇗](https://github.com/postcss/postcss-custom-properties)),
+
+## [reduced `calc()`](https://github.com/MoOx/reduce-css-calc#readme)
+
+to optimize previously parsed `var()` references
+([⇗](https://github.com/postcss/postcss-calc)),
+
+## [custom media queries](http://dev.w3.org/csswg/mediaqueries/#custom-mq)
+
+a nice way to have semantic media queries
+([⇗](https://github.com/postcss/postcss-custom-media)),
+
+## [media queries ranges](http://dev.w3.org/csswg/mediaqueries/#mq-ranges)
+
+that allows to replace min-/max- with `<=` & `>=` (syntax easier to read)
+([⇗](https://github.com/postcss/postcss-media-minmax)),
+
+## [custom selectors](http://dev.w3.org/csswg/css-extensions/#custom-selectors)
+
+to create your own selectors
+([⇗](https://github.com/postcss/postcss-custom-selector)),
+
+## [`color()`](http://dev.w3.org/csswg/css-color/#modifying-colors)
+
+a color function to modify colors (transpiled to: `rgba()`)
+([⇗](https://github.com/postcss/postcss-color-function)),
+
+## [`hwb()`](http://dev.w3.org/csswg/css-color/#the-hwb-notation)
+
+similar to `hsl()` but easier for humans to work with (transpiled to: `rgba()`)
+([⇗](https://github.com/postcss/postcss-color-hwb)) ,
+
+## [`gray()`](http://dev.w3.org/csswg/css-color/#grays)
+
+(transpiled to: `rgba()`)
+([⇗](https://github.com/postcss/postcss-color-gray)),
+
+## [#rrggbbaa](http://dev.w3.org/csswg/css-color/#hex-notation)
+
+(transpiled to: `rgba()`)
+([⇗](https://github.com/postcss/postcss-color-hex-alpha)),
+
+## [`rebeccapurple`](http://dev.w3.org/csswg/css-color/#valdef-color-rebeccapurple)
+
+([⇗](https://github.com/postcss/postcss-color-rebeccapurple)),
+
+
+## [font-variant](http://dev.w3.org/csswg/css-fonts/#propdef-font-variant)
+
+properties (fallback: `font-feature-settings`)
+([⇗](https://github.com/postcss/postcss-font-variant)),
+
+## [filter](http://www.w3.org/TR/filter-effects/)
+
+properties (fallback: inlined `` filter)
+([⇗](https://github.com/iamvdo/pleeease-filters))
+
+## [`rem` units](http://www.w3.org/TR/css3-values/#rem-unit)
+
+(fallback: `px`)
+([⇗](https://github.com/robwierzbowski/node-pixrem))
+
+## [pseudo-elements](http://www.w3.org/TR/css3-selectors/#pseudo-elements)
+
+(adjust `::` to `:`)
+([⇗](https://github.com/axa-ch/postcss-pseudoelements))
+
+## [`:matches` pseudo-class](http://dev.w3.org/csswg/selectors-4/#matches)
+
+([⇗](https://github.com/postcss/postcss-selector-matches))
+
+
+## [`:not` pseudo-class](http://dev.w3.org/csswg/selectors-4/#negation)
+
+([⇗](https://github.com/postcss/postcss-selector-NOT))
+
+
+## alpha colors for browser that don't understand [css 3 colors](http://www.w3.org/TR/css3-color/)
+ (fallback: solid hexa colors)
+([⇗](https://github.com/postcss/postcss-color-rgba-fallback))
+
+_Note that according to your [browser scope](#nodejs-options) some might be not transpiled to avoid extra useless output._
+
+## Bonus features
+
+_The features below are considered as bonus since it's totally not related to CSS specs ._
+
+* `@import` inline local files and modules - `node_modules` or `web_modules` ([⇗](https://github.com/postcss/postcss-import)) to output a bundled CSS file. `url()` referenced are also rebased.
+* minification is available ([⇗](https://github.com/hail2u/node-csswring)) if you want to compress the output for production.
+
+
+## @todo
+
+Any omissions of the CSS specifications (even in draft) that are subject to be handled by cssnext are not intentional.
+You can take a look at the [list of features that are waiting to be implemented](https://github.com/cssnext/cssnext/issues?q=is%3Aopen+is%3Aissue+label%3Afeature+label%3Aready).
+Feel free to work on a feature ready to be added, or [open a new issue](https://github.com/cssnext/cssnext/issues/new) if you find something that should be handled.
+Keep in mind that, as of right now, this project is intended to support new CSS *syntax* only.
+
+## Limitations
+
+### Custom properties
+
+The current transformation for custom properties just aims to provide a future-proof way of using a **limited subset (to top-level `:root` selector)** of the features provided by native CSS custom properties.
+The transformation is not complete and can't be properly. By injecting selectors with new computed rules, we will break original cascade & unexpected results might happen.
+
+### Font variant
+
+`font-variant` are transformed to `font-feature-settings`. You might take a look at the support of [font feature settings](http://caniuse.com/#feat=font-feature).
+
+### Filter
+
+The W3C filters are only transformed as svg filter using the `url(data:*)` trick for Firefox < 35.
diff --git a/docs/content/index.md b/docs/content/index.md
new file mode 100644
index 0000000..306f389
--- /dev/null
+++ b/docs/content/index.md
@@ -0,0 +1,249 @@
+---
+template: Simple
+title: cssnext
+---
+
+
+
+
+
What is cssnext?
+
+ cssnext is a CSS transpiler that allows you to use
+ the latest CSS syntax today.
+ It transforms CSS specs into more compatible CSS
+ so you don't need to wait for browser support.
+
+
+ You can literally write future-proof CSS
+ and forget old preprocessor specific syntax.
+
+
+
+
+
+
+
+ custom properties & `var()`
+
+
+ reduced `calc()`
+
+
+ custom media queries
+
+
+ media queries ranges
+
+
+ custom selectors
+
+
+ automatic vendor prefixes
+
+
+ `color()` support
+
+
+ `gray()` support
+
+
+ `hwb()` support
+
+
+ hexa `#rrggbbaa` support
+
+
+ `rebeccapurple`
+
+
+ `:matches` pseudo-class
+
+
+ `:not` pseudo-class
+
+ (to l.3)
+
+
+
+ font-variant
+
+ (to font-feature-settings)
+
+
+
+ filters
+
+ (svg fallback)
+
+
+
+ `rem` units fallback
+
+ (to px)
+
+
+
+ ::pseudo syntax
+
+ (`:` compat)
+
+
+
+
+
+ _l.* are level of the specification (when information is relevant)_
+
+
+
+
+
+
+
+
+
Why cssnext?
+
+ Prior to 2015, CSS was frustrating by not having any specification for features we were looking for.
+ No variables, no math, no color manipulation & no customization.
+ Things are going to change soon since a lot of work has been made by the W3C to write new specs to make our life easier.
+ With cssnext, you can start using some new features today!
+
+
+
+
+
+
+
+
+
Future-proof code
+
+ In a near future, browsers will implement new CSS specifications. As time passes, cssnext will remove some transformations that won't be necessary anymore.
+ And maybe one day, you will be able to completely remove cssnext from your workflow without touching your CSS.
+
+
+
+
+
+
+
+
+
+
It's fast. Lightning fast.
+
+ cssnext uses PostCSS
+ which has
+ a way faster CSS parser .
+
+ It's a good competitor to libsass, a bit faster than LESS and Stylecow,
+ and way faster than Myth or original Ruby Sass.
+
+
+
+
+
+
+
+
+
Active development
+
+ No longer wait for releases.
+ A fixed bug will be released ASAP.
+
+ Minor features will never be idle for long.
+
+ See that by yourself on
+ cssnext
+ &
+ PostCSS .
+ activities graphs.
+
+
+ cssnext uses lots of PostCSS plugins,
+ so check them out too.
+
+
+
+
+
+
+
+
+
+
Based on NPM ecosystem
+
+ cssnext uses npm packages that should respect semver .
+
+ Bugfixes are pushed often.
+ Minor changes won't break your code.
+ Major releases are, well, major and are not supposed to happen a lot.
+
+ Codebase is exploded into smart and standalone packages so it's easier to work on something or fix a bug.
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/content/it-s-cssnext-not-CSSNext.md b/docs/content/it-s-cssnext-not-CSSNext.md
new file mode 100644
index 0000000..5ded767
--- /dev/null
+++ b/docs/content/it-s-cssnext-not-CSSNext.md
@@ -0,0 +1,28 @@
+---
+title: "It's cssnext, not CSSNext"
+footer: false
+---
+
+## Is it cssnext or CSSNext or CSSnext?
+
+The official name is **cssnext**, which should never be capitalized, especially not at the start of a sentence, unless it is being displayed in a location that is customarily all-caps (such as the title of man pages).
+
+### Why ?
+
+```js
+function nameify(string) {
+ return string
+ .replace(" ", "")
+ .toLowerCase()
+}
+
+nameify("CSS Next")
+nameify("CSSNext")
+nameify("CSSnext")
+nameify("CSS next")
+nameify("css next")
+nameify("cssnext")
+
+// all the results above are just the same
+// -> "cssnext" !
+```
diff --git a/docs/content/playground.html b/docs/content/playground.html
new file mode 100644
index 0000000..a647ebc
--- /dev/null
+++ b/docs/content/playground.html
@@ -0,0 +1,70 @@
+---
+template: Simple
+title: Playground
+className: js-cssnext-Playground cssnext-Playground
+footer: false
+scripts:
+ - /playground.js
+---
+
+
+
+
diff --git a/docs/content/setup.md b/docs/content/setup.md
new file mode 100644
index 0000000..485d76f
--- /dev/null
+++ b/docs/content/setup.md
@@ -0,0 +1,130 @@
+---
+title: Install & setup cssnext
+backgroundModifier: darkTeam
+incomplete: true
+---
+
+## Installation
+
+cssnext is available on
+[github](https://github.com/cssnext/cssnext)
+and [npm](https://www.npmjs.org/package/cssnext).
+
+You can install it:
+
+- locally (`--save` or `--save-dev`), to use it through [npm scripts](https://www.npmjs.org/doc/misc/npm-scripts.html) (`npm run`) or via `.node_modules/.bin/cssnext`
+- globally (`-g`), to use it through the [CLI](cli) _(not recommanded)_
+- by using [other plugins & tools](#usage) like [gulp-cssnext](https://github.com/cssnext/gulp-cssnext)
+
+The main package offers
+[a CLI](https://github.com/cssnext/cssnext#cli) and
+[a Node.js/io.js API](https://github.com/cssnext/cssnext#nodejs-api").
+
+
+```
+$ npm install cssnext
+```
+
+
+## Usage
+
+You can use cssnext using [CLI](#cli),
+as [a JavaScript library](#nodejs-api),
+as a [PostCSS](https://github.com/postcss/postcss) plugin
+or through others tools below:
+
+
+[webpack](https://github.com/cssnext/cssnext-loader)
+,
+[gulp](https://github.com/cssnext/gulp-cssnext)
+,
+[grunt](https://github.com/cssnext/grunt-cssnext)
+,
+[brunch](https://github.com/cssnext/cssnext-brunch)
+,
+[broccoli](https://github.com/cssnext/broccoli-cssnext)
+,
+[connect](https://github.com/cssnext/cssnext-connect)
+,
+[duo](https://github.com/cssnext/duo-cssnext)
+or in
+[prepros 5](https://prepros.io/)
+
+
+
+### CLI
+
+cssnext offers a command-line interface.
+Here's how to compile a file and print it to stdout:
+
+```console
+$ cssnext index.css
+```
+
+To create an output file, you can just add a second argument
+
+```console
+$ cssnext index.css output.css
+```
+
+Or use CLI std(in|out) redirection(s)
+
+```console
+$ cat input.css | cssnext > output.css
+```
+
+### CLI options
+
+If you don't care about a certain feature, such as custom media queries, you can omit support for them like so:
+
+```console
+$ cssnext --no-custom-media index.css
+```
+
+To enable source maps for these files, add the `--sourcemap` flag.
+
+**To see all CLI options**
+
+```console
+$ cssnext --help
+```
+
+### Node.js API
+
+cssnext can be used with its own API or as a PostCSS plugin.
+
+#### `var string = cssnext(string, options)`
+
+cssnext accepts 2 arguments: a css string and an object of options.
+
+```js
+var fs = require("fs")
+var cssnext = require("cssnext")
+
+var input = fs.readFileSync("index.css", "utf8")
+
+var output = cssnext(input)
+fs.writeFileSync("dist/index.css", output)
+```
+
+**`/!\` Note: if you are using non inlined sourcemaps, cssnext will return an object: `{css: string, map: sourcemap}`**
+
+See [sourcemap](#sourcemap-default-false) & [map](#map-default-depends-on-sourcemap) options for more informations.
+
+#### `var postcssPlugin = cssnext(options)`
+
+cssnext can be used as a postcss plugin:
+
+```js
+var fs = require("fs")
+var postcss = require("postcss")
+var cssnext = require("cssnext")
+
+var input = fs.readFileSync("index.css", "utf8")
+
+var output = postcss()
+ .use(cssnext())
+ .use(/* your other postcss plugin */)
+ .process(input)
+fs.writeFileSync("dist/index.css", output)
+```
diff --git a/docs/content/usage.md b/docs/content/usage.md
new file mode 100644
index 0000000..08cc3e4
--- /dev/null
+++ b/docs/content/usage.md
@@ -0,0 +1,145 @@
+---
+title: How to use cssnext ?
+incomplete: true
+---
+
+When you have correctly [setup](/setup/) cssnext, you might want to tweak it a
+little bit. You will find below all the available options.
+
+# Options
+
+## `browsers`
+
+(default: [browserslist default](https://github.com/ai/browserslist#readme) - `> 1%, last 2 versions, Firefox ESR, Opera 12.1`)
+
+Allows you to specify your browser scope.
+**This option enables or disables `features` according to [caniuse](http://caniuse.com/) database.**
+This is the exact same option that you might know from Autoprefixer.
+Since cssnext includes Autoprefixer, the option is propagated.
+
+See [Browserslist](https://github.com/ai/browserslist#queries) queries syntax to adjust this option to your needs.
+
+_Note: if you don't specify this option, Browserslist will automatically try to find a `browserslist`
+config file or use its default value._
+
+## `features`
+
+(default: all features)
+
+**You should probably use `browsers` option instead of this one.**
+
+Object containing key of features to enable/disable.
+_Features are enabled by default: no key means feature is enabled_.
+
+```js
+//eg: disable custom properties support
+var output = cssnext(input, {
+ features: {
+ customProperties: false
+ }
+})
+```
+
+Each feature is based on PostCSS plugins & can get its own options.
+To pass options to a feature, you can just pass an object to the feature:
+
+```js
+//eg: preserve custom properties
+var output = cssnext(input, {
+ features: {
+ customProperties: {
+ preserve: true
+ }
+ }
+})
+```
+
+To know all available options, please check corresponding postcss plugin:
+
+- `customProperties` (=> postcss-custom-properties)
+- `calc` (=> postcss-calc)
+- `customMedia` (=> postcss-custom-media)
+- `mediaQueriesRange` (=> postcss-media-minmax)
+- `customSelectors` (=> postcss-custom-selectors)
+- `colorRebeccapurple` (=> postcss-color-rebeccapurple)
+- `colorHwb` (=> postcss-color-hwb)
+- `colorGray` (=> postcss-color-gray)
+- `colorHexAlpha` (=> postcss-color-hex-alpha)
+- `colorFunction` (=> postcss-color-function)
+- `fontVariant` (=> postcss-font-variant)
+- `filter` (=> pleeease-filters)
+- `rem` (=> pixrem)
+- `pseudoElements` (=> postcss-pseudoelements)
+- `pseudoClassMatches` (=> postcss-selector-matches)
+- `pseudoClassNot` (=> postcss-selector-not)
+- `colorRgba` (=> postcss-color-rgba-fallback)
+- `autoprefixer` (=> autoprefixer-core)
+
+_Note: order is important to get everything working correctly._
+
+## `import`
+
+(default: `true`)
+
+Allows you to inline local `@import` files (thanks to [postcss-import](https://github.com/postcss/postcss-import#readme)):
+
+* you can refer to `node_modules` and `web_modules` packages
+* you can omit .css extension
+
+_Note: you can pass [postcss-import options](https://github.com/postcss/postcss-import#readme) directly._
+
+## `url`
+
+(default: `true`)
+
+By default, `url()` are rebased according to `from` (and `to`) option(s). This is convenient especially for `@import`ed files.
+
+_Note: you can pass [postcss-url options](https://github.com/postcss/postcss-url#options) directly in order to inline or have more control over urls._
+
+## `compress`
+
+(default: `false`)
+
+Allows you to compress the output (using [cssnano](https://github.com/ben-eb/cssnano)).
+You can enable minification by passing `true` or by providing an object containing [cssnano options](https://github.com/ben-eb/cssnano#options).
+
+## `sourcemap`
+
+(default: `false`)
+
+This option is a shortcut to enable inlined sourcemap in the output.
+Just pass `true` to get the sourcemap at the end of the output.
+
+- _If you want an accurate sourcemap, please also use the `from` option._
+- _If you want more control on the sourcemap, please use the `map` option instead._
+
+## `map`
+
+(default: _depends on `sourcemap`_)
+
+_(default: `undefined` if `sourcemap` is `false`, `inline` if `sourcemap` it true)_
+
+If you want better control on sourcemap, you are at the right place.
+This is the [postcss `map` option](https://github.com/postcss/postcss#source-map-1), so checkout the related documentation directly.
+
+_If you specify this option, `sourcemap` value will be ignored._
+
+**`/!\` Using this option might change the return value of `cssnext()` (`object` instead of css `string` if map is not inlined. The object will be like {css: "{css string}", map: {sourcemap object}})**
+
+## `from`
+
+(default: `null`)
+
+Source of the file. Required for accurate sourcemap.
+
+```js
+var cssnext = require("cssnext")
+var fs = require("fs")
+
+var source = "./index.css"
+var output = cssnext(
+ fs.readFileSync(source, "utf8"),
+ {from: source}
+)
+fs.writeFileSync("dist/index.css", output)
+```
diff --git a/docs/scripts/build.js b/docs/scripts/build.js
new file mode 100644
index 0000000..0a988ca
--- /dev/null
+++ b/docs/scripts/build.js
@@ -0,0 +1,185 @@
+import path from "path"
+
+import {sync as rm} from "rimraf"
+import async from "async"
+import color from "chalk"
+import nanoLogger from "nano-logger"
+
+import Metalsmith from "metalsmith"
+import markdown from "metalsmith-md"
+import addFilenames from "metalsmith-filenames"
+import url from "metalsmith-url"
+import rename from "metalsmith-rename"
+// import collections from "metalsmith-collections"
+// import rss from "metalsmith-rss"
+import react from "metalsmith-react"
+
+import webpack from "webpack"
+import webpackConfig from "./webpack.config"
+
+// prod
+import copyWithContentHash from "copy-with-content-hash/hash-file"
+
+// dev
+import watch from "metalsmith-watch"
+import devServer from "./webpack-dev-server"
+
+// customize marked
+import "./marked"
+
+import pkg from "../../package"
+
+import variables, {defineGlobalVariables} from "./variables"
+defineGlobalVariables()
+const DEV_SERVER = process.argv.includes("--dev-server")
+
+const log = nanoLogger("./build")
+
+log(color.cyan("- Variables"))
+JSON.stringify(variables, null, 2).split("\n").forEach(l => log(l))
+
+const mdToHtmlReplacement = [/\.md$/, ".html"]
+
+// We clean ./dist by hand mainly for prod, in order to be able to build
+// assets with webpack before metalsmith build.
+// This allows us to get hashes in filename and pass them to the build
+rm(path.join(__dirname, "..", "dist"))
+
+const smith = new Metalsmith(path.join(__dirname, ".."))
+smith
+.source("content")
+.destination("dist")
+// clean is made before
+.clean(false)
+
+// convert markdown
+.use(
+ markdown({
+ baseHref: `${__SERVER_URL__}/`,
+ })
+)
+
+// useful for some homemade plugins
+.use(
+ addFilenames()
+)
+
+// add url meta data with some replacements
+.use(
+ url([
+ mdToHtmlReplacement,
+ [/index\.html?$/, ""],
+ ])
+)
+// wrap .html into react `template:`
+.use(
+ react({
+ pattern: [
+ "**/*.md",
+ "**/*.html",
+ ],
+ templatesPath: "src/layouts",
+ defaultTemplate: "Default",
+ before: "",
+ data: {
+ pkg: pkg,
+ metadata: smith.metadata(),
+ },
+ })
+)
+
+.use(
+ rename([
+ mdToHtmlReplacement,
+ // no .html at the end of urls
+ [/\.html$/, "/index.html"],
+ // ensure we only have index.html, no index/index
+ [/index\/index\.html$/, "index.html"],
+ ])
+)
+
+// for development, we build metalsmith first, then we serve via
+// webpack-dev-server which build assets too (no hashes involved)
+if (DEV_SERVER) {
+ smith.metadata().assets = {
+ scripts: [
+ "/index.js",
+ `http://${__SERVER_HOSTNAME__}:${__LR_SERVER_PORT__}/livereload.js`,
+ ],
+ // css is handled by the js via webpack style-loader
+ }
+ smith
+ .use(
+ watch({
+ log: nanoLogger("watcher"),
+ livereload: __LR_SERVER_PORT__,
+ paths: {
+ "${source}/**/*": true,
+ "src/layouts/**/*": "**/*.md",
+ "src/modules/**/*": "**/*.md",
+ },
+ })
+ )
+ .build((err) => {
+ if (err) {
+ throw err
+ }
+
+ devServer({
+ protocol: __SERVER_PROTOCOL__,
+ host: __SERVER_HOSTNAME__,
+ port: __SERVER_PORT__,
+ open: process.argv.includes("--open"),
+ })
+ })
+}
+
+// for production we build assets first to be able to pass some assets hashes
+// to metalsmith
+else {
+ webpack(webpackConfig, (err, stats) => {
+ if (err) {
+ throw err
+ }
+
+ if (stats.hasErrors()) {
+ stats.compilation.errors.forEach(
+ item => log(...[color.red("Error:"), ...item.message.split("\n")])
+ )
+ throw new Error("webpack build failed with errors")
+ }
+ if (stats.hasWarnings()) {
+ stats.compilation.warnings.forEach(
+ item => log(...[color.yellow("Warning:"), ...item.message.split("\n")])
+ )
+ }
+
+ console.log(color.green("\n✓ Assets build completed"))
+
+ async.map(
+ [
+ "index.js",
+ ...(__PROD__ ? ["index.css"] : []),
+ ],
+ (file, cb) => copyWithContentHash(`./docs/dist/${file}`, false, cb),
+ (asynErr, results) => {
+ if (asynErr) {
+ throw asynErr
+ }
+
+ smith.metadata().assets = {
+ scripts: ["/" + results[0]],
+ ...(__PROD__ ? {stylesheets: ["/" + results[1]]} : {}),
+ }
+ smith
+ .build(buildErr => {
+ if (buildErr) {
+ throw buildErr
+ }
+
+ console.log(color.green("\n✓ Static build completed"))
+ })
+ }
+ )
+ })
+}
diff --git a/docs/scripts/deploy-to-gh-pages.sh b/docs/scripts/deploy-to-gh-pages.sh
new file mode 100755
index 0000000..94950b1
--- /dev/null
+++ b/docs/scripts/deploy-to-gh-pages.sh
@@ -0,0 +1,133 @@
+#!/usr/bin/env bash
+
+set -o errexit #abort if any command fails
+
+# https://github.com/X1011/git-directory-deploy/pull/10
+deploy_directory=${GIT_DEPLOY_DIR:-dist}
+deploy_branch=${GIT_DEPLOY_BRANCH:-gh-pages}
+
+#if no user identity is already set in the current git environment, use this:
+default_username=${GIT_DEPLOY_USERNAME:-deploy.sh}
+default_email=${GIT_DEPLOY_EMAIL:-}
+
+#repository to deploy to. must be readable and writable.
+repo=${GIT_DEPLOY_REPO:-origin}
+
+# Parse arg flags
+while : ; do
+ if [[ $1 = "-v" || $1 = "--verbose" ]]; then
+ verbose=true
+ shift
+ elif [[ $1 = "-s" || $1 = "--setup" ]]; then
+ setup=true
+ shift
+ elif [[ $1 = "-e" || $1 = "--allow-empty" ]]; then
+ allow_empty=true
+ shift
+ else
+ break
+ fi
+done
+
+#echo expanded commands as they are executed (for debugging)
+function enable_expanded_output {
+ if [ $verbose ]; then
+ set -o xtrace
+ set +o verbose
+ fi
+}
+
+#this is used to avoid outputting the repo URL, which may contain a secret token
+function disable_expanded_output {
+ if [ $verbose ]; then
+ set +o xtrace
+ set -o verbose
+ fi
+}
+
+enable_expanded_output
+
+function set_user_id {
+ if [[ -z `git config user.name` ]]; then
+ git config user.name "$default_username"
+ fi
+ if [[ -z `git config user.email` ]]; then
+ git config user.email "$default_email"
+ fi
+}
+
+function restore_head {
+ if [[ $previous_branch = "HEAD" ]]; then
+ #we weren't on any branch before, so just set HEAD back to the commit it was on
+ git update-ref --no-deref HEAD $commit_hash $deploy_branch
+ else
+ git symbolic-ref HEAD refs/heads/$previous_branch
+ fi
+
+ git reset --mixed
+}
+
+if ! git diff --exit-code --quiet --cached; then
+ echo Aborting due to uncommitted changes in the index >&2
+ exit 1
+fi
+
+commit_title=`git log -n 1 --format="%s" HEAD`
+commit_hash=`git log -n 1 --format="%H" HEAD`
+previous_branch=`git rev-parse --abbrev-ref HEAD`
+
+if [ $setup ]; then
+ mkdir -p "$deploy_directory"
+ git --work-tree "$deploy_directory" checkout --orphan $deploy_branch
+ git --work-tree "$deploy_directory" rm -r "*"
+ git --work-tree "$deploy_directory" add --all
+ git --work-tree "$deploy_directory" commit -m "initial publish"$'\n\n'"generated from commit $commit_hash"
+ git push $repo $deploy_branch
+ restore_head
+ exit
+fi
+
+if [ ! -d "$deploy_directory" ]; then
+ echo "Deploy directory '$deploy_directory' does not exist. Aborting." >&2
+ exit 1
+fi
+
+if [[ -z `ls -A "$deploy_directory" 2> /dev/null` && -z $allow_empty ]]; then
+ echo "Deploy directory '$deploy_directory' is empty. Aborting. If you're sure you want to deploy an empty tree, use the -e flag." >&2
+ exit 1
+fi
+
+disable_expanded_output
+git fetch --force $repo $deploy_branch:$deploy_branch
+enable_expanded_output
+
+#make deploy_branch the current branch
+git symbolic-ref HEAD refs/heads/$deploy_branch
+
+#put the previously committed contents of deploy_branch branch into the index
+git --work-tree "$deploy_directory" reset --mixed --quiet
+
+git --work-tree "$deploy_directory" add --all
+
+set +o errexit
+diff=$(git --work-tree "$deploy_directory" diff --exit-code --quiet HEAD)$?
+set -o errexit
+case $diff in
+ 0) echo No changes to files in $deploy_directory. Skipping commit.;;
+ 1)
+ set_user_id
+ git --work-tree "$deploy_directory" commit -m \
+ "publish: $commit_title"$'\n\n'"generated from commit $commit_hash"
+
+ disable_expanded_output
+ #--quiet is important here to avoid outputting the repo URL, which may contain a secret token
+ git push --quiet $repo $deploy_branch
+ enable_expanded_output
+ ;;
+ *)
+ echo git diff exited with code $diff. Aborting. Staying on branch $deploy_branch so you can debug. To switch back to master, use: git symbolic-ref HEAD refs/heads/master && git reset --mixed >&2
+ exit $diff
+ ;;
+esac
+
+restore_head
diff --git a/docs/scripts/marked.js b/docs/scripts/marked.js
new file mode 100644
index 0000000..e768e9c
--- /dev/null
+++ b/docs/scripts/marked.js
@@ -0,0 +1,145 @@
+/* eslint no-script-url: 0 */
+import path from "path"
+
+import marked from "marked"
+import hljs from "highlight.js"
+
+// https://github.com/chjj/marked/blob/master/lib/marked.js#L1096
+function unescape(html) {
+ return html.replace(/&([#\w]+);/g, function(_, n) {
+ n = n.toLowerCase()
+ if (n === "colon") {
+ return ":"
+ }
+ if (n.charAt(0) === "#") {
+ return n.charAt(1) === "x"
+ ? String.fromCharCode(parseInt(n.substring(2), 16))
+ : String.fromCharCode(+n.substring(1))
+ }
+ return ""
+ })
+}
+
+function rebaseUrl(baseHref, currentPath, uri) {
+ // don't touch non relative uri
+ if (
+ // skip absolute url
+ uri.indexOf("/") === 0 ||
+ // datauris
+ uri.indexOf("data:") === 0 ||
+ // internal links
+ // uri.indexOf("#") === 0 ||
+ // protocol based
+ /^[a-z]+:\/\//.test(uri)
+ ) {
+ return uri
+ }
+ else {
+ // make it absolute
+ return baseHref + path.normalize(path.join(currentPath, uri))
+ }
+}
+
+const renderer = new marked.Renderer()
+const headingIds = {}
+renderer.heading = function(text, level, raw) {
+ const escaped = raw
+ // url in lower case are cool
+ .toLowerCase()
+
+ // dashify
+ // .replace(/[^\w]+/g, "-")
+ .replace(/\W+/g, "-")
+ .replace(/^-+/, "")
+ .replace(/-+$/, "")
+
+ const key = this.options.__metalsmith.__filename + "#" + escaped
+ if (!headingIds[key]) {
+ headingIds[key] = 0
+ }
+ headingIds[key]++
+ const id = escaped + (
+ headingIds[key] > 1 ? `-${headingIds[key]}` : ""
+ )
+
+ return (
+ `
+ #
+ ${text}
+ `
+ )
+}
+
+renderer.link = function(href, title, text) {
+
+ // DON'T PLAY WITH US OK ?
+ // (this came from original marked source code and should remain I think)
+ if (this.options.sanitize) {
+ try {
+ var prot = decodeURIComponent(unescape(href))
+ .replace(/[^\w:]/g, "")
+ .toLowerCase()
+ }
+ catch (e) {
+ return ""
+ }
+
+ if (
+ prot.indexOf("javascript:") === 0 ||
+ prot.indexOf("vbscript:") === 0
+ ) {
+ return ""
+ }
+ }
+
+ return `${text} `
+}
+
+renderer.image = function(href, title, text) {
+ return (
+ ` " : ">"}`
+ )
+}
+
+marked.setOptions({
+
+ renderer: renderer,
+
+ highlight: (code, language) => {
+ code = code.trim()
+
+ // language is recognized by highlight.js
+ if (hljs.getLanguage(language)) {
+ return hljs.highlight(language, code).value
+ }
+
+ // fallback to auto
+ return hljs.highlightAuto(code).value
+ },
+
+ gfm: true,
+ tables: true,
+ smartypants: true,
+})
+
+export default marked
diff --git a/docs/scripts/variables.js b/docs/scripts/variables.js
new file mode 100644
index 0000000..58096f8
--- /dev/null
+++ b/docs/scripts/variables.js
@@ -0,0 +1,39 @@
+const __PROD__ = process.argv.includes("--production")
+
+const variables = {
+ __DEV__: !__PROD__,
+ __PROD__,
+ ...__PROD__ && {
+ "process.env": {
+ NODE_ENV: JSON.stringify("production"),
+ },
+ },
+ __SERVER_PROTOCOL__: "http://",
+ ...(
+ __PROD__ ?
+ {
+ __SERVER_HOSTNAME__: "cssnext.io",
+ __SERVER_HOST__: "cssnext.io",
+ "process.env": {
+ NODE_ENV: JSON.stringify("production"),
+ },
+ }
+ :
+ {
+ __SERVER_HOSTNAME__: "0.0.0.0",
+ __SERVER_PORT__: 1985,
+ __SERVER_HOST__: "0.0.0.0:1985",
+ __LR_SERVER_PORT__: 1986,
+ }
+ ),
+}
+
+variables.__SERVER_URL__ =
+ `${variables.__SERVER_PROTOCOL__}${variables.__SERVER_HOST__}`
+
+export default variables
+
+// define some global var like __DEV__
+export function defineGlobalVariables() {
+ Object.keys(variables).forEach((k) => global[k] = variables[k])
+}
diff --git a/docs/scripts/webpack-dev-server.js b/docs/scripts/webpack-dev-server.js
new file mode 100644
index 0000000..456e2a1
--- /dev/null
+++ b/docs/scripts/webpack-dev-server.js
@@ -0,0 +1,79 @@
+import webpack from "webpack"
+import webpackNanoLogs from "webpack-nano-logs"
+import WebpackDevServer from "webpack-dev-server"
+import opn from "opn"
+import logger from "nano-logger"
+
+import config from "./webpack.config"
+
+const log = logger("webpack-dev-server")
+
+export default (options) => {
+ options = {
+ protocol: "http://",
+ host: "0.0.0.0",
+ port: 3000,
+ open: true,
+ ...(options || {}),
+ }
+
+ const serverUrl = `${options.protocol}${options.host}:${options.port}`
+
+ const devEntries = [
+ `webpack-dev-server/client?${serverUrl}`,
+ `webpack/hot/only-dev-server`,
+ ]
+
+ const devConfig = {
+ ...config,
+ debug: true,
+ watch: true,
+ colors: true,
+ progress: true,
+ entry: {
+ // add devEntries
+ ...Object.keys(config.entry)
+ .reduce(
+ (acc, key) => {
+ // entries with name that start with "test" do not need extra stuff
+ acc[key] = key.indexOf("tests") === 0 ?
+ config.entry[key] :
+ [
+ ...devEntries,
+ ...config.entry[key],
+ ]
+ return acc
+ },
+ {}
+ ),
+ },
+ plugins: [
+ ...(config.plugins || []),
+ new webpack.NoErrorsPlugin(),
+ new webpack.HotModuleReplacementPlugin(),
+ webpackNanoLogs,
+ ],
+ eslint: {
+ ...config.eslint,
+ emitWarning: true,
+ },
+ }
+
+ return new WebpackDevServer(
+ webpack(devConfig),
+ {
+ https: options.protocol === "https://",
+ contentBase: config.output.path,
+ hot: true,
+ stats: {
+ colors: true,
+ },
+ noInfo: true,
+ })
+ .listen(options.port, options.host, () => {
+ log(`Dev server started on ${serverUrl}`)
+ if (options.open) {
+ opn(`${serverUrl}`)
+ }
+ })
+}
diff --git a/docs/scripts/webpack.config.js b/docs/scripts/webpack.config.js
new file mode 100644
index 0000000..ec68999
--- /dev/null
+++ b/docs/scripts/webpack.config.js
@@ -0,0 +1,97 @@
+import path from "path"
+
+import webpack from "webpack"
+import ExtractTextPlugin from "extract-text-webpack-plugin"
+
+import variables, {defineGlobalVariables} from "./variables"
+defineGlobalVariables()
+
+const production = __PROD__ || process.argv.includes("--production")
+
+var config = {
+ entry: {
+ index: [
+ "./docs/src/index",
+ ],
+ playground: [
+ "./docs/src/modules/playground/index",
+ ],
+ },
+
+ output: {
+ path: path.join(__dirname, "..", "dist"),
+ filename: "[name].js",
+ publicPath: "/",
+ },
+
+ resolve: {
+ extensions: [
+ "",
+ ".js",
+ ".json",
+ ".css",
+ ],
+
+ alias: {
+ "caniuse-db": path.resolve(__dirname, "../../node_modules/caniuse-db"),
+ },
+ },
+
+ module: {
+ // ! \\ note that loaders are executed from bottom to top !
+ loaders: [
+ {
+ test: /\.(jsx?|es)$/,
+ loaders: [
+ "babel?" + JSON.stringify({
+ stage: 0,
+ }),
+ "eslint",
+ ],
+ exclude: /node_modules/,
+ },
+ {
+ test: /\.json$/,
+ loaders: [
+ "json",
+ ],
+ },
+ {
+ test: /\.css$/,
+ loader: ExtractTextPlugin.extract(
+ "style-loader",
+ "css-loader!cssnext-loader"
+ ),
+ },
+ {
+ test: /\.(ico|jpe?g|png|gif|svg)$/,
+ loaders: [
+ "file?name=[path][name].[ext]&context=./docs/src",
+ ],
+ },
+ ],
+ },
+
+ plugins: [
+ new webpack.DefinePlugin(variables),
+ new ExtractTextPlugin("[name].css", {disable: !production}),
+ ...(production ?
+ [
+ new webpack.optimize.UglifyJsPlugin({
+ compress: {
+ warnings: false,
+ },
+ }),
+ ] :
+ []
+ ),
+ ],
+
+ node: {
+ // https://github.com/webpack/webpack/issues/451
+ // run tape test with webpack
+ fs: "empty",
+ },
+}
+
+export default config
diff --git a/docs/src/assets/cssnext.svg b/docs/src/assets/cssnext.svg
new file mode 100644
index 0000000..b5202b7
--- /dev/null
+++ b/docs/src/assets/cssnext.svg
@@ -0,0 +1,164 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/src/assets/delorean-back.jpg b/docs/src/assets/delorean-back.jpg
new file mode 100644
index 0000000..9da9033
Binary files /dev/null and b/docs/src/assets/delorean-back.jpg differ
diff --git a/docs/src/assets/delorean-front.jpg b/docs/src/assets/delorean-front.jpg
new file mode 100644
index 0000000..ecd6636
Binary files /dev/null and b/docs/src/assets/delorean-front.jpg differ
diff --git a/docs/src/assets/engine.jpg b/docs/src/assets/engine.jpg
new file mode 100644
index 0000000..fb4a530
Binary files /dev/null and b/docs/src/assets/engine.jpg differ
diff --git a/docs/src/assets/fast.jpg b/docs/src/assets/fast.jpg
new file mode 100644
index 0000000..b707eb3
Binary files /dev/null and b/docs/src/assets/fast.jpg differ
diff --git a/docs/src/assets/flux.jpg b/docs/src/assets/flux.jpg
new file mode 100644
index 0000000..0510614
Binary files /dev/null and b/docs/src/assets/flux.jpg differ
diff --git a/docs/src/assets/github.svg b/docs/src/assets/github.svg
new file mode 100644
index 0000000..193277b
--- /dev/null
+++ b/docs/src/assets/github.svg
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/src/assets/road.jpg b/docs/src/assets/road.jpg
new file mode 100644
index 0000000..ce250e8
Binary files /dev/null and b/docs/src/assets/road.jpg differ
diff --git a/docs/src/assets/team.jpg b/docs/src/assets/team.jpg
new file mode 100644
index 0000000..bdaf191
Binary files /dev/null and b/docs/src/assets/team.jpg differ
diff --git a/docs/src/assets/twitter.svg b/docs/src/assets/twitter.svg
new file mode 100644
index 0000000..acc81b7
--- /dev/null
+++ b/docs/src/assets/twitter.svg
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/src/index.css b/docs/src/index.css
new file mode 100644
index 0000000..8690692
--- /dev/null
+++ b/docs/src/index.css
@@ -0,0 +1,335 @@
+/* base */
+@import "normalize.css/normalize.css";
+@import "cssrecipes-defaults";
+
+/* grid */
+@import "cssrecipes-custom-media-queries";
+@import "cssrecipes-grid";
+@import "cssrecipes-utils";
+
+@import "cssrecipes-vertical-rhythm";
+@import "cssrecipes-vertical-rhythm/lib/ratio/minor-third.css";
+
+@import "./modules/Header";
+@import "./modules/Footer";
+@import "./modules/SVGIcon";
+@import "./modules/playground";
+
+:root {
+ --cssnext-Color-blue: #318edf;
+ --cssnext-Color-purple: #8053ca;
+ --cssnext-Color-green: #46C340;
+}
+
+/**
+ * generic typography
+ */
+
+html {
+ /*height: 100%;*/
+ margin: 0;
+ padding: 0;
+
+ background: #f1f1f1
+}
+
+body {
+ /*min-height: 100%;*/
+ display: flex;
+ flex-direction: column;
+
+ min-height: 100vh;
+ margin: 0;
+ padding: 0;
+
+ font-family: Avenir Next, Calibri, Calibri Light, Segoe UI, Segoe UI Light, Myanmar Text, sans-serif;
+}
+
+::selection {
+ color: #fff;
+ background: #428BCA;
+}
+
+a,
+a:visited {
+ color: inherit;
+ position: relative;
+ text-decoration: none;
+}
+
+ a::before {
+ content: "";
+ position: absolute;
+ height: 1px;
+ left: 0;
+ right: 0;
+ bottom: 0;
+
+ background: currentColor;
+ opacity: .25;
+
+ transform: scaleX(.85) translateY(.085rem);
+ transition: .2s;
+ }
+ a:hover::before,
+ a:focus::before {
+ opacity: 0.75;
+ transform: scaleX(.95);
+ }
+ a:active::before {
+ opacity: .2;
+ }
+
+h1,
+h2,
+h3 {
+ font-weight: 300;
+}
+
+/**
+ * customise recipes
+ */
+
+.r-Grid {
+ width: auto;
+ margin: 0 auto;
+ padding: 0 1rem;
+}
+ @media (--r-minM) {
+ .r-Grid {
+ max-width: 65rem;
+ padding: 0;
+ }
+ }
+ /*@media (--r-minM) { .r-Grid { width: 70rem } }*/
+ /*@media (--r-minXL) { .r-Grid { width: 70rem } }*/
+
+
+/**
+ * cssnext stuff
+ */
+
+.cssnext-Icon {
+ display: inline-block;
+
+ width: 1.2em; /* required for IE */
+ height: 1.2em;
+ line-height: 1;
+ vertical-align: middle;
+
+ color: inherit;
+ fill: currentColor;
+
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ transform: translate3d(0,0,0); /* fix webkit/blink poor rendering issues */
+}
+
+:root {
+ --cssnext-Header-height: calc(var(--r-lineHeight) * 2.5);
+}
+
+.r-VerticalRhythm {font-size: .8333rem}
+@media (--r-minM) {
+ .r-VerticalRhythm {font-size: 1rem}
+}
+
+@media (--r-minM) {
+ .cssnext-Body {padding-top: var(--cssnext-Header-height)}
+}
+
+
+
+.cssnext-Center { text-align: center }
+
+.cssnext-Light {
+ color: #fff;
+ font-weight: 300;
+}
+
+ .cssnext-Light a { color: #fff !important }
+ .cssnext-Light a::before { background: #f1f1f1 }
+
+.cssnext-Jumbotron {
+ overflow: auto;
+ padding: 6rem 0;
+}
+
+ .cssnext-Jumbotron + :not(.cssnext-Jumbotron) { margin-top: var(--r-lineHeight) }
+
+ .cssnext-Jumbotron--default {
+ background: linear-gradient(160deg,
+ color(var(--cssnext-Color-purple) l(-5%) a(.9)),
+ color(var(--cssnext-Color-blue) a(.9))
+ ),
+ url("assets/delorean-back.jpg") no-repeat 50% 50%/cover
+ ;
+ }
+
+ .cssnext-Jumbotron--whiteRoad {
+ background: linear-gradient(160deg,
+ color(var(--cssnext-Color-purple) l(90%) a(.9)),
+ color(var(--cssnext-Color-blue) l(90%) a(.9))
+ ),
+ url("assets/road.jpg") no-repeat 50% 10%/cover
+ ;
+ }
+ .cssnext-Jumbotron--darkRoad {
+ background: linear-gradient(160deg,
+ color(var(--cssnext-Color-blue) a(.9)),
+ color(var(--cssnext-Color-purple) a(.9))
+ ),
+ url("assets/road.jpg") no-repeat 50% 10%/cover
+ ;
+ }
+ .cssnext-Jumbotron--darkDeloreanFront {
+ background: linear-gradient(160deg,
+ color(var(--cssnext-Color-purple) l(-10%) a(.95)),
+ color(var(--cssnext-Color-blue) l(-5%) a(.9))
+ ),
+ url("assets/delorean-front.jpg") no-repeat 50% 70%/cover
+ ;
+ }
+ .cssnext-Jumbotron--lightFast {
+ background: linear-gradient(160deg,
+ color(var(--cssnext-Color-blue) l(90%) a(.9)),
+ color(var(--cssnext-Color-purple) l(90%) a(.9))
+ ),
+ url("assets/fast.jpg") no-repeat 50% 50%/cover
+ ;
+ }
+ .cssnext-Jumbotron--darkFlux {
+ background: linear-gradient(160deg,
+ color(var(--cssnext-Color-blue) a(.7)),
+ color(var(--cssnext-Color-purple) a(.9))
+ ),
+ url("assets/flux.jpg") no-repeat 50% 50%/cover
+ ;
+ }
+ .cssnext-Jumbotron--lightTeam {
+ background: linear-gradient(160deg,
+ color(var(--cssnext-Color-purple) l(90%) a(.95)),
+ color(var(--cssnext-Color-blue) l(90%) a(.95))
+ ),
+ url("assets/team.jpg") no-repeat 50% 50%/cover
+ ;
+ }
+ .cssnext-Jumbotron--darkTeam {
+ background: linear-gradient(160deg,
+ color(var(--cssnext-Color-blue) a(.95)),
+ color(var(--cssnext-Color-purple) a(.95))
+ ),
+ url("assets/team.jpg") no-repeat 50% 50%/cover
+ ;
+ }
+ .cssnext-Jumbotron--cssrecipes {
+ background: linear-gradient(160deg,
+ color(var(--cssnext-Color-blue) a(.85)),
+ color(var(--cssnext-Color-green) a(.85))
+ ),
+ url("assets/engine.jpg") no-repeat 50% 50%/cover
+ ;
+ }
+
+ .cssnext-Jumbotron-title {
+ display: block;
+ font-size: calc(var(--r-h1-fontSize) * 1.5);
+ line-height: calc(var(--r-h1-lineHeight) * 1.5);
+ font-weight: 400;
+ margin: 6rem auto;
+ text-shadow: 0 .1rem .1rem rgba(0, 0, 0, 0.4);
+ }
+
+ .cssnext-Jumbotron-title--smaller {
+ font-size: var(--r-h1-fontSize);
+ line-height: var(--r-h1-lineHeight);
+ }
+
+.cssnext-List {
+ margin: 0 4rem var(--r-lineHeight) !important;
+ /*margin-right: 0 !important ;*/
+}
+
+
+.cssnext-FeaturesList {
+}
+
+ .cssnext-FeaturesList li::before {
+ content: "〉 ";
+ padding-right: .4rem;
+ opacity: .4;
+ font-size: var(--r-small-fontSize);
+ }
+
+ .cssnext-FeaturesList-small {
+ opacity: .4;
+ font-size: var(--r-small-fontSize);
+ }
+
+.cssnext-Section {
+ margin: 0 auto var(--r-lineHeight);
+ /*max-width: 50rem;*/
+}
+
+ .cssnext-Section-title { text-align: center }
+
+ .cssnext-Section-content {
+
+ }
+
+ .cssnext-Section-highlight {
+ display: block;
+ text-align: center;
+ margin: var(--r-lineHeight);
+ }
+
+ .cssnext-Section-link {
+ text-align: center;
+ font-size: var(--r-small-fontSize);
+ color: var(--cssnext-Color-blue);
+ }
+
+ .cssnext-Section-link:hover { color: var(--cssnext-Color-purple) }
+
+.cssnext-Tools {
+ text-align: center;
+ font-size: var(--r-h3-fontSize);
+ font-weight: 300;
+}
+
+.cssnext-INeedSpace {
+ margin-top: calc(var(--r-lineHeight) * 2);
+ margin-bottom: calc(var(--r-lineHeight) * 2);
+}
+
+
+.cssnext-Callout {
+ font-size: var(--r-small-fontSize);
+ padding: 1rem 1rem 0;
+ margin-bottom: var(--r-lineHeight);
+ border: 1px solid color(#000 a(.1));
+ border-left-width: .2rem;
+ border-radius: 3px;
+}
+
+ .cssnext-Callout--danger { border-left-color: #d9534f; }
+ .cssnext-Callout--danger .cssnext-Callout-title { color: #ce4844; }
+
+ .cssnext-Callout--warning { border-left-color: #f0ad4e; }
+ .cssnext-Callout--warning .cssnext-Callout-title { color: #aa6708; }
+
+ .cssnext-Callout--info { border-left-color: var(--cssnext-Color-blue); }
+ .cssnext-Callout--info .cssnext-Callout-title { color: color(var(--cssnext-Color-blue) b(+20%)); }
+
+pre {
+ margin: 1rem 0;
+ padding: 1rem;
+
+ font-size: var(--r-small-fontSize);
+ font-weight: 400;
+
+ color: color(var(--cssnext-Color-blue) l(-10%));
+ border: 1px solid #DDD;
+ border-radius: 0.3em;
+ background: color(#fafafa a(.6));
+}
diff --git a/docs/src/index.js b/docs/src/index.js
new file mode 100644
index 0000000..feff3ff
--- /dev/null
+++ b/docs/src/index.js
@@ -0,0 +1,6 @@
+// import "./modules/polyfills"
+import "./index.css"
+
+if (console && console.info) {
+ console.info("cssnext")
+}
diff --git a/docs/src/layouts/Default.js b/docs/src/layouts/Default.js
new file mode 100644
index 0000000..9fffc97
--- /dev/null
+++ b/docs/src/layouts/Default.js
@@ -0,0 +1,135 @@
+import React, {Component, PropTypes} from "react"
+import cx from "classnames"
+
+import dashify from "../modules/dashify"
+
+import Html from "../modules/Html"
+import Head from "../modules/Head"
+import Body from "../modules/Body"
+
+export default class Default extends Component {
+
+ static propTypes = {
+ pkg: PropTypes.object.isRequired,
+ metadata: PropTypes.object.isRequired,
+ // collections: PropTypes.object.isRequired,
+ file: PropTypes.object.isRequired,
+ }
+
+ static childContextTypes = {
+ pkg: PropTypes.object.isRequired,
+ // collections: PropTypes.object.isRequired,
+ file: PropTypes.object.isRequired,
+ }
+
+ getChildContext() {
+ return {
+ pkg: this.props.pkg,
+ // collections: this.props.collections,
+ file: this.props.file,
+ }
+ }
+
+ render() {
+ const {
+ file,
+ } = this.props
+ const footer = file.footer === undefined ? true : file.footer
+
+ if (!file.title) {
+ console.log(`${file.filename} doesn't have a title`)
+ }
+ return (
+
+
+
+
+
+ {
+ file.incomplete &&
+
+
+
Incomplete
+
+ {
+ "This documentation is still a work in progress. "
+ }
+
+
+ Pull requests
+
+ {
+ " expanding on existing or adding additional content " +
+ " are "
+ }
+ extremely appreciated.
+
+
+
+ }
+
+
+
+ {
+ footer &&
+
+ }
+
+
+
+ )
+ }
+}
diff --git a/docs/src/layouts/Simple.js b/docs/src/layouts/Simple.js
new file mode 100644
index 0000000..30af7b9
--- /dev/null
+++ b/docs/src/layouts/Simple.js
@@ -0,0 +1,60 @@
+import React, {Component, PropTypes} from "react"
+
+import Html from "../modules/Html"
+import Head from "../modules/Head"
+import Body from "../modules/Body"
+
+export default class Simple extends Component {
+
+ static propTypes = {
+ pkg: PropTypes.object.isRequired,
+ metadata: PropTypes.object.isRequired,
+ // collections: PropTypes.object.isRequired,
+ file: PropTypes.object.isRequired,
+ }
+
+ static childContextTypes = {
+ pkg: PropTypes.object.isRequired,
+ // collections: PropTypes.object.isRequired,
+ file: PropTypes.object.isRequired,
+ }
+
+ getChildContext() {
+ return {
+ pkg: this.props.pkg,
+ // collections: this.props.collections,
+ file: this.props.file,
+ }
+ }
+
+ render() {
+ const {
+ file,
+ } = this.props
+ const footer = file.footer === undefined ? true : file.footer
+
+ if (!file.title) {
+ console.log(`${file.filename} doesn't have a title`)
+ }
+ return (
+
+
+
+
+
+
+ )
+ }
+}
diff --git a/docs/src/modules/Analytics/index.js b/docs/src/modules/Analytics/index.js
new file mode 100644
index 0000000..73bdee8
--- /dev/null
+++ b/docs/src/modules/Analytics/index.js
@@ -0,0 +1,25 @@
+import React, {Component} from "react"
+
+import isogram from "isogram"
+
+export default class Analytics extends Component {
+
+ render() {
+ return (
+
+ )
+ }
+}
diff --git a/docs/src/modules/Body/index.js b/docs/src/modules/Body/index.js
new file mode 100644
index 0000000..5de0c53
--- /dev/null
+++ b/docs/src/modules/Body/index.js
@@ -0,0 +1,47 @@
+import React, {Component, PropTypes} from "react"
+
+import Header from "../Header"
+import Footer from "../Footer"
+import Analytics from "../Analytics"
+
+export default class Body extends Component {
+
+ static defaultProps = {
+ scripts: [],
+ footer: true,
+ }
+
+ static contextTypes = {
+ pkg: PropTypes.object.isRequired,
+ file: PropTypes.object.isRequired,
+ }
+
+ static propTypes = {
+ children: PropTypes.oneOfType([
+ PropTypes.array,
+ PropTypes.object,
+ ]).isRequired,
+ scripts: PropTypes.array,
+ footer: PropTypes.bool,
+ }
+
+ render() {
+ return (
+
+
+
+
+ {this.props.children}
+
+
+ {
+ this.props.scripts.map(script => (
+
+ ))
+ }
+
+
+
+ )
+ }
+}
diff --git a/docs/src/modules/Footer/index.css b/docs/src/modules/Footer/index.css
new file mode 100644
index 0000000..bfcce0e
--- /dev/null
+++ b/docs/src/modules/Footer/index.css
@@ -0,0 +1,6 @@
+.cssnext-Footer {
+ font-size: var(--r-small-fontSize);
+ text-align: center;
+ padding: calc(var(--r-lineHeight) * 2) 0 var(--r-lineHeight);
+ border-top: 1px solid color(#000 a(.1));
+}
diff --git a/docs/src/modules/Footer/index.js b/docs/src/modules/Footer/index.js
new file mode 100644
index 0000000..d2dbac4
--- /dev/null
+++ b/docs/src/modules/Footer/index.js
@@ -0,0 +1,62 @@
+import React, {Component, PropTypes} from "react"
+
+import SVGIcon from "../SVGIcon"
+import requireRaw from "../requireRaw"
+
+export default class Footer extends Component {
+
+ static contextTypes = {
+ file: PropTypes.object.isRequired,
+ }
+
+ static defaultProps = {
+ plagryound: true,
+ }
+
+ static propTypes = {
+ plagyround: PropTypes.bool,
+ }
+
+ render() {
+ return (
+
+ )
+ }
+}
diff --git a/docs/src/modules/Head/index.js b/docs/src/modules/Head/index.js
new file mode 100644
index 0000000..b1c1ed2
--- /dev/null
+++ b/docs/src/modules/Head/index.js
@@ -0,0 +1,43 @@
+import React, {Component, PropTypes} from "react"
+
+export default class Head extends Component {
+
+ static defaultProps = {
+ stylesheets: [],
+ }
+
+ static propTypes = {
+ title: PropTypes.string.isRequired,
+ children: PropTypes.oneOfType([
+ PropTypes.array,
+ PropTypes.object,
+ ]),
+ stylesheets: PropTypes.array,
+ }
+
+ render() {
+ return (
+
+
+
+
+ {this.props.title}
+ {
+ this.props.stylesheets.map(stylesheet => (
+
+ ))
+ }
+
+ {this.props.children}
+
+ )
+ }
+}
diff --git a/docs/src/modules/Header/index.css b/docs/src/modules/Header/index.css
new file mode 100644
index 0000000..11239f9
--- /dev/null
+++ b/docs/src/modules/Header/index.css
@@ -0,0 +1,102 @@
+.cssnext-Header {
+ line-height: var(--cssnext-Header-height);
+}
+
+@media (--r-minM) {
+ .cssnext-Header {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ background: color(#fff a(.99));
+ z-index: 1; /* on top of position relative */
+ box-shadow: 0 0 .5rem color(#000 a(.1));
+ }
+}
+
+ .cssnext-Header-logo {
+ display: block;
+ text-align: center;
+ }
+ @media (--r-minM) {
+ .cssnext-Header-logo {
+ display: inline-block;
+ margin: 0 1.5rem 0 0 !important;
+ }
+ }
+
+ /* remvove default link effect */
+ .cssnext-Header-logo::before {display: none}
+
+ .cssnext-Header-logo-img {
+ height: var(--r-lineHeight);
+ width: auto;
+ vertical-align: middle;
+ display: inline-block;
+ }
+
+ .cssnext-Header-logo-img-svg {
+ display: block;
+ }
+
+ .cssnext-Header-version {
+ font-size: .725rem;
+ padding: 0 1rem;
+ transition: .2s;
+ }
+
+ @media (--r-minM) {
+ .cssnext-Header-version {
+ position: absolute;
+ bottom: -1.2rem;
+ right: 4rem;
+
+ line-height: 1;
+ color: #fff;
+ opacity: .2;
+ }
+
+
+ .cssnext-Header-logo:hover .cssnext-Header-version {
+ opacity: .6;
+ }
+ }
+
+ .cssnext-Header-nav {
+
+ }
+
+ @media (--r-minM) {
+ .cssnext-Header-nav {
+ text-align: right
+ }
+ }
+
+ .cssnext-Header-nav-item {
+ padding: 0 1rem;
+ display: inline-block;
+ height: var(--cssnext-Header-height);
+ }
+
+ /* adjust link underline position */
+ .cssnext-Header-nav-item::before {
+ bottom: calc((var(--cssnext-Header-height) / 2) - 1rem);
+ transform: scaleX(0.50) translateY(0.1rem)
+ }
+
+ .cssnext-Header-nav-item:hover::before,
+ .cssnext-Header-nav-item:focus::before {
+ transform: scaleX(.65);
+ }
+
+ .cssnext-Header-nav-item--active,
+ .cssnext-Header-nav-item--active:visited {
+ color: #fff;
+ background:
+ linear-gradient(
+ 160deg,
+ color(var(--cssnext-Color-blue) a(.9)),
+ color(var(--cssnext-Color-purple) a(.9))
+ )
+ ;
+ }
diff --git a/docs/src/modules/Header/index.js b/docs/src/modules/Header/index.js
new file mode 100644
index 0000000..16bb4d1
--- /dev/null
+++ b/docs/src/modules/Header/index.js
@@ -0,0 +1,65 @@
+import React, {Component, PropTypes} from "react"
+
+import SVGIcon from "../SVGIcon"
+import requireRaw from "../requireRaw"
+
+import Link from "./link"
+
+export default class Header extends Component {
+
+ static contextTypes = {
+ pkg: PropTypes.object.isRequired,
+ file: PropTypes.object.isRequired,
+ }
+
+ render() {
+ return (
+
+
+
+
+
+
+ Support
+
+
+ GitHub
+
+
+ Twitter
+
+
+
+
+
+ )
+ }
+}
diff --git a/docs/src/modules/Header/link.js b/docs/src/modules/Header/link.js
new file mode 100644
index 0000000..a64bef3
--- /dev/null
+++ b/docs/src/modules/Header/link.js
@@ -0,0 +1,44 @@
+import React, {Component, PropTypes} from "react"
+import cx from "classnames"
+
+export default class HeaderLink extends Component {
+
+ static contextTypes = {
+ file: PropTypes.object.isRequired,
+ }
+
+ static propTypes = {
+ href: PropTypes.string.isRequired,
+ className: PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.object,
+ PropTypes.array,
+ ]),
+ children: PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.array,
+ PropTypes.object,
+ ]).isRequired,
+ }
+
+ render() {
+ const currentUrl = "/" + this.context.file.url
+
+ return (
+
+ {this.props.children}
+
+ )
+ }
+}
diff --git a/docs/src/modules/Html/index.js b/docs/src/modules/Html/index.js
new file mode 100644
index 0000000..897a500
--- /dev/null
+++ b/docs/src/modules/Html/index.js
@@ -0,0 +1,16 @@
+import React, {Component, PropTypes} from "react"
+
+export default class Html extends Component {
+
+ static propTypes = {
+ children: PropTypes.array.isRequired,
+ }
+
+ render() {
+ return (
+
+ {this.props.children}
+
+ )
+ }
+}
diff --git a/docs/src/modules/SVGIcon/__tests__/index.js b/docs/src/modules/SVGIcon/__tests__/index.js
new file mode 100644
index 0000000..44815f1
--- /dev/null
+++ b/docs/src/modules/SVGIcon/__tests__/index.js
@@ -0,0 +1,105 @@
+import tape from "tape-catch"
+import React, {Component} from "react"
+import SVGIcon from ".."
+
+tape("SVGIcon", (test) => {
+
+ test.equal(
+ React.renderToStaticMarkup(
+
+ ),
+ ` `,
+ "passes & merges className"
+ )
+
+ test.equal(
+ React.renderToStaticMarkup(
+
+ ),
+ `
`,
+ "parent component can be chosen by tagName"
+ )
+
+ class TestComponent extends Component {
+ render() {
+ return (
+
+ )
+ }
+ }
+
+ test.equal(
+ React.renderToStaticMarkup(
+
+ ),
+ ` ` +
+ `
`,
+ "parent composite component can be chosen"
+ )
+
+ const svgPiece = `width="24" height="16px"> `
+ const SVGIconStart = `` +
+ `
+ ),
+ `${SVGIconStart} ${svgPiece} `,
+ "doesn't cleanup the svg by default"
+ )
+
+ test.equal(
+ React.renderToStaticMarkup(
+
+ ),
+ `${SVGIconCleanedStart}> `,
+ "can cleanup the svg"
+ )
+
+ test.equal(
+ React.renderToStaticMarkup(
+
+ ),
+ `${SVGIconCleanedStart}> ` +
+ ``,
+ "cleanup the svg with exceptions"
+ )
+
+ test.equal(
+ React.renderToStaticMarkup(
+ `} width="1rem" />
+ ),
+ `${SVGIconStart} style="width: 1rem;height: 1rem;"> `,
+ "should add width (and height automatically)"
+ )
+
+ test.equal(
+ React.renderToStaticMarkup(
+ `} width="1rem" height="auto" />
+ ),
+ `${SVGIconStart} style="width: 1rem;height: auto;"> `,
+ "should add width & height"
+ )
+
+ test.equal(
+ React.renderToStaticMarkup(
+ `} height="1rem" />
+ ),
+ `${SVGIconStart} style="height: 1rem;"> `,
+ "should add height"
+ )
+
+ test.end()
+})
diff --git a/docs/src/modules/SVGIcon/index.css b/docs/src/modules/SVGIcon/index.css
new file mode 100644
index 0000000..3bf41e7
--- /dev/null
+++ b/docs/src/modules/SVGIcon/index.css
@@ -0,0 +1,25 @@
+.SVGIcon {
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+
+ /* fix webkit/blink poor rendering issues */
+ transform: translate3d(0,0,0);
+
+ /* it's better defined directly because of the cascade shit
+ width: inherit;
+ height: inherit;
+ line-height: inherit;
+ */
+
+ /*vertical-align: middle;*/
+}
+
+ .SVGIcon-svg {
+ width: inherit;
+ height: inherit;
+ line-height: inherit;
+ /*vertical-align: inherit;*/
+
+ color: inherit;
+ fill: currentColor;
+ }
diff --git a/docs/src/modules/SVGIcon/index.js b/docs/src/modules/SVGIcon/index.js
new file mode 100644
index 0000000..07d534b
--- /dev/null
+++ b/docs/src/modules/SVGIcon/index.js
@@ -0,0 +1,144 @@
+import React, {Component, PropTypes} from "react"
+// import styled from "bloody-react-styled"
+import cx from "classnames"
+
+// import styles from "./styles"
+
+const cleanups = {
+ // some useless stuff for us
+ // that svgo doesn't remove
+ title: /.* <\/title>/gi,
+ desc: /.*<\/desc>/gi,
+ comment: //gi,
+ defs: /.*<\/defs>/gi,
+
+ // remove hardcoded dimensions
+ width: / +width="\d+(\.\d+)?(px)?"/gi,
+ height: / +height="\d+(\.\d+)?(px)?"/gi,
+
+ // remove fill
+ fill: / +fill=\"(none|#[0-9a-f]+)\"/gi,
+
+ // Sketch.app shit
+ sketchMSShapeGroup: / +sketch:type=\"MSShapeGroup\"/gi,
+ sketchMSPage: / +sketch:type=\"MSPage\"/gi,
+ sketchMSLayerGroup: / +sketch:type=\"MSLayerGroup\"/gi,
+}
+
+// @styled(styles)
+export default class SVGIcon extends Component {
+
+ static defaultProps = {
+ component: "span",
+ classSuffix: "-svg",
+ cleanup: [],
+ cleanupExceptions: [],
+ }
+
+ static propTypes = {
+ component: PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.func,
+ ]),
+ svg: PropTypes.string.isRequired,
+ fill: PropTypes.string,
+ cleanup: PropTypes.oneOfType([
+ PropTypes.bool,
+ PropTypes.array,
+ ]),
+ width: PropTypes.string,
+ height: PropTypes.string,
+ }
+
+ static cleanupSvg(svg, cleanup = []) {
+ return Object.keys(cleanups)
+ .filter(key => cleanup.includes(key))
+ .reduce((acc, key) => {
+ return acc.replace(cleanups[key], "")
+ }, svg)
+ .trim()
+ }
+
+ render() {
+ const {
+ className,
+ component,
+ svg,
+ fill
+ } = this.props
+
+ let cleanup = this.props.cleanup
+ if (
+ // simple way to enable entire cleanup
+ cleanup === true ||
+ // passing cleanupExceptions enable cleanup as well
+ (
+ this.props.cleanup.length === 0 &&
+ this.props.cleanupExceptions.length > 0
+ )
+ ) {
+ cleanup = Object.keys(cleanups)
+ }
+ cleanup = cleanup.filter(
+ key => {
+ return !this.props.cleanupExceptions.includes(key)
+ }
+ )
+
+ let {
+ width,
+ height
+ } = this.props
+
+ if (width && height === undefined) {
+ height = width
+ }
+
+ const props = {...this.props}
+ // remove useless props for wrapper
+ delete props.svg
+ delete props.fill
+ delete props.width
+ delete props.height
+
+ const classes = cx({
+ "SVGIcon": true,
+ "SVGIcon--cleaned": cleanup.length,
+ [className]: className,
+ })
+ const svgClasses = classes
+ .split(" ")
+ .join(this.props.classSuffix + " ") + this.props.classSuffix
+
+ return (
+ React.createElement(
+ component,
+ {
+ ...props, // take most props
+ className: classes,
+ dangerouslySetInnerHTML: {
+ __html: SVGIcon.cleanupSvg(svg, cleanup).replace(
+ / "
+ // use createTextNode to escape html entities
+ opts.console.insertBefore(
+ document.createTextNode(e.toString()),
+ opts.console.firstChild
+ )
+ }
+ }
+
+ opts.from.addEventListener("change", cssnextify)
+ opts.from.addEventListener("keyup", cssnextify)
+
+ cssnextify()
+}
+
+Array.prototype.slice.call(
+ document.querySelectorAll(".js-cssnext-Playground")
+).forEach(function(elPlayground) {
+ playground({
+ from: elPlayground.querySelector(".js-cssnext-Playground-from"),
+ to: elPlayground.querySelector(".js-cssnext-Playground-to"),
+ console: elPlayground.querySelector(".js-cssnext-Playground-console"),
+ })
+})
diff --git a/docs/src/modules/requireRaw.js b/docs/src/modules/requireRaw.js
new file mode 100644
index 0000000..7fe4aec
--- /dev/null
+++ b/docs/src/modules/requireRaw.js
@@ -0,0 +1,19 @@
+const BAD_ENV = "Cannot require raw file from the current environnement"
+
+const fs = require ? require("fs") : null
+const path = require ? require("path") : null
+
+let requireRaw = () => {
+ return BAD_ENV
+}
+
+if (fs && fs.readFileSync) {
+ requireRaw = (filename) => {
+ return fs.readFileSync(
+ path.join(__dirname, "..", "..", filename),
+ {encoding: "utf8"}
+ )
+ }
+}
+
+export default requireRaw
diff --git a/package.json b/package.json
index 8983d39..e573141 100644
--- a/package.json
+++ b/package.json
@@ -32,7 +32,7 @@
"chalk": "^1.0.0",
"chokidar": "^1.0.0",
"commander": "^2.3.0",
- "cssnano": "^1.2.0",
+ "cssnano": "^1.3.0",
"exit": "^0.1.2",
"object-assign": "^2.0.0",
"pixrem": "^1.1.0",
@@ -61,16 +61,65 @@
"write-file-stdout": "0.0.2"
},
"devDependencies": {
+ "async": "^1.0.0",
+ "babel": "^5.4.7",
+ "babel-core": "^5.4.7",
+ "babel-eslint": "^3.1.7",
+ "babel-loader": "^5.1.3",
"browserify": "^8.1.1",
+ "caniuse-db": "^1.0.30000180",
+ "classnames": "^2.1.1",
+ "copy-with-content-hash": "^1.1.0",
+ "css-loader": "^0.13.1",
+ "cssnext-loader": "^1.0.1",
+ "cssrecipes-custom-media-queries": "^0.3.0",
+ "cssrecipes-defaults": "^0.5.0",
+ "cssrecipes-grid": "^0.4.0",
+ "cssrecipes-utils": "^0.5.0",
+ "cssrecipes-vertical-rhythm": "^0.6.0",
+ "dashify": "^0.1.0",
"eslint": "^0.21.2",
+ "eslint-loader": "^0.11.2",
+ "eslint-plugin-react": "^2.3.0",
+ "extract-text-webpack-plugin": "^0.8.0",
+ "file-loader": "^0.8.3",
+ "highlight.js": "^8.6.0",
+ "isogram": "^0.5.0",
+ "js-yaml": "^3.3.1",
+ "json-loader": "^0.5.2",
+ "marked": "^0.3.3",
+ "metalsmith": "segmentio/metalsmith#wider-node-support",
+ "metalsmith-collections": "^0.7.0",
+ "metalsmith-filenames": "^1.0.0",
+ "metalsmith-md": "^1.1.1",
+ "metalsmith-react": "^1.1.0",
+ "metalsmith-rename": "^1.0.0",
+ "metalsmith-rss": "^1.0.0",
+ "metalsmith-url": "^1.0.0",
+ "metalsmith-watch": "^1.0.1",
"microtime": "^1.2.0",
- "tape": "^3.0.0"
+ "nano-logger": "^1.0.0",
+ "node-libs-browser": "^0.5.0",
+ "normalize.css": "^3.0.3",
+ "opn": "^1.0.2",
+ "react": "^0.13.3",
+ "rimraf": "^2.3.4",
+ "style-loader": "^0.12.2",
+ "tape": "^3.0.0",
+ "webpack": "^1.9.7",
+ "webpack-dev-server": "^1.8.2",
+ "webpack-nano-logs": "^1.0.0"
},
"scripts": {
"standalone": "browserify --standalone cssnext index.js -o dist/cssnext.js",
- "eslint": "eslint --ignore-path .gitignore -f tap .",
- "pretest": "npm run eslint && npm run standalone",
- "test": "tape test/*.js"
+ "lint": "eslint --ignore-path .gitignore .",
+ "tape": "tape test/*.js",
+ "test": "npm run lint && npm run standalone && npm run tape",
+ "docs-build": "babel-node docs/scripts/build",
+ "docs-start": "npm run docs-build -- --dev-server --open",
+ "docs-test": "npm run docs-build -- --production",
+ "_docs-deploy": "GIT_DEPLOY_DIR=docs/dist ./docs/scripts/deploy-to-gh-pages.sh -v",
+ "docs-deploy": "npm run docs-test && npm run _docs-deploy"
},
"bin": {
"cssnext": "bin/cssnext.js"