feat(docz-plugin-css): add initial version (#78)

* fix(docz-core): reduce from plugins arguments
* feat(docz-plugin-css): add initial version of plugin
* chore(docz-plugin-css): add some examples
This commit is contained in:
Pedro Nauck
2018-06-21 19:37:50 -03:00
committed by GitHub
parent bc0b7e0223
commit 299372ebca
39 changed files with 1982 additions and 39 deletions

View File

@@ -0,0 +1,10 @@
import { css } from 'docz-plugin-css'
export default {
plugins: [
css({
preprocessor: 'less',
cssmodules: true,
}),
],
}

View File

@@ -0,0 +1,20 @@
{
"name": "docz-example-css-less",
"version": "0.2.9",
"license": "MIT",
"scripts": {
"dev": "docz dev",
"build": "docz build"
},
"dependencies": {
"classnames": "^2.2.6",
"docz": "^0.2.9",
"docz-core": "^0.2.9",
"prop-types": "^15.6.2",
"react": "^16.4.1",
"react-dom": "^16.4.1"
},
"devDependencies": {
"docz-plugin-css": "^0.2.9"
}
}

View File

@@ -0,0 +1,23 @@
import React, { Fragment } from 'react'
import cx from 'classnames'
import t from 'prop-types'
import styles from './Alert.module.less'
export const Alert = ({ children, kind }) => (
<div
className={cx(styles.alert, {
[styles[kind]]: true,
})}
>
{children}
</div>
)
Alert.propTypes = {
kind: t.oneOf(['info', 'positive', 'negative', 'warning']),
}
Alert.defaultProps = {
kind: 'info',
}

View File

@@ -0,0 +1,41 @@
---
name: Alert
menu: Components
---
import './index.less'
import { Playground, PropsTable } from 'docz'
import { Alert } from './Alert'
# Alert
## Properties
<PropsTable of={Alert} />
## Basic usage
<Playground>
<Alert>Some message</Alert>
</Playground>
## Using different kinds
<Playground>
<Alert kind="info">Some message</Alert>
<Alert kind="positive">Some message</Alert>
<Alert kind="negative">Some message</Alert>
<Alert kind="warning">Some message</Alert>
</Playground>
## Use with children as a function
<Playground>
{() => {
const message = 'Hello world'
return (
<Alert>{message}</Alert>
)
}}
</Playground>

View File

@@ -0,0 +1,22 @@
.alert {
padding: 15px 20px;
background: white;
border-radius: 3px;
color: white;
}
.info {
background: #5352ED;
}
.positive {
background: #2ED573;
}
.negative {
background: #FF4757;
}
.warning {
background: #FFA502;
}

View File

@@ -0,0 +1,3 @@
body {
background: white;
}

View File

@@ -0,0 +1,21 @@
---
name: Getting Started
route: /
order: 1
---
# Getting Started
Design systems enable teams to build better products faster by making design reusable—reusability makes scale possible. This is the heart and primary value of design systems. A design system is a collection of reusable components, guided by clear standards, that can be assembled together to build any number of applications.
Regardless of the technologies and tools behind them, a successful design system follows these guiding principles:
- **Its consistent**. The way components are built and managed follows a predictable pattern.
- **Its self-contained**. Your design system is treated as a standalone dependency.
- **Its reusable**. Youve built components so they can be reused in many contexts.
- **Its accessible**. Applications built with your design system are usable by as many people as possible, no matter how they access the web.
- **Its robust**. No matter the product or platform to which your design system is applied, it should perform with grace and minimal bugs.
## Consistency
Your first, most important task when starting out is to define the rules of your system, document them, and ensure that everyone follows them. When you have clearly documented code standards and best practices in place, designers and developers from across your organization can easily use and, more importantly, contribute to your design system.

View File

@@ -0,0 +1,10 @@
import { css } from 'docz-plugin-css'
export default {
plugins: [
css({
preprocessor: 'stylus',
cssmodules: true,
}),
],
}

View File

@@ -0,0 +1,20 @@
{
"name": "docz-example-css-postcss",
"version": "0.2.9",
"license": "MIT",
"scripts": {
"dev": "docz dev",
"build": "docz build"
},
"dependencies": {
"classnames": "^2.2.6",
"docz": "^0.2.9",
"docz-core": "^0.2.9",
"prop-types": "^15.6.2",
"react": "^16.4.1",
"react-dom": "^16.4.1"
},
"devDependencies": {
"docz-plugin-css": "^0.2.9"
}
}

View File

@@ -0,0 +1,23 @@
import React, { Fragment } from 'react'
import cx from 'classnames'
import t from 'prop-types'
import styles from './Alert.module.css'
export const Alert = ({ children, kind }) => (
<div
className={cx(styles.alert, {
[styles[kind]]: true,
})}
>
{children}
</div>
)
Alert.propTypes = {
kind: t.oneOf(['info', 'positive', 'negative', 'warning']),
}
Alert.defaultProps = {
kind: 'info',
}

View File

@@ -0,0 +1,41 @@
---
name: Alert
menu: Components
---
import './index.css'
import { Playground, PropsTable } from 'docz'
import { Alert } from './Alert'
# Alert
## Properties
<PropsTable of={Alert} />
## Basic usage
<Playground>
<Alert>Some message</Alert>
</Playground>
## Using different kinds
<Playground>
<Alert kind="info">Some message</Alert>
<Alert kind="positive">Some message</Alert>
<Alert kind="negative">Some message</Alert>
<Alert kind="warning">Some message</Alert>
</Playground>
## Use with children as a function
<Playground>
{() => {
const message = 'Hello world'
return (
<Alert>{message}</Alert>
)
}}
</Playground>

View File

@@ -0,0 +1,22 @@
.alert {
padding: 15px 20px;
background: white;
border-radius: 3px;
color: white;
}
.info {
background: #5352ED;
}
.positive {
background: #2ED573;
}
.negative {
background: #FF4757;
}
.warning {
background: #FFA502;
}

View File

@@ -0,0 +1,3 @@
body {
background: white;
}

View File

@@ -0,0 +1,21 @@
---
name: Getting Started
route: /
order: 1
---
# Getting Started
Design systems enable teams to build better products faster by making design reusable—reusability makes scale possible. This is the heart and primary value of design systems. A design system is a collection of reusable components, guided by clear standards, that can be assembled together to build any number of applications.
Regardless of the technologies and tools behind them, a successful design system follows these guiding principles:
- **Its consistent**. The way components are built and managed follows a predictable pattern.
- **Its self-contained**. Your design system is treated as a standalone dependency.
- **Its reusable**. Youve built components so they can be reused in many contexts.
- **Its accessible**. Applications built with your design system are usable by as many people as possible, no matter how they access the web.
- **Its robust**. No matter the product or platform to which your design system is applied, it should perform with grace and minimal bugs.
## Consistency
Your first, most important task when starting out is to define the rules of your system, document them, and ensure that everyone follows them. When you have clearly documented code standards and best practices in place, designers and developers from across your organization can easily use and, more importantly, contribute to your design system.

View File

@@ -0,0 +1,10 @@
import { css } from 'docz-plugin-css'
export default {
plugins: [
css({
preprocessor: 'sass',
cssmodules: true,
}),
],
}

View File

@@ -0,0 +1,20 @@
{
"name": "docz-example-css-sass",
"version": "0.2.9",
"license": "MIT",
"scripts": {
"dev": "docz dev",
"build": "docz build"
},
"dependencies": {
"classnames": "^2.2.6",
"docz": "^0.2.9",
"docz-core": "^0.2.9",
"prop-types": "^15.6.2",
"react": "^16.4.1",
"react-dom": "^16.4.1"
},
"devDependencies": {
"docz-plugin-css": "^0.2.9"
}
}

View File

@@ -0,0 +1,23 @@
import React, { Fragment } from 'react'
import cx from 'classnames'
import t from 'prop-types'
import styles from './Alert.module.scss'
export const Alert = ({ children, kind }) => (
<div
className={cx(styles.alert, {
[styles[kind]]: true,
})}
>
{children}
</div>
)
Alert.propTypes = {
kind: t.oneOf(['info', 'positive', 'negative', 'warning']),
}
Alert.defaultProps = {
kind: 'info',
}

View File

@@ -0,0 +1,41 @@
---
name: Alert
menu: Components
---
import './index.scss'
import { Playground, PropsTable } from 'docz'
import { Alert } from './Alert'
# Alert
## Properties
<PropsTable of={Alert} />
## Basic usage
<Playground>
<Alert>Some message</Alert>
</Playground>
## Using different kinds
<Playground>
<Alert kind="info">Some message</Alert>
<Alert kind="positive">Some message</Alert>
<Alert kind="negative">Some message</Alert>
<Alert kind="warning">Some message</Alert>
</Playground>
## Use with children as a function
<Playground>
{() => {
const message = 'Hello world'
return (
<Alert>{message}</Alert>
)
}}
</Playground>

View File

@@ -0,0 +1,22 @@
.alert {
padding: 15px 20px;
background: white;
border-radius: 3px;
color: white;
}
.info {
background: #5352ED;
}
.positive {
background: #2ED573;
}
.negative {
background: #FF4757;
}
.warning {
background: #FFA502;
}

View File

@@ -0,0 +1,3 @@
body {
background: white;
}

View File

@@ -0,0 +1,21 @@
---
name: Getting Started
route: /
order: 1
---
# Getting Started
Design systems enable teams to build better products faster by making design reusable—reusability makes scale possible. This is the heart and primary value of design systems. A design system is a collection of reusable components, guided by clear standards, that can be assembled together to build any number of applications.
Regardless of the technologies and tools behind them, a successful design system follows these guiding principles:
- **Its consistent**. The way components are built and managed follows a predictable pattern.
- **Its self-contained**. Your design system is treated as a standalone dependency.
- **Its reusable**. Youve built components so they can be reused in many contexts.
- **Its accessible**. Applications built with your design system are usable by as many people as possible, no matter how they access the web.
- **Its robust**. No matter the product or platform to which your design system is applied, it should perform with grace and minimal bugs.
## Consistency
Your first, most important task when starting out is to define the rules of your system, document them, and ensure that everyone follows them. When you have clearly documented code standards and best practices in place, designers and developers from across your organization can easily use and, more importantly, contribute to your design system.

View File

@@ -0,0 +1,10 @@
import { css } from 'docz-plugin-css'
export default {
plugins: [
css({
preprocessor: 'stylus',
cssmodules: true,
}),
],
}

View File

@@ -0,0 +1,20 @@
{
"name": "docz-example-css-stylus",
"version": "0.2.9",
"license": "MIT",
"scripts": {
"dev": "docz dev",
"build": "docz build"
},
"dependencies": {
"classnames": "^2.2.6",
"docz": "^0.2.9",
"docz-core": "^0.2.9",
"prop-types": "^15.6.2",
"react": "^16.4.1",
"react-dom": "^16.4.1"
},
"devDependencies": {
"docz-plugin-css": "^0.2.9"
}
}

View File

@@ -0,0 +1,23 @@
import React, { Fragment } from 'react'
import cx from 'classnames'
import t from 'prop-types'
import styles from './Alert.module.styl'
export const Alert = ({ children, kind }) => (
<div
className={cx(styles.alert, {
[styles[kind]]: true,
})}
>
{children}
</div>
)
Alert.propTypes = {
kind: t.oneOf(['info', 'positive', 'negative', 'warning']),
}
Alert.defaultProps = {
kind: 'info',
}

View File

@@ -0,0 +1,41 @@
---
name: Alert
menu: Components
---
import './index.styl'
import { Playground, PropsTable } from 'docz'
import { Alert } from './Alert'
# Alert
## Properties
<PropsTable of={Alert} />
## Basic usage
<Playground>
<Alert>Some message</Alert>
</Playground>
## Using different kinds
<Playground>
<Alert kind="info">Some message</Alert>
<Alert kind="positive">Some message</Alert>
<Alert kind="negative">Some message</Alert>
<Alert kind="warning">Some message</Alert>
</Playground>
## Use with children as a function
<Playground>
{() => {
const message = 'Hello world'
return (
<Alert>{message}</Alert>
)
}}
</Playground>

View File

@@ -0,0 +1,22 @@
.alert {
padding: 15px 20px;
background: white;
border-radius: 3px;
color: white;
}
.info {
background: #5352ED;
}
.positive {
background: #2ED573;
}
.negative {
background: #FF4757;
}
.warning {
background: #FFA502;
}

View File

@@ -0,0 +1,3 @@
body {
background: white;
}

View File

@@ -0,0 +1,21 @@
---
name: Getting Started
route: /
order: 1
---
# Getting Started
Design systems enable teams to build better products faster by making design reusable—reusability makes scale possible. This is the heart and primary value of design systems. A design system is a collection of reusable components, guided by clear standards, that can be assembled together to build any number of applications.
Regardless of the technologies and tools behind them, a successful design system follows these guiding principles:
- **Its consistent**. The way components are built and managed follows a predictable pattern.
- **Its self-contained**. Your design system is treated as a standalone dependency.
- **Its reusable**. Youve built components so they can be reused in many contexts.
- **Its accessible**. Applications built with your design system are usable by as many people as possible, no matter how they access the web.
- **Its robust**. No matter the product or platform to which your design system is applied, it should perform with grace and minimal bugs.
## Consistency
Your first, most important task when starting out is to define the rules of your system, document them, and ensure that everyone follows them. When you have clearly documented code standards and best practices in place, designers and developers from across your organization can easily use and, more importantly, contribute to your design system.

View File

@@ -38,8 +38,8 @@ export class Bundler<C = any> {
}
public getConfig(): C {
const config = this.args.modifyBundlerConfig(this.config, !IS_PROD)
return this.mountConfig(config)
const config = this.mountConfig(this.config)
return this.args.modifyBundlerConfig(config, !IS_PROD)
}
public async createServer(config: C): Promise<BundlerServer> {

View File

@@ -53,7 +53,7 @@ export class Plugin<C = any> implements PluginFactory {
return (method, initial, ...args) => {
return [...(plugins || [])].reduce((obj: any, plugin) => {
const fn = get(plugin, method)
return fn && isFn(fn) ? fn(obj) : obj
return fn && isFn(fn) ? fn(obj, ...args) : obj
}, initial)
}
}

View File

@@ -0,0 +1,94 @@
# docz-plugin-css
Docz plugin to parse css files inside your documents
![](https://cdn-std.dprcdn.net/files/acc_649651/4Q4QBN)
## Instalation
First of all, install plugin:
```bash
$ yarn add docz-plugin-css --dev
```
After that, use the plugin on your `doczrc.js`:
```js
// doczrc.js
import { css } from 'docz-plugin-css'
export default {
plugins: [
css({
preprocessor: 'postcss',
cssmodules: true,
loaderOpts: {
/* whatever your preprocessor loader accept */
}
})
]
}
```
### Choosing PostCSS, Sass, Less or Stylus
Do you can choose how preprocessor your bundler will use just by changing the `preprocessor` property at the plugin definition:
```js
// doczrc.js
import { css } from 'docz-plugin-css'
export default {
plugins: [
css({
preprocessor: 'sass'
})
]
}
```
### Multiple pre-processor
You can still use multiple pre-processor together in the same configuration:
```js
// doczrc.js
import { css } from 'docz-plugin-css'
export default {
plugins: [
css({ preprocessor: 'sass' }),
css({ preprocessor: 'stylus' }),
]
}
```
## Api
### Params
#### `preprocessor`
- **Type:** `postcss | sass | less | stylus`
- **Default:** `postcss`
Use to define the preprocessor you want to use
#### `cssmodules`
- **Type:** `Boolean`
- **Default:** `false`
Use this option if you want to use css modules
#### `loaderOpts`
- **Type:** `{ [key:string]: any }`
- **Default:** `{}`
Custom options passed on pre-processor loader configuration
#### `cssOpts`
- **Type:** `{ [key:string]: any }`
- **Default:** `{}`
Custom options passed on [css-loader](https://github.com/webpack-contrib/css-loader) configuration

View File

@@ -0,0 +1,7 @@
const pkg = require('./package.json')
module.exports = {
external: Object.keys(pkg.dependencies).concat([
'react-dev-utils/getCSSModuleLocalIdent',
]),
}

View File

@@ -0,0 +1,44 @@
{
"name": "docz-plugin-css",
"version": "0.2.9",
"main": "dist/index.js",
"umd:main": "dist/index.umd.js",
"module": "dist/index.m.js",
"typings": "dist/index.d.ts",
"source": "src/index.ts",
"files": [
"dist/",
"package.json",
"README.md"
],
"license": "MIT",
"scripts": {
"dev": "libundler watch --ts",
"build": "libundler build --ts --c",
"fix": "run-s fix:*",
"fix:prettier": "prettier \"src/**/*.{ts,tsx}\" --write",
"fix:tslint": "tslint --fix --project .",
"tslint": "tslint --project ."
},
"dependencies": {
"autoprefixer": "^8.6.3",
"css-loader": "^0.28.11",
"deepmerge": "^2.1.1",
"docz-core": "^0.2.9",
"less": "^3.0.4",
"less-loader": "^4.1.0",
"loader-utils": "^1.1.0",
"mini-css-extract-plugin": "^0.4.0",
"node-sass": "^4.9.0",
"optimize-css-assets-webpack-plugin": "^4.0.2",
"postcss": "^6.0.23",
"postcss-flexbugs-fixes": "^3.3.1",
"postcss-loader": "^2.1.5",
"sass-loader": "^7.0.3",
"style-loader": "^0.21.0",
"stylus": "^0.54.5",
"stylus-loader": "^3.0.2",
"webpack": "^4.12.0",
"webpack-chain": "^4.8.0"
}
}

View File

@@ -0,0 +1,30 @@
import loaderUtils from 'loader-utils'
export const getLocalIdent = (
context: any,
localIdentName: any,
localName: any,
options: any
) => {
// Use the filename or folder name, based on some uses the index.js / index.module.(css|scss|sass) project style
const fileNameOrFolder = context.resourcePath.match(
/index\.module\.(css|scss|sass)$/
)
? '[folder]'
: '[name]'
// Create a hash based on a the file location and class name. Will be unique across a project, and close to globally unique.
const hash = loaderUtils.getHashDigest(
context.resourcePath + localName,
'md5',
'base64',
5
)
// Use loaderUtils to find the file or folder name
const className = loaderUtils.interpolateName(
context,
fileNameOrFolder + '_' + localName + '__' + hash,
options
)
// remove the .module that appears in every classname when based on the file.
return className.replace('.module_', '_')
}

View File

@@ -0,0 +1,153 @@
import { createPlugin } from 'docz-core'
import MiniCssExtractPlugin from 'mini-css-extract-plugin'
import OptimizeCSSAssetsPlugin from 'optimize-css-assets-webpack-plugin'
import merge from 'deepmerge'
import { getLocalIdent } from './get-local-ident'
/**
* Tests
*/
const tests: Record<string, RegExp> = {
postcss: /\.css$/,
'module-postcss': /\.module\.css$/,
sass: /\.s(a|c)ss$/,
'module-sass': /\.module\.s(a|c)ss$/,
less: /\.less$/,
'module-less': /\.module\.less$/,
stylus: /\.styl(us)?$/,
'module-stylus': /\.module\.styl(us)?$/,
}
/**
* Loaders
*/
export interface Opts {
[key: string]: any
}
const getStyleLoaders = (loader: any, opts: Opts) => (
cssopts: any,
dev: boolean
) => {
return [
{
loader: dev
? require.resolve('style-loader')
: MiniCssExtractPlugin.loader,
},
{
loader: require.resolve('css-loader'),
options: cssopts,
},
{
loader,
options: opts,
},
]
}
const loaders = {
postcss: (opts: Opts = { plugins: [] }) =>
getStyleLoaders(require.resolve('postcss-loader'), {
plugins: () =>
opts.plugins.concat([
require('postcss-flexbugs-fixes'),
require('autoprefixer')({
flexbox: 'no-2009',
}),
]),
}),
sass: (opts: Opts = {}) =>
getStyleLoaders(require.resolve('sass-loader'), opts),
less: (opts: Opts = {}) =>
getStyleLoaders(require.resolve('less-loader'), opts),
stylus: (opts: Opts = {}) =>
getStyleLoaders(
require.resolve('stylus-loader'),
merge(opts, { preferPathResolver: 'webpack' })
),
}
/**
* Rules
*/
const applyRule = (
opts: CSSPluginOptions,
cssmodules: boolean | undefined,
dev: boolean
) => {
const { preprocessor = 'postcss', cssOpts, loaderOpts } = opts
const regexp = tests[preprocessor]
const modulesRegexp = tests[`module-${preprocessor}`]
const test = cssmodules ? modulesRegexp : regexp
const exclude = [/node_modules/]
const loaderfn = loaders[preprocessor]
const loader = loaderfn(loaderOpts)
const cssoptions = merge(cssOpts, {
importLoaders: 1,
modules: cssmodules,
sourceMap: !dev,
...(cssmodules && { getLocalIdent }),
})
return {
test,
exclude: cssmodules ? exclude : exclude.concat([modulesRegexp]),
use: loader(cssoptions, dev),
}
}
export interface CSSPluginOptions {
preprocessor?: 'postcss' | 'sass' | 'less' | 'stylus'
cssmodules?: boolean
loaderOpts?: Opts
cssOpts?: Opts
}
export const css = (opts: CSSPluginOptions) =>
createPlugin({
modifyBundlerConfig: (config, dev) => {
config.module.rules.push(
applyRule(opts, false, dev),
applyRule(opts, opts.cssmodules, dev)
)
if (!dev) {
const minimizer = config.optimization.minimizer || []
const splitChunks = { ...config.optimization.splitChunks }
config.optimization.minimizer = minimizer.concat([
new OptimizeCSSAssetsPlugin({}),
])
config.optimization.splitChunks = merge(splitChunks, {
cacheGroups: {
styles: {
name: 'styles',
test: (m: any) => /css-extract/.test(m.type),
chunks: 'all',
enforce: true,
},
},
})
config.plugins.push(
new MiniCssExtractPlugin({
filename: '[name].[hash].css',
chunkFilename: '[id].[hash].css',
})
)
}
return config
},
})

View File

@@ -0,0 +1,3 @@
declare module 'optimize-css-assets-webpack-plugin'
declare module 'mini-css-extract-plugin'
declare module 'loader-utils'

View File

@@ -0,0 +1,12 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "dist",
"rootDir": "src",
"declaration": true,
"types": ["node"],
"typeRoots": ["node_modules/@types"]
},
"include": ["src/**/*", "src/types.d.ts"],
"exclude": ["node_modules/**"]
}

View File

@@ -0,0 +1,3 @@
{
"extends": "../../tslint.json"
}

1109
yarn.lock

File diff suppressed because it is too large Load Diff