From f0c68332bd0cb9be5969c0391d3fd722705c53d2 Mon Sep 17 00:00:00 2001
From: LoadingMore <biyuqiwan@163.com>
Date: Sun, 1 Sep 2019 22:29:39 +0800
Subject: [PATCH 01/56] Initial commit

---
 LICENSE   | 21 +++++++++++++++++++++
 README.md |  2 ++
 2 files changed, 23 insertions(+)
 create mode 100644 LICENSE
 create mode 100644 README.md

diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..7f97947
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2019 LoadingMore
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..9e4c119
--- /dev/null
+++ b/README.md
@@ -0,0 +1,2 @@
+# magic-programming
+Record the beauty of programming.

From 161b4836bf8d9869abaf59a657c74f6732567a6c Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Tue, 3 Sep 2019 00:25:07 +0800
Subject: [PATCH 02/56] chore: setup

---
 .eslintignore                |  6 +++
 .eslintrc.js                 | 27 ++++++++++++
 .gitignore                   |  6 +++
 .postcssrc.js                |  5 +++
 .prettierignore              |  6 +++
 .prettierrc.js               |  8 ++++
 babel.config.js              |  4 ++
 build/utils.js               | 43 +++++++++++++++++++
 build/webpack.base.config.js | 81 ++++++++++++++++++++++++++++++++++++
 build/webpack.dev.config.js  | 31 ++++++++++++++
 build/webpack.prod.config.js | 50 ++++++++++++++++++++++
 enzyme.setup.js              |  4 ++
 jest.config.js               | 24 +++++++++++
 jest.styleMock.js            |  1 +
 package.json                 | 65 +++++++++++++++++++++++++++++
 public/index.html            | 12 ++++++
 src/App.js                   | 12 ++++++
 src/App.scss                 | 10 +++++
 src/__test__/index.test.js   | 11 +++++
 src/index.js                 |  5 +++
 20 files changed, 411 insertions(+)
 create mode 100644 .eslintignore
 create mode 100644 .eslintrc.js
 create mode 100644 .gitignore
 create mode 100644 .postcssrc.js
 create mode 100644 .prettierignore
 create mode 100644 .prettierrc.js
 create mode 100644 babel.config.js
 create mode 100644 build/utils.js
 create mode 100644 build/webpack.base.config.js
 create mode 100644 build/webpack.dev.config.js
 create mode 100644 build/webpack.prod.config.js
 create mode 100644 enzyme.setup.js
 create mode 100644 jest.config.js
 create mode 100644 jest.styleMock.js
 create mode 100644 package.json
 create mode 100644 public/index.html
 create mode 100644 src/App.js
 create mode 100644 src/App.scss
 create mode 100644 src/__test__/index.test.js
 create mode 100644 src/index.js

diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..9708844
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,6 @@
+/coverage/
+/vendor/
+jest.config.js
+jest.styleMock.js
+enzyme.setup.js
+/node_modules/*
\ No newline at end of file
diff --git a/.eslintrc.js b/.eslintrc.js
new file mode 100644
index 0000000..5795a19
--- /dev/null
+++ b/.eslintrc.js
@@ -0,0 +1,27 @@
+module.exports = {
+  root: true,
+  extends: [
+    "plugin:prettier/recommended"
+  ],
+  plugins: ["prettier"],
+  parser: "babel-eslint",
+  parserOptions: {
+    sourceType: 'module',
+    ecmaVersion: 7,
+    parser: "babel-eslint",
+    ecmaFeatures: {
+      "jsx": true,
+      "modules": true
+    }
+  },
+  env: {
+    browser: true
+  },
+  rules: {
+    "indent": ["error", 2],
+    'generator-star-spacing': 'off',
+    "quotes": ["error", "single"],
+    "eqeqeq": 2,
+    "default-case": 2
+  }
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2ef5cd5
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+dist
+node_modules
+.DS_store
+package-lock.json
+.vscode
+.idea
\ No newline at end of file
diff --git a/.postcssrc.js b/.postcssrc.js
new file mode 100644
index 0000000..de5c67a
--- /dev/null
+++ b/.postcssrc.js
@@ -0,0 +1,5 @@
+module.exports = {
+  plugins: [
+    require('autoprefixer')()
+  ]
+}
\ No newline at end of file
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000..ba58d5a
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,6 @@
+.eslintrc.js
+.eslintignore
+.prettierignore
+.prettierrc.js
+/node_modules/
+/dist/
diff --git a/.prettierrc.js b/.prettierrc.js
new file mode 100644
index 0000000..7490bdf
--- /dev/null
+++ b/.prettierrc.js
@@ -0,0 +1,8 @@
+module.exports = {
+  printWidth: 100,
+  trailingComma: "none",
+  tabWidth: 2,
+  semi: false,
+  singleQuote: true,
+  proseWrap: 'never'
+}
\ No newline at end of file
diff --git a/babel.config.js b/babel.config.js
new file mode 100644
index 0000000..095c9c4
--- /dev/null
+++ b/babel.config.js
@@ -0,0 +1,4 @@
+module.exports = {
+  presets: ['@babel/preset-env', '@babel/preset-react'],
+  plugins: ['@babel/plugin-proposal-class-properties', '@babel/plugin-transform-modules-commonjs']
+}
\ No newline at end of file
diff --git a/build/utils.js b/build/utils.js
new file mode 100644
index 0000000..9dab540
--- /dev/null
+++ b/build/utils.js
@@ -0,0 +1,43 @@
+const path = require('path')
+
+const isProd = process.env.NODE_ENV === 'production'
+
+/**
+ * get file path
+ * @param {*} dir 
+ */
+const resolve = dir => {
+  return path.join(__dirname, dir)
+}
+
+/**
+ * get the config for webpack build
+ * @param {*} env 
+ */
+const webpackOutConfig = (env) => {
+  return env ? {
+    filename: 'js/[name].[chunkhash].js',
+    chunkFilename: 'js/[name].[id].[chunkhash].js'
+  } : {
+    filename: 'js/[name].js',
+  }
+}
+/**
+ * set eslint
+ */
+const webpackEslintConfig = () => ({
+  test: /\.js$/,
+  loader: 'eslint-loader',
+  enforce: 'pre',
+  include: resolve('../src'),
+  options: {
+    formatter: require('eslint-friendly-formatter')
+  }
+})
+
+module.exports = {
+  isProd,
+  resolve,
+  webpackEslintConfig,
+  webpackOutConfig
+}
diff --git a/build/webpack.base.config.js b/build/webpack.base.config.js
new file mode 100644
index 0000000..1d0fd4d
--- /dev/null
+++ b/build/webpack.base.config.js
@@ -0,0 +1,81 @@
+const path = require('path')
+const MiniCssExtractPlugin = require('mini-css-extract-plugin')
+const HtmlWebpackPlugin = require('html-webpack-plugin')
+const {
+  isProd,
+  resolve,
+  webpackEslintConfig,
+  webpackOutConfig
+} = require('./utils')
+
+const app = { 
+  entry: resolve('../src/index.js'),
+  output: {
+    path: resolve('../dist'),
+    publicPath: '/',
+    ...webpackOutConfig(isProd)
+  },
+  module: {
+    rules: [
+      webpackEslintConfig(),
+      {
+        test: /\.jsx?$/,
+        exclude: /node_modules/,
+        use: {
+          loader: 'babel-loader',
+          options: {
+            presets: ['@babel/preset-env', '@babel/preset-react']
+          }
+        }
+      },
+      {
+        test: /\.(sa|sc|c)ss$/,
+        use: [
+          {
+            loader: !isProd ? 'style-loader' : MiniCssExtractPlugin.loader
+          },
+          {
+            loader: 'css-loader'
+          },
+          {
+            loader: 'sass-loader'
+          },
+          {
+            loader: 'postcss-loader'
+          }
+        ]
+      },
+      {
+        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
+        loader: 'url-loader',
+        options: {
+          limit: 10000,
+          name: 'img/[name].[hash:7].[ext]'
+        }
+      },
+      {
+        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
+        loader: 'url-loader',
+        options: {
+          limit: 10000,
+          name: 'media/[name].[hash:7].[ext]'
+        }
+      },
+      {
+        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
+        loader: 'url-loader',
+        options: {
+          limit: 10000,
+          name: 'fonts/[name].[hash:7].[ext]'
+        }
+      }
+    ]
+  },
+  plugins: [
+    new HtmlWebpackPlugin({
+      template: path.resolve(__dirname, '../public/index.html')
+    })
+  ]
+}
+
+module.exports = app
\ No newline at end of file
diff --git a/build/webpack.dev.config.js b/build/webpack.dev.config.js
new file mode 100644
index 0000000..f34764e
--- /dev/null
+++ b/build/webpack.dev.config.js
@@ -0,0 +1,31 @@
+const path = require('path')
+const webpackAutoFindPort = require('webpack-auto-find-port')
+const chalk = require('chalk')
+const merge = require('webpack-merge')
+const webpack = require('webpack')
+const webpackBaseConfig = require('./webpack.base.config')
+
+const webpackDevConfig = merge(webpackBaseConfig, {
+  mode: 'development',
+  devtool: 'inline-source-map',
+  devServer: {
+    contentBase: path.resolve(`${process.cwd()}`, '../dist/index.html'),
+    publicPath: '/',
+    compress: true,
+    noInfo: true,
+    disableHostCheck: true,
+    open: true,
+    inline: true,
+    port: 8080
+  },
+  plugins: [
+    new webpack.HotModuleReplacementPlugin()
+  ]
+})
+
+module.exports = webpackAutoFindPort({
+  config: webpackDevConfig,
+  logger: (port) => {
+    console.log(chalk.green(`Project is Running at ${port}`))
+  }
+})
\ No newline at end of file
diff --git a/build/webpack.prod.config.js b/build/webpack.prod.config.js
new file mode 100644
index 0000000..e78d3e5
--- /dev/null
+++ b/build/webpack.prod.config.js
@@ -0,0 +1,50 @@
+const webpack = require('webpack')
+const webpackMerge = require('webpack-merge')
+const MiniCssExtractPlugin = require('mini-css-extract-plugin')
+const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
+const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
+const webpackBaseConfig = require('./webpack.base.config')
+
+module.exports = webpackMerge(webpackBaseConfig, {
+  mode: 'production',
+  optimization: {
+    splitChunks: {
+      cacheGroups: {
+        commons: {
+          name: 'commons',
+          chunks: 'all',
+          minChunks: 2,
+          minSize: 1,
+          priority: 0
+        },
+        vendor: {
+          name: 'vendor',
+          test: /[\\/]node_modules[\\/]/,
+          chunks: 'all',
+          priority: 10
+        }
+      }
+    },
+    minimizer: [
+      new UglifyJsPlugin({
+        uglifyOptions: {
+          cache: true,
+          parallel: true,
+          warnings: false,
+          comments: false,
+          compress: {
+            drop_console: true
+          }
+        }
+      }),
+      new OptimizeCSSAssetsPlugin({})
+    ]
+  },
+  plugins: [
+    new webpack.HashedModuleIdsPlugin(),
+
+    new MiniCssExtractPlugin({
+      filename: 'css/[name].css'
+    })
+  ]
+})
diff --git a/enzyme.setup.js b/enzyme.setup.js
new file mode 100644
index 0000000..7be1bb8
--- /dev/null
+++ b/enzyme.setup.js
@@ -0,0 +1,4 @@
+import Enzyme from 'enzyme'
+import Adapter from 'enzyme-adapter-react-16'
+
+Enzyme.configure({ adapter: new Adapter() })
\ No newline at end of file
diff --git a/jest.config.js b/jest.config.js
new file mode 100644
index 0000000..8f38c56
--- /dev/null
+++ b/jest.config.js
@@ -0,0 +1,24 @@
+module.exports = {
+  bail: true,
+  verbose: true,
+  setupFiles: ['<rootDir>/enzyme.setup.js'],
+  roots: ['./src'],
+  testPathIgnorePatterns: ['/node_modules/', '/dist/'],
+  coveragePathIgnorePatterns: ['/node_modules/', '/dist/'],
+  coverageThreshold: {
+    global: {
+      branches: 85,
+      functions: 85,
+      lines: 85,
+      statements: 85
+    }
+  },
+  transform: {
+    '.(js|jsx)': 'babel-jest'
+  },
+  testMatch: ['**/__tests__/**/*.js?(x)', '**/?(*.)+(spec|test).js?(x)'],
+  testURL: 'http://localhost',
+  moduleNameMapper: {
+    '\\.(css|scss|less|bmp|gif|jpg|jpeg|png|psd|svg|webp)$': '<rootDir>/jest.styleMock.js'
+  }
+}
\ No newline at end of file
diff --git a/jest.styleMock.js b/jest.styleMock.js
new file mode 100644
index 0000000..7c6d6c7
--- /dev/null
+++ b/jest.styleMock.js
@@ -0,0 +1 @@
+module.exports = {}
\ No newline at end of file
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..d00ca91
--- /dev/null
+++ b/package.json
@@ -0,0 +1,65 @@
+{
+  "name": "magin-programming",
+  "version": "0.0.0",
+  "description": "",
+  "main": "index.js",
+  "scripts": {
+    "fix": "eslint --fix 'src/**/*.js'",
+    "prettier": "prettier --write 'src/**/*.js'",
+    "test": "jest",
+    "dev": "webpack-dev-server --config build/webpack.dev.config",
+    "build": "cross-env NODE_ENV=production webpack --config build/webpack.prod.config"
+  },
+  "dependencies": {
+    "react": "^16.8.6",
+    "react-dom": "^16.8.6"
+  },
+  "devDependencies": {
+    "@babel/core": "^7.4.5",
+    "@babel/plugin-proposal-class-properties": "^7.4.4",
+    "@babel/plugin-syntax-dynamic-import": "^7.2.0",
+    "@babel/plugin-transform-modules-commonjs": "^7.4.4",
+    "@babel/plugin-transform-react-jsx": "^7.3.0",
+    "@babel/preset-env": "^7.4.5",
+    "@babel/preset-react": "^7.0.0",
+    "autoprefixer": "^9.6.0",
+    "babel-eslint": "^10.0.2",
+    "babel-jest": "^24.8.0",
+    "babel-loader": "^8.0.6",
+    "chalk": "^2.4.2",
+    "copy-webpack-plugin": "^5.0.3",
+    "cross-env": "^5.2.0",
+    "css-loader": "^2.1.1",
+    "enzyme": "^3.10.0",
+    "enzyme-adapter-react-16": "^1.14.0",
+    "eslint": "^6.0.0",
+    "eslint-config-prettier": "^5.0.0",
+    "eslint-friendly-formatter": "^4.0.1",
+    "eslint-loader": "^2.1.2",
+    "eslint-plugin-prettier": "^3.1.0",
+    "file-loader": "^4.0.0",
+    "fs-extra": "^8.0.1",
+    "html-webpack-plugin": "^3.2.0",
+    "jest": "^24.8.0",
+    "mini-css-extract-plugin": "^0.7.0",
+    "node-sass": "^4.12.0",
+    "optimize-css-assets-webpack-plugin": "^5.0.1",
+    "postcss-loader": "^3.0.0",
+    "prettier": "^1.18.2",
+    "sass-loader": "^7.1.0",
+    "style-loader": "^0.23.1",
+    "uglifyjs-webpack-plugin": "^2.1.3",
+    "url-loader": "^2.0.0",
+    "webpack-auto-find-port": "0.0.5",
+    "webpack": "^4.33.0",
+    "webpack-cli": "^3.3.3",
+    "webpack-dev-server": "^3.7.0",
+    "webpack-merge": "^4.2.1"
+  },
+  "browserslist": [
+    "> 1%",
+    "Firefox ESR",
+    "last 2 versions",
+    "ie >= 9"
+  ]
+}
diff --git a/public/index.html b/public/index.html
new file mode 100644
index 0000000..3e9a8e5
--- /dev/null
+++ b/public/index.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <meta http-equiv="X-UA-Compatible" content="ie=edge">
+  <title>Magic Program</title>
+</head>
+<body>
+  <div id="app"></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/App.js b/src/App.js
new file mode 100644
index 0000000..9bc4926
--- /dev/null
+++ b/src/App.js
@@ -0,0 +1,12 @@
+import React from 'react'
+import './App.scss'
+
+const App = () => {
+  return (
+    <div className="magic-program">
+      <div className="magic-program_title">Magic Programming</div>
+    </div>
+  )
+}
+
+export default App
diff --git a/src/App.scss b/src/App.scss
new file mode 100644
index 0000000..0f5f259
--- /dev/null
+++ b/src/App.scss
@@ -0,0 +1,10 @@
+.magic-program {
+  text-align: center;
+  max-width: 640px;
+  margin: 0 auto;
+
+  &_title {
+    font-size: 26px;
+    color: #5a5a5a;
+  }
+}
\ No newline at end of file
diff --git a/src/__test__/index.test.js b/src/__test__/index.test.js
new file mode 100644
index 0000000..b09ea3b
--- /dev/null
+++ b/src/__test__/index.test.js
@@ -0,0 +1,11 @@
+import React from "react"
+import { shallow } from "enzyme"
+import App from '../App'
+
+describe('App', () => {
+  const wrapper = shallow(<App />)
+
+  it('should render correct title', () => {
+    expect(wrapper.find('.magin-program_title').text()).toBe('Ftb React Demo')
+  })
+})
\ No newline at end of file
diff --git a/src/index.js b/src/index.js
new file mode 100644
index 0000000..3aefd43
--- /dev/null
+++ b/src/index.js
@@ -0,0 +1,5 @@
+import React from 'react'
+import ReactDom from 'react-dom'
+import App from './App'
+
+ReactDom.render(<App />, document.getElementById('app'))

From 8b006428bd08c8687f9f5a07965868e77319e4ce Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Fri, 6 Sep 2019 16:02:40 +0800
Subject: [PATCH 03/56] chore: add react releated library

---
 package.json                 | 5 ++++-
 src/shared/Header/index.js   | 8 ++++++++
 src/shared/Header/index.scss | 0
 3 files changed, 12 insertions(+), 1 deletion(-)
 create mode 100644 src/shared/Header/index.js
 create mode 100644 src/shared/Header/index.scss

diff --git a/package.json b/package.json
index d00ca91..c5deb11 100644
--- a/package.json
+++ b/package.json
@@ -12,7 +12,10 @@
   },
   "dependencies": {
     "react": "^16.8.6",
-    "react-dom": "^16.8.6"
+    "react-dom": "^16.8.6",
+    "react-router": "^5.0.1",
+    "react-router-config": "^5.0.1",
+    "react-router-dom": "^5.0.1"
   },
   "devDependencies": {
     "@babel/core": "^7.4.5",
diff --git a/src/shared/Header/index.js b/src/shared/Header/index.js
new file mode 100644
index 0000000..1f30699
--- /dev/null
+++ b/src/shared/Header/index.js
@@ -0,0 +1,8 @@
+import React from 'react'
+import './index.scss'
+
+export const Header = () => {
+  return (
+    <div>Header</div>
+  )
+}
\ No newline at end of file
diff --git a/src/shared/Header/index.scss b/src/shared/Header/index.scss
new file mode 100644
index 0000000..e69de29

From 6df8b31f7d6dec6ee0bd5faa63e5b8a2279316cb Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Sun, 15 Sep 2019 22:44:56 +0800
Subject: [PATCH 04/56] refactor: seperate dir

---
 src/App.js                                  | 12 ------------
 .eslintignore => web/.eslintignore          |  0
 .eslintrc.js => web/.eslintrc.js            |  0
 .gitignore => web/.gitignore                |  0
 .postcssrc.js => web/.postcssrc.js          |  0
 .prettierignore => web/.prettierignore      |  0
 .prettierrc.js => web/.prettierrc.js        |  0
 LICENSE => web/LICENSE                      |  0
 README.md => web/README.md                  |  0
 babel.config.js => web/babel.config.js      |  0
 {build => web/build}/utils.js               |  0
 {build => web/build}/webpack.base.config.js |  0
 {build => web/build}/webpack.dev.config.js  |  0
 {build => web/build}/webpack.prod.config.js |  0
 enzyme.setup.js => web/enzyme.setup.js      |  0
 jest.config.js => web/jest.config.js        |  0
 jest.styleMock.js => web/jest.styleMock.js  |  0
 package.json => web/package.json            |  0
 {public => web/public}/index.html           |  0
 web/src/App.js                              | 14 ++++++++++++++
 {src => web/src}/App.scss                   |  0
 {src => web/src}/__test__/index.test.js     |  0
 {src => web/src}/index.js                   |  0
 {src => web/src}/shared/Header/index.js     |  0
 {src => web/src}/shared/Header/index.scss   |  0
 25 files changed, 14 insertions(+), 12 deletions(-)
 delete mode 100644 src/App.js
 rename .eslintignore => web/.eslintignore (100%)
 rename .eslintrc.js => web/.eslintrc.js (100%)
 rename .gitignore => web/.gitignore (100%)
 rename .postcssrc.js => web/.postcssrc.js (100%)
 rename .prettierignore => web/.prettierignore (100%)
 rename .prettierrc.js => web/.prettierrc.js (100%)
 rename LICENSE => web/LICENSE (100%)
 rename README.md => web/README.md (100%)
 rename babel.config.js => web/babel.config.js (100%)
 rename {build => web/build}/utils.js (100%)
 rename {build => web/build}/webpack.base.config.js (100%)
 rename {build => web/build}/webpack.dev.config.js (100%)
 rename {build => web/build}/webpack.prod.config.js (100%)
 rename enzyme.setup.js => web/enzyme.setup.js (100%)
 rename jest.config.js => web/jest.config.js (100%)
 rename jest.styleMock.js => web/jest.styleMock.js (100%)
 rename package.json => web/package.json (100%)
 rename {public => web/public}/index.html (100%)
 create mode 100644 web/src/App.js
 rename {src => web/src}/App.scss (100%)
 rename {src => web/src}/__test__/index.test.js (100%)
 rename {src => web/src}/index.js (100%)
 rename {src => web/src}/shared/Header/index.js (100%)
 rename {src => web/src}/shared/Header/index.scss (100%)

diff --git a/src/App.js b/src/App.js
deleted file mode 100644
index 9bc4926..0000000
--- a/src/App.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import React from 'react'
-import './App.scss'
-
-const App = () => {
-  return (
-    <div className="magic-program">
-      <div className="magic-program_title">Magic Programming</div>
-    </div>
-  )
-}
-
-export default App
diff --git a/.eslintignore b/web/.eslintignore
similarity index 100%
rename from .eslintignore
rename to web/.eslintignore
diff --git a/.eslintrc.js b/web/.eslintrc.js
similarity index 100%
rename from .eslintrc.js
rename to web/.eslintrc.js
diff --git a/.gitignore b/web/.gitignore
similarity index 100%
rename from .gitignore
rename to web/.gitignore
diff --git a/.postcssrc.js b/web/.postcssrc.js
similarity index 100%
rename from .postcssrc.js
rename to web/.postcssrc.js
diff --git a/.prettierignore b/web/.prettierignore
similarity index 100%
rename from .prettierignore
rename to web/.prettierignore
diff --git a/.prettierrc.js b/web/.prettierrc.js
similarity index 100%
rename from .prettierrc.js
rename to web/.prettierrc.js
diff --git a/LICENSE b/web/LICENSE
similarity index 100%
rename from LICENSE
rename to web/LICENSE
diff --git a/README.md b/web/README.md
similarity index 100%
rename from README.md
rename to web/README.md
diff --git a/babel.config.js b/web/babel.config.js
similarity index 100%
rename from babel.config.js
rename to web/babel.config.js
diff --git a/build/utils.js b/web/build/utils.js
similarity index 100%
rename from build/utils.js
rename to web/build/utils.js
diff --git a/build/webpack.base.config.js b/web/build/webpack.base.config.js
similarity index 100%
rename from build/webpack.base.config.js
rename to web/build/webpack.base.config.js
diff --git a/build/webpack.dev.config.js b/web/build/webpack.dev.config.js
similarity index 100%
rename from build/webpack.dev.config.js
rename to web/build/webpack.dev.config.js
diff --git a/build/webpack.prod.config.js b/web/build/webpack.prod.config.js
similarity index 100%
rename from build/webpack.prod.config.js
rename to web/build/webpack.prod.config.js
diff --git a/enzyme.setup.js b/web/enzyme.setup.js
similarity index 100%
rename from enzyme.setup.js
rename to web/enzyme.setup.js
diff --git a/jest.config.js b/web/jest.config.js
similarity index 100%
rename from jest.config.js
rename to web/jest.config.js
diff --git a/jest.styleMock.js b/web/jest.styleMock.js
similarity index 100%
rename from jest.styleMock.js
rename to web/jest.styleMock.js
diff --git a/package.json b/web/package.json
similarity index 100%
rename from package.json
rename to web/package.json
diff --git a/public/index.html b/web/public/index.html
similarity index 100%
rename from public/index.html
rename to web/public/index.html
diff --git a/web/src/App.js b/web/src/App.js
new file mode 100644
index 0000000..2e16bcb
--- /dev/null
+++ b/web/src/App.js
@@ -0,0 +1,14 @@
+import React from 'react'
+import './App.scss'
+
+class App extends React.Component {
+  render(){
+    return (
+      <div className="magic-program">
+        <div className="magic-program_title">Magic Programming</div>
+      </div>
+    )
+  } 
+}
+
+export default App
diff --git a/src/App.scss b/web/src/App.scss
similarity index 100%
rename from src/App.scss
rename to web/src/App.scss
diff --git a/src/__test__/index.test.js b/web/src/__test__/index.test.js
similarity index 100%
rename from src/__test__/index.test.js
rename to web/src/__test__/index.test.js
diff --git a/src/index.js b/web/src/index.js
similarity index 100%
rename from src/index.js
rename to web/src/index.js
diff --git a/src/shared/Header/index.js b/web/src/shared/Header/index.js
similarity index 100%
rename from src/shared/Header/index.js
rename to web/src/shared/Header/index.js
diff --git a/src/shared/Header/index.scss b/web/src/shared/Header/index.scss
similarity index 100%
rename from src/shared/Header/index.scss
rename to web/src/shared/Header/index.scss

From b6a7fac41b668b989a50001818582d9d99c808a7 Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Mon, 16 Sep 2019 08:00:33 +0800
Subject: [PATCH 05/56] feat: add utils folder

---
 utils/flatten.js          |  5 ++++
 utils/pageVisibility.html | 12 ++++++++++
 utils/pageVisibility.js   | 50 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 67 insertions(+)
 create mode 100644 utils/flatten.js
 create mode 100644 utils/pageVisibility.html
 create mode 100644 utils/pageVisibility.js

diff --git a/utils/flatten.js b/utils/flatten.js
new file mode 100644
index 0000000..2996189
--- /dev/null
+++ b/utils/flatten.js
@@ -0,0 +1,5 @@
+const flatten = (arr, max = 1) => 
+  arr.reduce((initial, curr, index) => 
+  Array.isArray(curr) ? initial.concat(flatten(curr)) : initial.concat(curr), [])
+
+console.log(flatten([1, 2, 3, [3, [4, [5, [9, 10]]]]]))
\ No newline at end of file
diff --git a/utils/pageVisibility.html b/utils/pageVisibility.html
new file mode 100644
index 0000000..d349e1f
--- /dev/null
+++ b/utils/pageVisibility.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <meta http-equiv="X-UA-Compatible" content="ie=edge">
+  <title>Document</title>
+</head>
+<body>
+  <script src="./pageVisibility.js"></script>
+</body> 
+</html>
\ No newline at end of file
diff --git a/utils/pageVisibility.js b/utils/pageVisibility.js
new file mode 100644
index 0000000..e8fa351
--- /dev/null
+++ b/utils/pageVisibility.js
@@ -0,0 +1,50 @@
+class PageVisible {
+  constructor() {
+    this.visible = false
+    this.hidden = 'hidden'
+    this.visibilityChange = 'visibilitychange'
+    this.visibilitySupported()
+    this.onVisible()
+  }
+
+  visibilitySupported() {
+    if (typeof document.hidden !== 'undefined') {    // Opera 12.10 and Firefox 18 and later support 
+      this.hidden = 'hidden'
+      this.visibilityChange = 'visibilitychange'
+    } else if (typeof document.msHidden !== 'undefined') {
+      this.hidden = 'msHidden'
+      this.visibilityChange = 'msvisibilitychange'
+    } else if (typeof document.webkitHidden !== 'undefined') {
+      this.hidden = 'webkitHidden'
+      this.visibilityChange = 'webkitvisibilitychange'
+    }
+
+    if (typeof document.addEventListener === 'undefined' || typeof document[this.hidden] === 'undefined') {
+      this.visible = false
+    }
+    this.visible = true
+  }
+
+  onVisible(callback) {
+    document.addEventListener(this.visibilityChange, () => {
+      if (document[this.hidden]) {
+        callback && callback('hidden')
+      } else {
+        callback && callback('visible')
+      }
+    }, false)
+  }
+}
+
+new PageVisible().onVisible((state) => {
+  switch (state) {
+    case 'hidden':
+      document.title = '我被隐藏了'
+      break;
+    case 'visible':
+      document.title = '哈哈，请继续浏览'
+    break
+    default:
+      break;
+  }
+})
\ No newline at end of file

From 31d7b4ae76f2596ba1825e26e7f70ed6bfa0f13c Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Mon, 16 Sep 2019 18:34:29 +0800
Subject: [PATCH 06/56] feat: for pageVisibility

---
 utils/pageVisibility.js | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/utils/pageVisibility.js b/utils/pageVisibility.js
index e8fa351..080a57e 100644
--- a/utils/pageVisibility.js
+++ b/utils/pageVisibility.js
@@ -4,7 +4,12 @@ class PageVisible {
     this.hidden = 'hidden'
     this.visibilityChange = 'visibilitychange'
     this.visibilitySupported()
-    this.onVisible()
+    
+    if (this.visible) {
+      this.onVisible()
+    } else {
+      throw new Error('Not support visibilitychange, Please double check your browser!')
+    }
   }
 
   visibilitySupported() {

From 7f38ba7d8c442482e119bb04014dfff066601f08 Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Tue, 17 Sep 2019 23:50:09 +0800
Subject: [PATCH 07/56] feat: add some string func

---
 utils/camelize.js   |  7 +++++++
 utils/dasherize.js  |  6 ++++++
 utils/parsequery.js | 40 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 53 insertions(+)
 create mode 100644 utils/camelize.js
 create mode 100644 utils/dasherize.js
 create mode 100644 utils/parsequery.js

diff --git a/utils/camelize.js b/utils/camelize.js
new file mode 100644
index 0000000..ae3045a
--- /dev/null
+++ b/utils/camelize.js
@@ -0,0 +1,7 @@
+function camelize (str) {
+  return str.replace(/[-_\s]+(.)?/g, function (match, c) {
+    return c ? c.toUpperCase() : ''
+  })
+}
+
+console.log('result:', camelize('__--hello--_--world--'))
\ No newline at end of file
diff --git a/utils/dasherize.js b/utils/dasherize.js
new file mode 100644
index 0000000..7b3aaaf
--- /dev/null
+++ b/utils/dasherize.js
@@ -0,0 +1,6 @@
+function dasherize (str) {
+  // .replace(/[-_\s]+/g, '-') no used
+  return str.replace(/([A-Z])/g, '-$1').replace(/[-_\s]+/g, '-').toLowerCase();
+}
+
+console.log( dasherize('MozTransform') );
\ No newline at end of file
diff --git a/utils/parsequery.js b/utils/parsequery.js
new file mode 100644
index 0000000..f9d71af
--- /dev/null
+++ b/utils/parsequery.js
@@ -0,0 +1,40 @@
+const flatten = (arr, max = 1) => 
+  arr.reduce((initial, curr, index) => 
+  Array.isArray(curr) ? initial.concat(flatten(curr)) : initial.concat(curr), [])
+
+const parseQuery = (query) => {
+  // need to double check this regular
+  const regexp = /(\w+)=([^&]+)/g
+  const result = {}
+  let match
+
+  while(match = regexp.exec(query)) {
+    let key = match[1], value = match[2].replace(/\n/g, '')
+    result[key] ? result[key] = flatten([result[key], value]) : result[key] = value
+  }
+
+  return result
+}
+const query = `
+https://www.baidu.com/s?ie=utf8&f=8&f=90&rsv_bp=1&rsv_idx=1&rsv_bp=1&tn=baidu&wd=%E6%B0%B4%E7%94%B5%E8%B4%B9&rsv_pq=c7797024000434a8&rsv_t=b786FJnGwOOxPk7E7gsn1VbYHpmSP93UpP1470GL9ajYJkd09MOyBzSTsVk&rqlang=cn&rsv_enter=1&rsv_dl=tb&rsv_sug3=5&rsv_sug1=4&rsv_sug7=101&rsv_bp=234&rsv_sug2=0&inputT=1760&rsv_sug4=2010&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmcm9tX3VzZXIiOiJCIiwidGFyZ2V0X3VzZXIiOiJBIn0.rSWamyAYwuHCo7IFAgd1oRpSP7nzL7BF5t7ItqpKViM
+`.split('?')[1]
+
+console.log(parseQuery(query))
+
+// { ie: 'utf8',
+//   f: [ '8', '90' ],
+//   rsv_bp: [ '1', '1', '234' ],
+//   rsv_idx: '1',
+//   tn: 'baidu',
+//   rsv_pq: 'c7797024000434a8',
+//   rsv_t: 'b786FJnGwOOxPk7E7gsn1VbYHpmSP93UpP1470GL9ajYJkd09MOyBzSTsVk',
+//   rqlang: 'cn',
+//   rsv_enter: '1',
+//   rsv_dl: 'tb',
+//   rsv_sug3: '5',
+//   rsv_sug1: '4',
+//   rsv_sug7: '101',
+//   rsv_sug2: '0',
+//   inputT: '1760',
+//   rsv_sug4: '2010' 
+// }
\ No newline at end of file

From a4e7ce29fe4dc884947733d79a0a9a2ba3c209bd Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Fri, 20 Sep 2019 00:55:25 +0800
Subject: [PATCH 08/56] feat: add component

---
 web/.eslintrc.js                       |  1 -
 web/src/App.js                         | 21 ++++++++++++++++++---
 web/src/__test__/index.test.js         |  6 +++---
 web/src/components/Conditions/index.js |  9 +++++++++
 web/src/components/Toggles/index.js    | 16 ++++++++++++++++
 web/src/components/Toggles/toggles.js  |  4 ++++
 web/src/shared/Header/index.js         |  6 ++----
 web/src/utils/parseQuery.js            | 23 +++++++++++++++++++++++
 8 files changed, 75 insertions(+), 11 deletions(-)
 create mode 100644 web/src/components/Conditions/index.js
 create mode 100644 web/src/components/Toggles/index.js
 create mode 100644 web/src/components/Toggles/toggles.js
 create mode 100644 web/src/utils/parseQuery.js

diff --git a/web/.eslintrc.js b/web/.eslintrc.js
index 5795a19..125a750 100644
--- a/web/.eslintrc.js
+++ b/web/.eslintrc.js
@@ -21,7 +21,6 @@ module.exports = {
     "indent": ["error", 2],
     'generator-star-spacing': 'off',
     "quotes": ["error", "single"],
-    "eqeqeq": 2,
     "default-case": 2
   }
 }
\ No newline at end of file
diff --git a/web/src/App.js b/web/src/App.js
index 2e16bcb..7b90717 100644
--- a/web/src/App.js
+++ b/web/src/App.js
@@ -1,14 +1,29 @@
 import React from 'react'
+import { FeatureToggle } from './components/toggles'
+import { Conditions } from './components/conditions'
 import './App.scss'
 
 class App extends React.Component {
-  render(){
+  render() {
     return (
       <div className="magic-program">
-        <div className="magic-program_title">Magic Programming</div>
+        <FeatureToggle toggleName="breadcrumbToggles">
+          {isToggleOn =>
+            isToggleOn ? (
+              <div className="magic-program_title">Hard Code</div>
+            ) : (
+              <div className="magic-program_title">Magic Programming</div>
+            )
+          }
+        </FeatureToggle>
+        <Conditions
+          data={{ isLogin: true }}
+          yes={<div>我是组件Conditions, 我的状态是Yes</div>}
+          no={<div>我是组件Conditions, 我的状态是No</div>}
+        />
       </div>
     )
-  } 
+  }
 }
 
 export default App
diff --git a/web/src/__test__/index.test.js b/web/src/__test__/index.test.js
index b09ea3b..ed1951d 100644
--- a/web/src/__test__/index.test.js
+++ b/web/src/__test__/index.test.js
@@ -1,5 +1,5 @@
-import React from "react"
-import { shallow } from "enzyme"
+import React from 'react'
+import { shallow } from 'enzyme'
 import App from '../App'
 
 describe('App', () => {
@@ -8,4 +8,4 @@ describe('App', () => {
   it('should render correct title', () => {
     expect(wrapper.find('.magin-program_title').text()).toBe('Ftb React Demo')
   })
-})
\ No newline at end of file
+})
diff --git a/web/src/components/Conditions/index.js b/web/src/components/Conditions/index.js
new file mode 100644
index 0000000..c014a4d
--- /dev/null
+++ b/web/src/components/Conditions/index.js
@@ -0,0 +1,9 @@
+import React from 'react'
+
+export const Conditions = props => {
+  const { data, yes, no } = props
+  // 假设data可以判断用户相关信息
+  const { isLogin } = data
+
+  return isLogin ? yes : no || null
+}
diff --git a/web/src/components/Toggles/index.js b/web/src/components/Toggles/index.js
new file mode 100644
index 0000000..bac276d
--- /dev/null
+++ b/web/src/components/Toggles/index.js
@@ -0,0 +1,16 @@
+import React from 'react'
+import toggles from './toggles.js'
+import parseQuery from '../../utils/parseQuery'
+
+export const FeatureToggle = props => {
+  const { toggleName } = props
+  const parseQueryValue = parseQuery(window.location.href)
+  let isToggleOn
+
+  if (!toggles.features.includes(toggleName)) {
+    isToggleOn = false
+  }
+  isToggleOn =
+    parseQueryValue[toggleName] && parseQueryValue[toggleName] === 'true' ? true : false || false
+  return <React.Fragment>{props.children(isToggleOn)}</React.Fragment>
+}
diff --git a/web/src/components/Toggles/toggles.js b/web/src/components/Toggles/toggles.js
new file mode 100644
index 0000000..a30623d
--- /dev/null
+++ b/web/src/components/Toggles/toggles.js
@@ -0,0 +1,4 @@
+export default {
+  // set the toggle name
+  features: ['breadcrumbToggles']
+}
diff --git a/web/src/shared/Header/index.js b/web/src/shared/Header/index.js
index 1f30699..a7dca61 100644
--- a/web/src/shared/Header/index.js
+++ b/web/src/shared/Header/index.js
@@ -2,7 +2,5 @@ import React from 'react'
 import './index.scss'
 
 export const Header = () => {
-  return (
-    <div>Header</div>
-  )
-}
\ No newline at end of file
+  return <div>Header</div>
+}
diff --git a/web/src/utils/parseQuery.js b/web/src/utils/parseQuery.js
new file mode 100644
index 0000000..d0448e8
--- /dev/null
+++ b/web/src/utils/parseQuery.js
@@ -0,0 +1,23 @@
+const flatten = (arr, max = 1) =>
+  arr.reduce(
+    (initial, curr, index) =>
+      Array.isArray(curr) ? initial.concat(flatten(curr)) : initial.concat(curr),
+    []
+  )
+
+const parseQuery = query => {
+  // need to double check this regular
+  const regexp = /(\w+)=([^&]+)/g
+  const result = {}
+  let match
+
+  while ((match = regexp.exec(query))) {
+    let key = match[1],
+      value = match[2].replace(/\n/g, '')
+    result[key] ? (result[key] = flatten([result[key], value])) : (result[key] = value)
+  }
+
+  return result
+}
+
+export default parseQuery

From dcc5abf11a8cd2b78750f53eb5c2ec1df0bd0578 Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Tue, 24 Sep 2019 23:05:00 +0800
Subject: [PATCH 09/56] feat: hooks components

---
 web/src/App.js                           | 34 ++++++++----------------
 web/src/App.scss                         | 32 ++++++++++++++++++----
 web/src/components/Conditions/example.js | 17 ++++++++++++
 web/src/components/Toggles/example.js    | 26 ++++++++++++++++++
 web/src/hooks/click-outside/example.js   | 15 +++++++++++
 web/src/hooks/click-outside/index.js     | 15 +++++++++++
 web/src/shared/Layout/index.js           |  7 +++++
 7 files changed, 118 insertions(+), 28 deletions(-)
 create mode 100644 web/src/components/Conditions/example.js
 create mode 100644 web/src/components/Toggles/example.js
 create mode 100644 web/src/hooks/click-outside/example.js
 create mode 100644 web/src/hooks/click-outside/index.js
 create mode 100644 web/src/shared/Layout/index.js

diff --git a/web/src/App.js b/web/src/App.js
index 7b90717..607c981 100644
--- a/web/src/App.js
+++ b/web/src/App.js
@@ -1,29 +1,17 @@
 import React from 'react'
-import { FeatureToggle } from './components/toggles'
-import { Conditions } from './components/conditions'
+import FeatureToggle from './components/toggles/example'
+import Conditions from './components/conditions/example'
+import { ClickBox } from './hooks/click-outside/example'
 import './App.scss'
 
-class App extends React.Component {
-  render() {
-    return (
-      <div className="magic-program">
-        <FeatureToggle toggleName="breadcrumbToggles">
-          {isToggleOn =>
-            isToggleOn ? (
-              <div className="magic-program_title">Hard Code</div>
-            ) : (
-              <div className="magic-program_title">Magic Programming</div>
-            )
-          }
-        </FeatureToggle>
-        <Conditions
-          data={{ isLogin: true }}
-          yes={<div>我是组件Conditions, 我的状态是Yes</div>}
-          no={<div>我是组件Conditions, 我的状态是No</div>}
-        />
-      </div>
-    )
-  }
+const App = () => {
+  return (
+    <div className="magic-program">
+      <FeatureToggle />
+      <Conditions />
+      <ClickBox onClickOutside={() => console.log('You clicked me!')} />
+    </div>
+  )
 }
 
 export default App
diff --git a/web/src/App.scss b/web/src/App.scss
index 0f5f259..d83bbff 100644
--- a/web/src/App.scss
+++ b/web/src/App.scss
@@ -1,10 +1,32 @@
+* {
+  margin: 0;
+  padding: 0;
+  box-sizing: border-box;
+}
 .magic-program {
-  text-align: center;
-  max-width: 640px;
+  max-width: 100%;
   margin: 0 auto;
+  display: flex;
+  justify-content: flex-start;
+  flex-wrap: wrap;
 
-  &_title {
-    font-size: 26px;
-    color: #5a5a5a;
+  .layout-default {
+    max-width: 15%;
+    border: 1px solid #666;
+    padding: 10px;
+    margin: 10px;
+    font-size: 16px;
+    min-height: 60px;
+    line-height: 1.5;
+
+    button {
+      outline: none;
+      font-size: 16px;
+      color: #fff;
+      padding: 8px 10px;
+      background-color: #19cfd8;
+      border: none;
+      cursor: pointer;
+    }
   }
 }
\ No newline at end of file
diff --git a/web/src/components/Conditions/example.js b/web/src/components/Conditions/example.js
new file mode 100644
index 0000000..2ee748f
--- /dev/null
+++ b/web/src/components/Conditions/example.js
@@ -0,0 +1,17 @@
+import React, { useState } from 'react'
+import Layout from '../../shared/Layout'
+import { Conditions } from './index'
+
+export default () => {
+  const [status, setStatus] = useState(true)
+  return (
+    <Layout>
+      <Conditions
+        data={{ isLogin: status }}
+        yes={<div>我是组件Conditions, 我的状态是Yes</div>}
+        no={<div>我是组件Conditions, 我的状态是No</div>}
+      />
+      <button onClick={() => (status ? setStatus(false) : setStatus(true))}>点击切换状态</button>
+    </Layout>
+  )
+}
diff --git a/web/src/components/Toggles/example.js b/web/src/components/Toggles/example.js
new file mode 100644
index 0000000..3107feb
--- /dev/null
+++ b/web/src/components/Toggles/example.js
@@ -0,0 +1,26 @@
+import React from 'react'
+import Layout from '../../shared/Layout'
+import { FeatureToggle } from './index'
+
+export default () => {
+  return (
+    <Layout>
+      <FeatureToggle toggleName="breadcrumbToggles">
+        {isToggleOn =>
+          isToggleOn ? (
+            <div className="magic-program_title">
+              😝赶快切换回来吧!!!😝
+              <br />
+              <a href="/?breadcrumbToggles=false">false</a>
+            </div>
+          ) : (
+            <div className="magic-program_title">
+              地址栏用query可以切换我的显示 ?breadcrumbToggles=true <br />
+              <a href="/?breadcrumbToggles=true">true</a>
+            </div>
+          )
+        }
+      </FeatureToggle>
+    </Layout>
+  )
+}
diff --git a/web/src/hooks/click-outside/example.js b/web/src/hooks/click-outside/example.js
new file mode 100644
index 0000000..edc8fac
--- /dev/null
+++ b/web/src/hooks/click-outside/example.js
@@ -0,0 +1,15 @@
+import React, { useRef } from 'react'
+import Layout from '../../shared/Layout'
+import { useClickOutside } from './index'
+
+export const ClickBox = ({ onClickOutside }) => {
+  const clickRef = useRef()
+  useClickOutside(clickRef, onClickOutside)
+
+  return (
+    <Layout>
+      <div>点击按钮以外的地方，都会触发事件，在控制台打印log</div>
+      <button ref={clickRef}>点击我吧</button>
+    </Layout>
+  )
+}
diff --git a/web/src/hooks/click-outside/index.js b/web/src/hooks/click-outside/index.js
new file mode 100644
index 0000000..6aadd55
--- /dev/null
+++ b/web/src/hooks/click-outside/index.js
@@ -0,0 +1,15 @@
+import { useEffect } from 'react'
+
+export const useClickOutside = (ref, callback) => {
+  const handleClick = e => {
+    if (ref.current && !ref.current.contains(e.target)) {
+      callback()
+    }
+  }
+  useEffect(() => {
+    document.addEventListener('click', handleClick)
+    return () => {
+      document.removeEventListener('click', handleClick)
+    }
+  })
+}
diff --git a/web/src/shared/Layout/index.js b/web/src/shared/Layout/index.js
new file mode 100644
index 0000000..d20d846
--- /dev/null
+++ b/web/src/shared/Layout/index.js
@@ -0,0 +1,7 @@
+import React from 'react'
+
+const Layout = ({ className = '', children }) => {
+  return <div className={`layout-default ${className}`}>{children}</div>
+}
+
+export default Layout

From 17d13b98b03e6e0a7622ae94128916405de3308e Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Wed, 25 Sep 2019 22:36:18 +0800
Subject: [PATCH 10/56] feat: add new feature

---
 web/build/webpack.base.config.js   |  8 ++++++++
 web/src/App.js                     |  8 +++++---
 web/src/hooks/is-online/example.js |  9 +++++++++
 web/src/hooks/is-online/index.js   | 26 ++++++++++++++++++++++++++
 4 files changed, 48 insertions(+), 3 deletions(-)
 create mode 100644 web/src/hooks/is-online/example.js
 create mode 100644 web/src/hooks/is-online/index.js

diff --git a/web/build/webpack.base.config.js b/web/build/webpack.base.config.js
index 1d0fd4d..a0c8169 100644
--- a/web/build/webpack.base.config.js
+++ b/web/build/webpack.base.config.js
@@ -71,6 +71,14 @@ const app = {
       }
     ]
   },
+  resolve: {
+    alias: {
+      '@': resolve('../src'),
+      '@shared': resolve('../src/shared'),
+      '@cpts': resolve('../src/components'),
+      '@hooks': resolve('../src/hooks')
+    }
+  },
   plugins: [
     new HtmlWebpackPlugin({
       template: path.resolve(__dirname, '../public/index.html')
diff --git a/web/src/App.js b/web/src/App.js
index 607c981..f325abd 100644
--- a/web/src/App.js
+++ b/web/src/App.js
@@ -1,7 +1,8 @@
 import React from 'react'
-import FeatureToggle from './components/toggles/example'
-import Conditions from './components/conditions/example'
-import { ClickBox } from './hooks/click-outside/example'
+import FeatureToggle from '@cpts/toggles/example'
+import Conditions from '@cpts/conditions/example'
+import { ClickBox } from '@hooks/click-outside/example'
+import { IsOnline } from '@hooks/is-online/example'
 import './App.scss'
 
 const App = () => {
@@ -10,6 +11,7 @@ const App = () => {
       <FeatureToggle />
       <Conditions />
       <ClickBox onClickOutside={() => console.log('You clicked me!')} />
+      <IsOnline />
     </div>
   )
 }
diff --git a/web/src/hooks/is-online/example.js b/web/src/hooks/is-online/example.js
new file mode 100644
index 0000000..2f5e4d3
--- /dev/null
+++ b/web/src/hooks/is-online/example.js
@@ -0,0 +1,9 @@
+import React from 'react'
+import Layout from '@shared/Layout'
+import { useIsOnline } from './index'
+
+export const IsOnline = () => {
+  const status = useIsOnline()
+
+  return <Layout>你现在的网络状态: {status ? '在线' : '断网'}</Layout>
+}
diff --git a/web/src/hooks/is-online/index.js b/web/src/hooks/is-online/index.js
new file mode 100644
index 0000000..318ba75
--- /dev/null
+++ b/web/src/hooks/is-online/index.js
@@ -0,0 +1,26 @@
+import React, { useState, useEffect } from 'react'
+
+const getOnlineStatus = () => {
+  return typeof navigator !== 'undefined' && navigator.onLine === 'boolean'
+    ? navigator.onLine
+    : true
+}
+
+export const useIsOnline = () => {
+  const [status, setStatus] = useState(getOnlineStatus())
+
+  const setOnline = () => setStatus(true)
+  const setOffline = () => setStatus(false)
+
+  useEffect(() => {
+    window.addEventListener('online', setOnline)
+    window.addEventListener('offline', setOffline)
+
+    return () => {
+      window.removeEventListener('online', setOnline)
+      window.removeEventListener('offline', setOffline)
+    }
+  }, [])
+
+  return status
+}

From a0d0ad1cdf3f7650159360974c4bb6cfa2980779 Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Wed, 25 Sep 2019 23:54:52 +0800
Subject: [PATCH 11/56] feat: use antd

---
 web/babel.config.js                           | 10 ++++-
 web/package.json                              |  4 +-
 web/src/App.js                                | 27 ++++++++++----
 web/src/App.scss                              | 37 +++++++------------
 web/src/components/Conditions/example.js      | 17 +++++----
 web/src/components/Toggles/example.js         | 26 -------------
 web/src/components/feature-toggle/example.js  | 32 ++++++++++++++++
 .../{Toggles => feature-toggle}/index.js      |  0
 .../{Toggles => feature-toggle}/toggles.js    |  0
 web/src/hooks/click-outside/example.js        |  9 +++--
 web/src/hooks/is-online/example.js            |  8 +++-
 web/src/shared/Layout/index.js                |  6 ++-
 12 files changed, 102 insertions(+), 74 deletions(-)
 delete mode 100644 web/src/components/Toggles/example.js
 create mode 100644 web/src/components/feature-toggle/example.js
 rename web/src/components/{Toggles => feature-toggle}/index.js (100%)
 rename web/src/components/{Toggles => feature-toggle}/toggles.js (100%)

diff --git a/web/babel.config.js b/web/babel.config.js
index 095c9c4..79024fa 100644
--- a/web/babel.config.js
+++ b/web/babel.config.js
@@ -1,4 +1,12 @@
 module.exports = {
   presets: ['@babel/preset-env', '@babel/preset-react'],
-  plugins: ['@babel/plugin-proposal-class-properties', '@babel/plugin-transform-modules-commonjs']
+  plugins: [
+    '@babel/plugin-proposal-class-properties',
+    '@babel/plugin-transform-modules-commonjs',
+    ["import", {
+      "libraryName": "antd",
+      "libraryDirectory": "es",
+      "style": "css"
+    }]
+  ]
 }
\ No newline at end of file
diff --git a/web/package.json b/web/package.json
index c5deb11..37b4ceb 100644
--- a/web/package.json
+++ b/web/package.json
@@ -11,6 +11,7 @@
     "build": "cross-env NODE_ENV=production webpack --config build/webpack.prod.config"
   },
   "dependencies": {
+    "antd": "^3.23.4",
     "react": "^16.8.6",
     "react-dom": "^16.8.6",
     "react-router": "^5.0.1",
@@ -29,6 +30,7 @@
     "babel-eslint": "^10.0.2",
     "babel-jest": "^24.8.0",
     "babel-loader": "^8.0.6",
+    "babel-plugin-import": "^1.12.2",
     "chalk": "^2.4.2",
     "copy-webpack-plugin": "^5.0.3",
     "cross-env": "^5.2.0",
@@ -53,8 +55,8 @@
     "style-loader": "^0.23.1",
     "uglifyjs-webpack-plugin": "^2.1.3",
     "url-loader": "^2.0.0",
-    "webpack-auto-find-port": "0.0.5",
     "webpack": "^4.33.0",
+    "webpack-auto-find-port": "0.0.5",
     "webpack-cli": "^3.3.3",
     "webpack-dev-server": "^3.7.0",
     "webpack-merge": "^4.2.1"
diff --git a/web/src/App.js b/web/src/App.js
index f325abd..593405d 100644
--- a/web/src/App.js
+++ b/web/src/App.js
@@ -1,5 +1,6 @@
-import React from 'react'
-import FeatureToggle from '@cpts/toggles/example'
+import React, { Fragment } from 'react'
+import { Row, Col } from 'antd'
+import FeatureToggle from '@cpts/feature-toggle/example'
 import Conditions from '@cpts/conditions/example'
 import { ClickBox } from '@hooks/click-outside/example'
 import { IsOnline } from '@hooks/is-online/example'
@@ -7,12 +8,22 @@ import './App.scss'
 
 const App = () => {
   return (
-    <div className="magic-program">
-      <FeatureToggle />
-      <Conditions />
-      <ClickBox onClickOutside={() => console.log('You clicked me!')} />
-      <IsOnline />
-    </div>
+    <Fragment>
+      <Row gutter={24} align="middle">
+        <Col span={3}>
+          <FeatureToggle />
+        </Col>
+        <Col span={3}>
+          <Conditions />
+        </Col>
+        <Col span={3}>
+          <ClickBox onClickOutside={() => console.log('You clicked me!')} />
+        </Col>
+        <Col span={3}>
+          <IsOnline />
+        </Col>
+      </Row>
+    </Fragment>
   )
 }
 
diff --git a/web/src/App.scss b/web/src/App.scss
index d83bbff..6ceecb7 100644
--- a/web/src/App.scss
+++ b/web/src/App.scss
@@ -3,30 +3,19 @@
   padding: 0;
   box-sizing: border-box;
 }
-.magic-program {
-  max-width: 100%;
-  margin: 0 auto;
-  display: flex;
-  justify-content: flex-start;
-  flex-wrap: wrap;
 
-  .layout-default {
-    max-width: 15%;
-    border: 1px solid #666;
-    padding: 10px;
-    margin: 10px;
-    font-size: 16px;
-    min-height: 60px;
-    line-height: 1.5;
+body {
+  padding: 20px;
+}
+
+.layout-default {
+  font-size: 16px;
+  border: 1px solid #53d5c1;
+  padding: 10px;
+  border-radius: 6px;
+  height: auto;
+  word-wrap: break-word;
+}
 
-    button {
-      outline: none;
-      font-size: 16px;
-      color: #fff;
-      padding: 8px 10px;
-      background-color: #19cfd8;
-      border: none;
-      cursor: pointer;
-    }
-  }
+.layout-innder-default {
 }
\ No newline at end of file
diff --git a/web/src/components/Conditions/example.js b/web/src/components/Conditions/example.js
index 2ee748f..32b0c75 100644
--- a/web/src/components/Conditions/example.js
+++ b/web/src/components/Conditions/example.js
@@ -1,17 +1,20 @@
 import React, { useState } from 'react'
-import Layout from '../../shared/Layout'
+import { Button } from 'antd'
+import { Layout, InnerContent } from '@shared/layout'
 import { Conditions } from './index'
 
 export default () => {
   const [status, setStatus] = useState(true)
   return (
     <Layout>
-      <Conditions
-        data={{ isLogin: status }}
-        yes={<div>我是组件Conditions, 我的状态是Yes</div>}
-        no={<div>我是组件Conditions, 我的状态是No</div>}
-      />
-      <button onClick={() => (status ? setStatus(false) : setStatus(true))}>点击切换状态</button>
+      <InnerContent>
+        <Conditions
+          data={{ isLogin: status }}
+          yes={<div>我是组件Conditions, 我的状态是Yes</div>}
+          no={<div>我是组件Conditions, 我的状态是No</div>}
+        />
+      </InnerContent>
+      <Button onClick={() => (status ? setStatus(false) : setStatus(true))}>点击切换状态</Button>
     </Layout>
   )
 }
diff --git a/web/src/components/Toggles/example.js b/web/src/components/Toggles/example.js
deleted file mode 100644
index 3107feb..0000000
--- a/web/src/components/Toggles/example.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import React from 'react'
-import Layout from '../../shared/Layout'
-import { FeatureToggle } from './index'
-
-export default () => {
-  return (
-    <Layout>
-      <FeatureToggle toggleName="breadcrumbToggles">
-        {isToggleOn =>
-          isToggleOn ? (
-            <div className="magic-program_title">
-              😝赶快切换回来吧!!!😝
-              <br />
-              <a href="/?breadcrumbToggles=false">false</a>
-            </div>
-          ) : (
-            <div className="magic-program_title">
-              地址栏用query可以切换我的显示 ?breadcrumbToggles=true <br />
-              <a href="/?breadcrumbToggles=true">true</a>
-            </div>
-          )
-        }
-      </FeatureToggle>
-    </Layout>
-  )
-}
diff --git a/web/src/components/feature-toggle/example.js b/web/src/components/feature-toggle/example.js
new file mode 100644
index 0000000..bc92b8f
--- /dev/null
+++ b/web/src/components/feature-toggle/example.js
@@ -0,0 +1,32 @@
+import React, { Fragment } from 'react'
+import { Button } from 'antd'
+import { Layout, InnerContent } from '@shared/layout'
+import { FeatureToggle } from './index'
+
+export default () => {
+  return (
+    <Layout>
+      <InnerContent>
+        <FeatureToggle toggleName="breadcrumbToggles">
+          {isToggleOn =>
+            isToggleOn ? (
+              <Fragment>
+                <p>😝赶快切换回来吧!!!😝</p>
+                <Button>
+                  <a href="/?breadcrumbToggles=false">false</a>
+                </Button>
+              </Fragment>
+            ) : (
+              <Fragment>
+                <p>地址栏用query可以切换我的显示 ?breadcrumbToggles=true</p>
+                <Button>
+                  <a href="/?breadcrumbToggles=true">true</a>
+                </Button>
+              </Fragment>
+            )
+          }
+        </FeatureToggle>
+      </InnerContent>
+    </Layout>
+  )
+}
diff --git a/web/src/components/Toggles/index.js b/web/src/components/feature-toggle/index.js
similarity index 100%
rename from web/src/components/Toggles/index.js
rename to web/src/components/feature-toggle/index.js
diff --git a/web/src/components/Toggles/toggles.js b/web/src/components/feature-toggle/toggles.js
similarity index 100%
rename from web/src/components/Toggles/toggles.js
rename to web/src/components/feature-toggle/toggles.js
diff --git a/web/src/hooks/click-outside/example.js b/web/src/hooks/click-outside/example.js
index edc8fac..94c49a8 100644
--- a/web/src/hooks/click-outside/example.js
+++ b/web/src/hooks/click-outside/example.js
@@ -1,5 +1,6 @@
 import React, { useRef } from 'react'
-import Layout from '../../shared/Layout'
+import { Button } from 'antd'
+import { Layout, InnerContent } from '@shared/layout'
 import { useClickOutside } from './index'
 
 export const ClickBox = ({ onClickOutside }) => {
@@ -8,8 +9,10 @@ export const ClickBox = ({ onClickOutside }) => {
 
   return (
     <Layout>
-      <div>点击按钮以外的地方，都会触发事件，在控制台打印log</div>
-      <button ref={clickRef}>点击我吧</button>
+      <InnerContent>
+        <p>点击按钮以外的地方，都会触发事件，在控制台打印log</p>
+      </InnerContent>
+      <Button ref={clickRef}>点击我吧</Button>
     </Layout>
   )
 }
diff --git a/web/src/hooks/is-online/example.js b/web/src/hooks/is-online/example.js
index 2f5e4d3..ab0e7bd 100644
--- a/web/src/hooks/is-online/example.js
+++ b/web/src/hooks/is-online/example.js
@@ -1,9 +1,13 @@
 import React from 'react'
-import Layout from '@shared/Layout'
+import { Layout, InnerContent } from '@shared/layout'
 import { useIsOnline } from './index'
 
 export const IsOnline = () => {
   const status = useIsOnline()
 
-  return <Layout>你现在的网络状态: {status ? '在线' : '断网'}</Layout>
+  return (
+    <Layout>
+      <InnerContent>你现在的网络状态: {status ? '在线' : '断网'}</InnerContent>
+    </Layout>
+  )
 }
diff --git a/web/src/shared/Layout/index.js b/web/src/shared/Layout/index.js
index d20d846..c65615b 100644
--- a/web/src/shared/Layout/index.js
+++ b/web/src/shared/Layout/index.js
@@ -1,7 +1,9 @@
 import React from 'react'
 
-const Layout = ({ className = '', children }) => {
+export const Layout = ({ className = '', children }) => {
   return <div className={`layout-default ${className}`}>{children}</div>
 }
 
-export default Layout
+export const InnerContent = ({ children }) => {
+  return <div className="layout-innder-default">{children}</div>
+}

From b6c137a972bca3352abf91552c2dd7b06955bf97 Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Fri, 27 Sep 2019 22:48:38 +0800
Subject: [PATCH 12/56] refactor: refactor folder

---
 {web => react-code}/.eslintignore             |  0
 {web => react-code}/.eslintrc.js              |  0
 {web => react-code}/.gitignore                |  0
 {web => react-code}/.postcssrc.js             |  0
 {web => react-code}/.prettierignore           |  0
 {web => react-code}/.prettierrc.js            |  0
 {web => react-code}/LICENSE                   |  0
 {web => react-code}/README.md                 |  0
 {web => react-code}/babel.config.js           |  0
 {web => react-code}/build/utils.js            |  0
 .../build/webpack.base.config.js              |  0
 .../build/webpack.dev.config.js               |  0
 .../build/webpack.prod.config.js              |  0
 {web => react-code}/enzyme.setup.js           |  0
 {web => react-code}/jest.config.js            |  0
 {web => react-code}/jest.styleMock.js         |  0
 {web => react-code}/package.json              |  0
 {web => react-code}/public/index.html         |  0
 {web => react-code}/src/App.js                | 12 ++++--
 {web => react-code}/src/App.scss              |  7 +++-
 .../src/__test__/index.test.js                |  0
 .../src/components/conditions}/example.js     | 17 +++++---
 .../src/components/conditions}/index.js       |  0
 .../src/components/feature-toggle/example.js  | 15 +++----
 .../src/components/feature-toggle/index.js    |  0
 .../src/components/feature-toggle/toggles.js  |  0
 react-code/src/hooks/click-outside/example.js | 23 +++++++++++
 .../src/hooks/click-outside/index.js          |  0
 .../src/hooks/crontrolled-input/example.js    | 34 ++++++++++++++++
 .../src/hooks/crontrolled-input/index.js      | 35 ++++++++++++++++
 react-code/src/hooks/is-online/example.js     | 14 +++++++
 .../src/hooks/is-online/index.js              |  0
 {web => react-code}/src/index.js              |  0
 .../src/shared/header}/index.js               |  0
 .../src/shared/header}/index.scss             |  0
 react-code/src/shared/layout/index.js         | 40 +++++++++++++++++++
 {web => react-code}/src/utils/parseQuery.js   |  0
 web/src/hooks/click-outside/example.js        | 18 ---------
 web/src/hooks/is-online/example.js            | 13 ------
 web/src/shared/Layout/index.js                |  9 -----
 40 files changed, 179 insertions(+), 58 deletions(-)
 rename {web => react-code}/.eslintignore (100%)
 rename {web => react-code}/.eslintrc.js (100%)
 rename {web => react-code}/.gitignore (100%)
 rename {web => react-code}/.postcssrc.js (100%)
 rename {web => react-code}/.prettierignore (100%)
 rename {web => react-code}/.prettierrc.js (100%)
 rename {web => react-code}/LICENSE (100%)
 rename {web => react-code}/README.md (100%)
 rename {web => react-code}/babel.config.js (100%)
 rename {web => react-code}/build/utils.js (100%)
 rename {web => react-code}/build/webpack.base.config.js (100%)
 rename {web => react-code}/build/webpack.dev.config.js (100%)
 rename {web => react-code}/build/webpack.prod.config.js (100%)
 rename {web => react-code}/enzyme.setup.js (100%)
 rename {web => react-code}/jest.config.js (100%)
 rename {web => react-code}/jest.styleMock.js (100%)
 rename {web => react-code}/package.json (100%)
 rename {web => react-code}/public/index.html (100%)
 rename {web => react-code}/src/App.js (58%)
 rename {web => react-code}/src/App.scss (74%)
 rename {web => react-code}/src/__test__/index.test.js (100%)
 rename {web/src/components/Conditions => react-code/src/components/conditions}/example.js (57%)
 rename {web/src/components/Conditions => react-code/src/components/conditions}/index.js (100%)
 rename {web => react-code}/src/components/feature-toggle/example.js (77%)
 rename {web => react-code}/src/components/feature-toggle/index.js (100%)
 rename {web => react-code}/src/components/feature-toggle/toggles.js (100%)
 create mode 100644 react-code/src/hooks/click-outside/example.js
 rename {web => react-code}/src/hooks/click-outside/index.js (100%)
 create mode 100644 react-code/src/hooks/crontrolled-input/example.js
 create mode 100644 react-code/src/hooks/crontrolled-input/index.js
 create mode 100644 react-code/src/hooks/is-online/example.js
 rename {web => react-code}/src/hooks/is-online/index.js (100%)
 rename {web => react-code}/src/index.js (100%)
 rename {web/src/shared/Header => react-code/src/shared/header}/index.js (100%)
 rename {web/src/shared/Header => react-code/src/shared/header}/index.scss (100%)
 create mode 100644 react-code/src/shared/layout/index.js
 rename {web => react-code}/src/utils/parseQuery.js (100%)
 delete mode 100644 web/src/hooks/click-outside/example.js
 delete mode 100644 web/src/hooks/is-online/example.js
 delete mode 100644 web/src/shared/Layout/index.js

diff --git a/web/.eslintignore b/react-code/.eslintignore
similarity index 100%
rename from web/.eslintignore
rename to react-code/.eslintignore
diff --git a/web/.eslintrc.js b/react-code/.eslintrc.js
similarity index 100%
rename from web/.eslintrc.js
rename to react-code/.eslintrc.js
diff --git a/web/.gitignore b/react-code/.gitignore
similarity index 100%
rename from web/.gitignore
rename to react-code/.gitignore
diff --git a/web/.postcssrc.js b/react-code/.postcssrc.js
similarity index 100%
rename from web/.postcssrc.js
rename to react-code/.postcssrc.js
diff --git a/web/.prettierignore b/react-code/.prettierignore
similarity index 100%
rename from web/.prettierignore
rename to react-code/.prettierignore
diff --git a/web/.prettierrc.js b/react-code/.prettierrc.js
similarity index 100%
rename from web/.prettierrc.js
rename to react-code/.prettierrc.js
diff --git a/web/LICENSE b/react-code/LICENSE
similarity index 100%
rename from web/LICENSE
rename to react-code/LICENSE
diff --git a/web/README.md b/react-code/README.md
similarity index 100%
rename from web/README.md
rename to react-code/README.md
diff --git a/web/babel.config.js b/react-code/babel.config.js
similarity index 100%
rename from web/babel.config.js
rename to react-code/babel.config.js
diff --git a/web/build/utils.js b/react-code/build/utils.js
similarity index 100%
rename from web/build/utils.js
rename to react-code/build/utils.js
diff --git a/web/build/webpack.base.config.js b/react-code/build/webpack.base.config.js
similarity index 100%
rename from web/build/webpack.base.config.js
rename to react-code/build/webpack.base.config.js
diff --git a/web/build/webpack.dev.config.js b/react-code/build/webpack.dev.config.js
similarity index 100%
rename from web/build/webpack.dev.config.js
rename to react-code/build/webpack.dev.config.js
diff --git a/web/build/webpack.prod.config.js b/react-code/build/webpack.prod.config.js
similarity index 100%
rename from web/build/webpack.prod.config.js
rename to react-code/build/webpack.prod.config.js
diff --git a/web/enzyme.setup.js b/react-code/enzyme.setup.js
similarity index 100%
rename from web/enzyme.setup.js
rename to react-code/enzyme.setup.js
diff --git a/web/jest.config.js b/react-code/jest.config.js
similarity index 100%
rename from web/jest.config.js
rename to react-code/jest.config.js
diff --git a/web/jest.styleMock.js b/react-code/jest.styleMock.js
similarity index 100%
rename from web/jest.styleMock.js
rename to react-code/jest.styleMock.js
diff --git a/web/package.json b/react-code/package.json
similarity index 100%
rename from web/package.json
rename to react-code/package.json
diff --git a/web/public/index.html b/react-code/public/index.html
similarity index 100%
rename from web/public/index.html
rename to react-code/public/index.html
diff --git a/web/src/App.js b/react-code/src/App.js
similarity index 58%
rename from web/src/App.js
rename to react-code/src/App.js
index 593405d..f4eb7aa 100644
--- a/web/src/App.js
+++ b/react-code/src/App.js
@@ -1,9 +1,10 @@
 import React, { Fragment } from 'react'
 import { Row, Col } from 'antd'
-import FeatureToggle from '@cpts/feature-toggle/example'
-import Conditions from '@cpts/conditions/example'
-import { ClickBox } from '@hooks/click-outside/example'
-import { IsOnline } from '@hooks/is-online/example'
+import FeatureToggle from './components/feature-toggle/example'
+import Conditions from './components/conditions/example'
+import { ClickBox } from './hooks/click-outside/example'
+import { IsOnline } from './hooks/is-online/example'
+import { ControlledInputExample } from './hooks/crontrolled-input/example'
 import './App.scss'
 
 const App = () => {
@@ -22,6 +23,9 @@ const App = () => {
         <Col span={3}>
           <IsOnline />
         </Col>
+        <Col span={6}>
+          <ControlledInputExample />
+        </Col>
       </Row>
     </Fragment>
   )
diff --git a/web/src/App.scss b/react-code/src/App.scss
similarity index 74%
rename from web/src/App.scss
rename to react-code/src/App.scss
index 6ceecb7..44feaf6 100644
--- a/web/src/App.scss
+++ b/react-code/src/App.scss
@@ -8,6 +8,10 @@ body {
   padding: 20px;
 }
 
+p {
+  margin: 0;
+  padding: 0;
+}
 .layout-default {
   font-size: 16px;
   border: 1px solid #53d5c1;
@@ -17,5 +21,6 @@ body {
   word-wrap: break-word;
 }
 
-.layout-innder-default {
+.layout-inner-default {
+  margin-bottom: 25px;
 }
\ No newline at end of file
diff --git a/web/src/__test__/index.test.js b/react-code/src/__test__/index.test.js
similarity index 100%
rename from web/src/__test__/index.test.js
rename to react-code/src/__test__/index.test.js
diff --git a/web/src/components/Conditions/example.js b/react-code/src/components/conditions/example.js
similarity index 57%
rename from web/src/components/Conditions/example.js
rename to react-code/src/components/conditions/example.js
index 32b0c75..1c8ce28 100644
--- a/web/src/components/Conditions/example.js
+++ b/react-code/src/components/conditions/example.js
@@ -1,20 +1,25 @@
 import React, { useState } from 'react'
 import { Button } from 'antd'
-import { Layout, InnerContent } from '@shared/layout'
+import { Layout } from '../../shared/layout'
 import { Conditions } from './index'
 
 export default () => {
   const [status, setStatus] = useState(true)
   return (
-    <Layout>
-      <InnerContent>
+    <Layout
+      title="测试react组件条件渲染"
+      content={
         <Conditions
           data={{ isLogin: status }}
           yes={<div>我是组件Conditions, 我的状态是Yes</div>}
           no={<div>我是组件Conditions, 我的状态是No</div>}
         />
-      </InnerContent>
-      <Button onClick={() => (status ? setStatus(false) : setStatus(true))}>点击切换状态</Button>
-    </Layout>
+      }
+      actions={
+        <Button type="primary" onClick={() => (status ? setStatus(false) : setStatus(true))}>
+          点击切换状态
+        </Button>
+      }
+    />
   )
 }
diff --git a/web/src/components/Conditions/index.js b/react-code/src/components/conditions/index.js
similarity index 100%
rename from web/src/components/Conditions/index.js
rename to react-code/src/components/conditions/index.js
diff --git a/web/src/components/feature-toggle/example.js b/react-code/src/components/feature-toggle/example.js
similarity index 77%
rename from web/src/components/feature-toggle/example.js
rename to react-code/src/components/feature-toggle/example.js
index bc92b8f..df5199a 100644
--- a/web/src/components/feature-toggle/example.js
+++ b/react-code/src/components/feature-toggle/example.js
@@ -1,32 +1,33 @@
 import React, { Fragment } from 'react'
 import { Button } from 'antd'
-import { Layout, InnerContent } from '@shared/layout'
+import { Layout } from '@shared/layout'
 import { FeatureToggle } from './index'
 
 export default () => {
   return (
-    <Layout>
-      <InnerContent>
+    <Layout
+      title="Feature Toggle 多用来测试新功能"
+      content={
         <FeatureToggle toggleName="breadcrumbToggles">
           {isToggleOn =>
             isToggleOn ? (
               <Fragment>
                 <p>😝赶快切换回来吧!!!😝</p>
-                <Button>
+                <Button type="primary">
                   <a href="/?breadcrumbToggles=false">false</a>
                 </Button>
               </Fragment>
             ) : (
               <Fragment>
                 <p>地址栏用query可以切换我的显示 ?breadcrumbToggles=true</p>
-                <Button>
+                <Button type="primary">
                   <a href="/?breadcrumbToggles=true">true</a>
                 </Button>
               </Fragment>
             )
           }
         </FeatureToggle>
-      </InnerContent>
-    </Layout>
+      }
+    />
   )
 }
diff --git a/web/src/components/feature-toggle/index.js b/react-code/src/components/feature-toggle/index.js
similarity index 100%
rename from web/src/components/feature-toggle/index.js
rename to react-code/src/components/feature-toggle/index.js
diff --git a/web/src/components/feature-toggle/toggles.js b/react-code/src/components/feature-toggle/toggles.js
similarity index 100%
rename from web/src/components/feature-toggle/toggles.js
rename to react-code/src/components/feature-toggle/toggles.js
diff --git a/react-code/src/hooks/click-outside/example.js b/react-code/src/hooks/click-outside/example.js
new file mode 100644
index 0000000..97a244d
--- /dev/null
+++ b/react-code/src/hooks/click-outside/example.js
@@ -0,0 +1,23 @@
+import React, { useRef } from 'react'
+import { Button, message } from 'antd'
+import { Layout } from '@shared/layout'
+import { useClickOutside } from './index'
+
+export const ClickBox = ({ onClickOutside }) => {
+  const clickRef = useRef()
+  useClickOutside(clickRef, onClickOutside)
+
+  return (
+    <Layout
+      title="实现click outside功能"
+      content={<p>点击按钮以外的地方，都会触发事件，在控制台打印log</p>}
+      actions={
+        <span ref={clickRef}>
+          <Button type="primary" onClick={() => message.success('哈哈，点击我没用的')}>
+            点击我吧
+          </Button>
+        </span>
+      }
+    />
+  )
+}
diff --git a/web/src/hooks/click-outside/index.js b/react-code/src/hooks/click-outside/index.js
similarity index 100%
rename from web/src/hooks/click-outside/index.js
rename to react-code/src/hooks/click-outside/index.js
diff --git a/react-code/src/hooks/crontrolled-input/example.js b/react-code/src/hooks/crontrolled-input/example.js
new file mode 100644
index 0000000..5747eb8
--- /dev/null
+++ b/react-code/src/hooks/crontrolled-input/example.js
@@ -0,0 +1,34 @@
+import React, { useEffect, useState } from 'react'
+import { Button, message } from 'antd'
+import { Layout } from '../../shared/layout'
+import { ControlledInput } from './index'
+
+export const ControlledInputExample = () => {
+  const [value, setValue] = useState('')
+
+  useEffect(() => {
+    setValue(value)
+  }, [value])
+
+  const handleButtonClick = () => {
+    message.success(`Current value is: ${value}`)
+  }
+
+  return (
+    <Layout
+      title="定制化input"
+      content={
+        <ControlledInput
+          type="text"
+          placeholder="Please input..."
+          onChange={val => setValue(val)}
+        />
+      }
+      actions={
+        <Button type="primary" onClick={handleButtonClick}>
+          点击查看
+        </Button>
+      }
+    />
+  )
+}
diff --git a/react-code/src/hooks/crontrolled-input/index.js b/react-code/src/hooks/crontrolled-input/index.js
new file mode 100644
index 0000000..52b7ad8
--- /dev/null
+++ b/react-code/src/hooks/crontrolled-input/index.js
@@ -0,0 +1,35 @@
+import React, { useEffect, useState } from 'react'
+
+const style = {
+  outline: 'none',
+  border: '1px solid rgb(186, 204, 218)',
+  padding: '4px 6px',
+  width: '100%'
+}
+
+export const ControlledInput = ({
+  onChange,
+  type = 'text',
+  disabled = false,
+  readOnly = false,
+  defaultValue,
+  placeholder = ''
+}) => {
+  const [value, setValue] = useState(defaultValue)
+
+  useEffect(() => {
+    onChange(value)
+  }, [value])
+
+  return (
+    <input
+      defaultValue={defaultValue}
+      type={type}
+      disabled={disabled}
+      readOnly={readOnly}
+      placeholder={placeholder}
+      onChange={e => setValue(e.target.value)}
+      style={style}
+    />
+  )
+}
diff --git a/react-code/src/hooks/is-online/example.js b/react-code/src/hooks/is-online/example.js
new file mode 100644
index 0000000..f823214
--- /dev/null
+++ b/react-code/src/hooks/is-online/example.js
@@ -0,0 +1,14 @@
+import React from 'react'
+import { Layout } from '../../shared/layout'
+import { useIsOnline } from './index'
+
+export const IsOnline = () => {
+  const status = useIsOnline()
+
+  return (
+    <Layout
+      title="实时检测网络是否联网"
+      content={<p>你现在的网络状态: {status ? '在线' : '断网'}</p>}
+    />
+  )
+}
diff --git a/web/src/hooks/is-online/index.js b/react-code/src/hooks/is-online/index.js
similarity index 100%
rename from web/src/hooks/is-online/index.js
rename to react-code/src/hooks/is-online/index.js
diff --git a/web/src/index.js b/react-code/src/index.js
similarity index 100%
rename from web/src/index.js
rename to react-code/src/index.js
diff --git a/web/src/shared/Header/index.js b/react-code/src/shared/header/index.js
similarity index 100%
rename from web/src/shared/Header/index.js
rename to react-code/src/shared/header/index.js
diff --git a/web/src/shared/Header/index.scss b/react-code/src/shared/header/index.scss
similarity index 100%
rename from web/src/shared/Header/index.scss
rename to react-code/src/shared/header/index.scss
diff --git a/react-code/src/shared/layout/index.js b/react-code/src/shared/layout/index.js
new file mode 100644
index 0000000..77a91e8
--- /dev/null
+++ b/react-code/src/shared/layout/index.js
@@ -0,0 +1,40 @@
+import React, { Component } from 'react'
+import { Empty, Card } from 'antd'
+
+export class Layout extends Component {
+  constructor(props) {
+    super(props)
+    this.state = {
+      hasError: false
+    }
+  }
+
+  static getDerivedStateFromError(error) {
+    console.log({ error })
+    return {
+      hasError: true
+    }
+  }
+
+  componentDidCatch(error, info) {
+    console.log({
+      error,
+      info
+    })
+  }
+
+  render() {
+    if (this.state.hasError) {
+      return <Empty description={<span>当前组件渲染失败，请检查错误</span>} />
+    }
+    const { title = '', content, actions } = this.props
+    return (
+      <Card>
+        {title && <h4>{title}</h4>}
+        {content}
+        <div style={{ height: '20px' }} />
+        {actions}
+      </Card>
+    )
+  }
+}
diff --git a/web/src/utils/parseQuery.js b/react-code/src/utils/parseQuery.js
similarity index 100%
rename from web/src/utils/parseQuery.js
rename to react-code/src/utils/parseQuery.js
diff --git a/web/src/hooks/click-outside/example.js b/web/src/hooks/click-outside/example.js
deleted file mode 100644
index 94c49a8..0000000
--- a/web/src/hooks/click-outside/example.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import React, { useRef } from 'react'
-import { Button } from 'antd'
-import { Layout, InnerContent } from '@shared/layout'
-import { useClickOutside } from './index'
-
-export const ClickBox = ({ onClickOutside }) => {
-  const clickRef = useRef()
-  useClickOutside(clickRef, onClickOutside)
-
-  return (
-    <Layout>
-      <InnerContent>
-        <p>点击按钮以外的地方，都会触发事件，在控制台打印log</p>
-      </InnerContent>
-      <Button ref={clickRef}>点击我吧</Button>
-    </Layout>
-  )
-}
diff --git a/web/src/hooks/is-online/example.js b/web/src/hooks/is-online/example.js
deleted file mode 100644
index ab0e7bd..0000000
--- a/web/src/hooks/is-online/example.js
+++ /dev/null
@@ -1,13 +0,0 @@
-import React from 'react'
-import { Layout, InnerContent } from '@shared/layout'
-import { useIsOnline } from './index'
-
-export const IsOnline = () => {
-  const status = useIsOnline()
-
-  return (
-    <Layout>
-      <InnerContent>你现在的网络状态: {status ? '在线' : '断网'}</InnerContent>
-    </Layout>
-  )
-}
diff --git a/web/src/shared/Layout/index.js b/web/src/shared/Layout/index.js
deleted file mode 100644
index c65615b..0000000
--- a/web/src/shared/Layout/index.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import React from 'react'
-
-export const Layout = ({ className = '', children }) => {
-  return <div className={`layout-default ${className}`}>{children}</div>
-}
-
-export const InnerContent = ({ children }) => {
-  return <div className="layout-innder-default">{children}</div>
-}

From a724578520e6076f45cbce505e4141b72852a820 Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Sat, 28 Sep 2019 22:56:35 +0800
Subject: [PATCH 13/56] feat: add limited textarea component

---
 react-code/src/App.js                         |  4 +++
 react-code/src/hooks/is-online/example.js     |  5 +--
 .../src/hooks/limited-textarea/example.js     | 12 +++++++
 .../src/hooks/limited-textarea/index.js       | 36 +++++++++++++++++++
 4 files changed, 53 insertions(+), 4 deletions(-)
 create mode 100644 react-code/src/hooks/limited-textarea/example.js
 create mode 100644 react-code/src/hooks/limited-textarea/index.js

diff --git a/react-code/src/App.js b/react-code/src/App.js
index f4eb7aa..abae93b 100644
--- a/react-code/src/App.js
+++ b/react-code/src/App.js
@@ -5,6 +5,7 @@ import Conditions from './components/conditions/example'
 import { ClickBox } from './hooks/click-outside/example'
 import { IsOnline } from './hooks/is-online/example'
 import { ControlledInputExample } from './hooks/crontrolled-input/example'
+import { LimitedTextareaExample } from './hooks/limited-textarea/example'
 import './App.scss'
 
 const App = () => {
@@ -26,6 +27,9 @@ const App = () => {
         <Col span={6}>
           <ControlledInputExample />
         </Col>
+        <Col span={6}>
+          <LimitedTextareaExample />
+        </Col>
       </Row>
     </Fragment>
   )
diff --git a/react-code/src/hooks/is-online/example.js b/react-code/src/hooks/is-online/example.js
index f823214..5d14ec2 100644
--- a/react-code/src/hooks/is-online/example.js
+++ b/react-code/src/hooks/is-online/example.js
@@ -6,9 +6,6 @@ export const IsOnline = () => {
   const status = useIsOnline()
 
   return (
-    <Layout
-      title="实时检测网络是否联网"
-      content={<p>你现在的网络状态: {status ? '在线' : '断网'}</p>}
-    />
+    <Layout title="实时检测网络是否联网" content={<p>网络状态: {status ? '在线' : '断网'}</p>} />
   )
 }
diff --git a/react-code/src/hooks/limited-textarea/example.js b/react-code/src/hooks/limited-textarea/example.js
new file mode 100644
index 0000000..88668c3
--- /dev/null
+++ b/react-code/src/hooks/limited-textarea/example.js
@@ -0,0 +1,12 @@
+import React from 'react'
+import { Layout } from '../../shared/layout'
+import { LimitedTextarea } from './index'
+
+export const LimitedTextareaExample = () => {
+  return (
+    <Layout
+      title="限制字符输入"
+      content={<LimitedTextarea rows={5} limit={100} value="Please input your suggestions!" />}
+    />
+  )
+}
diff --git a/react-code/src/hooks/limited-textarea/index.js b/react-code/src/hooks/limited-textarea/index.js
new file mode 100644
index 0000000..5555256
--- /dev/null
+++ b/react-code/src/hooks/limited-textarea/index.js
@@ -0,0 +1,36 @@
+import React, { useState, useEffect } from 'react'
+import { Button } from 'antd'
+
+const styles = {
+  width: '100%',
+  outline: 'none',
+  border: '1px solid #333f38'
+}
+
+export const LimitedTextarea = ({ rows, cols, value, limit, name }) => {
+  const [content, setContent] = useState(value)
+
+  const setFormattedContent = text => {
+    text.length > limit ? setContent(text.slice(0, limit)) : setContent(text)
+  }
+
+  useEffect(() => {
+    setFormattedContent(content)
+  }, [])
+
+  return (
+    <div>
+      <textarea
+        style={styles}
+        name={name}
+        cols={cols}
+        rows={rows}
+        value={content}
+        onChange={event => setFormattedContent(event.target.value)}
+      />
+      <p>
+        {content.length}/{limit}
+      </p>
+    </div>
+  )
+}

From 83de1091e522d3f5715380469983172c5a587631 Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Mon, 7 Oct 2019 22:58:20 +0800
Subject: [PATCH 14/56] Add MultiselectCheckboxExample

---
 react-code/src/App.js                         |  4 ++
 .../hooks/multi-select-checkbox/example.js    | 21 ++++++++++
 .../src/hooks/multi-select-checkbox/index.js  | 39 +++++++++++++++++++
 3 files changed, 64 insertions(+)
 create mode 100644 react-code/src/hooks/multi-select-checkbox/example.js
 create mode 100644 react-code/src/hooks/multi-select-checkbox/index.js

diff --git a/react-code/src/App.js b/react-code/src/App.js
index abae93b..1d16eda 100644
--- a/react-code/src/App.js
+++ b/react-code/src/App.js
@@ -6,6 +6,7 @@ import { ClickBox } from './hooks/click-outside/example'
 import { IsOnline } from './hooks/is-online/example'
 import { ControlledInputExample } from './hooks/crontrolled-input/example'
 import { LimitedTextareaExample } from './hooks/limited-textarea/example'
+import { MultiselectCheckboxExample } from './hooks/multi-select-checkbox/example'
 import './App.scss'
 
 const App = () => {
@@ -30,6 +31,9 @@ const App = () => {
         <Col span={6}>
           <LimitedTextareaExample />
         </Col>
+        <Col span={6}>
+          <MultiselectCheckboxExample />
+        </Col>
       </Row>
     </Fragment>
   )
diff --git a/react-code/src/hooks/multi-select-checkbox/example.js b/react-code/src/hooks/multi-select-checkbox/example.js
new file mode 100644
index 0000000..5eabd3b
--- /dev/null
+++ b/react-code/src/hooks/multi-select-checkbox/example.js
@@ -0,0 +1,21 @@
+import React from 'react'
+import { Layout } from '../../shared/layout'
+import { MultiselectCheckbox } from './index'
+
+const options = [{ label: 'Item One' }, { label: 'Item Two' }]
+
+export const MultiselectCheckboxExample = () => {
+  return (
+    <Layout
+      title="多项选择"
+      content={
+        <MultiselectCheckbox
+          options={options}
+          onChange={data => {
+            console.log(data)
+          }}
+        />
+      }
+    />
+  )
+}
diff --git a/react-code/src/hooks/multi-select-checkbox/index.js b/react-code/src/hooks/multi-select-checkbox/index.js
new file mode 100644
index 0000000..edc311b
--- /dev/null
+++ b/react-code/src/hooks/multi-select-checkbox/index.js
@@ -0,0 +1,39 @@
+import React, { useState } from 'react'
+
+const styles = {
+  listContainer: {
+    listStyle: 'none',
+    paddingLeft: 0
+  },
+  itemStyle: {
+    cursor: 'pointer',
+    padding: 5
+  }
+}
+
+export const MultiselectCheckbox = ({ options, onChange }) => {
+  const [data, setData] = useState(options)
+
+  const toggle = item => {
+    data.forEach((_, key) => {
+      if (data[key].label === item.label) {
+        data[key].checked = !item.checked
+      }
+    })
+    setData([...data])
+    onChange(data)
+  }
+
+  return (
+    <ul style={styles.listContainer}>
+      {data.map(item => {
+        return (
+          <li style={styles.itemStyle} key={item.label} onClick={() => toggle(item)}>
+            <input readOnly type="checkbox" checked={item.checked || false} />
+            {item.label}
+          </li>
+        )
+      })}
+    </ul>
+  )
+}

From e04f81c8ccc45967dff09291151268975321d1c6 Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Tue, 8 Oct 2019 23:56:38 +0800
Subject: [PATCH 15/56] add password revealer

---
 react-code/src/App.js                         | 13 ++++++++++---
 .../limited-textarea/example.js               |  0
 .../limited-textarea/index.js                 |  0
 .../multi-select-checkbox/example.js          |  2 +-
 .../multi-select-checkbox/index.js            |  0
 .../components/password-revealer/example.js   | 19 +++++++++++++++++++
 .../src/components/password-revealer/index.js | 16 ++++++++++++++++
 7 files changed, 46 insertions(+), 4 deletions(-)
 rename react-code/src/{hooks => components}/limited-textarea/example.js (100%)
 rename react-code/src/{hooks => components}/limited-textarea/index.js (100%)
 rename react-code/src/{hooks => components}/multi-select-checkbox/example.js (80%)
 rename react-code/src/{hooks => components}/multi-select-checkbox/index.js (100%)
 create mode 100644 react-code/src/components/password-revealer/example.js
 create mode 100644 react-code/src/components/password-revealer/index.js

diff --git a/react-code/src/App.js b/react-code/src/App.js
index 1d16eda..6233060 100644
--- a/react-code/src/App.js
+++ b/react-code/src/App.js
@@ -5,8 +5,10 @@ import Conditions from './components/conditions/example'
 import { ClickBox } from './hooks/click-outside/example'
 import { IsOnline } from './hooks/is-online/example'
 import { ControlledInputExample } from './hooks/crontrolled-input/example'
-import { LimitedTextareaExample } from './hooks/limited-textarea/example'
-import { MultiselectCheckboxExample } from './hooks/multi-select-checkbox/example'
+import { LimitedTextareaExample } from './components/limited-textarea/example'
+import { MultiselectCheckboxExample } from './components/multi-select-checkbox/example'
+import { PasswordRevealerExample } from './components/password-revealer/example'
+
 import './App.scss'
 
 const App = () => {
@@ -31,9 +33,14 @@ const App = () => {
         <Col span={6}>
           <LimitedTextareaExample />
         </Col>
-        <Col span={6}>
+      </Row>
+      <Row gutter={24} align="middle">
+        <Col span={3}>
           <MultiselectCheckboxExample />
         </Col>
+        <Col span={3}>
+          <PasswordRevealerExample />
+        </Col>
       </Row>
     </Fragment>
   )
diff --git a/react-code/src/hooks/limited-textarea/example.js b/react-code/src/components/limited-textarea/example.js
similarity index 100%
rename from react-code/src/hooks/limited-textarea/example.js
rename to react-code/src/components/limited-textarea/example.js
diff --git a/react-code/src/hooks/limited-textarea/index.js b/react-code/src/components/limited-textarea/index.js
similarity index 100%
rename from react-code/src/hooks/limited-textarea/index.js
rename to react-code/src/components/limited-textarea/index.js
diff --git a/react-code/src/hooks/multi-select-checkbox/example.js b/react-code/src/components/multi-select-checkbox/example.js
similarity index 80%
rename from react-code/src/hooks/multi-select-checkbox/example.js
rename to react-code/src/components/multi-select-checkbox/example.js
index 5eabd3b..799bbcc 100644
--- a/react-code/src/hooks/multi-select-checkbox/example.js
+++ b/react-code/src/components/multi-select-checkbox/example.js
@@ -2,7 +2,7 @@ import React from 'react'
 import { Layout } from '../../shared/layout'
 import { MultiselectCheckbox } from './index'
 
-const options = [{ label: 'Item One' }, { label: 'Item Two' }]
+const options = [{ label: 'Item One', checked: true }, { label: 'Item Two', checked: false }]
 
 export const MultiselectCheckboxExample = () => {
   return (
diff --git a/react-code/src/hooks/multi-select-checkbox/index.js b/react-code/src/components/multi-select-checkbox/index.js
similarity index 100%
rename from react-code/src/hooks/multi-select-checkbox/index.js
rename to react-code/src/components/multi-select-checkbox/index.js
diff --git a/react-code/src/components/password-revealer/example.js b/react-code/src/components/password-revealer/example.js
new file mode 100644
index 0000000..51ca3d0
--- /dev/null
+++ b/react-code/src/components/password-revealer/example.js
@@ -0,0 +1,19 @@
+import React from 'react'
+import { Layout } from '../../shared/layout'
+import { PasswordRevealer } from './index'
+
+export const PasswordRevealerExample = () => {
+  return (
+    <Layout
+      title="密码框"
+      content={
+        <PasswordRevealer
+          placeholder="Please input your password."
+          onChange={data => {
+            console.log(data.target.value)
+          }}
+        />
+      }
+    />
+  )
+}
diff --git a/react-code/src/components/password-revealer/index.js b/react-code/src/components/password-revealer/index.js
new file mode 100644
index 0000000..51f20c4
--- /dev/null
+++ b/react-code/src/components/password-revealer/index.js
@@ -0,0 +1,16 @@
+import React, { useState } from 'react'
+
+export const PasswordRevealer = ({ onChange, ...props }) => {
+  const [shown, setShown] = useState(false)
+
+  return (
+    <div>
+      <input
+        {...props}
+        type={shown ? 'text' : 'password'}
+        onChange={e => onChange(e)}
+        />
+      <button onClick={() => setShown(!shown)}>Show/Hide</button>
+    </div>
+  )
+}

From 89786c54b98a080b22440c778383b5cf67da25e7 Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Wed, 9 Oct 2019 23:50:49 +0800
Subject: [PATCH 16/56] add select

---
 react-code/src/App.js                         |  5 +++-
 .../src/components/password-revealer/index.js |  6 +----
 react-code/src/components/select/example.js   | 26 +++++++++++++++++++
 react-code/src/components/select/index.js     | 18 +++++++++++++
 4 files changed, 49 insertions(+), 6 deletions(-)
 create mode 100644 react-code/src/components/select/example.js
 create mode 100644 react-code/src/components/select/index.js

diff --git a/react-code/src/App.js b/react-code/src/App.js
index 6233060..165f92b 100644
--- a/react-code/src/App.js
+++ b/react-code/src/App.js
@@ -8,7 +8,7 @@ import { ControlledInputExample } from './hooks/crontrolled-input/example'
 import { LimitedTextareaExample } from './components/limited-textarea/example'
 import { MultiselectCheckboxExample } from './components/multi-select-checkbox/example'
 import { PasswordRevealerExample } from './components/password-revealer/example'
-
+import { SelectExample } from './components/select/example'
 import './App.scss'
 
 const App = () => {
@@ -41,6 +41,9 @@ const App = () => {
         <Col span={3}>
           <PasswordRevealerExample />
         </Col>
+        <Col span={3}>
+          <SelectExample />
+        </Col>
       </Row>
     </Fragment>
   )
diff --git a/react-code/src/components/password-revealer/index.js b/react-code/src/components/password-revealer/index.js
index 51f20c4..c7f681c 100644
--- a/react-code/src/components/password-revealer/index.js
+++ b/react-code/src/components/password-revealer/index.js
@@ -5,11 +5,7 @@ export const PasswordRevealer = ({ onChange, ...props }) => {
 
   return (
     <div>
-      <input
-        {...props}
-        type={shown ? 'text' : 'password'}
-        onChange={e => onChange(e)}
-        />
+      <input {...props} type={shown ? 'text' : 'password'} onChange={e => onChange(e)} />
       <button onClick={() => setShown(!shown)}>Show/Hide</button>
     </div>
   )
diff --git a/react-code/src/components/select/example.js b/react-code/src/components/select/example.js
new file mode 100644
index 0000000..ba7823c
--- /dev/null
+++ b/react-code/src/components/select/example.js
@@ -0,0 +1,26 @@
+import React, { useState } from 'react'
+import { Layout } from '../../shared/layout'
+import { Select } from './index'
+import { Divider } from 'antd'
+
+const choices = [['banana', 'Banana'], ['apple', 'Apple'], ['orange', 'Orange']]
+const defaultValue = 'apple'
+
+export const SelectExample = () => {
+  const [value, setValue] = useState(defaultValue)
+  return (
+    <Layout
+      title="选择下拉框"
+      content={
+        <Select
+          options={choices}
+          defaultValue={defaultValue}
+          onChange={data => {
+            setValue(data)
+          }}
+        />
+      }
+      actions={<div>Select value: {value}</div>}
+    />
+  )
+}
diff --git a/react-code/src/components/select/index.js b/react-code/src/components/select/index.js
new file mode 100644
index 0000000..e995206
--- /dev/null
+++ b/react-code/src/components/select/index.js
@@ -0,0 +1,18 @@
+import React from 'react'
+
+export const Select = ({ options, onChange, defaultValue, disabled = false, readOnly = false }) => {
+  return (
+    <select
+      disabled={disabled}
+      readOnly={readOnly}
+      defaultValue={defaultValue}
+      onChange={({ target: { value } }) => onChange(value)}
+    >
+      {options.map(([value, text]) => (
+        <option value={value} key={text}>
+          {text}
+        </option>
+      ))}
+    </select>
+  )
+}

From 6e77f9a579a0b2a8afa6289b005e52601c519807 Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Fri, 6 Mar 2020 11:10:49 +0800
Subject: [PATCH 17/56] chore: new commit

---
 README.md                                     |  1 +
 react-code/.eslintignore                      |  6 --
 react-code/.eslintrc.js                       | 26 ------
 react-code/.gitignore                         |  6 --
 react-code/.postcssrc.js                      |  5 --
 react-code/.prettierignore                    |  6 --
 react-code/.prettierrc.js                     |  8 --
 react-code/LICENSE                            | 21 -----
 react-code/README.md                          |  2 -
 react-code/babel.config.js                    | 12 ---
 react-code/build/utils.js                     | 43 ---------
 react-code/build/webpack.base.config.js       | 89 -------------------
 react-code/build/webpack.dev.config.js        | 31 -------
 react-code/build/webpack.prod.config.js       | 50 -----------
 react-code/enzyme.setup.js                    |  4 -
 react-code/jest.config.js                     | 24 -----
 react-code/jest.styleMock.js                  |  1 -
 react-code/package.json                       | 70 ---------------
 react-code/public/index.html                  | 12 ---
 react-code/src/App.js                         | 52 -----------
 react-code/src/App.scss                       | 26 ------
 react-code/src/__test__/index.test.js         | 11 ---
 .../src/components/conditions/example.js      | 25 ------
 react-code/src/components/conditions/index.js |  9 --
 .../src/components/feature-toggle/example.js  | 33 -------
 .../src/components/feature-toggle/index.js    | 16 ----
 .../src/components/feature-toggle/toggles.js  |  4 -
 .../components/limited-textarea/example.js    | 12 ---
 .../src/components/limited-textarea/index.js  | 36 --------
 .../multi-select-checkbox/example.js          | 21 -----
 .../components/multi-select-checkbox/index.js | 39 --------
 .../components/password-revealer/example.js   | 19 ----
 .../src/components/password-revealer/index.js | 12 ---
 react-code/src/components/select/example.js   | 26 ------
 react-code/src/components/select/index.js     | 18 ----
 react-code/src/hooks/click-outside/example.js | 23 -----
 react-code/src/hooks/click-outside/index.js   | 15 ----
 .../src/hooks/crontrolled-input/example.js    | 34 -------
 .../src/hooks/crontrolled-input/index.js      | 35 --------
 react-code/src/hooks/is-online/example.js     | 11 ---
 react-code/src/hooks/is-online/index.js       | 26 ------
 react-code/src/index.js                       |  5 --
 react-code/src/shared/header/index.js         |  6 --
 react-code/src/shared/header/index.scss       |  0
 react-code/src/shared/layout/index.js         | 40 ---------
 react-code/src/utils/parseQuery.js            | 23 -----
 utils/camelize.js                             |  7 --
 utils/dasherize.js                            |  6 --
 utils/flatten.js                              |  5 --
 utils/pageVisibility.html                     | 12 ---
 utils/pageVisibility.js                       | 55 ------------
 utils/parsequery.js                           | 40 ---------
 52 files changed, 1 insertion(+), 1118 deletions(-)
 create mode 100644 README.md
 delete mode 100644 react-code/.eslintignore
 delete mode 100644 react-code/.eslintrc.js
 delete mode 100644 react-code/.gitignore
 delete mode 100644 react-code/.postcssrc.js
 delete mode 100644 react-code/.prettierignore
 delete mode 100644 react-code/.prettierrc.js
 delete mode 100644 react-code/LICENSE
 delete mode 100644 react-code/README.md
 delete mode 100644 react-code/babel.config.js
 delete mode 100644 react-code/build/utils.js
 delete mode 100644 react-code/build/webpack.base.config.js
 delete mode 100644 react-code/build/webpack.dev.config.js
 delete mode 100644 react-code/build/webpack.prod.config.js
 delete mode 100644 react-code/enzyme.setup.js
 delete mode 100644 react-code/jest.config.js
 delete mode 100644 react-code/jest.styleMock.js
 delete mode 100644 react-code/package.json
 delete mode 100644 react-code/public/index.html
 delete mode 100644 react-code/src/App.js
 delete mode 100644 react-code/src/App.scss
 delete mode 100644 react-code/src/__test__/index.test.js
 delete mode 100644 react-code/src/components/conditions/example.js
 delete mode 100644 react-code/src/components/conditions/index.js
 delete mode 100644 react-code/src/components/feature-toggle/example.js
 delete mode 100644 react-code/src/components/feature-toggle/index.js
 delete mode 100644 react-code/src/components/feature-toggle/toggles.js
 delete mode 100644 react-code/src/components/limited-textarea/example.js
 delete mode 100644 react-code/src/components/limited-textarea/index.js
 delete mode 100644 react-code/src/components/multi-select-checkbox/example.js
 delete mode 100644 react-code/src/components/multi-select-checkbox/index.js
 delete mode 100644 react-code/src/components/password-revealer/example.js
 delete mode 100644 react-code/src/components/password-revealer/index.js
 delete mode 100644 react-code/src/components/select/example.js
 delete mode 100644 react-code/src/components/select/index.js
 delete mode 100644 react-code/src/hooks/click-outside/example.js
 delete mode 100644 react-code/src/hooks/click-outside/index.js
 delete mode 100644 react-code/src/hooks/crontrolled-input/example.js
 delete mode 100644 react-code/src/hooks/crontrolled-input/index.js
 delete mode 100644 react-code/src/hooks/is-online/example.js
 delete mode 100644 react-code/src/hooks/is-online/index.js
 delete mode 100644 react-code/src/index.js
 delete mode 100644 react-code/src/shared/header/index.js
 delete mode 100644 react-code/src/shared/header/index.scss
 delete mode 100644 react-code/src/shared/layout/index.js
 delete mode 100644 react-code/src/utils/parseQuery.js
 delete mode 100644 utils/camelize.js
 delete mode 100644 utils/dasherize.js
 delete mode 100644 utils/flatten.js
 delete mode 100644 utils/pageVisibility.html
 delete mode 100644 utils/pageVisibility.js
 delete mode 100644 utils/parsequery.js

diff --git a/README.md b/README.md
new file mode 100644
index 0000000..f599ac4
--- /dev/null
+++ b/README.md
@@ -0,0 +1 @@
+## 记录收集文章
\ No newline at end of file
diff --git a/react-code/.eslintignore b/react-code/.eslintignore
deleted file mode 100644
index 9708844..0000000
--- a/react-code/.eslintignore
+++ /dev/null
@@ -1,6 +0,0 @@
-/coverage/
-/vendor/
-jest.config.js
-jest.styleMock.js
-enzyme.setup.js
-/node_modules/*
\ No newline at end of file
diff --git a/react-code/.eslintrc.js b/react-code/.eslintrc.js
deleted file mode 100644
index 125a750..0000000
--- a/react-code/.eslintrc.js
+++ /dev/null
@@ -1,26 +0,0 @@
-module.exports = {
-  root: true,
-  extends: [
-    "plugin:prettier/recommended"
-  ],
-  plugins: ["prettier"],
-  parser: "babel-eslint",
-  parserOptions: {
-    sourceType: 'module',
-    ecmaVersion: 7,
-    parser: "babel-eslint",
-    ecmaFeatures: {
-      "jsx": true,
-      "modules": true
-    }
-  },
-  env: {
-    browser: true
-  },
-  rules: {
-    "indent": ["error", 2],
-    'generator-star-spacing': 'off',
-    "quotes": ["error", "single"],
-    "default-case": 2
-  }
-}
\ No newline at end of file
diff --git a/react-code/.gitignore b/react-code/.gitignore
deleted file mode 100644
index 2ef5cd5..0000000
--- a/react-code/.gitignore
+++ /dev/null
@@ -1,6 +0,0 @@
-dist
-node_modules
-.DS_store
-package-lock.json
-.vscode
-.idea
\ No newline at end of file
diff --git a/react-code/.postcssrc.js b/react-code/.postcssrc.js
deleted file mode 100644
index de5c67a..0000000
--- a/react-code/.postcssrc.js
+++ /dev/null
@@ -1,5 +0,0 @@
-module.exports = {
-  plugins: [
-    require('autoprefixer')()
-  ]
-}
\ No newline at end of file
diff --git a/react-code/.prettierignore b/react-code/.prettierignore
deleted file mode 100644
index ba58d5a..0000000
--- a/react-code/.prettierignore
+++ /dev/null
@@ -1,6 +0,0 @@
-.eslintrc.js
-.eslintignore
-.prettierignore
-.prettierrc.js
-/node_modules/
-/dist/
diff --git a/react-code/.prettierrc.js b/react-code/.prettierrc.js
deleted file mode 100644
index 7490bdf..0000000
--- a/react-code/.prettierrc.js
+++ /dev/null
@@ -1,8 +0,0 @@
-module.exports = {
-  printWidth: 100,
-  trailingComma: "none",
-  tabWidth: 2,
-  semi: false,
-  singleQuote: true,
-  proseWrap: 'never'
-}
\ No newline at end of file
diff --git a/react-code/LICENSE b/react-code/LICENSE
deleted file mode 100644
index 7f97947..0000000
--- a/react-code/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2019 LoadingMore
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/react-code/README.md b/react-code/README.md
deleted file mode 100644
index 9e4c119..0000000
--- a/react-code/README.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# magic-programming
-Record the beauty of programming.
diff --git a/react-code/babel.config.js b/react-code/babel.config.js
deleted file mode 100644
index 79024fa..0000000
--- a/react-code/babel.config.js
+++ /dev/null
@@ -1,12 +0,0 @@
-module.exports = {
-  presets: ['@babel/preset-env', '@babel/preset-react'],
-  plugins: [
-    '@babel/plugin-proposal-class-properties',
-    '@babel/plugin-transform-modules-commonjs',
-    ["import", {
-      "libraryName": "antd",
-      "libraryDirectory": "es",
-      "style": "css"
-    }]
-  ]
-}
\ No newline at end of file
diff --git a/react-code/build/utils.js b/react-code/build/utils.js
deleted file mode 100644
index 9dab540..0000000
--- a/react-code/build/utils.js
+++ /dev/null
@@ -1,43 +0,0 @@
-const path = require('path')
-
-const isProd = process.env.NODE_ENV === 'production'
-
-/**
- * get file path
- * @param {*} dir 
- */
-const resolve = dir => {
-  return path.join(__dirname, dir)
-}
-
-/**
- * get the config for webpack build
- * @param {*} env 
- */
-const webpackOutConfig = (env) => {
-  return env ? {
-    filename: 'js/[name].[chunkhash].js',
-    chunkFilename: 'js/[name].[id].[chunkhash].js'
-  } : {
-    filename: 'js/[name].js',
-  }
-}
-/**
- * set eslint
- */
-const webpackEslintConfig = () => ({
-  test: /\.js$/,
-  loader: 'eslint-loader',
-  enforce: 'pre',
-  include: resolve('../src'),
-  options: {
-    formatter: require('eslint-friendly-formatter')
-  }
-})
-
-module.exports = {
-  isProd,
-  resolve,
-  webpackEslintConfig,
-  webpackOutConfig
-}
diff --git a/react-code/build/webpack.base.config.js b/react-code/build/webpack.base.config.js
deleted file mode 100644
index a0c8169..0000000
--- a/react-code/build/webpack.base.config.js
+++ /dev/null
@@ -1,89 +0,0 @@
-const path = require('path')
-const MiniCssExtractPlugin = require('mini-css-extract-plugin')
-const HtmlWebpackPlugin = require('html-webpack-plugin')
-const {
-  isProd,
-  resolve,
-  webpackEslintConfig,
-  webpackOutConfig
-} = require('./utils')
-
-const app = { 
-  entry: resolve('../src/index.js'),
-  output: {
-    path: resolve('../dist'),
-    publicPath: '/',
-    ...webpackOutConfig(isProd)
-  },
-  module: {
-    rules: [
-      webpackEslintConfig(),
-      {
-        test: /\.jsx?$/,
-        exclude: /node_modules/,
-        use: {
-          loader: 'babel-loader',
-          options: {
-            presets: ['@babel/preset-env', '@babel/preset-react']
-          }
-        }
-      },
-      {
-        test: /\.(sa|sc|c)ss$/,
-        use: [
-          {
-            loader: !isProd ? 'style-loader' : MiniCssExtractPlugin.loader
-          },
-          {
-            loader: 'css-loader'
-          },
-          {
-            loader: 'sass-loader'
-          },
-          {
-            loader: 'postcss-loader'
-          }
-        ]
-      },
-      {
-        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
-        loader: 'url-loader',
-        options: {
-          limit: 10000,
-          name: 'img/[name].[hash:7].[ext]'
-        }
-      },
-      {
-        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
-        loader: 'url-loader',
-        options: {
-          limit: 10000,
-          name: 'media/[name].[hash:7].[ext]'
-        }
-      },
-      {
-        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
-        loader: 'url-loader',
-        options: {
-          limit: 10000,
-          name: 'fonts/[name].[hash:7].[ext]'
-        }
-      }
-    ]
-  },
-  resolve: {
-    alias: {
-      '@': resolve('../src'),
-      '@shared': resolve('../src/shared'),
-      '@cpts': resolve('../src/components'),
-      '@hooks': resolve('../src/hooks')
-    }
-  },
-  plugins: [
-    new HtmlWebpackPlugin({
-      template: path.resolve(__dirname, '../public/index.html')
-    })
-  ]
-}
-
-module.exports = app
\ No newline at end of file
diff --git a/react-code/build/webpack.dev.config.js b/react-code/build/webpack.dev.config.js
deleted file mode 100644
index f34764e..0000000
--- a/react-code/build/webpack.dev.config.js
+++ /dev/null
@@ -1,31 +0,0 @@
-const path = require('path')
-const webpackAutoFindPort = require('webpack-auto-find-port')
-const chalk = require('chalk')
-const merge = require('webpack-merge')
-const webpack = require('webpack')
-const webpackBaseConfig = require('./webpack.base.config')
-
-const webpackDevConfig = merge(webpackBaseConfig, {
-  mode: 'development',
-  devtool: 'inline-source-map',
-  devServer: {
-    contentBase: path.resolve(`${process.cwd()}`, '../dist/index.html'),
-    publicPath: '/',
-    compress: true,
-    noInfo: true,
-    disableHostCheck: true,
-    open: true,
-    inline: true,
-    port: 8080
-  },
-  plugins: [
-    new webpack.HotModuleReplacementPlugin()
-  ]
-})
-
-module.exports = webpackAutoFindPort({
-  config: webpackDevConfig,
-  logger: (port) => {
-    console.log(chalk.green(`Project is Running at ${port}`))
-  }
-})
\ No newline at end of file
diff --git a/react-code/build/webpack.prod.config.js b/react-code/build/webpack.prod.config.js
deleted file mode 100644
index e78d3e5..0000000
--- a/react-code/build/webpack.prod.config.js
+++ /dev/null
@@ -1,50 +0,0 @@
-const webpack = require('webpack')
-const webpackMerge = require('webpack-merge')
-const MiniCssExtractPlugin = require('mini-css-extract-plugin')
-const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
-const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
-const webpackBaseConfig = require('./webpack.base.config')
-
-module.exports = webpackMerge(webpackBaseConfig, {
-  mode: 'production',
-  optimization: {
-    splitChunks: {
-      cacheGroups: {
-        commons: {
-          name: 'commons',
-          chunks: 'all',
-          minChunks: 2,
-          minSize: 1,
-          priority: 0
-        },
-        vendor: {
-          name: 'vendor',
-          test: /[\\/]node_modules[\\/]/,
-          chunks: 'all',
-          priority: 10
-        }
-      }
-    },
-    minimizer: [
-      new UglifyJsPlugin({
-        uglifyOptions: {
-          cache: true,
-          parallel: true,
-          warnings: false,
-          comments: false,
-          compress: {
-            drop_console: true
-          }
-        }
-      }),
-      new OptimizeCSSAssetsPlugin({})
-    ]
-  },
-  plugins: [
-    new webpack.HashedModuleIdsPlugin(),
-
-    new MiniCssExtractPlugin({
-      filename: 'css/[name].css'
-    })
-  ]
-})
diff --git a/react-code/enzyme.setup.js b/react-code/enzyme.setup.js
deleted file mode 100644
index 7be1bb8..0000000
--- a/react-code/enzyme.setup.js
+++ /dev/null
@@ -1,4 +0,0 @@
-import Enzyme from 'enzyme'
-import Adapter from 'enzyme-adapter-react-16'
-
-Enzyme.configure({ adapter: new Adapter() })
\ No newline at end of file
diff --git a/react-code/jest.config.js b/react-code/jest.config.js
deleted file mode 100644
index 8f38c56..0000000
--- a/react-code/jest.config.js
+++ /dev/null
@@ -1,24 +0,0 @@
-module.exports = {
-  bail: true,
-  verbose: true,
-  setupFiles: ['<rootDir>/enzyme.setup.js'],
-  roots: ['./src'],
-  testPathIgnorePatterns: ['/node_modules/', '/dist/'],
-  coveragePathIgnorePatterns: ['/node_modules/', '/dist/'],
-  coverageThreshold: {
-    global: {
-      branches: 85,
-      functions: 85,
-      lines: 85,
-      statements: 85
-    }
-  },
-  transform: {
-    '.(js|jsx)': 'babel-jest'
-  },
-  testMatch: ['**/__tests__/**/*.js?(x)', '**/?(*.)+(spec|test).js?(x)'],
-  testURL: 'http://localhost',
-  moduleNameMapper: {
-    '\\.(css|scss|less|bmp|gif|jpg|jpeg|png|psd|svg|webp)$': '<rootDir>/jest.styleMock.js'
-  }
-}
\ No newline at end of file
diff --git a/react-code/jest.styleMock.js b/react-code/jest.styleMock.js
deleted file mode 100644
index 7c6d6c7..0000000
--- a/react-code/jest.styleMock.js
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = {}
\ No newline at end of file
diff --git a/react-code/package.json b/react-code/package.json
deleted file mode 100644
index 37b4ceb..0000000
--- a/react-code/package.json
+++ /dev/null
@@ -1,70 +0,0 @@
-{
-  "name": "magin-programming",
-  "version": "0.0.0",
-  "description": "",
-  "main": "index.js",
-  "scripts": {
-    "fix": "eslint --fix 'src/**/*.js'",
-    "prettier": "prettier --write 'src/**/*.js'",
-    "test": "jest",
-    "dev": "webpack-dev-server --config build/webpack.dev.config",
-    "build": "cross-env NODE_ENV=production webpack --config build/webpack.prod.config"
-  },
-  "dependencies": {
-    "antd": "^3.23.4",
-    "react": "^16.8.6",
-    "react-dom": "^16.8.6",
-    "react-router": "^5.0.1",
-    "react-router-config": "^5.0.1",
-    "react-router-dom": "^5.0.1"
-  },
-  "devDependencies": {
-    "@babel/core": "^7.4.5",
-    "@babel/plugin-proposal-class-properties": "^7.4.4",
-    "@babel/plugin-syntax-dynamic-import": "^7.2.0",
-    "@babel/plugin-transform-modules-commonjs": "^7.4.4",
-    "@babel/plugin-transform-react-jsx": "^7.3.0",
-    "@babel/preset-env": "^7.4.5",
-    "@babel/preset-react": "^7.0.0",
-    "autoprefixer": "^9.6.0",
-    "babel-eslint": "^10.0.2",
-    "babel-jest": "^24.8.0",
-    "babel-loader": "^8.0.6",
-    "babel-plugin-import": "^1.12.2",
-    "chalk": "^2.4.2",
-    "copy-webpack-plugin": "^5.0.3",
-    "cross-env": "^5.2.0",
-    "css-loader": "^2.1.1",
-    "enzyme": "^3.10.0",
-    "enzyme-adapter-react-16": "^1.14.0",
-    "eslint": "^6.0.0",
-    "eslint-config-prettier": "^5.0.0",
-    "eslint-friendly-formatter": "^4.0.1",
-    "eslint-loader": "^2.1.2",
-    "eslint-plugin-prettier": "^3.1.0",
-    "file-loader": "^4.0.0",
-    "fs-extra": "^8.0.1",
-    "html-webpack-plugin": "^3.2.0",
-    "jest": "^24.8.0",
-    "mini-css-extract-plugin": "^0.7.0",
-    "node-sass": "^4.12.0",
-    "optimize-css-assets-webpack-plugin": "^5.0.1",
-    "postcss-loader": "^3.0.0",
-    "prettier": "^1.18.2",
-    "sass-loader": "^7.1.0",
-    "style-loader": "^0.23.1",
-    "uglifyjs-webpack-plugin": "^2.1.3",
-    "url-loader": "^2.0.0",
-    "webpack": "^4.33.0",
-    "webpack-auto-find-port": "0.0.5",
-    "webpack-cli": "^3.3.3",
-    "webpack-dev-server": "^3.7.0",
-    "webpack-merge": "^4.2.1"
-  },
-  "browserslist": [
-    "> 1%",
-    "Firefox ESR",
-    "last 2 versions",
-    "ie >= 9"
-  ]
-}
diff --git a/react-code/public/index.html b/react-code/public/index.html
deleted file mode 100644
index 3e9a8e5..0000000
--- a/react-code/public/index.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-  <meta charset="UTF-8">
-  <meta name="viewport" content="width=device-width, initial-scale=1.0">
-  <meta http-equiv="X-UA-Compatible" content="ie=edge">
-  <title>Magic Program</title>
-</head>
-<body>
-  <div id="app"></div>
-</body>
-</html>
\ No newline at end of file
diff --git a/react-code/src/App.js b/react-code/src/App.js
deleted file mode 100644
index 165f92b..0000000
--- a/react-code/src/App.js
+++ /dev/null
@@ -1,52 +0,0 @@
-import React, { Fragment } from 'react'
-import { Row, Col } from 'antd'
-import FeatureToggle from './components/feature-toggle/example'
-import Conditions from './components/conditions/example'
-import { ClickBox } from './hooks/click-outside/example'
-import { IsOnline } from './hooks/is-online/example'
-import { ControlledInputExample } from './hooks/crontrolled-input/example'
-import { LimitedTextareaExample } from './components/limited-textarea/example'
-import { MultiselectCheckboxExample } from './components/multi-select-checkbox/example'
-import { PasswordRevealerExample } from './components/password-revealer/example'
-import { SelectExample } from './components/select/example'
-import './App.scss'
-
-const App = () => {
-  return (
-    <Fragment>
-      <Row gutter={24} align="middle">
-        <Col span={3}>
-          <FeatureToggle />
-        </Col>
-        <Col span={3}>
-          <Conditions />
-        </Col>
-        <Col span={3}>
-          <ClickBox onClickOutside={() => console.log('You clicked me!')} />
-        </Col>
-        <Col span={3}>
-          <IsOnline />
-        </Col>
-        <Col span={6}>
-          <ControlledInputExample />
-        </Col>
-        <Col span={6}>
-          <LimitedTextareaExample />
-        </Col>
-      </Row>
-      <Row gutter={24} align="middle">
-        <Col span={3}>
-          <MultiselectCheckboxExample />
-        </Col>
-        <Col span={3}>
-          <PasswordRevealerExample />
-        </Col>
-        <Col span={3}>
-          <SelectExample />
-        </Col>
-      </Row>
-    </Fragment>
-  )
-}
-
-export default App
diff --git a/react-code/src/App.scss b/react-code/src/App.scss
deleted file mode 100644
index 44feaf6..0000000
--- a/react-code/src/App.scss
+++ /dev/null
@@ -1,26 +0,0 @@
-* {
-  margin: 0;
-  padding: 0;
-  box-sizing: border-box;
-}
-
-body {
-  padding: 20px;
-}
-
-p {
-  margin: 0;
-  padding: 0;
-}
-.layout-default {
-  font-size: 16px;
-  border: 1px solid #53d5c1;
-  padding: 10px;
-  border-radius: 6px;
-  height: auto;
-  word-wrap: break-word;
-}
-
-.layout-inner-default {
-  margin-bottom: 25px;
-}
\ No newline at end of file
diff --git a/react-code/src/__test__/index.test.js b/react-code/src/__test__/index.test.js
deleted file mode 100644
index ed1951d..0000000
--- a/react-code/src/__test__/index.test.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import React from 'react'
-import { shallow } from 'enzyme'
-import App from '../App'
-
-describe('App', () => {
-  const wrapper = shallow(<App />)
-
-  it('should render correct title', () => {
-    expect(wrapper.find('.magin-program_title').text()).toBe('Ftb React Demo')
-  })
-})
diff --git a/react-code/src/components/conditions/example.js b/react-code/src/components/conditions/example.js
deleted file mode 100644
index 1c8ce28..0000000
--- a/react-code/src/components/conditions/example.js
+++ /dev/null
@@ -1,25 +0,0 @@
-import React, { useState } from 'react'
-import { Button } from 'antd'
-import { Layout } from '../../shared/layout'
-import { Conditions } from './index'
-
-export default () => {
-  const [status, setStatus] = useState(true)
-  return (
-    <Layout
-      title="测试react组件条件渲染"
-      content={
-        <Conditions
-          data={{ isLogin: status }}
-          yes={<div>我是组件Conditions, 我的状态是Yes</div>}
-          no={<div>我是组件Conditions, 我的状态是No</div>}
-        />
-      }
-      actions={
-        <Button type="primary" onClick={() => (status ? setStatus(false) : setStatus(true))}>
-          点击切换状态
-        </Button>
-      }
-    />
-  )
-}
diff --git a/react-code/src/components/conditions/index.js b/react-code/src/components/conditions/index.js
deleted file mode 100644
index c014a4d..0000000
--- a/react-code/src/components/conditions/index.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import React from 'react'
-
-export const Conditions = props => {
-  const { data, yes, no } = props
-  // 假设data可以判断用户相关信息
-  const { isLogin } = data
-
-  return isLogin ? yes : no || null
-}
diff --git a/react-code/src/components/feature-toggle/example.js b/react-code/src/components/feature-toggle/example.js
deleted file mode 100644
index df5199a..0000000
--- a/react-code/src/components/feature-toggle/example.js
+++ /dev/null
@@ -1,33 +0,0 @@
-import React, { Fragment } from 'react'
-import { Button } from 'antd'
-import { Layout } from '@shared/layout'
-import { FeatureToggle } from './index'
-
-export default () => {
-  return (
-    <Layout
-      title="Feature Toggle 多用来测试新功能"
-      content={
-        <FeatureToggle toggleName="breadcrumbToggles">
-          {isToggleOn =>
-            isToggleOn ? (
-              <Fragment>
-                <p>😝赶快切换回来吧!!!😝</p>
-                <Button type="primary">
-                  <a href="/?breadcrumbToggles=false">false</a>
-                </Button>
-              </Fragment>
-            ) : (
-              <Fragment>
-                <p>地址栏用query可以切换我的显示 ?breadcrumbToggles=true</p>
-                <Button type="primary">
-                  <a href="/?breadcrumbToggles=true">true</a>
-                </Button>
-              </Fragment>
-            )
-          }
-        </FeatureToggle>
-      }
-    />
-  )
-}
diff --git a/react-code/src/components/feature-toggle/index.js b/react-code/src/components/feature-toggle/index.js
deleted file mode 100644
index bac276d..0000000
--- a/react-code/src/components/feature-toggle/index.js
+++ /dev/null
@@ -1,16 +0,0 @@
-import React from 'react'
-import toggles from './toggles.js'
-import parseQuery from '../../utils/parseQuery'
-
-export const FeatureToggle = props => {
-  const { toggleName } = props
-  const parseQueryValue = parseQuery(window.location.href)
-  let isToggleOn
-
-  if (!toggles.features.includes(toggleName)) {
-    isToggleOn = false
-  }
-  isToggleOn =
-    parseQueryValue[toggleName] && parseQueryValue[toggleName] === 'true' ? true : false || false
-  return <React.Fragment>{props.children(isToggleOn)}</React.Fragment>
-}
diff --git a/react-code/src/components/feature-toggle/toggles.js b/react-code/src/components/feature-toggle/toggles.js
deleted file mode 100644
index a30623d..0000000
--- a/react-code/src/components/feature-toggle/toggles.js
+++ /dev/null
@@ -1,4 +0,0 @@
-export default {
-  // set the toggle name
-  features: ['breadcrumbToggles']
-}
diff --git a/react-code/src/components/limited-textarea/example.js b/react-code/src/components/limited-textarea/example.js
deleted file mode 100644
index 88668c3..0000000
--- a/react-code/src/components/limited-textarea/example.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import React from 'react'
-import { Layout } from '../../shared/layout'
-import { LimitedTextarea } from './index'
-
-export const LimitedTextareaExample = () => {
-  return (
-    <Layout
-      title="限制字符输入"
-      content={<LimitedTextarea rows={5} limit={100} value="Please input your suggestions!" />}
-    />
-  )
-}
diff --git a/react-code/src/components/limited-textarea/index.js b/react-code/src/components/limited-textarea/index.js
deleted file mode 100644
index 5555256..0000000
--- a/react-code/src/components/limited-textarea/index.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import React, { useState, useEffect } from 'react'
-import { Button } from 'antd'
-
-const styles = {
-  width: '100%',
-  outline: 'none',
-  border: '1px solid #333f38'
-}
-
-export const LimitedTextarea = ({ rows, cols, value, limit, name }) => {
-  const [content, setContent] = useState(value)
-
-  const setFormattedContent = text => {
-    text.length > limit ? setContent(text.slice(0, limit)) : setContent(text)
-  }
-
-  useEffect(() => {
-    setFormattedContent(content)
-  }, [])
-
-  return (
-    <div>
-      <textarea
-        style={styles}
-        name={name}
-        cols={cols}
-        rows={rows}
-        value={content}
-        onChange={event => setFormattedContent(event.target.value)}
-      />
-      <p>
-        {content.length}/{limit}
-      </p>
-    </div>
-  )
-}
diff --git a/react-code/src/components/multi-select-checkbox/example.js b/react-code/src/components/multi-select-checkbox/example.js
deleted file mode 100644
index 799bbcc..0000000
--- a/react-code/src/components/multi-select-checkbox/example.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import React from 'react'
-import { Layout } from '../../shared/layout'
-import { MultiselectCheckbox } from './index'
-
-const options = [{ label: 'Item One', checked: true }, { label: 'Item Two', checked: false }]
-
-export const MultiselectCheckboxExample = () => {
-  return (
-    <Layout
-      title="多项选择"
-      content={
-        <MultiselectCheckbox
-          options={options}
-          onChange={data => {
-            console.log(data)
-          }}
-        />
-      }
-    />
-  )
-}
diff --git a/react-code/src/components/multi-select-checkbox/index.js b/react-code/src/components/multi-select-checkbox/index.js
deleted file mode 100644
index edc311b..0000000
--- a/react-code/src/components/multi-select-checkbox/index.js
+++ /dev/null
@@ -1,39 +0,0 @@
-import React, { useState } from 'react'
-
-const styles = {
-  listContainer: {
-    listStyle: 'none',
-    paddingLeft: 0
-  },
-  itemStyle: {
-    cursor: 'pointer',
-    padding: 5
-  }
-}
-
-export const MultiselectCheckbox = ({ options, onChange }) => {
-  const [data, setData] = useState(options)
-
-  const toggle = item => {
-    data.forEach((_, key) => {
-      if (data[key].label === item.label) {
-        data[key].checked = !item.checked
-      }
-    })
-    setData([...data])
-    onChange(data)
-  }
-
-  return (
-    <ul style={styles.listContainer}>
-      {data.map(item => {
-        return (
-          <li style={styles.itemStyle} key={item.label} onClick={() => toggle(item)}>
-            <input readOnly type="checkbox" checked={item.checked || false} />
-            {item.label}
-          </li>
-        )
-      })}
-    </ul>
-  )
-}
diff --git a/react-code/src/components/password-revealer/example.js b/react-code/src/components/password-revealer/example.js
deleted file mode 100644
index 51ca3d0..0000000
--- a/react-code/src/components/password-revealer/example.js
+++ /dev/null
@@ -1,19 +0,0 @@
-import React from 'react'
-import { Layout } from '../../shared/layout'
-import { PasswordRevealer } from './index'
-
-export const PasswordRevealerExample = () => {
-  return (
-    <Layout
-      title="密码框"
-      content={
-        <PasswordRevealer
-          placeholder="Please input your password."
-          onChange={data => {
-            console.log(data.target.value)
-          }}
-        />
-      }
-    />
-  )
-}
diff --git a/react-code/src/components/password-revealer/index.js b/react-code/src/components/password-revealer/index.js
deleted file mode 100644
index c7f681c..0000000
--- a/react-code/src/components/password-revealer/index.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import React, { useState } from 'react'
-
-export const PasswordRevealer = ({ onChange, ...props }) => {
-  const [shown, setShown] = useState(false)
-
-  return (
-    <div>
-      <input {...props} type={shown ? 'text' : 'password'} onChange={e => onChange(e)} />
-      <button onClick={() => setShown(!shown)}>Show/Hide</button>
-    </div>
-  )
-}
diff --git a/react-code/src/components/select/example.js b/react-code/src/components/select/example.js
deleted file mode 100644
index ba7823c..0000000
--- a/react-code/src/components/select/example.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import React, { useState } from 'react'
-import { Layout } from '../../shared/layout'
-import { Select } from './index'
-import { Divider } from 'antd'
-
-const choices = [['banana', 'Banana'], ['apple', 'Apple'], ['orange', 'Orange']]
-const defaultValue = 'apple'
-
-export const SelectExample = () => {
-  const [value, setValue] = useState(defaultValue)
-  return (
-    <Layout
-      title="选择下拉框"
-      content={
-        <Select
-          options={choices}
-          defaultValue={defaultValue}
-          onChange={data => {
-            setValue(data)
-          }}
-        />
-      }
-      actions={<div>Select value: {value}</div>}
-    />
-  )
-}
diff --git a/react-code/src/components/select/index.js b/react-code/src/components/select/index.js
deleted file mode 100644
index e995206..0000000
--- a/react-code/src/components/select/index.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import React from 'react'
-
-export const Select = ({ options, onChange, defaultValue, disabled = false, readOnly = false }) => {
-  return (
-    <select
-      disabled={disabled}
-      readOnly={readOnly}
-      defaultValue={defaultValue}
-      onChange={({ target: { value } }) => onChange(value)}
-    >
-      {options.map(([value, text]) => (
-        <option value={value} key={text}>
-          {text}
-        </option>
-      ))}
-    </select>
-  )
-}
diff --git a/react-code/src/hooks/click-outside/example.js b/react-code/src/hooks/click-outside/example.js
deleted file mode 100644
index 97a244d..0000000
--- a/react-code/src/hooks/click-outside/example.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import React, { useRef } from 'react'
-import { Button, message } from 'antd'
-import { Layout } from '@shared/layout'
-import { useClickOutside } from './index'
-
-export const ClickBox = ({ onClickOutside }) => {
-  const clickRef = useRef()
-  useClickOutside(clickRef, onClickOutside)
-
-  return (
-    <Layout
-      title="实现click outside功能"
-      content={<p>点击按钮以外的地方，都会触发事件，在控制台打印log</p>}
-      actions={
-        <span ref={clickRef}>
-          <Button type="primary" onClick={() => message.success('哈哈，点击我没用的')}>
-            点击我吧
-          </Button>
-        </span>
-      }
-    />
-  )
-}
diff --git a/react-code/src/hooks/click-outside/index.js b/react-code/src/hooks/click-outside/index.js
deleted file mode 100644
index 6aadd55..0000000
--- a/react-code/src/hooks/click-outside/index.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import { useEffect } from 'react'
-
-export const useClickOutside = (ref, callback) => {
-  const handleClick = e => {
-    if (ref.current && !ref.current.contains(e.target)) {
-      callback()
-    }
-  }
-  useEffect(() => {
-    document.addEventListener('click', handleClick)
-    return () => {
-      document.removeEventListener('click', handleClick)
-    }
-  })
-}
diff --git a/react-code/src/hooks/crontrolled-input/example.js b/react-code/src/hooks/crontrolled-input/example.js
deleted file mode 100644
index 5747eb8..0000000
--- a/react-code/src/hooks/crontrolled-input/example.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import React, { useEffect, useState } from 'react'
-import { Button, message } from 'antd'
-import { Layout } from '../../shared/layout'
-import { ControlledInput } from './index'
-
-export const ControlledInputExample = () => {
-  const [value, setValue] = useState('')
-
-  useEffect(() => {
-    setValue(value)
-  }, [value])
-
-  const handleButtonClick = () => {
-    message.success(`Current value is: ${value}`)
-  }
-
-  return (
-    <Layout
-      title="定制化input"
-      content={
-        <ControlledInput
-          type="text"
-          placeholder="Please input..."
-          onChange={val => setValue(val)}
-        />
-      }
-      actions={
-        <Button type="primary" onClick={handleButtonClick}>
-          点击查看
-        </Button>
-      }
-    />
-  )
-}
diff --git a/react-code/src/hooks/crontrolled-input/index.js b/react-code/src/hooks/crontrolled-input/index.js
deleted file mode 100644
index 52b7ad8..0000000
--- a/react-code/src/hooks/crontrolled-input/index.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import React, { useEffect, useState } from 'react'
-
-const style = {
-  outline: 'none',
-  border: '1px solid rgb(186, 204, 218)',
-  padding: '4px 6px',
-  width: '100%'
-}
-
-export const ControlledInput = ({
-  onChange,
-  type = 'text',
-  disabled = false,
-  readOnly = false,
-  defaultValue,
-  placeholder = ''
-}) => {
-  const [value, setValue] = useState(defaultValue)
-
-  useEffect(() => {
-    onChange(value)
-  }, [value])
-
-  return (
-    <input
-      defaultValue={defaultValue}
-      type={type}
-      disabled={disabled}
-      readOnly={readOnly}
-      placeholder={placeholder}
-      onChange={e => setValue(e.target.value)}
-      style={style}
-    />
-  )
-}
diff --git a/react-code/src/hooks/is-online/example.js b/react-code/src/hooks/is-online/example.js
deleted file mode 100644
index 5d14ec2..0000000
--- a/react-code/src/hooks/is-online/example.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import React from 'react'
-import { Layout } from '../../shared/layout'
-import { useIsOnline } from './index'
-
-export const IsOnline = () => {
-  const status = useIsOnline()
-
-  return (
-    <Layout title="实时检测网络是否联网" content={<p>网络状态: {status ? '在线' : '断网'}</p>} />
-  )
-}
diff --git a/react-code/src/hooks/is-online/index.js b/react-code/src/hooks/is-online/index.js
deleted file mode 100644
index 318ba75..0000000
--- a/react-code/src/hooks/is-online/index.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import React, { useState, useEffect } from 'react'
-
-const getOnlineStatus = () => {
-  return typeof navigator !== 'undefined' && navigator.onLine === 'boolean'
-    ? navigator.onLine
-    : true
-}
-
-export const useIsOnline = () => {
-  const [status, setStatus] = useState(getOnlineStatus())
-
-  const setOnline = () => setStatus(true)
-  const setOffline = () => setStatus(false)
-
-  useEffect(() => {
-    window.addEventListener('online', setOnline)
-    window.addEventListener('offline', setOffline)
-
-    return () => {
-      window.removeEventListener('online', setOnline)
-      window.removeEventListener('offline', setOffline)
-    }
-  }, [])
-
-  return status
-}
diff --git a/react-code/src/index.js b/react-code/src/index.js
deleted file mode 100644
index 3aefd43..0000000
--- a/react-code/src/index.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import React from 'react'
-import ReactDom from 'react-dom'
-import App from './App'
-
-ReactDom.render(<App />, document.getElementById('app'))
diff --git a/react-code/src/shared/header/index.js b/react-code/src/shared/header/index.js
deleted file mode 100644
index a7dca61..0000000
--- a/react-code/src/shared/header/index.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import React from 'react'
-import './index.scss'
-
-export const Header = () => {
-  return <div>Header</div>
-}
diff --git a/react-code/src/shared/header/index.scss b/react-code/src/shared/header/index.scss
deleted file mode 100644
index e69de29..0000000
diff --git a/react-code/src/shared/layout/index.js b/react-code/src/shared/layout/index.js
deleted file mode 100644
index 77a91e8..0000000
--- a/react-code/src/shared/layout/index.js
+++ /dev/null
@@ -1,40 +0,0 @@
-import React, { Component } from 'react'
-import { Empty, Card } from 'antd'
-
-export class Layout extends Component {
-  constructor(props) {
-    super(props)
-    this.state = {
-      hasError: false
-    }
-  }
-
-  static getDerivedStateFromError(error) {
-    console.log({ error })
-    return {
-      hasError: true
-    }
-  }
-
-  componentDidCatch(error, info) {
-    console.log({
-      error,
-      info
-    })
-  }
-
-  render() {
-    if (this.state.hasError) {
-      return <Empty description={<span>当前组件渲染失败，请检查错误</span>} />
-    }
-    const { title = '', content, actions } = this.props
-    return (
-      <Card>
-        {title && <h4>{title}</h4>}
-        {content}
-        <div style={{ height: '20px' }} />
-        {actions}
-      </Card>
-    )
-  }
-}
diff --git a/react-code/src/utils/parseQuery.js b/react-code/src/utils/parseQuery.js
deleted file mode 100644
index d0448e8..0000000
--- a/react-code/src/utils/parseQuery.js
+++ /dev/null
@@ -1,23 +0,0 @@
-const flatten = (arr, max = 1) =>
-  arr.reduce(
-    (initial, curr, index) =>
-      Array.isArray(curr) ? initial.concat(flatten(curr)) : initial.concat(curr),
-    []
-  )
-
-const parseQuery = query => {
-  // need to double check this regular
-  const regexp = /(\w+)=([^&]+)/g
-  const result = {}
-  let match
-
-  while ((match = regexp.exec(query))) {
-    let key = match[1],
-      value = match[2].replace(/\n/g, '')
-    result[key] ? (result[key] = flatten([result[key], value])) : (result[key] = value)
-  }
-
-  return result
-}
-
-export default parseQuery
diff --git a/utils/camelize.js b/utils/camelize.js
deleted file mode 100644
index ae3045a..0000000
--- a/utils/camelize.js
+++ /dev/null
@@ -1,7 +0,0 @@
-function camelize (str) {
-  return str.replace(/[-_\s]+(.)?/g, function (match, c) {
-    return c ? c.toUpperCase() : ''
-  })
-}
-
-console.log('result:', camelize('__--hello--_--world--'))
\ No newline at end of file
diff --git a/utils/dasherize.js b/utils/dasherize.js
deleted file mode 100644
index 7b3aaaf..0000000
--- a/utils/dasherize.js
+++ /dev/null
@@ -1,6 +0,0 @@
-function dasherize (str) {
-  // .replace(/[-_\s]+/g, '-') no used
-  return str.replace(/([A-Z])/g, '-$1').replace(/[-_\s]+/g, '-').toLowerCase();
-}
-
-console.log( dasherize('MozTransform') );
\ No newline at end of file
diff --git a/utils/flatten.js b/utils/flatten.js
deleted file mode 100644
index 2996189..0000000
--- a/utils/flatten.js
+++ /dev/null
@@ -1,5 +0,0 @@
-const flatten = (arr, max = 1) => 
-  arr.reduce((initial, curr, index) => 
-  Array.isArray(curr) ? initial.concat(flatten(curr)) : initial.concat(curr), [])
-
-console.log(flatten([1, 2, 3, [3, [4, [5, [9, 10]]]]]))
\ No newline at end of file
diff --git a/utils/pageVisibility.html b/utils/pageVisibility.html
deleted file mode 100644
index d349e1f..0000000
--- a/utils/pageVisibility.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-  <meta charset="UTF-8">
-  <meta name="viewport" content="width=device-width, initial-scale=1.0">
-  <meta http-equiv="X-UA-Compatible" content="ie=edge">
-  <title>Document</title>
-</head>
-<body>
-  <script src="./pageVisibility.js"></script>
-</body> 
-</html>
\ No newline at end of file
diff --git a/utils/pageVisibility.js b/utils/pageVisibility.js
deleted file mode 100644
index 080a57e..0000000
--- a/utils/pageVisibility.js
+++ /dev/null
@@ -1,55 +0,0 @@
-class PageVisible {
-  constructor() {
-    this.visible = false
-    this.hidden = 'hidden'
-    this.visibilityChange = 'visibilitychange'
-    this.visibilitySupported()
-    
-    if (this.visible) {
-      this.onVisible()
-    } else {
-      throw new Error('Not support visibilitychange, Please double check your browser!')
-    }
-  }
-
-  visibilitySupported() {
-    if (typeof document.hidden !== 'undefined') {    // Opera 12.10 and Firefox 18 and later support 
-      this.hidden = 'hidden'
-      this.visibilityChange = 'visibilitychange'
-    } else if (typeof document.msHidden !== 'undefined') {
-      this.hidden = 'msHidden'
-      this.visibilityChange = 'msvisibilitychange'
-    } else if (typeof document.webkitHidden !== 'undefined') {
-      this.hidden = 'webkitHidden'
-      this.visibilityChange = 'webkitvisibilitychange'
-    }
-
-    if (typeof document.addEventListener === 'undefined' || typeof document[this.hidden] === 'undefined') {
-      this.visible = false
-    }
-    this.visible = true
-  }
-
-  onVisible(callback) {
-    document.addEventListener(this.visibilityChange, () => {
-      if (document[this.hidden]) {
-        callback && callback('hidden')
-      } else {
-        callback && callback('visible')
-      }
-    }, false)
-  }
-}
-
-new PageVisible().onVisible((state) => {
-  switch (state) {
-    case 'hidden':
-      document.title = '我被隐藏了'
-      break;
-    case 'visible':
-      document.title = '哈哈，请继续浏览'
-    break
-    default:
-      break;
-  }
-})
\ No newline at end of file
diff --git a/utils/parsequery.js b/utils/parsequery.js
deleted file mode 100644
index f9d71af..0000000
--- a/utils/parsequery.js
+++ /dev/null
@@ -1,40 +0,0 @@
-const flatten = (arr, max = 1) => 
-  arr.reduce((initial, curr, index) => 
-  Array.isArray(curr) ? initial.concat(flatten(curr)) : initial.concat(curr), [])
-
-const parseQuery = (query) => {
-  // need to double check this regular
-  const regexp = /(\w+)=([^&]+)/g
-  const result = {}
-  let match
-
-  while(match = regexp.exec(query)) {
-    let key = match[1], value = match[2].replace(/\n/g, '')
-    result[key] ? result[key] = flatten([result[key], value]) : result[key] = value
-  }
-
-  return result
-}
-const query = `
-https://www.baidu.com/s?ie=utf8&f=8&f=90&rsv_bp=1&rsv_idx=1&rsv_bp=1&tn=baidu&wd=%E6%B0%B4%E7%94%B5%E8%B4%B9&rsv_pq=c7797024000434a8&rsv_t=b786FJnGwOOxPk7E7gsn1VbYHpmSP93UpP1470GL9ajYJkd09MOyBzSTsVk&rqlang=cn&rsv_enter=1&rsv_dl=tb&rsv_sug3=5&rsv_sug1=4&rsv_sug7=101&rsv_bp=234&rsv_sug2=0&inputT=1760&rsv_sug4=2010&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmcm9tX3VzZXIiOiJCIiwidGFyZ2V0X3VzZXIiOiJBIn0.rSWamyAYwuHCo7IFAgd1oRpSP7nzL7BF5t7ItqpKViM
-`.split('?')[1]
-
-console.log(parseQuery(query))
-
-// { ie: 'utf8',
-//   f: [ '8', '90' ],
-//   rsv_bp: [ '1', '1', '234' ],
-//   rsv_idx: '1',
-//   tn: 'baidu',
-//   rsv_pq: 'c7797024000434a8',
-//   rsv_t: 'b786FJnGwOOxPk7E7gsn1VbYHpmSP93UpP1470GL9ajYJkd09MOyBzSTsVk',
-//   rqlang: 'cn',
-//   rsv_enter: '1',
-//   rsv_dl: 'tb',
-//   rsv_sug3: '5',
-//   rsv_sug1: '4',
-//   rsv_sug7: '101',
-//   rsv_sug2: '0',
-//   inputT: '1760',
-//   rsv_sug4: '2010' 
-// }
\ No newline at end of file

From c9acd6816803715e921d968af4c4fc16e333d159 Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Fri, 6 Mar 2020 12:08:39 +0800
Subject: [PATCH 18/56] chore: add ci auto generate readme according the github
 issues

---
 .github/workflows/main.yml | 39 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)
 create mode 100644 .github/workflows/main.yml

diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
new file mode 100644
index 0000000..7612870
--- /dev/null
+++ b/.github/workflows/main.yml
@@ -0,0 +1,39 @@
+name: CI
+
+on: [issues, issue_comment]
+
+jobs:
+  build:
+
+    runs-on: ubuntu-latest
+    
+    steps:
+    - uses: actions/checkout@master
+    - name: install dependencies
+      run: |
+        pip3 install setuptools --user
+        pip3 install PyGithub --user
+        pip3 install wordcloud --user
+        pip3 install matplotlib --user
+    - name: run python script
+      env:
+        GITHUB_LOGIN: BiYuqi
+        GITHUB_TOKEN: ${{ secrets.GITHUB_SNIPPETS }}
+      run: python3 main.py
+    - name: config git info
+      run: |
+        git config --global user.email "biyuqiwan@163.com"
+        git config --global user.name "BiYuqi"
+    - name: commit change
+      run: |
+        git checkout master
+        git add .
+        git commit -m "Update from Github Action"
+    - name: push change
+      env:
+        GITHUB_LOGIN: BiYuqi
+        GITHUB_TOKEN: ${{ secrets.GITHUB_SNIPPETS }}
+      run: |
+        git push https://$GITHUB_LOGIN:$GITHUB_TOKEN@github.com/$GITHUB_REPOSITORY.git
+    - name: done
+      run: echo 'done'
\ No newline at end of file

From 1eea2d6f4144bfcd527fdd183d3fc0c15995b264 Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Fri, 6 Mar 2020 23:00:12 +0800
Subject: [PATCH 19/56] chore: remove the ci

---
 .github/workflows/main.yml | 39 --------------------------------------
 1 file changed, 39 deletions(-)
 delete mode 100644 .github/workflows/main.yml

diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
deleted file mode 100644
index 7612870..0000000
--- a/.github/workflows/main.yml
+++ /dev/null
@@ -1,39 +0,0 @@
-name: CI
-
-on: [issues, issue_comment]
-
-jobs:
-  build:
-
-    runs-on: ubuntu-latest
-    
-    steps:
-    - uses: actions/checkout@master
-    - name: install dependencies
-      run: |
-        pip3 install setuptools --user
-        pip3 install PyGithub --user
-        pip3 install wordcloud --user
-        pip3 install matplotlib --user
-    - name: run python script
-      env:
-        GITHUB_LOGIN: BiYuqi
-        GITHUB_TOKEN: ${{ secrets.GITHUB_SNIPPETS }}
-      run: python3 main.py
-    - name: config git info
-      run: |
-        git config --global user.email "biyuqiwan@163.com"
-        git config --global user.name "BiYuqi"
-    - name: commit change
-      run: |
-        git checkout master
-        git add .
-        git commit -m "Update from Github Action"
-    - name: push change
-      env:
-        GITHUB_LOGIN: BiYuqi
-        GITHUB_TOKEN: ${{ secrets.GITHUB_SNIPPETS }}
-      run: |
-        git push https://$GITHUB_LOGIN:$GITHUB_TOKEN@github.com/$GITHUB_REPOSITORY.git
-    - name: done
-      run: echo 'done'
\ No newline at end of file

From 4a12351d7fc30326fb784334da158741daa6447b Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Sat, 7 Mar 2020 00:37:55 +0800
Subject: [PATCH 20/56] feat: support auto generate catefory

---
 .gitignore                 | 24 ++++++++++
 README.md                  | 94 +++++++++++++++++++++++++++++++++++++-
 index.js                   |  3 ++
 package.json               | 22 +++++++++
 scripts/CreateReadme.js    | 41 +++++++++++++++++
 scripts/FetchRepoIssue.js  | 32 +++++++++++++
 scripts/ReStructureJson.js | 33 +++++++++++++
 7 files changed, 248 insertions(+), 1 deletion(-)
 create mode 100644 .gitignore
 create mode 100644 index.js
 create mode 100644 package.json
 create mode 100644 scripts/CreateReadme.js
 create mode 100644 scripts/FetchRepoIssue.js
 create mode 100644 scripts/ReStructureJson.js

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1e25920
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,24 @@
+.DS_Store
+node_modules
+/dist
+/jsondata/basedata.json
+# local env files
+.env.local
+.env.*.local
+
+# Log files
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+
+package-lock.json
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/README.md b/README.md
index f599ac4..aa977af 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,93 @@
-## 记录收集文章
\ No newline at end of file
+
+<h1 align="center">日常技术摘录 👋</h1>
+   <details>
+   <summary>Vue<sup>1</sup></summary>
+   
+   - [Vue动态修改路由](https://github.com/BiYuqi/snippets/issues/2)
+ 
+ </details>
+  <details>
+   <summary>NodeJs<sup>1</sup></summary>
+   
+   - [node 技术预研  模板引擎](https://github.com/BiYuqi/snippets/issues/3)
+ 
+ </details>
+  <details>
+   <summary>CSS<sup>2</sup></summary>
+   
+   - [怎么画一条0.5px的边更新 - 掘金](https://github.com/BiYuqi/snippets/issues/12)
+ 
+   - [写CSS动效的常用套路(附demo的效果实现与源码](https://github.com/BiYuqi/snippets/issues/7)
+ 
+ </details>
+  <details>
+   <summary>Tools<sup>1</sup></summary>
+   
+   - [Poi](https://github.com/BiYuqi/snippets/issues/6)
+ 
+ </details>
+  <details>
+   <summary>算法<sup>1</sup></summary>
+   
+   - [labuladong的算法小抄](https://github.com/BiYuqi/snippets/issues/5)
+ 
+ </details>
+  <details>
+   <summary>学习<sup>2</sup></summary>
+   
+   - [人是怎么废掉的 - 知乎](https://github.com/BiYuqi/snippets/issues/10)
+ 
+   - [不想学习的时候如何逼迫自己学习 - 知乎](https://github.com/BiYuqi/snippets/issues/8)
+ 
+ </details>
+  <details>
+   <summary>读书<sup>1</sup></summary>
+   
+   - [你最庆幸自己读过什么书? - 知乎](https://github.com/BiYuqi/snippets/issues/9)
+ 
+ </details>
+  <details>
+   <summary>思考<sup>1</sup></summary>
+   
+   - [认知逻辑思维系统思考能力如何提升 - 知乎](https://github.com/BiYuqi/snippets/issues/11)
+ 
+ </details>
+  <details>
+   <summary>技巧<sup>2</sup></summary>
+   
+   - [利用github api获取issue  Issue #44  isaaxite/blog](https://github.com/BiYuqi/snippets/issues/18)
+ 
+   - [基于Github Action自动生成并更新GitHub Issue博客的ReadMe  Issue #1  jwenjian/ghiblog](https://github.com/BiYuqi/snippets/issues/13)
+ 
+ </details>
+  <details>
+   <summary>workflow<sup>1</sup></summary>
+   
+   - [Awesome Actions](https://github.com/BiYuqi/snippets/issues/14)
+ 
+ </details>
+  <details>
+   <summary>:framed_picture:封面<sup>1</sup></summary>
+   
+   - [封面](https://github.com/BiYuqi/snippets/issues/15)
+ 
+ </details>
+  <details>
+   <summary>数据结构与算法<sup>1</sup></summary>
+   
+   - [我接触过的前端数据结构与算法](https://github.com/BiYuqi/snippets/issues/16)
+ 
+ </details>
+  <details>
+   <summary>知乎专栏<sup>1</sup></summary>
+   
+   - [FE FAME](https://github.com/BiYuqi/snippets/issues/17)
+ 
+ </details>
+  <details>
+   <summary>人际交往<sup>1</sup></summary>
+   
+   - [如何辨认身边的聪明人 - 知乎](https://github.com/BiYuqi/snippets/issues/20)
+ 
+ </details>
+    
\ No newline at end of file
diff --git a/index.js b/index.js
new file mode 100644
index 0000000..18d104b
--- /dev/null
+++ b/index.js
@@ -0,0 +1,3 @@
+const CreateReadme = require('./scripts/CreateReadme')
+
+CreateReadme()
\ No newline at end of file
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..45de529
--- /dev/null
+++ b/package.json
@@ -0,0 +1,22 @@
+{
+  "name": "snippets",
+  "version": "1.0.0",
+  "description": "<!-- <details open=\"open\">     <summary>         <img src=\"assets/wordcloud.png\" title=\"词云, 点击展开详细分类\" alt=\"词云， 点击展开详细分类\">         <p align=\"center\">:cloud: 词云 :cloud: <sub>点击词云展开详细分类:point_down: </sub></p>     </summary>",
+  "main": "index.js",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/BiYuqi/snippets.git"
+  },
+  "author": "",
+  "license": "MIT",
+  "bugs": {
+    "url": "https://github.com/BiYuqi/snippets/issues"
+  },
+  "homepage": "https://github.com/BiYuqi/snippets#readme",
+  "dependencies": {
+    "node-fetch": "^2.6.0"
+  }
+}
diff --git a/scripts/CreateReadme.js b/scripts/CreateReadme.js
new file mode 100644
index 0000000..c7a3a12
--- /dev/null
+++ b/scripts/CreateReadme.js
@@ -0,0 +1,41 @@
+const fs = require('fs')
+
+const FetchRepoIssue = require('./FetchRepoIssue')
+const ReStructureJson = require('./ReStructureJson')
+
+const TOP = `
+<h1 align="center">日常技术摘录 👋</h1>
+---
+`
+module.exports = async () => {
+  const issues = await FetchRepoIssue()
+  const result = ReStructureJson(issues)
+  const README = []
+  README.push(TOP)
+  
+  Object.keys(result).forEach(cateGory => {
+    const cateGoryData = result[cateGory]
+    const readme = []
+    const name = cateGoryData[0].displayLabel
+
+    cateGoryData.forEach(data => {
+      readme.push(`
+        - [${data.name}](${data.issueUrl})
+      `)
+    })
+    
+    const template = `
+      <details>
+        <summary>${name}<sup>${cateGoryData.length}</sup></summary>
+        ${readme.join('')}
+      </details>
+    `
+
+    README.push(template)
+  })
+
+  const RemoveSpace = /^\s{5}/gmi
+  
+
+  fs.writeFileSync('README.md', README.join('\n').replace(RemoveSpace, ''))
+}
\ No newline at end of file
diff --git a/scripts/FetchRepoIssue.js b/scripts/FetchRepoIssue.js
new file mode 100644
index 0000000..0bba326
--- /dev/null
+++ b/scripts/FetchRepoIssue.js
@@ -0,0 +1,32 @@
+const fetch = require('node-fetch')
+
+const GITHUB_ISSUE_API = ({owner, repo}) => {
+  return `https://api.github.com/repos/${owner}/${repo}/issues`
+}
+
+const generateQuery = ({owner, token}) => {
+  return `?creator=${owner}&per_page=1000&access_token=${token.join('')}`
+}
+
+const REDIRECT_URL = ({owner, repo}) => {
+  return `https://github.com/${owner}/${repo}/issues`;
+}
+
+const CONFIG = {
+  owner: 'BiYuqi',
+  repo: 'snippets',
+  token: ['07413d81b67fcb2cc', 'b0376044c9d52f9640863d8']
+}
+
+module.exports = () => {
+  return new Promise((resolve, reject) => {
+    fetch(GITHUB_ISSUE_API(CONFIG))
+      .then(res => res.json())
+      .then(json => {
+        resolve(json)
+      })
+      .catch(e => {
+        reject(e)
+      })
+  })
+}
\ No newline at end of file
diff --git a/scripts/ReStructureJson.js b/scripts/ReStructureJson.js
new file mode 100644
index 0000000..fcf58b8
--- /dev/null
+++ b/scripts/ReStructureJson.js
@@ -0,0 +1,33 @@
+const exactRealLink = /via Instapaper\s*(.*)/gmi
+
+const exactUrl = (content, html_url) => {
+  const match = content.match(exactRealLink)
+  if (match) {
+    return match[1]
+  }
+  return html_url
+}
+
+const dataReduction = (issues) => {
+  return issues.map(({ title, html_url, labels, body }) => {
+    // skip unmark label link
+    if (labels.length > 0) {
+      return {
+        name: title,
+        issueUrl: html_url,
+        labels: labels[0],
+        pageUrl: exactUrl(body, html_url)
+      }
+    }
+  })
+}
+
+ module.exports = (issues) => {
+  return dataReduction(issues).reduce((result, current) => {
+    const {id, name} = current.labels
+    current.displayLabel = name
+    result[id] ? result[id].push(current) : result[id] = [current]
+    return result
+  }, {})
+
+}
\ No newline at end of file

From 199b70d3a22f29f9bee4059c5437c2717bcb8860 Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Sat, 7 Mar 2020 15:51:47 +0800
Subject: [PATCH 21/56] chore: refactor

---
 .github/workflows/main.yml |  0
 index.js                   |  4 ++--
 scripts/CreateReadme.js    |  8 ++++----
 scripts/createReadme.js    | 41 ++++++++++++++++++++++++++++++++++++++
 scripts/fetchRepoIssue.js  | 32 +++++++++++++++++++++++++++++
 scripts/reStructureJson.js | 33 ++++++++++++++++++++++++++++++
 6 files changed, 112 insertions(+), 6 deletions(-)
 create mode 100644 .github/workflows/main.yml
 create mode 100644 scripts/createReadme.js
 create mode 100644 scripts/fetchRepoIssue.js
 create mode 100644 scripts/reStructureJson.js

diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
new file mode 100644
index 0000000..e69de29
diff --git a/index.js b/index.js
index 18d104b..8fa37dc 100644
--- a/index.js
+++ b/index.js
@@ -1,3 +1,3 @@
-const CreateReadme = require('./scripts/CreateReadme')
+const createReadme = require('./scripts/createReadme')
 
-CreateReadme()
\ No newline at end of file
+createReadme()
\ No newline at end of file
diff --git a/scripts/CreateReadme.js b/scripts/CreateReadme.js
index c7a3a12..23dc2e0 100644
--- a/scripts/CreateReadme.js
+++ b/scripts/CreateReadme.js
@@ -1,15 +1,15 @@
 const fs = require('fs')
 
-const FetchRepoIssue = require('./FetchRepoIssue')
-const ReStructureJson = require('./ReStructureJson')
+const fetchRepoIssue = require('./fetchRepoIssue')
+const reStructureJson = require('./reStructureJson')
 
 const TOP = `
 <h1 align="center">日常技术摘录 👋</h1>
 ---
 `
 module.exports = async () => {
-  const issues = await FetchRepoIssue()
-  const result = ReStructureJson(issues)
+  const issues = await fetchRepoIssue()
+  const result = reStructureJson(issues)
   const README = []
   README.push(TOP)
   
diff --git a/scripts/createReadme.js b/scripts/createReadme.js
new file mode 100644
index 0000000..23dc2e0
--- /dev/null
+++ b/scripts/createReadme.js
@@ -0,0 +1,41 @@
+const fs = require('fs')
+
+const fetchRepoIssue = require('./fetchRepoIssue')
+const reStructureJson = require('./reStructureJson')
+
+const TOP = `
+<h1 align="center">日常技术摘录 👋</h1>
+---
+`
+module.exports = async () => {
+  const issues = await fetchRepoIssue()
+  const result = reStructureJson(issues)
+  const README = []
+  README.push(TOP)
+  
+  Object.keys(result).forEach(cateGory => {
+    const cateGoryData = result[cateGory]
+    const readme = []
+    const name = cateGoryData[0].displayLabel
+
+    cateGoryData.forEach(data => {
+      readme.push(`
+        - [${data.name}](${data.issueUrl})
+      `)
+    })
+    
+    const template = `
+      <details>
+        <summary>${name}<sup>${cateGoryData.length}</sup></summary>
+        ${readme.join('')}
+      </details>
+    `
+
+    README.push(template)
+  })
+
+  const RemoveSpace = /^\s{5}/gmi
+  
+
+  fs.writeFileSync('README.md', README.join('\n').replace(RemoveSpace, ''))
+}
\ No newline at end of file
diff --git a/scripts/fetchRepoIssue.js b/scripts/fetchRepoIssue.js
new file mode 100644
index 0000000..0bba326
--- /dev/null
+++ b/scripts/fetchRepoIssue.js
@@ -0,0 +1,32 @@
+const fetch = require('node-fetch')
+
+const GITHUB_ISSUE_API = ({owner, repo}) => {
+  return `https://api.github.com/repos/${owner}/${repo}/issues`
+}
+
+const generateQuery = ({owner, token}) => {
+  return `?creator=${owner}&per_page=1000&access_token=${token.join('')}`
+}
+
+const REDIRECT_URL = ({owner, repo}) => {
+  return `https://github.com/${owner}/${repo}/issues`;
+}
+
+const CONFIG = {
+  owner: 'BiYuqi',
+  repo: 'snippets',
+  token: ['07413d81b67fcb2cc', 'b0376044c9d52f9640863d8']
+}
+
+module.exports = () => {
+  return new Promise((resolve, reject) => {
+    fetch(GITHUB_ISSUE_API(CONFIG))
+      .then(res => res.json())
+      .then(json => {
+        resolve(json)
+      })
+      .catch(e => {
+        reject(e)
+      })
+  })
+}
\ No newline at end of file
diff --git a/scripts/reStructureJson.js b/scripts/reStructureJson.js
new file mode 100644
index 0000000..fcf58b8
--- /dev/null
+++ b/scripts/reStructureJson.js
@@ -0,0 +1,33 @@
+const exactRealLink = /via Instapaper\s*(.*)/gmi
+
+const exactUrl = (content, html_url) => {
+  const match = content.match(exactRealLink)
+  if (match) {
+    return match[1]
+  }
+  return html_url
+}
+
+const dataReduction = (issues) => {
+  return issues.map(({ title, html_url, labels, body }) => {
+    // skip unmark label link
+    if (labels.length > 0) {
+      return {
+        name: title,
+        issueUrl: html_url,
+        labels: labels[0],
+        pageUrl: exactUrl(body, html_url)
+      }
+    }
+  })
+}
+
+ module.exports = (issues) => {
+  return dataReduction(issues).reduce((result, current) => {
+    const {id, name} = current.labels
+    current.displayLabel = name
+    result[id] ? result[id].push(current) : result[id] = [current]
+    return result
+  }, {})
+
+}
\ No newline at end of file

From 00aec136e7925f4e14ea05603e89e6d149ea3cf0 Mon Sep 17 00:00:00 2001
From: LoadingMore <biyuqiwan@163.com>
Date: Sat, 7 Mar 2020 15:53:58 +0800
Subject: [PATCH 22/56] Delete CreateReadme.js

---
 scripts/CreateReadme.js | 41 -----------------------------------------
 1 file changed, 41 deletions(-)
 delete mode 100644 scripts/CreateReadme.js

diff --git a/scripts/CreateReadme.js b/scripts/CreateReadme.js
deleted file mode 100644
index 23dc2e0..0000000
--- a/scripts/CreateReadme.js
+++ /dev/null
@@ -1,41 +0,0 @@
-const fs = require('fs')
-
-const fetchRepoIssue = require('./fetchRepoIssue')
-const reStructureJson = require('./reStructureJson')
-
-const TOP = `
-<h1 align="center">日常技术摘录 👋</h1>
----
-`
-module.exports = async () => {
-  const issues = await fetchRepoIssue()
-  const result = reStructureJson(issues)
-  const README = []
-  README.push(TOP)
-  
-  Object.keys(result).forEach(cateGory => {
-    const cateGoryData = result[cateGory]
-    const readme = []
-    const name = cateGoryData[0].displayLabel
-
-    cateGoryData.forEach(data => {
-      readme.push(`
-        - [${data.name}](${data.issueUrl})
-      `)
-    })
-    
-    const template = `
-      <details>
-        <summary>${name}<sup>${cateGoryData.length}</sup></summary>
-        ${readme.join('')}
-      </details>
-    `
-
-    README.push(template)
-  })
-
-  const RemoveSpace = /^\s{5}/gmi
-  
-
-  fs.writeFileSync('README.md', README.join('\n').replace(RemoveSpace, ''))
-}
\ No newline at end of file

From 935deb270c5e4143672d12fc02a98bd7d28a73d9 Mon Sep 17 00:00:00 2001
From: LoadingMore <biyuqiwan@163.com>
Date: Sat, 7 Mar 2020 15:54:09 +0800
Subject: [PATCH 23/56] Delete FetchRepoIssue.js

---
 scripts/FetchRepoIssue.js | 32 --------------------------------
 1 file changed, 32 deletions(-)
 delete mode 100644 scripts/FetchRepoIssue.js

diff --git a/scripts/FetchRepoIssue.js b/scripts/FetchRepoIssue.js
deleted file mode 100644
index 0bba326..0000000
--- a/scripts/FetchRepoIssue.js
+++ /dev/null
@@ -1,32 +0,0 @@
-const fetch = require('node-fetch')
-
-const GITHUB_ISSUE_API = ({owner, repo}) => {
-  return `https://api.github.com/repos/${owner}/${repo}/issues`
-}
-
-const generateQuery = ({owner, token}) => {
-  return `?creator=${owner}&per_page=1000&access_token=${token.join('')}`
-}
-
-const REDIRECT_URL = ({owner, repo}) => {
-  return `https://github.com/${owner}/${repo}/issues`;
-}
-
-const CONFIG = {
-  owner: 'BiYuqi',
-  repo: 'snippets',
-  token: ['07413d81b67fcb2cc', 'b0376044c9d52f9640863d8']
-}
-
-module.exports = () => {
-  return new Promise((resolve, reject) => {
-    fetch(GITHUB_ISSUE_API(CONFIG))
-      .then(res => res.json())
-      .then(json => {
-        resolve(json)
-      })
-      .catch(e => {
-        reject(e)
-      })
-  })
-}
\ No newline at end of file

From 7989c92a23bf852b9f8cf1e53e72febcc53263e6 Mon Sep 17 00:00:00 2001
From: LoadingMore <biyuqiwan@163.com>
Date: Sat, 7 Mar 2020 15:54:18 +0800
Subject: [PATCH 24/56] Delete ReStructureJson.js

---
 scripts/ReStructureJson.js | 33 ---------------------------------
 1 file changed, 33 deletions(-)
 delete mode 100644 scripts/ReStructureJson.js

diff --git a/scripts/ReStructureJson.js b/scripts/ReStructureJson.js
deleted file mode 100644
index fcf58b8..0000000
--- a/scripts/ReStructureJson.js
+++ /dev/null
@@ -1,33 +0,0 @@
-const exactRealLink = /via Instapaper\s*(.*)/gmi
-
-const exactUrl = (content, html_url) => {
-  const match = content.match(exactRealLink)
-  if (match) {
-    return match[1]
-  }
-  return html_url
-}
-
-const dataReduction = (issues) => {
-  return issues.map(({ title, html_url, labels, body }) => {
-    // skip unmark label link
-    if (labels.length > 0) {
-      return {
-        name: title,
-        issueUrl: html_url,
-        labels: labels[0],
-        pageUrl: exactUrl(body, html_url)
-      }
-    }
-  })
-}
-
- module.exports = (issues) => {
-  return dataReduction(issues).reduce((result, current) => {
-    const {id, name} = current.labels
-    current.displayLabel = name
-    result[id] ? result[id].push(current) : result[id] = [current]
-    return result
-  }, {})
-
-}
\ No newline at end of file

From a9490581f080665e94080600f260a7bd7d96b84e Mon Sep 17 00:00:00 2001
From: yuqi-bi <yuqi.bi@rea-group.com>
Date: Sat, 7 Mar 2020 16:17:36 +0800
Subject: [PATCH 25/56] chore: add ci

---
 .github/workflows/main.yml | 41 ++++++++++++++++++++++++++++++++++++++
 package.json               |  2 +-
 scripts/fetchRepoIssue.js  | 10 +++++-----
 3 files changed, 47 insertions(+), 6 deletions(-)

diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index e69de29..15bfaf4 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -0,0 +1,41 @@
+name: Auto Generate Issue Blog
+
+on: [issues, issue_comment, label, milestone]
+
+jobs:
+  build:
+    runs-on: ubuntu-latest
+
+    steps:
+    - name: Checkout
+      uses: actions/checkout@v1
+
+    - name: Use Node.js 10.x
+      uses: actions/setup-node@v1
+      with:
+        node-version: "10.x"
+
+    - name: Setup Global Env
+      env:
+        GITHUB_LOGIN: BiYuqi
+        GITHUB_REPO: snippets
+        GITHUB_TOKEN: ${{ secrets.GITHUB_SNIPPETS }}
+      run: |
+        git config --global user.email "biyuqiwan@163.com"
+        git config --global user.name "BiYuqi"
+
+        npm install
+        npm run build
+    - name: commit change
+      run: |
+        git add .
+        git commit -m "Update from Github Action"
+    - name: push change
+      env:
+        GITHUB_LOGIN: BiYuqi
+        GITHUB_REPO: snippets
+        GITHUB_TOKEN: ${{ secrets.GITHUB_SNIPPETS }}
+      run: |
+        git push https://$GITHUB_LOGIN:$GITHUB_TOKEN@github.com/$GITHUB_REPOSITORY.git
+    - name: done
+      run: echo 'done'
\ No newline at end of file
diff --git a/package.json b/package.json
index 45de529..f1e317f 100644
--- a/package.json
+++ b/package.json
@@ -4,7 +4,7 @@
   "description": "<!-- <details open=\"open\">     <summary>         <img src=\"assets/wordcloud.png\" title=\"词云, 点击展开详细分类\" alt=\"词云， 点击展开详细分类\">         <p align=\"center\">:cloud: 词云 :cloud: <sub>点击词云展开详细分类:point_down: </sub></p>     </summary>",
   "main": "index.js",
   "scripts": {
-    "test": "echo \"Error: no test specified\" && exit 1"
+    "build": "node ./index.js"
   },
   "repository": {
     "type": "git",
diff --git a/scripts/fetchRepoIssue.js b/scripts/fetchRepoIssue.js
index 0bba326..bf7d299 100644
--- a/scripts/fetchRepoIssue.js
+++ b/scripts/fetchRepoIssue.js
@@ -1,11 +1,11 @@
 const fetch = require('node-fetch')
 
 const GITHUB_ISSUE_API = ({owner, repo}) => {
-  return `https://api.github.com/repos/${owner}/${repo}/issues`
+  return `https://api.github.com/repos/${owner}/${repo}/issues${generateQuery({owner, repo})}`
 }
 
 const generateQuery = ({owner, token}) => {
-  return `?creator=${owner}&per_page=1000&access_token=${token.join('')}`
+  return `?creator=${owner}&per_page=1000&access_token=${token}`
 }
 
 const REDIRECT_URL = ({owner, repo}) => {
@@ -13,9 +13,9 @@ const REDIRECT_URL = ({owner, repo}) => {
 }
 
 const CONFIG = {
-  owner: 'BiYuqi',
-  repo: 'snippets',
-  token: ['07413d81b67fcb2cc', 'b0376044c9d52f9640863d8']
+  owner: process.env.GITHUB_LOGIN,
+  repo: process.env.GITHUB_REPO,
+  token: process.env.GITHUB_TOKEN
 }
 
 module.exports = () => {

From f25c2e0e3db2f2883e69867173d4205335b393fe Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Sat, 7 Mar 2020 16:21:33 +0800
Subject: [PATCH 26/56] fix: typo

---
 .github/workflows/main.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 15bfaf4..6fad59d 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -1,6 +1,6 @@
 name: Auto Generate Issue Blog
 
-on: [issues, issue_comment, label, milestone]
+on: [issues, issue_comment, label, push]
 
 jobs:
   build:
@@ -36,6 +36,6 @@ jobs:
         GITHUB_REPO: snippets
         GITHUB_TOKEN: ${{ secrets.GITHUB_SNIPPETS }}
       run: |
-        git push https://$GITHUB_LOGIN:$GITHUB_TOKEN@github.com/$GITHUB_REPOSITORY.git
+        git push https://$GITHUB_LOGIN:$GITHUB_TOKEN@github.com/$GITHUB_REPO.git
     - name: done
       run: echo 'done'
\ No newline at end of file

From 6b4d503d0865b47ace1266f03bcfcf8d9d769aba Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Sat, 7 Mar 2020 16:28:24 +0800
Subject: [PATCH 27/56] fix: error

---
 .github/workflows/main.yml | 17 +++++++----------
 .gitignore                 |  3 ---
 package-lock.json          | 13 +++++++++++++
 package.json               |  2 +-
 scripts/createReadme.js    |  6 ++++++
 scripts/fetchRepoIssue.js  |  6 ++++--
 scripts/reStructureJson.js |  5 +++++
 7 files changed, 36 insertions(+), 16 deletions(-)
 create mode 100644 package-lock.json

diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 6fad59d..80eaf31 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -19,23 +19,20 @@ jobs:
       env:
         GITHUB_LOGIN: BiYuqi
         GITHUB_REPO: snippets
-        GITHUB_TOKEN: ${{ secrets.GITHUB_SNIPPETS }}
+        GITHUB_TOKEN: 07413d81b67fcb2ccb0376044c9d52f9640863d8
       run: |
         git config --global user.email "biyuqiwan@163.com"
         git config --global user.name "BiYuqi"
-
-        npm install
-        npm run build
-    - name: commit change
-      run: |
-        git add .
-        git commit -m "Update from Github Action"
-    - name: push change
+    - name: Install
       env:
         GITHUB_LOGIN: BiYuqi
         GITHUB_REPO: snippets
-        GITHUB_TOKEN: ${{ secrets.GITHUB_SNIPPETS }}
+        GITHUB_TOKEN: 07413d81b67fcb2ccb0376044c9d52f9640863d8
       run: |
+        npm install
+        npm run build
+        git add .
+        git commit -m "Update from Github Action"
         git push https://$GITHUB_LOGIN:$GITHUB_TOKEN@github.com/$GITHUB_REPO.git
     - name: done
       run: echo 'done'
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 1e25920..89e1335 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,9 +11,6 @@ npm-debug.log*
 yarn-debug.log*
 yarn-error.log*
 
-
-package-lock.json
-
 # Editor directories and files
 .idea
 .vscode
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..0af1647
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,13 @@
+{
+  "name": "snippets",
+  "version": "1.0.0",
+  "lockfileVersion": 1,
+  "requires": true,
+  "dependencies": {
+    "node-fetch": {
+      "version": "2.6.0",
+      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
+      "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA=="
+    }
+  }
+}
diff --git a/package.json b/package.json
index f1e317f..389e99c 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "snippets",
   "version": "1.0.0",
-  "description": "<!-- <details open=\"open\">     <summary>         <img src=\"assets/wordcloud.png\" title=\"词云, 点击展开详细分类\" alt=\"词云， 点击展开详细分类\">         <p align=\"center\">:cloud: 词云 :cloud: <sub>点击词云展开详细分类:point_down: </sub></p>     </summary>",
+  "description": "",
   "main": "index.js",
   "scripts": {
     "build": "node ./index.js"
diff --git a/scripts/createReadme.js b/scripts/createReadme.js
index 23dc2e0..4a4a16b 100644
--- a/scripts/createReadme.js
+++ b/scripts/createReadme.js
@@ -9,6 +9,12 @@ const TOP = `
 `
 module.exports = async () => {
   const issues = await fetchRepoIssue()
+
+  if (!issues) {
+    console.log('Get the data faild. Please check.')
+    console.log(JSON.stringify(issues))
+    process.exit(1)
+  }
   const result = reStructureJson(issues)
   const README = []
   README.push(TOP)
diff --git a/scripts/fetchRepoIssue.js b/scripts/fetchRepoIssue.js
index bf7d299..03e2efc 100644
--- a/scripts/fetchRepoIssue.js
+++ b/scripts/fetchRepoIssue.js
@@ -1,7 +1,7 @@
 const fetch = require('node-fetch')
 
-const GITHUB_ISSUE_API = ({owner, repo}) => {
-  return `https://api.github.com/repos/${owner}/${repo}/issues${generateQuery({owner, repo})}`
+const GITHUB_ISSUE_API = ({owner, repo, token}) => {
+  return `https://api.github.com/repos/${owner}/${repo}/issues${generateQuery({owner, token})}`
 }
 
 const generateQuery = ({owner, token}) => {
@@ -17,6 +17,8 @@ const CONFIG = {
   repo: process.env.GITHUB_REPO,
   token: process.env.GITHUB_TOKEN
 }
+console.log(CONFIG)
+console.log(process.env)
 
 module.exports = () => {
   return new Promise((resolve, reject) => {
diff --git a/scripts/reStructureJson.js b/scripts/reStructureJson.js
index fcf58b8..07f9604 100644
--- a/scripts/reStructureJson.js
+++ b/scripts/reStructureJson.js
@@ -9,6 +9,11 @@ const exactUrl = (content, html_url) => {
 }
 
 const dataReduction = (issues) => {
+  if (!issues || issues.length <= 0) {
+    console.log('dataReduction error')
+    process.exit(1)
+  }
+
   return issues.map(({ title, html_url, labels, body }) => {
     // skip unmark label link
     if (labels.length > 0) {

From 76a53136db94dd96ac718d722ba11d64ec50ce3b Mon Sep 17 00:00:00 2001
From: LoadingMore <biyuqiwan@163.com>
Date: Sat, 7 Mar 2020 20:08:57 +0800
Subject: [PATCH 28/56] Update main.yml

---
 .github/workflows/main.yml | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 80eaf31..a87feb0 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -31,8 +31,16 @@ jobs:
       run: |
         npm install
         npm run build
+    - name: commit change
+      run: |
         git add .
         git commit -m "Update from Github Action"
+    - name: push change
+      env:
+        GITHUB_LOGIN: BiYuqi
+        GITHUB_REPO: snippets
+        GITHUB_TOKEN: 07413d81b67fcb2ccb0376044c9d52f9640863d8
+      run: |
         git push https://$GITHUB_LOGIN:$GITHUB_TOKEN@github.com/$GITHUB_REPO.git
     - name: done
-      run: echo 'done'
\ No newline at end of file
+      run: echo 'done'

From 8bb7f868da729498e23524bcfd5662ea081a842a Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Sat, 7 Mar 2020 20:12:13 +0800
Subject: [PATCH 29/56] feat: log

---
 scripts/createReadme.js   | 2 ++
 scripts/fetchRepoIssue.js | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/scripts/createReadme.js b/scripts/createReadme.js
index 4a4a16b..5809278 100644
--- a/scripts/createReadme.js
+++ b/scripts/createReadme.js
@@ -15,6 +15,8 @@ module.exports = async () => {
     console.log(JSON.stringify(issues))
     process.exit(1)
   }
+  console.log(issues)
+  console.log('From createReame file')
   const result = reStructureJson(issues)
   const README = []
   README.push(TOP)
diff --git a/scripts/fetchRepoIssue.js b/scripts/fetchRepoIssue.js
index 03e2efc..2cc33ea 100644
--- a/scripts/fetchRepoIssue.js
+++ b/scripts/fetchRepoIssue.js
@@ -18,9 +18,9 @@ const CONFIG = {
   token: process.env.GITHUB_TOKEN
 }
 console.log(CONFIG)
-console.log(process.env)
 
 module.exports = () => {
+  console.log(GITHUB_ISSUE_API(CONFIG))
   return new Promise((resolve, reject) => {
     fetch(GITHUB_ISSUE_API(CONFIG))
       .then(res => res.json())

From 6b8ffb96eb46187dad97edae6a89abb9f40c5a3c Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Sat, 7 Mar 2020 20:15:10 +0800
Subject: [PATCH 30/56] feat: log

---
 scripts/fetchRepoIssue.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/scripts/fetchRepoIssue.js b/scripts/fetchRepoIssue.js
index 2cc33ea..d6af115 100644
--- a/scripts/fetchRepoIssue.js
+++ b/scripts/fetchRepoIssue.js
@@ -5,7 +5,7 @@ const GITHUB_ISSUE_API = ({owner, repo, token}) => {
 }
 
 const generateQuery = ({owner, token}) => {
-  return `?creator=${owner}&per_page=1000&access_token=${token}`
+  return `?creator=${owner}&per_page=1000&access_token=${token.join('')}`
 }
 
 const REDIRECT_URL = ({owner, repo}) => {
@@ -15,7 +15,7 @@ const REDIRECT_URL = ({owner, repo}) => {
 const CONFIG = {
   owner: process.env.GITHUB_LOGIN,
   repo: process.env.GITHUB_REPO,
-  token: process.env.GITHUB_TOKEN
+  token: process.env.GITHUB_TOKEN.split('')
 }
 console.log(CONFIG)
 

From 1ffd0fdc4f615fc9141d95e009b6fcbbbbe0e131 Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Sat, 7 Mar 2020 20:17:21 +0800
Subject: [PATCH 31/56] feat: log

---
 .github/workflows/main.yml | 2 --
 scripts/fetchRepoIssue.js  | 2 +-
 2 files changed, 1 insertion(+), 3 deletions(-)

diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index a87feb0..bb5c436 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -19,7 +19,6 @@ jobs:
       env:
         GITHUB_LOGIN: BiYuqi
         GITHUB_REPO: snippets
-        GITHUB_TOKEN: 07413d81b67fcb2ccb0376044c9d52f9640863d8
       run: |
         git config --global user.email "biyuqiwan@163.com"
         git config --global user.name "BiYuqi"
@@ -27,7 +26,6 @@ jobs:
       env:
         GITHUB_LOGIN: BiYuqi
         GITHUB_REPO: snippets
-        GITHUB_TOKEN: 07413d81b67fcb2ccb0376044c9d52f9640863d8
       run: |
         npm install
         npm run build
diff --git a/scripts/fetchRepoIssue.js b/scripts/fetchRepoIssue.js
index d6af115..55ec6ad 100644
--- a/scripts/fetchRepoIssue.js
+++ b/scripts/fetchRepoIssue.js
@@ -15,7 +15,7 @@ const REDIRECT_URL = ({owner, repo}) => {
 const CONFIG = {
   owner: process.env.GITHUB_LOGIN,
   repo: process.env.GITHUB_REPO,
-  token: process.env.GITHUB_TOKEN.split('')
+  token: ['07413d81b67fcb2cc', 'b0376044c9d52f9640863d8']
 }
 console.log(CONFIG)
 

From 457e25858c55ff047d2af15c51d81832e1e03d2c Mon Sep 17 00:00:00 2001
From: LoadingMore <biyuqiwan@163.com>
Date: Sat, 7 Mar 2020 20:35:52 +0800
Subject: [PATCH 32/56] Update fetchRepoIssue.js

---
 scripts/fetchRepoIssue.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/scripts/fetchRepoIssue.js b/scripts/fetchRepoIssue.js
index 55ec6ad..4a7de13 100644
--- a/scripts/fetchRepoIssue.js
+++ b/scripts/fetchRepoIssue.js
@@ -15,7 +15,7 @@ const REDIRECT_URL = ({owner, repo}) => {
 const CONFIG = {
   owner: process.env.GITHUB_LOGIN,
   repo: process.env.GITHUB_REPO,
-  token: ['07413d81b67fcb2cc', 'b0376044c9d52f9640863d8']
+  token: [d2f398601e81a5cf, 5649f2ec1dd3ed65e2335768]
 }
 console.log(CONFIG)
 
@@ -31,4 +31,4 @@ module.exports = () => {
         reject(e)
       })
   })
-}
\ No newline at end of file
+}

From 70e4d7aa94827227bf2adedddf08060979723418 Mon Sep 17 00:00:00 2001
From: LoadingMore <biyuqiwan@163.com>
Date: Sat, 7 Mar 2020 20:37:01 +0800
Subject: [PATCH 33/56] Update fetchRepoIssue.js

---
 scripts/fetchRepoIssue.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/fetchRepoIssue.js b/scripts/fetchRepoIssue.js
index 4a7de13..d141369 100644
--- a/scripts/fetchRepoIssue.js
+++ b/scripts/fetchRepoIssue.js
@@ -15,7 +15,7 @@ const REDIRECT_URL = ({owner, repo}) => {
 const CONFIG = {
   owner: process.env.GITHUB_LOGIN,
   repo: process.env.GITHUB_REPO,
-  token: [d2f398601e81a5cf, 5649f2ec1dd3ed65e2335768]
+  token: ['d2f398601e81a5cf', '5649f2ec1dd3ed65e2335768']
 }
 console.log(CONFIG)
 

From 9a9c24ab68c6563b1c05e698804a43aae3b86fff Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Sat, 7 Mar 2020 20:44:20 +0800
Subject: [PATCH 34/56] ddd

---
 .github/workflows/main.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index bb5c436..0f8d97e 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -37,8 +37,8 @@ jobs:
       env:
         GITHUB_LOGIN: BiYuqi
         GITHUB_REPO: snippets
-        GITHUB_TOKEN: 07413d81b67fcb2ccb0376044c9d52f9640863d8
+        ACCESS_TOKEN: ${{secrets.ACCESS_TOKEN}}
       run: |
-        git push https://$GITHUB_LOGIN:$GITHUB_TOKEN@github.com/$GITHUB_REPO.git
+        git push https://$GITHUB_LOGIN:$ACCESS_TOKEN@github.com/$GITHUB_REPO.git
     - name: done
       run: echo 'done'

From 92d2ec07ee36214f59323d475e59c1645a626873 Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Sat, 7 Mar 2020 22:17:24 +0800
Subject: [PATCH 35/56] clean

---
 .github/workflows/main.yml | 44 --------------------------------------
 scripts/fetchRepoIssue.js  |  6 +++---
 2 files changed, 3 insertions(+), 47 deletions(-)
 delete mode 100644 .github/workflows/main.yml

diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
deleted file mode 100644
index 0f8d97e..0000000
--- a/.github/workflows/main.yml
+++ /dev/null
@@ -1,44 +0,0 @@
-name: Auto Generate Issue Blog
-
-on: [issues, issue_comment, label, push]
-
-jobs:
-  build:
-    runs-on: ubuntu-latest
-
-    steps:
-    - name: Checkout
-      uses: actions/checkout@v1
-
-    - name: Use Node.js 10.x
-      uses: actions/setup-node@v1
-      with:
-        node-version: "10.x"
-
-    - name: Setup Global Env
-      env:
-        GITHUB_LOGIN: BiYuqi
-        GITHUB_REPO: snippets
-      run: |
-        git config --global user.email "biyuqiwan@163.com"
-        git config --global user.name "BiYuqi"
-    - name: Install
-      env:
-        GITHUB_LOGIN: BiYuqi
-        GITHUB_REPO: snippets
-      run: |
-        npm install
-        npm run build
-    - name: commit change
-      run: |
-        git add .
-        git commit -m "Update from Github Action"
-    - name: push change
-      env:
-        GITHUB_LOGIN: BiYuqi
-        GITHUB_REPO: snippets
-        ACCESS_TOKEN: ${{secrets.ACCESS_TOKEN}}
-      run: |
-        git push https://$GITHUB_LOGIN:$ACCESS_TOKEN@github.com/$GITHUB_REPO.git
-    - name: done
-      run: echo 'done'
diff --git a/scripts/fetchRepoIssue.js b/scripts/fetchRepoIssue.js
index d141369..e69deef 100644
--- a/scripts/fetchRepoIssue.js
+++ b/scripts/fetchRepoIssue.js
@@ -13,9 +13,9 @@ const REDIRECT_URL = ({owner, repo}) => {
 }
 
 const CONFIG = {
-  owner: process.env.GITHUB_LOGIN,
-  repo: process.env.GITHUB_REPO,
-  token: ['d2f398601e81a5cf', '5649f2ec1dd3ed65e2335768']
+  owner: 'BiYuqi',
+  repo: 'snippets',
+  token: ['737719cae24371de', '39cac47ed76ee084513f8389']
 }
 console.log(CONFIG)
 

From 83d2d4f2c9991688ef8965cf5bcb443a3dd7eeaa Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Sat, 7 Mar 2020 22:24:45 +0800
Subject: [PATCH 36/56] add ci

---
 .travis.yml               | 30 ++++++++++++++++++++++++++++++
 scripts/fetchRepoIssue.js |  6 ++++--
 2 files changed, 34 insertions(+), 2 deletions(-)
 create mode 100644 .travis.yml

diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..893409f
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,30 @@
+language: node_js
+node_js: stable
+
+cache:
+  directories:
+    - node_modules
+
+before_install:
+  - export TZ='Asia/Shanghai'
+
+install:
+  - npm install
+
+script:
+  - npm run build "${GITHUB_SNIPPET}"
+
+after_script:
+  - git init 
+  - git config user.name "BiYuqi"
+  - git config user.email "biyuqiwan@163.com"
+  - git add README.md
+  - git commit -m "Travis CI Auto Generate at `date +"%Y-%m-%d %H:%M"`"
+  - git push --force --quiet "https://${GITHUB_SNIPPET}@${GH_REF}" master:master
+
+branches:
+  only:
+    - issue-branch
+env:
+ global:
+   - GH_REF: github.com/BiYuqi/snippets.git
\ No newline at end of file
diff --git a/scripts/fetchRepoIssue.js b/scripts/fetchRepoIssue.js
index e69deef..40783a3 100644
--- a/scripts/fetchRepoIssue.js
+++ b/scripts/fetchRepoIssue.js
@@ -1,11 +1,13 @@
 const fetch = require('node-fetch')
+const COS_ENV = process.argv.slice(2)
+const [GITHUB_SNIPPET] = COS_ENV
 
 const GITHUB_ISSUE_API = ({owner, repo, token}) => {
   return `https://api.github.com/repos/${owner}/${repo}/issues${generateQuery({owner, token})}`
 }
 
 const generateQuery = ({owner, token}) => {
-  return `?creator=${owner}&per_page=1000&access_token=${token.join('')}`
+  return `?creator=${owner}&per_page=1000&access_token=${token}`
 }
 
 const REDIRECT_URL = ({owner, repo}) => {
@@ -15,7 +17,7 @@ const REDIRECT_URL = ({owner, repo}) => {
 const CONFIG = {
   owner: 'BiYuqi',
   repo: 'snippets',
-  token: ['737719cae24371de', '39cac47ed76ee084513f8389']
+  token: GITHUB_SNIPPET
 }
 console.log(CONFIG)
 

From 5dfe52e0e5e5fee7cefba558b1d40b0f68c1f431 Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Sat, 7 Mar 2020 22:36:58 +0800
Subject: [PATCH 37/56] build dir

---
 .travis.yml             | 5 +++--
 scripts/createReadme.js | 2 +-
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 893409f..396a42d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -15,10 +15,11 @@ script:
   - npm run build "${GITHUB_SNIPPET}"
 
 after_script:
-  - git init 
+  - cd ./dist
+  - git init
   - git config user.name "BiYuqi"
   - git config user.email "biyuqiwan@163.com"
-  - git add README.md
+  - git add .
   - git commit -m "Travis CI Auto Generate at `date +"%Y-%m-%d %H:%M"`"
   - git push --force --quiet "https://${GITHUB_SNIPPET}@${GH_REF}" master:master
 
diff --git a/scripts/createReadme.js b/scripts/createReadme.js
index 5809278..b94c255 100644
--- a/scripts/createReadme.js
+++ b/scripts/createReadme.js
@@ -45,5 +45,5 @@ module.exports = async () => {
   const RemoveSpace = /^\s{5}/gmi
   
 
-  fs.writeFileSync('README.md', README.join('\n').replace(RemoveSpace, ''))
+  fs.writeFileSync('dist/README.md', README.join('\n').replace(RemoveSpace, ''))
 }
\ No newline at end of file

From afe5591984571a626f9910eff6eb7fc834dd44d7 Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Sat, 7 Mar 2020 22:41:08 +0800
Subject: [PATCH 38/56] fix error dit

---
 scripts/createReadme.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/scripts/createReadme.js b/scripts/createReadme.js
index b94c255..d309612 100644
--- a/scripts/createReadme.js
+++ b/scripts/createReadme.js
@@ -44,6 +44,6 @@ module.exports = async () => {
 
   const RemoveSpace = /^\s{5}/gmi
   
-
-  fs.writeFileSync('dist/README.md', README.join('\n').replace(RemoveSpace, ''))
+  fs.mkdirSync('./dist')
+  fs.writeFileSync('./dist/README.md', README.join('\n').replace(RemoveSpace, ''))
 }
\ No newline at end of file

From a3b932c686160b154083050ba5105acde70309ff Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Sun, 8 Mar 2020 01:07:39 +0800
Subject: [PATCH 39/56] chore: remove js

---
 README.md                  | 93 --------------------------------------
 index.js                   |  3 --
 package-lock.json          | 13 ------
 package.json               | 22 ---------
 scripts/createReadme.js    | 49 --------------------
 scripts/fetchRepoIssue.js  | 36 ---------------
 scripts/reStructureJson.js | 38 ----------------
 7 files changed, 254 deletions(-)
 delete mode 100644 README.md
 delete mode 100644 index.js
 delete mode 100644 package-lock.json
 delete mode 100644 package.json
 delete mode 100644 scripts/createReadme.js
 delete mode 100644 scripts/fetchRepoIssue.js
 delete mode 100644 scripts/reStructureJson.js

diff --git a/README.md b/README.md
deleted file mode 100644
index aa977af..0000000
--- a/README.md
+++ /dev/null
@@ -1,93 +0,0 @@
-
-<h1 align="center">日常技术摘录 👋</h1>
-   <details>
-   <summary>Vue<sup>1</sup></summary>
-   
-   - [Vue动态修改路由](https://github.com/BiYuqi/snippets/issues/2)
- 
- </details>
-  <details>
-   <summary>NodeJs<sup>1</sup></summary>
-   
-   - [node 技术预研  模板引擎](https://github.com/BiYuqi/snippets/issues/3)
- 
- </details>
-  <details>
-   <summary>CSS<sup>2</sup></summary>
-   
-   - [怎么画一条0.5px的边更新 - 掘金](https://github.com/BiYuqi/snippets/issues/12)
- 
-   - [写CSS动效的常用套路(附demo的效果实现与源码](https://github.com/BiYuqi/snippets/issues/7)
- 
- </details>
-  <details>
-   <summary>Tools<sup>1</sup></summary>
-   
-   - [Poi](https://github.com/BiYuqi/snippets/issues/6)
- 
- </details>
-  <details>
-   <summary>算法<sup>1</sup></summary>
-   
-   - [labuladong的算法小抄](https://github.com/BiYuqi/snippets/issues/5)
- 
- </details>
-  <details>
-   <summary>学习<sup>2</sup></summary>
-   
-   - [人是怎么废掉的 - 知乎](https://github.com/BiYuqi/snippets/issues/10)
- 
-   - [不想学习的时候如何逼迫自己学习 - 知乎](https://github.com/BiYuqi/snippets/issues/8)
- 
- </details>
-  <details>
-   <summary>读书<sup>1</sup></summary>
-   
-   - [你最庆幸自己读过什么书? - 知乎](https://github.com/BiYuqi/snippets/issues/9)
- 
- </details>
-  <details>
-   <summary>思考<sup>1</sup></summary>
-   
-   - [认知逻辑思维系统思考能力如何提升 - 知乎](https://github.com/BiYuqi/snippets/issues/11)
- 
- </details>
-  <details>
-   <summary>技巧<sup>2</sup></summary>
-   
-   - [利用github api获取issue  Issue #44  isaaxite/blog](https://github.com/BiYuqi/snippets/issues/18)
- 
-   - [基于Github Action自动生成并更新GitHub Issue博客的ReadMe  Issue #1  jwenjian/ghiblog](https://github.com/BiYuqi/snippets/issues/13)
- 
- </details>
-  <details>
-   <summary>workflow<sup>1</sup></summary>
-   
-   - [Awesome Actions](https://github.com/BiYuqi/snippets/issues/14)
- 
- </details>
-  <details>
-   <summary>:framed_picture:封面<sup>1</sup></summary>
-   
-   - [封面](https://github.com/BiYuqi/snippets/issues/15)
- 
- </details>
-  <details>
-   <summary>数据结构与算法<sup>1</sup></summary>
-   
-   - [我接触过的前端数据结构与算法](https://github.com/BiYuqi/snippets/issues/16)
- 
- </details>
-  <details>
-   <summary>知乎专栏<sup>1</sup></summary>
-   
-   - [FE FAME](https://github.com/BiYuqi/snippets/issues/17)
- 
- </details>
-  <details>
-   <summary>人际交往<sup>1</sup></summary>
-   
-   - [如何辨认身边的聪明人 - 知乎](https://github.com/BiYuqi/snippets/issues/20)
- 
- </details>
-    
\ No newline at end of file
diff --git a/index.js b/index.js
deleted file mode 100644
index 8fa37dc..0000000
--- a/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-const createReadme = require('./scripts/createReadme')
-
-createReadme()
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
deleted file mode 100644
index 0af1647..0000000
--- a/package-lock.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-  "name": "snippets",
-  "version": "1.0.0",
-  "lockfileVersion": 1,
-  "requires": true,
-  "dependencies": {
-    "node-fetch": {
-      "version": "2.6.0",
-      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
-      "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA=="
-    }
-  }
-}
diff --git a/package.json b/package.json
deleted file mode 100644
index 389e99c..0000000
--- a/package.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
-  "name": "snippets",
-  "version": "1.0.0",
-  "description": "",
-  "main": "index.js",
-  "scripts": {
-    "build": "node ./index.js"
-  },
-  "repository": {
-    "type": "git",
-    "url": "git+https://github.com/BiYuqi/snippets.git"
-  },
-  "author": "",
-  "license": "MIT",
-  "bugs": {
-    "url": "https://github.com/BiYuqi/snippets/issues"
-  },
-  "homepage": "https://github.com/BiYuqi/snippets#readme",
-  "dependencies": {
-    "node-fetch": "^2.6.0"
-  }
-}
diff --git a/scripts/createReadme.js b/scripts/createReadme.js
deleted file mode 100644
index d309612..0000000
--- a/scripts/createReadme.js
+++ /dev/null
@@ -1,49 +0,0 @@
-const fs = require('fs')
-
-const fetchRepoIssue = require('./fetchRepoIssue')
-const reStructureJson = require('./reStructureJson')
-
-const TOP = `
-<h1 align="center">日常技术摘录 👋</h1>
----
-`
-module.exports = async () => {
-  const issues = await fetchRepoIssue()
-
-  if (!issues) {
-    console.log('Get the data faild. Please check.')
-    console.log(JSON.stringify(issues))
-    process.exit(1)
-  }
-  console.log(issues)
-  console.log('From createReame file')
-  const result = reStructureJson(issues)
-  const README = []
-  README.push(TOP)
-  
-  Object.keys(result).forEach(cateGory => {
-    const cateGoryData = result[cateGory]
-    const readme = []
-    const name = cateGoryData[0].displayLabel
-
-    cateGoryData.forEach(data => {
-      readme.push(`
-        - [${data.name}](${data.issueUrl})
-      `)
-    })
-    
-    const template = `
-      <details>
-        <summary>${name}<sup>${cateGoryData.length}</sup></summary>
-        ${readme.join('')}
-      </details>
-    `
-
-    README.push(template)
-  })
-
-  const RemoveSpace = /^\s{5}/gmi
-  
-  fs.mkdirSync('./dist')
-  fs.writeFileSync('./dist/README.md', README.join('\n').replace(RemoveSpace, ''))
-}
\ No newline at end of file
diff --git a/scripts/fetchRepoIssue.js b/scripts/fetchRepoIssue.js
deleted file mode 100644
index 40783a3..0000000
--- a/scripts/fetchRepoIssue.js
+++ /dev/null
@@ -1,36 +0,0 @@
-const fetch = require('node-fetch')
-const COS_ENV = process.argv.slice(2)
-const [GITHUB_SNIPPET] = COS_ENV
-
-const GITHUB_ISSUE_API = ({owner, repo, token}) => {
-  return `https://api.github.com/repos/${owner}/${repo}/issues${generateQuery({owner, token})}`
-}
-
-const generateQuery = ({owner, token}) => {
-  return `?creator=${owner}&per_page=1000&access_token=${token}`
-}
-
-const REDIRECT_URL = ({owner, repo}) => {
-  return `https://github.com/${owner}/${repo}/issues`;
-}
-
-const CONFIG = {
-  owner: 'BiYuqi',
-  repo: 'snippets',
-  token: GITHUB_SNIPPET
-}
-console.log(CONFIG)
-
-module.exports = () => {
-  console.log(GITHUB_ISSUE_API(CONFIG))
-  return new Promise((resolve, reject) => {
-    fetch(GITHUB_ISSUE_API(CONFIG))
-      .then(res => res.json())
-      .then(json => {
-        resolve(json)
-      })
-      .catch(e => {
-        reject(e)
-      })
-  })
-}
diff --git a/scripts/reStructureJson.js b/scripts/reStructureJson.js
deleted file mode 100644
index 07f9604..0000000
--- a/scripts/reStructureJson.js
+++ /dev/null
@@ -1,38 +0,0 @@
-const exactRealLink = /via Instapaper\s*(.*)/gmi
-
-const exactUrl = (content, html_url) => {
-  const match = content.match(exactRealLink)
-  if (match) {
-    return match[1]
-  }
-  return html_url
-}
-
-const dataReduction = (issues) => {
-  if (!issues || issues.length <= 0) {
-    console.log('dataReduction error')
-    process.exit(1)
-  }
-
-  return issues.map(({ title, html_url, labels, body }) => {
-    // skip unmark label link
-    if (labels.length > 0) {
-      return {
-        name: title,
-        issueUrl: html_url,
-        labels: labels[0],
-        pageUrl: exactUrl(body, html_url)
-      }
-    }
-  })
-}
-
- module.exports = (issues) => {
-  return dataReduction(issues).reduce((result, current) => {
-    const {id, name} = current.labels
-    current.displayLabel = name
-    result[id] ? result[id].push(current) : result[id] = [current]
-    return result
-  }, {})
-
-}
\ No newline at end of file

From 7a8d1dc91bed23ab9c678999eb10d6b0f9655f63 Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Sun, 8 Mar 2020 15:50:28 +0800
Subject: [PATCH 40/56] chore: first commit

---
 .prettierignore       |    4 +
 .prettierrc.js        |    5 +
 package-lock.json     | 2596 +++++++++++++++++++++++++++++++++++++++++
 package.json          |   48 +
 src/fetchIssue.ts     |    8 +
 src/generateReadme.ts |    1 +
 src/index.ts          |    2 +
 src/simplifyIssue.ts  |    0
 tsconfig.json         |   15 +
 9 files changed, 2679 insertions(+)
 create mode 100644 .prettierignore
 create mode 100644 .prettierrc.js
 create mode 100644 package-lock.json
 create mode 100644 package.json
 create mode 100644 src/fetchIssue.ts
 create mode 100644 src/generateReadme.ts
 create mode 100644 src/index.ts
 create mode 100644 src/simplifyIssue.ts
 create mode 100644 tsconfig.json

diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000..dc10eb0
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,4 @@
+/test/fixtures
+**/*.gif
+/dist
+/docs
\ No newline at end of file
diff --git a/.prettierrc.js b/.prettierrc.js
new file mode 100644
index 0000000..77c16b6
--- /dev/null
+++ b/.prettierrc.js
@@ -0,0 +1,5 @@
+module.exports = {
+  singleQuote: true,
+  printWidth: 100,
+  proseWrap: 'never'
+}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..1a0c2f4
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,2596 @@
+{
+  "name": "snippets",
+  "version": "1.0.0",
+  "lockfileVersion": 1,
+  "requires": true,
+  "dependencies": {
+    "@babel/code-frame": {
+      "version": "7.8.3",
+      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz",
+      "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==",
+      "dev": true,
+      "requires": {
+        "@babel/highlight": "^7.8.3"
+      }
+    },
+    "@babel/highlight": {
+      "version": "7.8.3",
+      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz",
+      "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==",
+      "dev": true,
+      "requires": {
+        "chalk": "^2.0.0",
+        "esutils": "^2.0.2",
+        "js-tokens": "^4.0.0"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "3.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+          "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+          "dev": true,
+          "requires": {
+            "color-convert": "^1.9.0"
+          }
+        },
+        "chalk": {
+          "version": "2.4.2",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+          "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^3.2.1",
+            "escape-string-regexp": "^1.0.5",
+            "supports-color": "^5.3.0"
+          }
+        },
+        "color-convert": {
+          "version": "1.9.3",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+          "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+          "dev": true,
+          "requires": {
+            "color-name": "1.1.3"
+          }
+        },
+        "color-name": {
+          "version": "1.1.3",
+          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+          "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+          "dev": true
+        },
+        "has-flag": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+          "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "5.5.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+          "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^3.0.0"
+          }
+        }
+      }
+    },
+    "@babel/runtime": {
+      "version": "7.8.7",
+      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.8.7.tgz",
+      "integrity": "sha512-+AATMUFppJDw6aiR5NVPHqIQBlV/Pj8wY/EZH+lmvRdUo9xBaz/rF3alAwFJQavvKfeOlPE7oaaDHVbcySbCsg==",
+      "dev": true,
+      "requires": {
+        "regenerator-runtime": "^0.13.4"
+      }
+    },
+    "@samverschueren/stream-to-observable": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz",
+      "integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==",
+      "dev": true,
+      "requires": {
+        "any-observable": "^0.3.0"
+      }
+    },
+    "@types/color-name": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
+      "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==",
+      "dev": true
+    },
+    "@types/node": {
+      "version": "13.9.0",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-13.9.0.tgz",
+      "integrity": "sha512-0ARSQootUG1RljH2HncpsY2TJBfGQIKOOi7kxzUY6z54ePu/ZD+wJA8zI2Q6v8rol2qpG/rvqsReco8zNMPvhQ==",
+      "dev": true
+    },
+    "@types/parse-json": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz",
+      "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==",
+      "dev": true
+    },
+    "abbrev": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+      "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
+      "dev": true
+    },
+    "ansi-align": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz",
+      "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=",
+      "dev": true,
+      "requires": {
+        "string-width": "^2.0.0"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+          "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+          "dev": true
+        },
+        "is-fullwidth-code-point": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+          "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+          "dev": true
+        },
+        "string-width": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+          "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+          "dev": true,
+          "requires": {
+            "is-fullwidth-code-point": "^2.0.0",
+            "strip-ansi": "^4.0.0"
+          }
+        },
+        "strip-ansi": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+          "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^3.0.0"
+          }
+        }
+      }
+    },
+    "ansi-escapes": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz",
+      "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==",
+      "dev": true
+    },
+    "ansi-regex": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+      "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+      "dev": true
+    },
+    "ansi-styles": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+      "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+      "dev": true,
+      "requires": {
+        "@types/color-name": "^1.1.1",
+        "color-convert": "^2.0.1"
+      }
+    },
+    "any-observable": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz",
+      "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==",
+      "dev": true
+    },
+    "anymatch": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
+      "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
+      "dev": true,
+      "requires": {
+        "normalize-path": "^3.0.0",
+        "picomatch": "^2.0.4"
+      }
+    },
+    "axios": {
+      "version": "0.19.2",
+      "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz",
+      "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==",
+      "dev": true,
+      "requires": {
+        "follow-redirects": "1.5.10"
+      }
+    },
+    "balanced-match": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+      "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+      "dev": true
+    },
+    "binary-extensions": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz",
+      "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==",
+      "dev": true
+    },
+    "boxen": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz",
+      "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==",
+      "dev": true,
+      "requires": {
+        "ansi-align": "^2.0.0",
+        "camelcase": "^4.0.0",
+        "chalk": "^2.0.1",
+        "cli-boxes": "^1.0.0",
+        "string-width": "^2.0.0",
+        "term-size": "^1.2.0",
+        "widest-line": "^2.0.0"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+          "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+          "dev": true
+        },
+        "ansi-styles": {
+          "version": "3.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+          "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+          "dev": true,
+          "requires": {
+            "color-convert": "^1.9.0"
+          }
+        },
+        "chalk": {
+          "version": "2.4.2",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+          "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^3.2.1",
+            "escape-string-regexp": "^1.0.5",
+            "supports-color": "^5.3.0"
+          }
+        },
+        "color-convert": {
+          "version": "1.9.3",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+          "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+          "dev": true,
+          "requires": {
+            "color-name": "1.1.3"
+          }
+        },
+        "color-name": {
+          "version": "1.1.3",
+          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+          "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+          "dev": true
+        },
+        "has-flag": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+          "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+          "dev": true
+        },
+        "is-fullwidth-code-point": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+          "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+          "dev": true
+        },
+        "string-width": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+          "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+          "dev": true,
+          "requires": {
+            "is-fullwidth-code-point": "^2.0.0",
+            "strip-ansi": "^4.0.0"
+          }
+        },
+        "strip-ansi": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+          "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^3.0.0"
+          }
+        },
+        "supports-color": {
+          "version": "5.5.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+          "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^3.0.0"
+          }
+        }
+      }
+    },
+    "brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dev": true,
+      "requires": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "braces": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+      "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+      "dev": true,
+      "requires": {
+        "fill-range": "^7.0.1"
+      }
+    },
+    "callsites": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+      "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+      "dev": true
+    },
+    "camelcase": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
+      "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=",
+      "dev": true
+    },
+    "capture-stack-trace": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz",
+      "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==",
+      "dev": true
+    },
+    "chalk": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
+      "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+      "dev": true,
+      "requires": {
+        "ansi-styles": "^4.1.0",
+        "supports-color": "^7.1.0"
+      }
+    },
+    "chokidar": {
+      "version": "3.3.1",
+      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.1.tgz",
+      "integrity": "sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg==",
+      "dev": true,
+      "requires": {
+        "anymatch": "~3.1.1",
+        "braces": "~3.0.2",
+        "fsevents": "~2.1.2",
+        "glob-parent": "~5.1.0",
+        "is-binary-path": "~2.1.0",
+        "is-glob": "~4.0.1",
+        "normalize-path": "~3.0.0",
+        "readdirp": "~3.3.0"
+      }
+    },
+    "ci-info": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
+      "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
+      "dev": true
+    },
+    "cli-boxes": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz",
+      "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=",
+      "dev": true
+    },
+    "cli-cursor": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
+      "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
+      "dev": true,
+      "requires": {
+        "restore-cursor": "^2.0.0"
+      }
+    },
+    "cli-truncate": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz",
+      "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=",
+      "dev": true,
+      "requires": {
+        "slice-ansi": "0.0.4",
+        "string-width": "^1.0.1"
+      }
+    },
+    "code-point-at": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
+      "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
+      "dev": true
+    },
+    "color-convert": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+      "dev": true,
+      "requires": {
+        "color-name": "~1.1.4"
+      }
+    },
+    "color-name": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+      "dev": true
+    },
+    "commander": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
+      "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
+      "dev": true
+    },
+    "compare-versions": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz",
+      "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==",
+      "dev": true
+    },
+    "concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+      "dev": true
+    },
+    "configstore": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz",
+      "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==",
+      "dev": true,
+      "requires": {
+        "dot-prop": "^4.1.0",
+        "graceful-fs": "^4.1.2",
+        "make-dir": "^1.0.0",
+        "unique-string": "^1.0.0",
+        "write-file-atomic": "^2.0.0",
+        "xdg-basedir": "^3.0.0"
+      }
+    },
+    "cosmiconfig": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz",
+      "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==",
+      "dev": true,
+      "requires": {
+        "@types/parse-json": "^4.0.0",
+        "import-fresh": "^3.1.0",
+        "parse-json": "^5.0.0",
+        "path-type": "^4.0.0",
+        "yaml": "^1.7.2"
+      }
+    },
+    "create-error-class": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz",
+      "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=",
+      "dev": true,
+      "requires": {
+        "capture-stack-trace": "^1.0.0"
+      }
+    },
+    "cross-spawn": {
+      "version": "7.0.1",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.1.tgz",
+      "integrity": "sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==",
+      "dev": true,
+      "requires": {
+        "path-key": "^3.1.0",
+        "shebang-command": "^2.0.0",
+        "which": "^2.0.1"
+      }
+    },
+    "crypto-random-string": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz",
+      "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=",
+      "dev": true
+    },
+    "date-fns": {
+      "version": "1.30.1",
+      "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz",
+      "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==",
+      "dev": true
+    },
+    "debug": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+      "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+      "dev": true,
+      "requires": {
+        "ms": "^2.1.1"
+      }
+    },
+    "dedent": {
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz",
+      "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=",
+      "dev": true
+    },
+    "deep-extend": {
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+      "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+      "dev": true
+    },
+    "define-properties": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
+      "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
+      "dev": true,
+      "requires": {
+        "object-keys": "^1.0.12"
+      }
+    },
+    "dot-prop": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz",
+      "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==",
+      "dev": true,
+      "requires": {
+        "is-obj": "^1.0.0"
+      }
+    },
+    "duplexer3": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
+      "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=",
+      "dev": true
+    },
+    "elegant-spinner": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz",
+      "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=",
+      "dev": true
+    },
+    "end-of-stream": {
+      "version": "1.4.4",
+      "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+      "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+      "dev": true,
+      "requires": {
+        "once": "^1.4.0"
+      }
+    },
+    "error-ex": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+      "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+      "dev": true,
+      "requires": {
+        "is-arrayish": "^0.2.1"
+      }
+    },
+    "es-abstract": {
+      "version": "1.17.4",
+      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz",
+      "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==",
+      "dev": true,
+      "requires": {
+        "es-to-primitive": "^1.2.1",
+        "function-bind": "^1.1.1",
+        "has": "^1.0.3",
+        "has-symbols": "^1.0.1",
+        "is-callable": "^1.1.5",
+        "is-regex": "^1.0.5",
+        "object-inspect": "^1.7.0",
+        "object-keys": "^1.1.1",
+        "object.assign": "^4.1.0",
+        "string.prototype.trimleft": "^2.1.1",
+        "string.prototype.trimright": "^2.1.1"
+      }
+    },
+    "es-to-primitive": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+      "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+      "dev": true,
+      "requires": {
+        "is-callable": "^1.1.4",
+        "is-date-object": "^1.0.1",
+        "is-symbol": "^1.0.2"
+      }
+    },
+    "escape-string-regexp": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+      "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+      "dev": true
+    },
+    "esutils": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+      "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+      "dev": true
+    },
+    "execa": {
+      "version": "3.4.0",
+      "resolved": "https://registry.npmjs.org/execa/-/execa-3.4.0.tgz",
+      "integrity": "sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g==",
+      "dev": true,
+      "requires": {
+        "cross-spawn": "^7.0.0",
+        "get-stream": "^5.0.0",
+        "human-signals": "^1.1.1",
+        "is-stream": "^2.0.0",
+        "merge-stream": "^2.0.0",
+        "npm-run-path": "^4.0.0",
+        "onetime": "^5.1.0",
+        "p-finally": "^2.0.0",
+        "signal-exit": "^3.0.2",
+        "strip-final-newline": "^2.0.0"
+      }
+    },
+    "figures": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz",
+      "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=",
+      "dev": true,
+      "requires": {
+        "escape-string-regexp": "^1.0.5",
+        "object-assign": "^4.1.0"
+      }
+    },
+    "fill-range": {
+      "version": "7.0.1",
+      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+      "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+      "dev": true,
+      "requires": {
+        "to-regex-range": "^5.0.1"
+      }
+    },
+    "find-up": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+      "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+      "dev": true,
+      "requires": {
+        "locate-path": "^5.0.0",
+        "path-exists": "^4.0.0"
+      }
+    },
+    "find-versions": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-3.2.0.tgz",
+      "integrity": "sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww==",
+      "dev": true,
+      "requires": {
+        "semver-regex": "^2.0.0"
+      }
+    },
+    "follow-redirects": {
+      "version": "1.5.10",
+      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
+      "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
+      "dev": true,
+      "requires": {
+        "debug": "=3.1.0"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "ms": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+          "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+          "dev": true
+        }
+      }
+    },
+    "fsevents": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz",
+      "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==",
+      "dev": true,
+      "optional": true
+    },
+    "function-bind": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+      "dev": true
+    },
+    "get-own-enumerable-property-symbols": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz",
+      "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==",
+      "dev": true
+    },
+    "get-stream": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz",
+      "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==",
+      "dev": true,
+      "requires": {
+        "pump": "^3.0.0"
+      }
+    },
+    "glob-parent": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz",
+      "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==",
+      "dev": true,
+      "requires": {
+        "is-glob": "^4.0.1"
+      }
+    },
+    "global-dirs": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz",
+      "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=",
+      "dev": true,
+      "requires": {
+        "ini": "^1.3.4"
+      }
+    },
+    "got": {
+      "version": "6.7.1",
+      "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz",
+      "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=",
+      "dev": true,
+      "requires": {
+        "create-error-class": "^3.0.0",
+        "duplexer3": "^0.1.4",
+        "get-stream": "^3.0.0",
+        "is-redirect": "^1.0.0",
+        "is-retry-allowed": "^1.0.0",
+        "is-stream": "^1.0.0",
+        "lowercase-keys": "^1.0.0",
+        "safe-buffer": "^5.0.1",
+        "timed-out": "^4.0.0",
+        "unzip-response": "^2.0.1",
+        "url-parse-lax": "^1.0.0"
+      },
+      "dependencies": {
+        "get-stream": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+          "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
+          "dev": true
+        },
+        "is-stream": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+          "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
+          "dev": true
+        }
+      }
+    },
+    "graceful-fs": {
+      "version": "4.2.3",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
+      "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==",
+      "dev": true
+    },
+    "has": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+      "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+      "dev": true,
+      "requires": {
+        "function-bind": "^1.1.1"
+      }
+    },
+    "has-ansi": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+      "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+      "dev": true,
+      "requires": {
+        "ansi-regex": "^2.0.0"
+      }
+    },
+    "has-flag": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+      "dev": true
+    },
+    "has-symbols": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
+      "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
+      "dev": true
+    },
+    "hosted-git-info": {
+      "version": "2.8.8",
+      "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
+      "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==",
+      "dev": true
+    },
+    "human-signals": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz",
+      "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==",
+      "dev": true
+    },
+    "husky": {
+      "version": "4.2.3",
+      "resolved": "https://registry.npmjs.org/husky/-/husky-4.2.3.tgz",
+      "integrity": "sha512-VxTsSTRwYveKXN4SaH1/FefRJYCtx+wx04sSVcOpD7N2zjoHxa+cEJ07Qg5NmV3HAK+IRKOyNVpi2YBIVccIfQ==",
+      "dev": true,
+      "requires": {
+        "chalk": "^3.0.0",
+        "ci-info": "^2.0.0",
+        "compare-versions": "^3.5.1",
+        "cosmiconfig": "^6.0.0",
+        "find-versions": "^3.2.0",
+        "opencollective-postinstall": "^2.0.2",
+        "pkg-dir": "^4.2.0",
+        "please-upgrade-node": "^3.2.0",
+        "slash": "^3.0.0",
+        "which-pm-runs": "^1.0.0"
+      }
+    },
+    "ignore-by-default": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
+      "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=",
+      "dev": true
+    },
+    "import-fresh": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz",
+      "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==",
+      "dev": true,
+      "requires": {
+        "parent-module": "^1.0.0",
+        "resolve-from": "^4.0.0"
+      }
+    },
+    "import-lazy": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz",
+      "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=",
+      "dev": true
+    },
+    "imurmurhash": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+      "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+      "dev": true
+    },
+    "indent-string": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz",
+      "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=",
+      "dev": true
+    },
+    "ini": {
+      "version": "1.3.5",
+      "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
+      "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
+      "dev": true
+    },
+    "is-arrayish": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+      "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+      "dev": true
+    },
+    "is-binary-path": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+      "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+      "dev": true,
+      "requires": {
+        "binary-extensions": "^2.0.0"
+      }
+    },
+    "is-callable": {
+      "version": "1.1.5",
+      "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz",
+      "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==",
+      "dev": true
+    },
+    "is-ci": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz",
+      "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==",
+      "dev": true,
+      "requires": {
+        "ci-info": "^1.5.0"
+      },
+      "dependencies": {
+        "ci-info": {
+          "version": "1.6.0",
+          "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz",
+          "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==",
+          "dev": true
+        }
+      }
+    },
+    "is-date-object": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz",
+      "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==",
+      "dev": true
+    },
+    "is-extglob": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+      "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+      "dev": true
+    },
+    "is-fullwidth-code-point": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+      "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+      "dev": true,
+      "requires": {
+        "number-is-nan": "^1.0.0"
+      }
+    },
+    "is-glob": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+      "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+      "dev": true,
+      "requires": {
+        "is-extglob": "^2.1.1"
+      }
+    },
+    "is-installed-globally": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz",
+      "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=",
+      "dev": true,
+      "requires": {
+        "global-dirs": "^0.1.0",
+        "is-path-inside": "^1.0.0"
+      }
+    },
+    "is-npm": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz",
+      "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=",
+      "dev": true
+    },
+    "is-number": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+      "dev": true
+    },
+    "is-obj": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
+      "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
+      "dev": true
+    },
+    "is-observable": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz",
+      "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==",
+      "dev": true,
+      "requires": {
+        "symbol-observable": "^1.1.0"
+      }
+    },
+    "is-path-inside": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
+      "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
+      "dev": true,
+      "requires": {
+        "path-is-inside": "^1.0.1"
+      }
+    },
+    "is-promise": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
+      "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
+      "dev": true
+    },
+    "is-redirect": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz",
+      "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=",
+      "dev": true
+    },
+    "is-regex": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz",
+      "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==",
+      "dev": true,
+      "requires": {
+        "has": "^1.0.3"
+      }
+    },
+    "is-regexp": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz",
+      "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=",
+      "dev": true
+    },
+    "is-retry-allowed": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz",
+      "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==",
+      "dev": true
+    },
+    "is-stream": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
+      "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==",
+      "dev": true
+    },
+    "is-symbol": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
+      "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==",
+      "dev": true,
+      "requires": {
+        "has-symbols": "^1.0.1"
+      }
+    },
+    "isexe": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+      "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+      "dev": true
+    },
+    "js-tokens": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+      "dev": true
+    },
+    "json-parse-better-errors": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+      "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
+      "dev": true
+    },
+    "latest-version": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz",
+      "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=",
+      "dev": true,
+      "requires": {
+        "package-json": "^4.0.0"
+      }
+    },
+    "lines-and-columns": {
+      "version": "1.1.6",
+      "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz",
+      "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=",
+      "dev": true
+    },
+    "lint-staged": {
+      "version": "10.0.8",
+      "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-10.0.8.tgz",
+      "integrity": "sha512-Oa9eS4DJqvQMVdywXfEor6F4vP+21fPHF8LUXgBbVWUSWBddjqsvO6Bv1LwMChmgQZZqwUvgJSHlu8HFHAPZmA==",
+      "dev": true,
+      "requires": {
+        "chalk": "^3.0.0",
+        "commander": "^4.0.1",
+        "cosmiconfig": "^6.0.0",
+        "debug": "^4.1.1",
+        "dedent": "^0.7.0",
+        "execa": "^3.4.0",
+        "listr": "^0.14.3",
+        "log-symbols": "^3.0.0",
+        "micromatch": "^4.0.2",
+        "normalize-path": "^3.0.0",
+        "please-upgrade-node": "^3.2.0",
+        "string-argv": "0.3.1",
+        "stringify-object": "^3.3.0"
+      }
+    },
+    "listr": {
+      "version": "0.14.3",
+      "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.3.tgz",
+      "integrity": "sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==",
+      "dev": true,
+      "requires": {
+        "@samverschueren/stream-to-observable": "^0.3.0",
+        "is-observable": "^1.1.0",
+        "is-promise": "^2.1.0",
+        "is-stream": "^1.1.0",
+        "listr-silent-renderer": "^1.1.1",
+        "listr-update-renderer": "^0.5.0",
+        "listr-verbose-renderer": "^0.5.0",
+        "p-map": "^2.0.0",
+        "rxjs": "^6.3.3"
+      },
+      "dependencies": {
+        "is-stream": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+          "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
+          "dev": true
+        }
+      }
+    },
+    "listr-silent-renderer": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz",
+      "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=",
+      "dev": true
+    },
+    "listr-update-renderer": {
+      "version": "0.5.0",
+      "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz",
+      "integrity": "sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==",
+      "dev": true,
+      "requires": {
+        "chalk": "^1.1.3",
+        "cli-truncate": "^0.2.1",
+        "elegant-spinner": "^1.0.1",
+        "figures": "^1.7.0",
+        "indent-string": "^3.0.0",
+        "log-symbols": "^1.0.2",
+        "log-update": "^2.3.0",
+        "strip-ansi": "^3.0.1"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "2.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+          "dev": true
+        },
+        "chalk": {
+          "version": "1.1.3",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^2.2.1",
+            "escape-string-regexp": "^1.0.2",
+            "has-ansi": "^2.0.0",
+            "strip-ansi": "^3.0.0",
+            "supports-color": "^2.0.0"
+          }
+        },
+        "log-symbols": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz",
+          "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=",
+          "dev": true,
+          "requires": {
+            "chalk": "^1.0.0"
+          }
+        },
+        "supports-color": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+          "dev": true
+        }
+      }
+    },
+    "listr-verbose-renderer": {
+      "version": "0.5.0",
+      "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz",
+      "integrity": "sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==",
+      "dev": true,
+      "requires": {
+        "chalk": "^2.4.1",
+        "cli-cursor": "^2.1.0",
+        "date-fns": "^1.27.2",
+        "figures": "^2.0.0"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "3.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+          "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+          "dev": true,
+          "requires": {
+            "color-convert": "^1.9.0"
+          }
+        },
+        "chalk": {
+          "version": "2.4.2",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+          "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^3.2.1",
+            "escape-string-regexp": "^1.0.5",
+            "supports-color": "^5.3.0"
+          }
+        },
+        "color-convert": {
+          "version": "1.9.3",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+          "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+          "dev": true,
+          "requires": {
+            "color-name": "1.1.3"
+          }
+        },
+        "color-name": {
+          "version": "1.1.3",
+          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+          "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+          "dev": true
+        },
+        "figures": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
+          "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
+          "dev": true,
+          "requires": {
+            "escape-string-regexp": "^1.0.5"
+          }
+        },
+        "has-flag": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+          "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "5.5.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+          "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^3.0.0"
+          }
+        }
+      }
+    },
+    "load-json-file": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
+      "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.2",
+        "parse-json": "^4.0.0",
+        "pify": "^3.0.0",
+        "strip-bom": "^3.0.0"
+      },
+      "dependencies": {
+        "parse-json": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+          "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
+          "dev": true,
+          "requires": {
+            "error-ex": "^1.3.1",
+            "json-parse-better-errors": "^1.0.1"
+          }
+        }
+      }
+    },
+    "locate-path": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+      "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+      "dev": true,
+      "requires": {
+        "p-locate": "^4.1.0"
+      }
+    },
+    "log-symbols": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz",
+      "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==",
+      "dev": true,
+      "requires": {
+        "chalk": "^2.4.2"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "3.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+          "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+          "dev": true,
+          "requires": {
+            "color-convert": "^1.9.0"
+          }
+        },
+        "chalk": {
+          "version": "2.4.2",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+          "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^3.2.1",
+            "escape-string-regexp": "^1.0.5",
+            "supports-color": "^5.3.0"
+          }
+        },
+        "color-convert": {
+          "version": "1.9.3",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+          "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+          "dev": true,
+          "requires": {
+            "color-name": "1.1.3"
+          }
+        },
+        "color-name": {
+          "version": "1.1.3",
+          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+          "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+          "dev": true
+        },
+        "has-flag": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+          "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "5.5.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+          "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^3.0.0"
+          }
+        }
+      }
+    },
+    "log-update": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz",
+      "integrity": "sha1-iDKP19HOeTiykoN0bwsbwSayRwg=",
+      "dev": true,
+      "requires": {
+        "ansi-escapes": "^3.0.0",
+        "cli-cursor": "^2.0.0",
+        "wrap-ansi": "^3.0.1"
+      }
+    },
+    "lowercase-keys": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
+      "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==",
+      "dev": true
+    },
+    "lru-cache": {
+      "version": "4.1.5",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+      "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+      "dev": true,
+      "requires": {
+        "pseudomap": "^1.0.2",
+        "yallist": "^2.1.2"
+      }
+    },
+    "make-dir": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
+      "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
+      "dev": true,
+      "requires": {
+        "pify": "^3.0.0"
+      }
+    },
+    "memorystream": {
+      "version": "0.3.1",
+      "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
+      "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=",
+      "dev": true
+    },
+    "merge-stream": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+      "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+      "dev": true
+    },
+    "micromatch": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz",
+      "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==",
+      "dev": true,
+      "requires": {
+        "braces": "^3.0.1",
+        "picomatch": "^2.0.5"
+      }
+    },
+    "mimic-fn": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+      "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+      "dev": true
+    },
+    "minimatch": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+      "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+      "dev": true,
+      "requires": {
+        "brace-expansion": "^1.1.7"
+      }
+    },
+    "minimist": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+      "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+      "dev": true
+    },
+    "ms": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+      "dev": true
+    },
+    "nice-try": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+      "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
+      "dev": true
+    },
+    "nodemon": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.2.tgz",
+      "integrity": "sha512-GWhYPMfde2+M0FsHnggIHXTqPDHXia32HRhh6H0d75Mt9FKUoCBvumNHr7LdrpPBTKxsWmIEOjoN+P4IU6Hcaw==",
+      "dev": true,
+      "requires": {
+        "chokidar": "^3.2.2",
+        "debug": "^3.2.6",
+        "ignore-by-default": "^1.0.1",
+        "minimatch": "^3.0.4",
+        "pstree.remy": "^1.1.7",
+        "semver": "^5.7.1",
+        "supports-color": "^5.5.0",
+        "touch": "^3.1.0",
+        "undefsafe": "^2.0.2",
+        "update-notifier": "^2.5.0"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "3.2.6",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+          "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+          "dev": true,
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        },
+        "has-flag": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+          "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "5.5.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+          "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^3.0.0"
+          }
+        }
+      }
+    },
+    "nopt": {
+      "version": "1.0.10",
+      "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
+      "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=",
+      "dev": true,
+      "requires": {
+        "abbrev": "1"
+      }
+    },
+    "normalize-package-data": {
+      "version": "2.5.0",
+      "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+      "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+      "dev": true,
+      "requires": {
+        "hosted-git-info": "^2.1.4",
+        "resolve": "^1.10.0",
+        "semver": "2 || 3 || 4 || 5",
+        "validate-npm-package-license": "^3.0.1"
+      }
+    },
+    "normalize-path": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+      "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+      "dev": true
+    },
+    "npm-run-all": {
+      "version": "4.1.5",
+      "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz",
+      "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==",
+      "dev": true,
+      "requires": {
+        "ansi-styles": "^3.2.1",
+        "chalk": "^2.4.1",
+        "cross-spawn": "^6.0.5",
+        "memorystream": "^0.3.1",
+        "minimatch": "^3.0.4",
+        "pidtree": "^0.3.0",
+        "read-pkg": "^3.0.0",
+        "shell-quote": "^1.6.1",
+        "string.prototype.padend": "^3.0.0"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "3.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+          "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+          "dev": true,
+          "requires": {
+            "color-convert": "^1.9.0"
+          }
+        },
+        "chalk": {
+          "version": "2.4.2",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+          "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^3.2.1",
+            "escape-string-regexp": "^1.0.5",
+            "supports-color": "^5.3.0"
+          }
+        },
+        "color-convert": {
+          "version": "1.9.3",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+          "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+          "dev": true,
+          "requires": {
+            "color-name": "1.1.3"
+          }
+        },
+        "color-name": {
+          "version": "1.1.3",
+          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+          "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+          "dev": true
+        },
+        "cross-spawn": {
+          "version": "6.0.5",
+          "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+          "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+          "dev": true,
+          "requires": {
+            "nice-try": "^1.0.4",
+            "path-key": "^2.0.1",
+            "semver": "^5.5.0",
+            "shebang-command": "^1.2.0",
+            "which": "^1.2.9"
+          }
+        },
+        "has-flag": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+          "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+          "dev": true
+        },
+        "path-key": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+          "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
+          "dev": true
+        },
+        "shebang-command": {
+          "version": "1.2.0",
+          "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+          "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+          "dev": true,
+          "requires": {
+            "shebang-regex": "^1.0.0"
+          }
+        },
+        "shebang-regex": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+          "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "5.5.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+          "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^3.0.0"
+          }
+        },
+        "which": {
+          "version": "1.3.1",
+          "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+          "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+          "dev": true,
+          "requires": {
+            "isexe": "^2.0.0"
+          }
+        }
+      }
+    },
+    "npm-run-path": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+      "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+      "dev": true,
+      "requires": {
+        "path-key": "^3.0.0"
+      }
+    },
+    "number-is-nan": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+      "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
+      "dev": true
+    },
+    "object-assign": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+      "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
+      "dev": true
+    },
+    "object-inspect": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz",
+      "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==",
+      "dev": true
+    },
+    "object-keys": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+      "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+      "dev": true
+    },
+    "object.assign": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
+      "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
+      "dev": true,
+      "requires": {
+        "define-properties": "^1.1.2",
+        "function-bind": "^1.1.1",
+        "has-symbols": "^1.0.0",
+        "object-keys": "^1.0.11"
+      }
+    },
+    "once": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+      "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+      "dev": true,
+      "requires": {
+        "wrappy": "1"
+      }
+    },
+    "onetime": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz",
+      "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==",
+      "dev": true,
+      "requires": {
+        "mimic-fn": "^2.1.0"
+      }
+    },
+    "opencollective-postinstall": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.2.tgz",
+      "integrity": "sha512-pVOEP16TrAO2/fjej1IdOyupJY8KDUM1CvsaScRbw6oddvpQoOfGk4ywha0HKKVAD6RkW4x6Q+tNBwhf3Bgpuw==",
+      "dev": true
+    },
+    "p-finally": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz",
+      "integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==",
+      "dev": true
+    },
+    "p-limit": {
+      "version": "2.2.2",
+      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz",
+      "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==",
+      "dev": true,
+      "requires": {
+        "p-try": "^2.0.0"
+      }
+    },
+    "p-locate": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+      "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+      "dev": true,
+      "requires": {
+        "p-limit": "^2.2.0"
+      }
+    },
+    "p-map": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz",
+      "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==",
+      "dev": true
+    },
+    "p-try": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+      "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+      "dev": true
+    },
+    "package-json": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz",
+      "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=",
+      "dev": true,
+      "requires": {
+        "got": "^6.7.1",
+        "registry-auth-token": "^3.0.1",
+        "registry-url": "^3.0.3",
+        "semver": "^5.1.0"
+      }
+    },
+    "parent-module": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+      "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+      "dev": true,
+      "requires": {
+        "callsites": "^3.0.0"
+      }
+    },
+    "parse-json": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz",
+      "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==",
+      "dev": true,
+      "requires": {
+        "@babel/code-frame": "^7.0.0",
+        "error-ex": "^1.3.1",
+        "json-parse-better-errors": "^1.0.1",
+        "lines-and-columns": "^1.1.6"
+      }
+    },
+    "path-exists": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+      "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+      "dev": true
+    },
+    "path-is-inside": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
+      "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=",
+      "dev": true
+    },
+    "path-key": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+      "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+      "dev": true
+    },
+    "path-parse": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
+      "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+      "dev": true
+    },
+    "path-type": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+      "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+      "dev": true
+    },
+    "picomatch": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.1.tgz",
+      "integrity": "sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA==",
+      "dev": true
+    },
+    "pidtree": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.0.tgz",
+      "integrity": "sha512-9CT4NFlDcosssyg8KVFltgokyKZIFjoBxw8CTGy+5F38Y1eQWrt8tRayiUOXE+zVKQnYu5BR8JjCtvK3BcnBhg==",
+      "dev": true
+    },
+    "pify": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+      "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+      "dev": true
+    },
+    "pkg-dir": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+      "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+      "dev": true,
+      "requires": {
+        "find-up": "^4.0.0"
+      }
+    },
+    "please-upgrade-node": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz",
+      "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==",
+      "dev": true,
+      "requires": {
+        "semver-compare": "^1.0.0"
+      }
+    },
+    "prepend-http": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
+      "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=",
+      "dev": true
+    },
+    "prettier": {
+      "version": "1.19.1",
+      "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz",
+      "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==",
+      "dev": true
+    },
+    "pseudomap": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+      "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
+      "dev": true
+    },
+    "pstree.remy": {
+      "version": "1.1.7",
+      "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.7.tgz",
+      "integrity": "sha512-xsMgrUwRpuGskEzBFkH8NmTimbZ5PcPup0LA8JJkHIm2IMUbQcpo3yeLNWVrufEYjh8YwtSVh0xz6UeWc5Oh5A==",
+      "dev": true
+    },
+    "pump": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+      "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+      "dev": true,
+      "requires": {
+        "end-of-stream": "^1.1.0",
+        "once": "^1.3.1"
+      }
+    },
+    "rc": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+      "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+      "dev": true,
+      "requires": {
+        "deep-extend": "^0.6.0",
+        "ini": "~1.3.0",
+        "minimist": "^1.2.0",
+        "strip-json-comments": "~2.0.1"
+      }
+    },
+    "read-pkg": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
+      "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=",
+      "dev": true,
+      "requires": {
+        "load-json-file": "^4.0.0",
+        "normalize-package-data": "^2.3.2",
+        "path-type": "^3.0.0"
+      },
+      "dependencies": {
+        "path-type": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
+          "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
+          "dev": true,
+          "requires": {
+            "pify": "^3.0.0"
+          }
+        }
+      }
+    },
+    "readdirp": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.3.0.tgz",
+      "integrity": "sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ==",
+      "dev": true,
+      "requires": {
+        "picomatch": "^2.0.7"
+      }
+    },
+    "regenerator-runtime": {
+      "version": "0.13.4",
+      "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.4.tgz",
+      "integrity": "sha512-plpwicqEzfEyTQohIKktWigcLzmNStMGwbOUbykx51/29Z3JOGYldaaNGK7ngNXV+UcoqvIMmloZ48Sr74sd+g==",
+      "dev": true
+    },
+    "registry-auth-token": {
+      "version": "3.4.0",
+      "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz",
+      "integrity": "sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==",
+      "dev": true,
+      "requires": {
+        "rc": "^1.1.6",
+        "safe-buffer": "^5.0.1"
+      }
+    },
+    "registry-url": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz",
+      "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=",
+      "dev": true,
+      "requires": {
+        "rc": "^1.0.1"
+      }
+    },
+    "resolve": {
+      "version": "1.15.1",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz",
+      "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==",
+      "dev": true,
+      "requires": {
+        "path-parse": "^1.0.6"
+      }
+    },
+    "resolve-from": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+      "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+      "dev": true
+    },
+    "restore-cursor": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
+      "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
+      "dev": true,
+      "requires": {
+        "onetime": "^2.0.0",
+        "signal-exit": "^3.0.2"
+      },
+      "dependencies": {
+        "mimic-fn": {
+          "version": "1.2.0",
+          "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
+          "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
+          "dev": true
+        },
+        "onetime": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
+          "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
+          "dev": true,
+          "requires": {
+            "mimic-fn": "^1.0.0"
+          }
+        }
+      }
+    },
+    "rxjs": {
+      "version": "6.5.4",
+      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz",
+      "integrity": "sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==",
+      "dev": true,
+      "requires": {
+        "tslib": "^1.9.0"
+      }
+    },
+    "safe-buffer": {
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
+      "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==",
+      "dev": true
+    },
+    "semver": {
+      "version": "5.7.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+      "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+      "dev": true
+    },
+    "semver-compare": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz",
+      "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=",
+      "dev": true
+    },
+    "semver-diff": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz",
+      "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=",
+      "dev": true,
+      "requires": {
+        "semver": "^5.0.3"
+      }
+    },
+    "semver-regex": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-2.0.0.tgz",
+      "integrity": "sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==",
+      "dev": true
+    },
+    "shebang-command": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+      "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+      "dev": true,
+      "requires": {
+        "shebang-regex": "^3.0.0"
+      }
+    },
+    "shebang-regex": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+      "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+      "dev": true
+    },
+    "shell-quote": {
+      "version": "1.7.2",
+      "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz",
+      "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==",
+      "dev": true
+    },
+    "signal-exit": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+      "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
+      "dev": true
+    },
+    "slash": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+      "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+      "dev": true
+    },
+    "slice-ansi": {
+      "version": "0.0.4",
+      "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz",
+      "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=",
+      "dev": true
+    },
+    "spdx-correct": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz",
+      "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==",
+      "dev": true,
+      "requires": {
+        "spdx-expression-parse": "^3.0.0",
+        "spdx-license-ids": "^3.0.0"
+      }
+    },
+    "spdx-exceptions": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz",
+      "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==",
+      "dev": true
+    },
+    "spdx-expression-parse": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
+      "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
+      "dev": true,
+      "requires": {
+        "spdx-exceptions": "^2.1.0",
+        "spdx-license-ids": "^3.0.0"
+      }
+    },
+    "spdx-license-ids": {
+      "version": "3.0.5",
+      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz",
+      "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==",
+      "dev": true
+    },
+    "string-argv": {
+      "version": "0.3.1",
+      "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz",
+      "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==",
+      "dev": true
+    },
+    "string-width": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+      "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+      "dev": true,
+      "requires": {
+        "code-point-at": "^1.0.0",
+        "is-fullwidth-code-point": "^1.0.0",
+        "strip-ansi": "^3.0.0"
+      }
+    },
+    "string.prototype.padend": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.0.tgz",
+      "integrity": "sha512-3aIv8Ffdp8EZj8iLwREGpQaUZiPyrWrpzMBHvkiSW/bK/EGve9np07Vwy7IJ5waydpGXzQZu/F8Oze2/IWkBaA==",
+      "dev": true,
+      "requires": {
+        "define-properties": "^1.1.3",
+        "es-abstract": "^1.17.0-next.1"
+      }
+    },
+    "string.prototype.trimleft": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz",
+      "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==",
+      "dev": true,
+      "requires": {
+        "define-properties": "^1.1.3",
+        "function-bind": "^1.1.1"
+      }
+    },
+    "string.prototype.trimright": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz",
+      "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==",
+      "dev": true,
+      "requires": {
+        "define-properties": "^1.1.3",
+        "function-bind": "^1.1.1"
+      }
+    },
+    "stringify-object": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz",
+      "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==",
+      "dev": true,
+      "requires": {
+        "get-own-enumerable-property-symbols": "^3.0.0",
+        "is-obj": "^1.0.1",
+        "is-regexp": "^1.0.0"
+      }
+    },
+    "strip-ansi": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+      "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+      "dev": true,
+      "requires": {
+        "ansi-regex": "^2.0.0"
+      }
+    },
+    "strip-bom": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+      "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+      "dev": true
+    },
+    "strip-eof": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+      "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
+      "dev": true
+    },
+    "strip-final-newline": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+      "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+      "dev": true
+    },
+    "strip-json-comments": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+      "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
+      "dev": true
+    },
+    "supports-color": {
+      "version": "7.1.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+      "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+      "dev": true,
+      "requires": {
+        "has-flag": "^4.0.0"
+      }
+    },
+    "symbol-observable": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
+      "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==",
+      "dev": true
+    },
+    "term-size": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz",
+      "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=",
+      "dev": true,
+      "requires": {
+        "execa": "^0.7.0"
+      },
+      "dependencies": {
+        "cross-spawn": {
+          "version": "5.1.0",
+          "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
+          "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
+          "dev": true,
+          "requires": {
+            "lru-cache": "^4.0.1",
+            "shebang-command": "^1.2.0",
+            "which": "^1.2.9"
+          }
+        },
+        "execa": {
+          "version": "0.7.0",
+          "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
+          "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=",
+          "dev": true,
+          "requires": {
+            "cross-spawn": "^5.0.1",
+            "get-stream": "^3.0.0",
+            "is-stream": "^1.1.0",
+            "npm-run-path": "^2.0.0",
+            "p-finally": "^1.0.0",
+            "signal-exit": "^3.0.0",
+            "strip-eof": "^1.0.0"
+          }
+        },
+        "get-stream": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+          "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
+          "dev": true
+        },
+        "is-stream": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+          "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
+          "dev": true
+        },
+        "npm-run-path": {
+          "version": "2.0.2",
+          "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
+          "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
+          "dev": true,
+          "requires": {
+            "path-key": "^2.0.0"
+          }
+        },
+        "p-finally": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
+          "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
+          "dev": true
+        },
+        "path-key": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+          "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
+          "dev": true
+        },
+        "shebang-command": {
+          "version": "1.2.0",
+          "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+          "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+          "dev": true,
+          "requires": {
+            "shebang-regex": "^1.0.0"
+          }
+        },
+        "shebang-regex": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+          "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
+          "dev": true
+        },
+        "which": {
+          "version": "1.3.1",
+          "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+          "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+          "dev": true,
+          "requires": {
+            "isexe": "^2.0.0"
+          }
+        }
+      }
+    },
+    "timed-out": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz",
+      "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=",
+      "dev": true
+    },
+    "to-regex-range": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+      "dev": true,
+      "requires": {
+        "is-number": "^7.0.0"
+      }
+    },
+    "touch": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
+      "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==",
+      "dev": true,
+      "requires": {
+        "nopt": "~1.0.10"
+      }
+    },
+    "tslib": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz",
+      "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==",
+      "dev": true
+    },
+    "typescript": {
+      "version": "3.8.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz",
+      "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==",
+      "dev": true
+    },
+    "undefsafe": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz",
+      "integrity": "sha512-nrXZwwXrD/T/JXeygJqdCO6NZZ1L66HrxM/Z7mIq2oPanoN0F1nLx3lwJMu6AwJY69hdixaFQOuoYsMjE5/C2A==",
+      "dev": true,
+      "requires": {
+        "debug": "^2.2.0"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "ms": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+          "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+          "dev": true
+        }
+      }
+    },
+    "unique-string": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz",
+      "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=",
+      "dev": true,
+      "requires": {
+        "crypto-random-string": "^1.0.0"
+      }
+    },
+    "unzip-response": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz",
+      "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=",
+      "dev": true
+    },
+    "update-notifier": {
+      "version": "2.5.0",
+      "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz",
+      "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==",
+      "dev": true,
+      "requires": {
+        "boxen": "^1.2.1",
+        "chalk": "^2.0.1",
+        "configstore": "^3.0.0",
+        "import-lazy": "^2.1.0",
+        "is-ci": "^1.0.10",
+        "is-installed-globally": "^0.1.0",
+        "is-npm": "^1.0.0",
+        "latest-version": "^3.0.0",
+        "semver-diff": "^2.0.0",
+        "xdg-basedir": "^3.0.0"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "3.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+          "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+          "dev": true,
+          "requires": {
+            "color-convert": "^1.9.0"
+          }
+        },
+        "chalk": {
+          "version": "2.4.2",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+          "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^3.2.1",
+            "escape-string-regexp": "^1.0.5",
+            "supports-color": "^5.3.0"
+          }
+        },
+        "color-convert": {
+          "version": "1.9.3",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+          "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+          "dev": true,
+          "requires": {
+            "color-name": "1.1.3"
+          }
+        },
+        "color-name": {
+          "version": "1.1.3",
+          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+          "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+          "dev": true
+        },
+        "has-flag": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+          "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "5.5.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+          "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^3.0.0"
+          }
+        }
+      }
+    },
+    "url-parse-lax": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz",
+      "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=",
+      "dev": true,
+      "requires": {
+        "prepend-http": "^1.0.1"
+      }
+    },
+    "validate-npm-package-license": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+      "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+      "dev": true,
+      "requires": {
+        "spdx-correct": "^3.0.0",
+        "spdx-expression-parse": "^3.0.0"
+      }
+    },
+    "which": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+      "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+      "dev": true,
+      "requires": {
+        "isexe": "^2.0.0"
+      }
+    },
+    "which-pm-runs": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz",
+      "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=",
+      "dev": true
+    },
+    "widest-line": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz",
+      "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==",
+      "dev": true,
+      "requires": {
+        "string-width": "^2.1.1"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+          "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+          "dev": true
+        },
+        "is-fullwidth-code-point": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+          "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+          "dev": true
+        },
+        "string-width": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+          "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+          "dev": true,
+          "requires": {
+            "is-fullwidth-code-point": "^2.0.0",
+            "strip-ansi": "^4.0.0"
+          }
+        },
+        "strip-ansi": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+          "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^3.0.0"
+          }
+        }
+      }
+    },
+    "wrap-ansi": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz",
+      "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=",
+      "dev": true,
+      "requires": {
+        "string-width": "^2.1.1",
+        "strip-ansi": "^4.0.0"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+          "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+          "dev": true
+        },
+        "is-fullwidth-code-point": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+          "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+          "dev": true
+        },
+        "string-width": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+          "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+          "dev": true,
+          "requires": {
+            "is-fullwidth-code-point": "^2.0.0",
+            "strip-ansi": "^4.0.0"
+          }
+        },
+        "strip-ansi": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+          "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^3.0.0"
+          }
+        }
+      }
+    },
+    "wrappy": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+      "dev": true
+    },
+    "write-file-atomic": {
+      "version": "2.4.3",
+      "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz",
+      "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.11",
+        "imurmurhash": "^0.1.4",
+        "signal-exit": "^3.0.2"
+      }
+    },
+    "xdg-basedir": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz",
+      "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=",
+      "dev": true
+    },
+    "yallist": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+      "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
+      "dev": true
+    },
+    "yaml": {
+      "version": "1.7.2",
+      "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.7.2.tgz",
+      "integrity": "sha512-qXROVp90sb83XtAoqE8bP9RwAkTTZbugRUTm5YeFCBfNRPEp2YzTeqWiz7m5OORHzEvrA/qcGS8hp/E+MMROYw==",
+      "dev": true,
+      "requires": {
+        "@babel/runtime": "^7.6.3"
+      }
+    }
+  }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..c8707ec
--- /dev/null
+++ b/package.json
@@ -0,0 +1,48 @@
+{
+  "name": "snippets",
+  "version": "1.0.0",
+  "description": "",
+  "main": "./dist/index.js",
+  "scripts": {
+    "start:dev": "nodemon --debug ./dist/index.js",
+    "start": "tsc",
+    "dev": "npm-run-all --serial --silent start start:*",
+    "build": "node ./dist/index.js",
+    "prettier": "prettier -c --write **/*"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/BiYuqi/snippets.git"
+  },
+  "author": "",
+  "license": "MIT",
+  "bugs": {
+    "url": "https://github.com/BiYuqi/snippets/issues"
+  },
+  "homepage": "https://github.com/BiYuqi/snippets#readme",
+  "husky": {
+    "hooks": {
+      "pre-commit": "lint-staged"
+    }
+  },
+  "lint-staged": {
+    "**/*.{js,ts,json,css,md}": [
+      "yarn prettier",
+      "git add"
+    ],
+    "**/*.{js,ts}": [
+      "yarn lint:fix",
+      "git add"
+    ]
+  },
+  "devDependencies": {
+    "@types/node": "^13.9.0",
+    "axios": "^0.19.2",
+    "husky": "^4.2.3",
+    "lint-staged": "^10.0.8",
+    "nodemon": "^2.0.2",
+    "npm-run-all": "^4.1.5",
+    "prettier": "^1.19.1",
+    "typescript": "^3.8.3"
+  }
+}
diff --git a/src/fetchIssue.ts b/src/fetchIssue.ts
new file mode 100644
index 0000000..10a538a
--- /dev/null
+++ b/src/fetchIssue.ts
@@ -0,0 +1,8 @@
+// import axios, { AxiosRequestConfig, AxiosPromise } from 'axios'
+
+interface Config {
+  owner: string,
+  repo: string,
+  token: string
+}
+
diff --git a/src/generateReadme.ts b/src/generateReadme.ts
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/src/generateReadme.ts
@@ -0,0 +1 @@
+
diff --git a/src/index.ts b/src/index.ts
new file mode 100644
index 0000000..83bc774
--- /dev/null
+++ b/src/index.ts
@@ -0,0 +1,2 @@
+console.log('I am form index.ts0000')
+console.log('测试222')
\ No newline at end of file
diff --git a/src/simplifyIssue.ts b/src/simplifyIssue.ts
new file mode 100644
index 0000000..e69de29
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..10f5f87
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,15 @@
+{
+  "compilerOptions": {
+    "outDir": "./dist",
+    "allowJs": true,
+    "target": "es5",
+    "module": "esnext",
+    "watch":true
+  },
+  "include": [
+    "./src/**/*"
+  ],
+  "exclude": [
+    "node_modules"
+  ]
+}

From 4c2f2dde05b1da0f3b60486a4fb1301697103d28 Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Sun, 8 Mar 2020 17:27:25 +0800
Subject: [PATCH 41/56] feat: add logic

---
 .prettierrc.js         |  3 ++-
 package.json           |  2 +-
 src/fetchIssue.ts      |  8 ------
 src/fetchIssues.ts     | 14 ++++++++++
 src/generateReadme.ts  | 43 ++++++++++++++++++++++++++++++
 src/index.ts           |  5 ++--
 src/refactoringData.ts | 10 +++++++
 src/simplifyIssue.ts   | 60 ++++++++++++++++++++++++++++++++++++++++++
 tsconfig.json          |  7 +++--
 9 files changed, 138 insertions(+), 14 deletions(-)
 delete mode 100644 src/fetchIssue.ts
 create mode 100644 src/fetchIssues.ts
 create mode 100644 src/refactoringData.ts

diff --git a/.prettierrc.js b/.prettierrc.js
index 77c16b6..5d76f8e 100644
--- a/.prettierrc.js
+++ b/.prettierrc.js
@@ -1,5 +1,6 @@
 module.exports = {
   singleQuote: true,
   printWidth: 100,
-  proseWrap: 'never'
+  proseWrap: 'never',
+  semi: false
 }
\ No newline at end of file
diff --git a/package.json b/package.json
index c8707ec..975a15a 100644
--- a/package.json
+++ b/package.json
@@ -5,7 +5,7 @@
   "main": "./dist/index.js",
   "scripts": {
     "start:dev": "nodemon --debug ./dist/index.js",
-    "start": "tsc",
+    "start": "tsc -w",
     "dev": "npm-run-all --serial --silent start start:*",
     "build": "node ./dist/index.js",
     "prettier": "prettier -c --write **/*"
diff --git a/src/fetchIssue.ts b/src/fetchIssue.ts
deleted file mode 100644
index 10a538a..0000000
--- a/src/fetchIssue.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-// import axios, { AxiosRequestConfig, AxiosPromise } from 'axios'
-
-interface Config {
-  owner: string,
-  repo: string,
-  token: string
-}
-
diff --git a/src/fetchIssues.ts b/src/fetchIssues.ts
new file mode 100644
index 0000000..6cdaba5
--- /dev/null
+++ b/src/fetchIssues.ts
@@ -0,0 +1,14 @@
+// import axios, { AxiosRequestConfig, AxiosPromise } from 'axios'
+import { Issues } from "./simplifyIssue";
+
+interface Config {
+  owner: string
+  repo: string
+  token: string
+}
+
+export function fetchIssues(): Promise<Array<Issues>> {
+  return new Promise((resolve, reject) => {
+    resolve([])
+  })
+}
\ No newline at end of file
diff --git a/src/generateReadme.ts b/src/generateReadme.ts
index 8b13789..5c1305a 100644
--- a/src/generateReadme.ts
+++ b/src/generateReadme.ts
@@ -1 +1,44 @@
+import * as fs from 'fs'
+import { refactoringData } from './refactoringData'
+import { fetchIssues } from './fetchIssues'
+import { Issues } from './simplifyIssue'
 
+const DefaultReadme: string = '<h1 align="center">日常技术摘录 👋</h1>'
+const RemoveSpace: RegExp = /^\s{5}/gmi
+
+export async function generateReadme() {
+  const README = []
+  const issues: Array<Issues> = await fetchIssues()
+  
+  if (!issues) {
+    console.log('Get the issue faild. Please check.')
+    process.exit(1)
+  }
+
+  const result = refactoringData(issues)
+  README.push(DefaultReadme)
+
+  Object.keys(result).forEach(cateGory => {
+    const cateGoryData = result[cateGory]
+    const readme = []
+    const name = cateGoryData[0].displayLabel
+
+    cateGoryData.forEach(data => {
+      readme.push(`
+        - [${data.name}](${data.issueUrl})
+      `)
+    })
+    
+    const template = `
+      <details>
+        <summary>${name}<sup>${cateGoryData.length}</sup></summary>
+        ${readme.join('')}
+      </details>
+    `
+
+    README.push(template)
+  })
+
+  fs.mkdirSync('./dist')
+  fs.writeFileSync('./dist/README.md', README.join('\n').replace(RemoveSpace, ''))
+}
\ No newline at end of file
diff --git a/src/index.ts b/src/index.ts
index 83bc774..238b38f 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,2 +1,3 @@
-console.log('I am form index.ts0000')
-console.log('测试222')
\ No newline at end of file
+import { generateReadme } from './generateReadme'
+
+generateReadme()
\ No newline at end of file
diff --git a/src/refactoringData.ts b/src/refactoringData.ts
new file mode 100644
index 0000000..6c7078d
--- /dev/null
+++ b/src/refactoringData.ts
@@ -0,0 +1,10 @@
+import { simplifyIssue, Issues } from './simplifyIssue'
+
+export function refactoringData(issues: Array<Issues>) {
+  return simplifyIssue(issues).reduce((result, issue) => {
+    const {id, name} = issue.labels
+    issue['displayLabel'] = name
+    result[id] ? result[id].push(issue) : result[id] = [issue]
+    return result
+  }, {})
+}
\ No newline at end of file
diff --git a/src/simplifyIssue.ts b/src/simplifyIssue.ts
index e69de29..2ab455a 100644
--- a/src/simplifyIssue.ts
+++ b/src/simplifyIssue.ts
@@ -0,0 +1,60 @@
+interface IssueContent {
+  content: string
+  htmlUrl: string
+}
+
+interface Labels {
+  id: string
+  name: string
+  [propName: string]: any
+}
+
+export interface Issues {
+  title: string
+  html_url: string
+  labels?: Labels[]
+  body: string
+  [propName: string]: any
+}
+
+const extractLinkReg: RegExp = /via Instapaper\s*(.*)/gim
+const defaultLabel: Labels = {
+  id: '2020-03-08',
+  name: '未分类'
+}
+
+function extractUrl (issueContent: IssueContent) {
+  const match = issueContent.content.match(extractLinkReg)
+  if (match) {
+    return match[1]
+  }
+  return issueContent.htmlUrl
+}
+
+export function simplifyIssue(issues: Array<Issues>) {
+  if (!issues || issues.length <= 0) {
+    console.log('SimplifyIssue got an error. Could not find any data!!')
+    process.exit(1)
+  }
+
+  return issues.map(({ title, html_url, labels, body }) => {
+    const baseIssue = {
+      name: title,
+      issueUrl: html_url,
+      pageUrl: extractUrl({
+        content: body,
+        htmlUrl: html_url
+      })
+    }
+
+    return labels.length > 0
+      ? {
+          ...baseIssue,
+          labels: labels[0]
+        }
+      : {
+          ...baseIssue,
+          labels: defaultLabel
+        }
+  })
+}
diff --git a/tsconfig.json b/tsconfig.json
index 10f5f87..9c2f318 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -3,8 +3,11 @@
     "outDir": "./dist",
     "allowJs": true,
     "target": "es5",
-    "module": "esnext",
-    "watch":true
+    "module": "commonjs",
+    "typeRoots": [
+      "typings",
+      "node_modules/@types"
+    ]
   },
   "include": [
     "./src/**/*"

From 48748fec63bfc653a11ce4b69a0120b91e043889 Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Sun, 8 Mar 2020 17:38:13 +0800
Subject: [PATCH 42/56] feat: refactor using typescript

---
 package-lock.json  | 88 ++++++++++++++++++++++++++++++----------------
 package.json       |  3 +-
 src/fetchIssues.ts | 40 +++++++++++++++++----
 3 files changed, 94 insertions(+), 37 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 1a0c2f4..239c7a0 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -106,6 +106,16 @@
       "integrity": "sha512-0ARSQootUG1RljH2HncpsY2TJBfGQIKOOi7kxzUY6z54ePu/ZD+wJA8zI2Q6v8rol2qpG/rvqsReco8zNMPvhQ==",
       "dev": true
     },
+    "@types/node-fetch": {
+      "version": "2.5.5",
+      "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.5.tgz",
+      "integrity": "sha512-IWwjsyYjGw+em3xTvWVQi5MgYKbRs0du57klfTaZkv/B24AEQ/p/IopNeqIYNy3EsfHOpg8ieQSDomPcsYMHpA==",
+      "dev": true,
+      "requires": {
+        "@types/node": "*",
+        "form-data": "^3.0.0"
+      }
+    },
     "@types/parse-json": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz",
@@ -198,14 +208,11 @@
         "picomatch": "^2.0.4"
       }
     },
-    "axios": {
-      "version": "0.19.2",
-      "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz",
-      "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==",
-      "dev": true,
-      "requires": {
-        "follow-redirects": "1.5.10"
-      }
+    "asynckit": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+      "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
+      "dev": true
     },
     "balanced-match": {
       "version": "1.0.0",
@@ -432,6 +439,15 @@
       "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
       "dev": true
     },
+    "combined-stream": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+      "dev": true,
+      "requires": {
+        "delayed-stream": "~1.0.0"
+      }
+    },
     "commander": {
       "version": "4.1.1",
       "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
@@ -539,6 +555,12 @@
         "object-keys": "^1.0.12"
       }
     },
+    "delayed-stream": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+      "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+      "dev": true
+    },
     "dot-prop": {
       "version": "4.2.0",
       "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz",
@@ -676,30 +698,15 @@
         "semver-regex": "^2.0.0"
       }
     },
-    "follow-redirects": {
-      "version": "1.5.10",
-      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
-      "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
+    "form-data": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz",
+      "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==",
       "dev": true,
       "requires": {
-        "debug": "=3.1.0"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
-          "dev": true,
-          "requires": {
-            "ms": "2.0.0"
-          }
-        },
-        "ms": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-          "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
-          "dev": true
-        }
+        "asynckit": "^0.4.0",
+        "combined-stream": "^1.0.8",
+        "mime-types": "^2.1.12"
       }
     },
     "fsevents": {
@@ -1411,6 +1418,21 @@
         "picomatch": "^2.0.5"
       }
     },
+    "mime-db": {
+      "version": "1.43.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz",
+      "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==",
+      "dev": true
+    },
+    "mime-types": {
+      "version": "2.1.26",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz",
+      "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==",
+      "dev": true,
+      "requires": {
+        "mime-db": "1.43.0"
+      }
+    },
     "mimic-fn": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
@@ -1444,6 +1466,12 @@
       "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
       "dev": true
     },
+    "node-fetch": {
+      "version": "2.6.0",
+      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
+      "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==",
+      "dev": true
+    },
     "nodemon": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.2.tgz",
diff --git a/package.json b/package.json
index 975a15a..3e5d545 100644
--- a/package.json
+++ b/package.json
@@ -37,9 +37,10 @@
   },
   "devDependencies": {
     "@types/node": "^13.9.0",
-    "axios": "^0.19.2",
+    "@types/node-fetch": "^2.5.5",
     "husky": "^4.2.3",
     "lint-staged": "^10.0.8",
+    "node-fetch": "^2.6.0",
     "nodemon": "^2.0.2",
     "npm-run-all": "^4.1.5",
     "prettier": "^1.19.1",
diff --git a/src/fetchIssues.ts b/src/fetchIssues.ts
index 6cdaba5..8ef5ec1 100644
--- a/src/fetchIssues.ts
+++ b/src/fetchIssues.ts
@@ -1,14 +1,42 @@
-// import axios, { AxiosRequestConfig, AxiosPromise } from 'axios'
-import { Issues } from "./simplifyIssue";
+import fetch from 'node-fetch'
+import { Issues } from "./simplifyIssue"
 
-interface Config {
-  owner: string
-  repo: string
+const COS_ENV = process.argv.slice(2)
+const [GITHUB_SNIPPET] = COS_ENV
+
+interface EnvConfig {
+  owner: string,
+  repo: string,
   token: string
 }
 
+const EnvConfig: EnvConfig = {
+  owner: 'BiYuqi',
+  repo: 'snippets',
+  token: GITHUB_SNIPPET
+}
+
+function githubIssueApi({owner, repo, token}): string {
+  return `https://api.github.com/repos/${owner}/${repo}/issues${generateQuery({owner, token})}`
+}
+
+function generateQuery({owner, token}): string {
+  return `?creator=${owner}&per_page=1000&access_token=${token}`
+}
+
+// const REDIRECT_URL = ({owner, repo}) => {
+//   return `https://github.com/${owner}/${repo}/issues`;
+// }
+
 export function fetchIssues(): Promise<Array<Issues>> {
   return new Promise((resolve, reject) => {
-    resolve([])
+    fetch(githubIssueApi(EnvConfig))
+      .then(res => res.json())
+      .then(json => {
+        resolve(json)
+      })
+      .catch(e => {
+        reject(e)
+      })
   })
 }
\ No newline at end of file

From dc25bbd0a6c88242340a865891dd5d6eae5ceb28 Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Sun, 8 Mar 2020 17:54:03 +0800
Subject: [PATCH 43/56] feat: switch the ci branch to issue-typescript

---
 .travis.yml           |  2 +-
 package.json          |  1 +
 src/generateReadme.ts | 14 ++++++++++++--
 3 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 396a42d..b86e3d9 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -25,7 +25,7 @@ after_script:
 
 branches:
   only:
-    - issue-branch
+    - issue-typescript
 env:
  global:
    - GH_REF: github.com/BiYuqi/snippets.git
\ No newline at end of file
diff --git a/package.json b/package.json
index 3e5d545..9822291 100644
--- a/package.json
+++ b/package.json
@@ -8,6 +8,7 @@
     "start": "tsc -w",
     "dev": "npm-run-all --serial --silent start start:*",
     "build": "node ./dist/index.js",
+    "build:ts": "tsc",
     "prettier": "prettier -c --write **/*"
   },
   "repository": {
diff --git a/src/generateReadme.ts b/src/generateReadme.ts
index 5c1305a..e3f4fff 100644
--- a/src/generateReadme.ts
+++ b/src/generateReadme.ts
@@ -1,4 +1,5 @@
 import * as fs from 'fs'
+import * as path from 'path'
 import { refactoringData } from './refactoringData'
 import { fetchIssues } from './fetchIssues'
 import { Issues } from './simplifyIssue'
@@ -39,6 +40,15 @@ export async function generateReadme() {
     README.push(template)
   })
 
-  fs.mkdirSync('./dist')
-  fs.writeFileSync('./dist/README.md', README.join('\n').replace(RemoveSpace, ''))
+  const cwd = process.cwd()
+  const ensureExist = fs.existsSync(path.resolve(cwd, 'dist'))
+
+  if (!ensureExist) {
+    fs.mkdirSync(path.resolve(cwd, 'dist'))
+  }
+  try {
+    fs.writeFileSync(path.resolve(cwd, 'dist/README.md'), README.join('\n').replace(RemoveSpace, ''))
+  } catch (error) {
+    console.log(error)
+  }
 }
\ No newline at end of file

From bbab15e1dc8b6fb9f624b4978250a4f5d3838a17 Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Sun, 8 Mar 2020 17:56:56 +0800
Subject: [PATCH 44/56] fix: ci

---
 .travis.yml | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/.travis.yml b/.travis.yml
index b86e3d9..73c9385 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -12,6 +12,7 @@ install:
   - npm install
 
 script:
+  - npm run build:ts
   - npm run build "${GITHUB_SNIPPET}"
 
 after_script:
@@ -19,7 +20,7 @@ after_script:
   - git init
   - git config user.name "BiYuqi"
   - git config user.email "biyuqiwan@163.com"
-  - git add .
+  - git add README.md
   - git commit -m "Travis CI Auto Generate at `date +"%Y-%m-%d %H:%M"`"
   - git push --force --quiet "https://${GITHUB_SNIPPET}@${GH_REF}" master:master
 

From ea95da1c315c183ef84737b6506a54d04c42085e Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Thu, 12 Mar 2020 08:55:33 +0800
Subject: [PATCH 45/56] chore: change the package.json config

---
 package.json | 14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/package.json b/package.json
index 9822291..8894e31 100644
--- a/package.json
+++ b/package.json
@@ -1,12 +1,12 @@
 {
   "name": "snippets",
   "version": "1.0.0",
-  "description": "",
+  "description": "Automatically categorize Github issues as a README",
   "main": "./dist/index.js",
   "scripts": {
-    "start:dev": "nodemon --debug ./dist/index.js",
-    "start": "tsc -w",
     "dev": "npm-run-all --serial --silent start start:*",
+    "start": "tsc -w",
+    "start:dev": "nodemon --debug ./dist/index.js",
     "build": "node ./dist/index.js",
     "build:ts": "tsc",
     "prettier": "prettier -c --write **/*"
@@ -15,7 +15,7 @@
     "type": "git",
     "url": "git+https://github.com/BiYuqi/snippets.git"
   },
-  "author": "",
+  "author": "biyuqiwan@163.com",
   "license": "MIT",
   "bugs": {
     "url": "https://github.com/BiYuqi/snippets/issues"
@@ -28,11 +28,7 @@
   },
   "lint-staged": {
     "**/*.{js,ts,json,css,md}": [
-      "yarn prettier",
-      "git add"
-    ],
-    "**/*.{js,ts}": [
-      "yarn lint:fix",
+      "npm run prettier",
       "git add"
     ]
   },

From 45befaa51e16b94614d95b56599fdf2c8994fd90 Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Thu, 12 Mar 2020 19:52:45 +0800
Subject: [PATCH 46/56] chore: add source code link

---
 src/generateReadme.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/generateReadme.ts b/src/generateReadme.ts
index e3f4fff..1acaf3f 100644
--- a/src/generateReadme.ts
+++ b/src/generateReadme.ts
@@ -4,7 +4,7 @@ import { refactoringData } from './refactoringData'
 import { fetchIssues } from './fetchIssues'
 import { Issues } from './simplifyIssue'
 
-const DefaultReadme: string = '<h1 align="center">日常技术摘录 👋</h1>'
+const DefaultReadme: string = '<h1 align="center">日常技术摘录 👋<a href="https://github.com/BiYuqi/snippets/tree/issue-typescript" style="font-size: 14px">Source Code</a></h1>'
 const RemoveSpace: RegExp = /^\s{5}/gmi
 
 export async function generateReadme() {

From d189901334dcf544a939238983795e75142eb961 Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Fri, 20 Mar 2020 23:42:53 +0800
Subject: [PATCH 47/56] Change the ts config & auto run prettier in pre commit

---
 .prettierignore | 3 ++-
 package.json    | 4 ++--
 tsconfig.json   | 2 ++
 3 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/.prettierignore b/.prettierignore
index dc10eb0..90ffb98 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -1,4 +1,5 @@
 /test/fixtures
 **/*.gif
 /dist
-/docs
\ No newline at end of file
+/docs
+/node_modules/
\ No newline at end of file
diff --git a/package.json b/package.json
index 8894e31..641b992 100644
--- a/package.json
+++ b/package.json
@@ -27,8 +27,8 @@
     }
   },
   "lint-staged": {
-    "**/*.{js,ts,json,css,md}": [
-      "npm run prettier",
+    "./**/.{js,jsx,ts,tsx,json,md}": [
+      "prettier --write",
       "git add"
     ]
   },
diff --git a/tsconfig.json b/tsconfig.json
index 9c2f318..eef52a7 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -4,6 +4,8 @@
     "allowJs": true,
     "target": "es5",
     "module": "commonjs",
+    "allowSyntheticDefaultImports": true,
+    "moduleResolution": "node",
     "typeRoots": [
       "typings",
       "node_modules/@types"

From dfaf3c18a2323ba1c35a7e05a661cfcf32ec7907 Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Tue, 24 Mar 2020 12:16:33 +0800
Subject: [PATCH 48/56] chore: add web site

---
 .travis.yml           |   5 +
 package-lock.json     | 214 ++++++++++++++++++++++++++++++++++++++++++
 package.json          |   7 +-
 public/index.html     |  60 ++++++++++++
 src/fetchIssues.ts    |   5 +-
 src/generatePage.ts   |  19 ++++
 src/generateReadme.ts |   1 +
 src/snippets.ts       |  61 ++++++++++++
 8 files changed, 369 insertions(+), 3 deletions(-)
 create mode 100644 public/index.html
 create mode 100644 src/generatePage.ts
 create mode 100644 src/snippets.ts

diff --git a/.travis.yml b/.travis.yml
index 73c9385..7f3174d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -14,15 +14,20 @@ install:
 script:
   - npm run build:ts
   - npm run build "${GITHUB_SNIPPET}"
+  - npm run build:snippets
 
 after_script:
   - cd ./dist
+  - echo 'snippets.loadingmore.com' > CNAME
   - git init
   - git config user.name "BiYuqi"
   - git config user.email "biyuqiwan@163.com"
   - git add README.md
   - git commit -m "Travis CI Auto Generate at `date +"%Y-%m-%d %H:%M"`"
   - git push --force --quiet "https://${GITHUB_SNIPPET}@${GH_REF}" master:master
+  - git add index.html CNAME snippets.js
+  - git commit -m "Travis CI Auto Generate at `date +"%Y-%m-%d %H:%M"`"
+  - git push --force --quiet "https://${GITHUB_SNIPPET}@${GH_REF}" master:gh-pages
 
 branches:
   only:
diff --git a/package-lock.json b/package-lock.json
index 239c7a0..5aeddf3 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -208,6 +208,15 @@
         "picomatch": "^2.0.4"
       }
     },
+    "async": {
+      "version": "2.6.3",
+      "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
+      "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
+      "dev": true,
+      "requires": {
+        "lodash": "^4.17.14"
+      }
+    },
     "asynckit": {
       "version": "0.4.0",
       "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@@ -220,6 +229,12 @@
       "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
       "dev": true
     },
+    "basic-auth": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.1.0.tgz",
+      "integrity": "sha1-RSIe5Cn37h5QNb4/UVM/HN/SmIQ=",
+      "dev": true
+    },
     "binary-extensions": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz",
@@ -439,6 +454,12 @@
       "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
       "dev": true
     },
+    "colors": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
+      "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==",
+      "dev": true
+    },
     "combined-stream": {
       "version": "1.0.8",
       "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -480,6 +501,12 @@
         "xdg-basedir": "^3.0.0"
       }
     },
+    "corser": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz",
+      "integrity": "sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c=",
+      "dev": true
+    },
     "cosmiconfig": {
       "version": "6.0.0",
       "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz",
@@ -576,6 +603,18 @@
       "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=",
       "dev": true
     },
+    "ecstatic": {
+      "version": "3.3.2",
+      "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.3.2.tgz",
+      "integrity": "sha512-fLf9l1hnwrHI2xn9mEDT7KIi22UDqA2jaCwyCbSUJh9a1V+LEUSL/JO/6TIz/QyuBURWUHrFL5Kg2TtO1bkkog==",
+      "dev": true,
+      "requires": {
+        "he": "^1.1.1",
+        "mime": "^1.6.0",
+        "minimist": "^1.1.0",
+        "url-join": "^2.0.5"
+      }
+    },
     "elegant-spinner": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz",
@@ -642,6 +681,12 @@
       "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
       "dev": true
     },
+    "eventemitter3": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.0.tgz",
+      "integrity": "sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==",
+      "dev": true
+    },
     "execa": {
       "version": "3.4.0",
       "resolved": "https://registry.npmjs.org/execa/-/execa-3.4.0.tgz",
@@ -698,6 +743,26 @@
         "semver-regex": "^2.0.0"
       }
     },
+    "follow-redirects": {
+      "version": "1.10.0",
+      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.10.0.tgz",
+      "integrity": "sha512-4eyLK6s6lH32nOvLLwlIOnr9zrL8Sm+OvW4pVTJNoXeGzYIkHVf+pADQi+OJ0E67hiuSLezPVPyBcIZO50TmmQ==",
+      "dev": true,
+      "requires": {
+        "debug": "^3.0.0"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "3.2.6",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+          "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+          "dev": true,
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        }
+      }
+    },
     "form-data": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz",
@@ -824,12 +889,47 @@
       "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
       "dev": true
     },
+    "he": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+      "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+      "dev": true
+    },
     "hosted-git-info": {
       "version": "2.8.8",
       "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
       "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==",
       "dev": true
     },
+    "http-proxy": {
+      "version": "1.18.0",
+      "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.0.tgz",
+      "integrity": "sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ==",
+      "dev": true,
+      "requires": {
+        "eventemitter3": "^4.0.0",
+        "follow-redirects": "^1.0.0",
+        "requires-port": "^1.0.0"
+      }
+    },
+    "http-server": {
+      "version": "0.12.1",
+      "resolved": "https://registry.npmjs.org/http-server/-/http-server-0.12.1.tgz",
+      "integrity": "sha512-T0jB+7J7GJ2Vo+a4/T7P7SbQ3x2GPDnqRqQXdfEuPuUOmES/9NBxPnDm7dh1HGEeUWqUmLUNtGV63ZC5Uy3tGA==",
+      "dev": true,
+      "requires": {
+        "basic-auth": "^1.0.3",
+        "colors": "^1.3.3",
+        "corser": "^2.0.1",
+        "ecstatic": "^3.3.2",
+        "http-proxy": "^1.17.0",
+        "opener": "^1.5.1",
+        "optimist": "~0.6.1",
+        "portfinder": "^1.0.20",
+        "secure-compare": "3.0.1",
+        "union": "~0.5.0"
+      }
+    },
     "human-signals": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz",
@@ -1299,6 +1399,12 @@
         "p-locate": "^4.1.0"
       }
     },
+    "lodash": {
+      "version": "4.17.15",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+      "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+      "dev": true
+    },
     "log-symbols": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz",
@@ -1418,6 +1524,12 @@
         "picomatch": "^2.0.5"
       }
     },
+    "mime": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+      "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+      "dev": true
+    },
     "mime-db": {
       "version": "1.43.0",
       "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz",
@@ -1454,6 +1566,23 @@
       "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
       "dev": true
     },
+    "mkdirp": {
+      "version": "0.5.3",
+      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.3.tgz",
+      "integrity": "sha512-P+2gwrFqx8lhew375MQHHeTlY8AuOJSrGf0R5ddkEndUkmwpgUob/vQuBD1V22/Cw1/lJr4x+EjllSezBThzBg==",
+      "dev": true,
+      "requires": {
+        "minimist": "^1.2.5"
+      },
+      "dependencies": {
+        "minimist": {
+          "version": "1.2.5",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+          "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
+          "dev": true
+        }
+      }
+    },
     "ms": {
       "version": "2.1.2",
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -1724,6 +1853,30 @@
       "integrity": "sha512-pVOEP16TrAO2/fjej1IdOyupJY8KDUM1CvsaScRbw6oddvpQoOfGk4ywha0HKKVAD6RkW4x6Q+tNBwhf3Bgpuw==",
       "dev": true
     },
+    "opener": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.1.tgz",
+      "integrity": "sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==",
+      "dev": true
+    },
+    "optimist": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
+      "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=",
+      "dev": true,
+      "requires": {
+        "minimist": "~0.0.1",
+        "wordwrap": "~0.0.2"
+      },
+      "dependencies": {
+        "minimist": {
+          "version": "0.0.10",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
+          "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=",
+          "dev": true
+        }
+      }
+    },
     "p-finally": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz",
@@ -1859,6 +2012,28 @@
         "semver-compare": "^1.0.0"
       }
     },
+    "portfinder": {
+      "version": "1.0.25",
+      "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.25.tgz",
+      "integrity": "sha512-6ElJnHBbxVA1XSLgBp7G1FiCkQdlqGzuF7DswL5tcea+E8UpuvPU7beVAjjRwCioTS9ZluNbu+ZyRvgTsmqEBg==",
+      "dev": true,
+      "requires": {
+        "async": "^2.6.2",
+        "debug": "^3.1.1",
+        "mkdirp": "^0.5.1"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "3.2.6",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+          "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+          "dev": true,
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        }
+      }
+    },
     "prepend-http": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
@@ -1893,6 +2068,12 @@
         "once": "^1.3.1"
       }
     },
+    "qs": {
+      "version": "6.9.2",
+      "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.2.tgz",
+      "integrity": "sha512-2eQ6zajpK7HwqrY1rRtGw5IZvjgtELXzJECaEDuzDFo2jjnIXpJSimzd4qflWZq6bLLi+Zgfj5eDrAzl/lptyg==",
+      "dev": true
+    },
     "rc": {
       "version": "1.2.8",
       "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
@@ -1961,6 +2142,12 @@
         "rc": "^1.0.1"
       }
     },
+    "requires-port": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+      "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
+      "dev": true
+    },
     "resolve": {
       "version": "1.15.1",
       "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz",
@@ -2018,6 +2205,12 @@
       "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==",
       "dev": true
     },
+    "secure-compare": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz",
+      "integrity": "sha1-8aAymzCLIh+uN7mXTz1XjQypmeM=",
+      "dev": true
+    },
     "semver": {
       "version": "5.7.1",
       "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
@@ -2378,6 +2571,15 @@
         }
       }
     },
+    "union": {
+      "version": "0.5.0",
+      "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz",
+      "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==",
+      "dev": true,
+      "requires": {
+        "qs": "^6.4.0"
+      }
+    },
     "unique-string": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz",
@@ -2463,6 +2665,12 @@
         }
       }
     },
+    "url-join": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz",
+      "integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=",
+      "dev": true
+    },
     "url-parse-lax": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz",
@@ -2539,6 +2747,12 @@
         }
       }
     },
+    "wordwrap": {
+      "version": "0.0.3",
+      "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
+      "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=",
+      "dev": true
+    },
     "wrap-ansi": {
       "version": "3.0.1",
       "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz",
diff --git a/package.json b/package.json
index 641b992..1126369 100644
--- a/package.json
+++ b/package.json
@@ -4,11 +4,13 @@
   "description": "Automatically categorize Github issues as a README",
   "main": "./dist/index.js",
   "scripts": {
-    "dev": "npm-run-all --serial --silent start start:*",
+    "dev": "npm run start && npm run build:ts && npm run server",
     "start": "tsc -w",
-    "start:dev": "nodemon --debug ./dist/index.js",
     "build": "node ./dist/index.js",
+    "build:site": "npm run build:ts && npm run build && npm run build:snippets",
     "build:ts": "tsc",
+    "build:snippets": "node ./dist/generatePage.js",
+    "server": "http-server ./dist -p 9967",
     "prettier": "prettier -c --write **/*"
   },
   "repository": {
@@ -35,6 +37,7 @@
   "devDependencies": {
     "@types/node": "^13.9.0",
     "@types/node-fetch": "^2.5.5",
+    "http-server": "^0.12.1",
     "husky": "^4.2.3",
     "lint-staged": "^10.0.8",
     "node-fetch": "^2.6.0",
diff --git a/public/index.html b/public/index.html
new file mode 100644
index 0000000..75e81cd
--- /dev/null
+++ b/public/index.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <title>Code Snippets</title>
+  <style type="text/css" rel="stylesheet">
+    .snippets-wrapper {
+      max-width: 1200px;
+      margin: 0 auto;
+    }
+    .snippets-label {
+    }
+    .snippets-label span {
+      position: relative;
+      display: inline-block;
+      padding: 6px 14px;
+      margin: 4px;
+      font-size: 14px;
+      background: #1aafb1;
+      border-radius: 10px;
+      color: #fff;
+      cursor: pointer;
+    }
+
+    .snippets-label span.active {
+      background: #af1275;
+    }
+
+    .snippets-label i {
+      position: absolute;
+      font-style: normal;
+      padding: 2px;
+      font-size: 12px;
+      top: 2px;
+      right: 2px;
+    }
+
+    .snippets-list {
+      padding: 6px;
+      list-style: none;
+      margin-top: 30px;
+    }
+
+    .snippets-list li {
+      margin-bottom: 6px
+    }
+    .snippets-list a {
+      color: #333f48
+    }
+  </style>
+</head>
+<body>
+  <div class="snippets-wrapper">
+    <div class="snippets-label"></div>
+    <div class="snippets-list"></div>
+  </div>
+  <<<PLACEHOLDER>>>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/fetchIssues.ts b/src/fetchIssues.ts
index 8ef5ec1..8ff787b 100644
--- a/src/fetchIssues.ts
+++ b/src/fetchIssues.ts
@@ -13,7 +13,7 @@ interface EnvConfig {
 const EnvConfig: EnvConfig = {
   owner: 'BiYuqi',
   repo: 'snippets',
-  token: GITHUB_SNIPPET
+  token: GITHUB_SNIPPET || ''
 }
 
 function githubIssueApi({owner, repo, token}): string {
@@ -21,6 +21,9 @@ function githubIssueApi({owner, repo, token}): string {
 }
 
 function generateQuery({owner, token}): string {
+  if (!token) {
+    return '?&per_page=30'
+  }
   return `?creator=${owner}&per_page=1000&access_token=${token}`
 }
 
diff --git a/src/generatePage.ts b/src/generatePage.ts
new file mode 100644
index 0000000..93f0fa8
--- /dev/null
+++ b/src/generatePage.ts
@@ -0,0 +1,19 @@
+import * as path from 'path'
+import * as fs from 'fs'
+
+function replacePlaceholderAndFillHtml(): void {
+  const RegRule: RegExp = /<<<PLACEHOLDER>>>/
+  const template = fs.readFileSync(path.resolve(process.cwd(), 'public/index.html')).toString()
+  const newData = template.replace(RegRule, generateRenderLogic())
+  fs.writeFileSync(path.resolve(process.cwd(), 'dist/index.html'), newData)
+}
+
+function generateRenderLogic() {
+  const Github_Issues = fs.readFileSync(path.resolve(process.cwd(), 'dist/snippets.json'), {encoding: 'utf8'})
+
+  return `
+    <script>window.Github_Issues = ${Github_Issues}</script>
+    <script src="/snippets.js"></script>
+  `
+}
+replacePlaceholderAndFillHtml()
\ No newline at end of file
diff --git a/src/generateReadme.ts b/src/generateReadme.ts
index 1acaf3f..15b78fe 100644
--- a/src/generateReadme.ts
+++ b/src/generateReadme.ts
@@ -48,6 +48,7 @@ export async function generateReadme() {
   }
   try {
     fs.writeFileSync(path.resolve(cwd, 'dist/README.md'), README.join('\n').replace(RemoveSpace, ''))
+    fs.writeFileSync(path.resolve(cwd, 'dist/snippets.json'), JSON.stringify(result))
   } catch (error) {
     console.log(error)
   }
diff --git a/src/snippets.ts b/src/snippets.ts
new file mode 100644
index 0000000..b5ac6de
--- /dev/null
+++ b/src/snippets.ts
@@ -0,0 +1,61 @@
+class Snippets {
+  Github_Issues: object
+  defautlLabel: string
+  defautlId: string
+  labelsWrapper: HTMLDivElement
+  listsWrapper: HTMLDivElement
+  constructor() {
+    this.Github_Issues = window['Github_Issues'] || {}
+    this.defautlLabel = '面试'
+    this.defautlId = '1897007925'
+    this.labelsWrapper = document.querySelector('.snippets-label')
+    this.listsWrapper = document.querySelector('.snippets-list')
+  }
+
+  renderTab() {
+    const labels = []
+    Object.keys(this.Github_Issues).forEach(id => {
+      const issue = this.Github_Issues[id]
+      const displayLabel = issue[0].displayLabel
+      const className = this.defautlLabel === displayLabel ? 'active' : ''
+      labels.push(
+        `<span data-id="${id}" data-display="${displayLabel}" class="${className}">${displayLabel}<i>${issue.length}</i></span>`
+      )
+    })
+    return labels
+  }
+
+  renderList(id) {
+    const issueList = this.Github_Issues[id]
+    const list = []
+    issueList.forEach(({issueUrl, name}) => {
+      list.push(`
+      <li><a href="${issueUrl}">${name}</a></li>
+      `)
+    })
+    return list
+  }
+
+  switchTab() {
+    this.labelsWrapper.addEventListener('click', (e: any) => {
+      if (e.target.nodeName === 'SPAN') {
+        const id = e.target.getAttribute('data-id')
+        const label = e.target.getAttribute('data-display')
+        this.defautlLabel = label
+        this.defautlId = id
+        this.render()
+      }
+    })
+  }
+
+  createTag(tag = 'div'): HTMLElement {
+    return document.createElement(tag)
+  }
+
+  render() {
+    this.labelsWrapper.innerHTML = this.renderTab().join('')
+    this.listsWrapper.innerHTML = this.renderList(this.defautlId).join('')
+    return this
+  }
+}
+new Snippets().render().switchTab()

From dde11572220b2a8959dabd7a901e08e680fc54ca Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Tue, 24 Mar 2020 21:03:35 +0800
Subject: [PATCH 49/56] chore: prettier code style

---
 .prettierignore        |  3 ++-
 package.json           |  4 ++--
 src/fetchIssues.ts     | 14 +++++++-------
 src/generatePage.ts    |  6 ++++--
 src/generateReadme.ts  | 16 ++++++++++------
 src/index.ts           |  2 +-
 src/refactoringData.ts |  6 +++---
 src/simplifyIssue.ts   |  2 +-
 src/snippets.ts        |  2 +-
 9 files changed, 31 insertions(+), 24 deletions(-)

diff --git a/.prettierignore b/.prettierignore
index 90ffb98..97b362a 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -2,4 +2,5 @@
 **/*.gif
 /dist
 /docs
-/node_modules/
\ No newline at end of file
+/node_modules/
+/public/
\ No newline at end of file
diff --git a/package.json b/package.json
index 1126369..1f85a18 100644
--- a/package.json
+++ b/package.json
@@ -29,8 +29,8 @@
     }
   },
   "lint-staged": {
-    "./**/.{js,jsx,ts,tsx,json,md}": [
-      "prettier --write",
+    ".{js,jsx,ts,tsx,json,md}": [
+      "prettier -c --write **/*",
       "git add"
     ]
   },
diff --git a/src/fetchIssues.ts b/src/fetchIssues.ts
index 8ff787b..a463bf9 100644
--- a/src/fetchIssues.ts
+++ b/src/fetchIssues.ts
@@ -1,12 +1,12 @@
 import fetch from 'node-fetch'
-import { Issues } from "./simplifyIssue"
+import { Issues } from './simplifyIssue'
 
 const COS_ENV = process.argv.slice(2)
 const [GITHUB_SNIPPET] = COS_ENV
 
 interface EnvConfig {
-  owner: string,
-  repo: string,
+  owner: string
+  repo: string
   token: string
 }
 
@@ -16,11 +16,11 @@ const EnvConfig: EnvConfig = {
   token: GITHUB_SNIPPET || ''
 }
 
-function githubIssueApi({owner, repo, token}): string {
-  return `https://api.github.com/repos/${owner}/${repo}/issues${generateQuery({owner, token})}`
+function githubIssueApi({ owner, repo, token }): string {
+  return `https://api.github.com/repos/${owner}/${repo}/issues${generateQuery({ owner, token })}`
 }
 
-function generateQuery({owner, token}): string {
+function generateQuery({ owner, token }): string {
   if (!token) {
     return '?&per_page=30'
   }
@@ -42,4 +42,4 @@ export function fetchIssues(): Promise<Array<Issues>> {
         reject(e)
       })
   })
-}
\ No newline at end of file
+}
diff --git a/src/generatePage.ts b/src/generatePage.ts
index 93f0fa8..e2628a4 100644
--- a/src/generatePage.ts
+++ b/src/generatePage.ts
@@ -9,11 +9,13 @@ function replacePlaceholderAndFillHtml(): void {
 }
 
 function generateRenderLogic() {
-  const Github_Issues = fs.readFileSync(path.resolve(process.cwd(), 'dist/snippets.json'), {encoding: 'utf8'})
+  const Github_Issues = fs.readFileSync(path.resolve(process.cwd(), 'dist/snippets.json'), {
+    encoding: 'utf8'
+  })
 
   return `
     <script>window.Github_Issues = ${Github_Issues}</script>
     <script src="/snippets.js"></script>
   `
 }
-replacePlaceholderAndFillHtml()
\ No newline at end of file
+replacePlaceholderAndFillHtml()
diff --git a/src/generateReadme.ts b/src/generateReadme.ts
index 15b78fe..8d29bc3 100644
--- a/src/generateReadme.ts
+++ b/src/generateReadme.ts
@@ -4,13 +4,14 @@ import { refactoringData } from './refactoringData'
 import { fetchIssues } from './fetchIssues'
 import { Issues } from './simplifyIssue'
 
-const DefaultReadme: string = '<h1 align="center">日常技术摘录 👋<a href="https://github.com/BiYuqi/snippets/tree/issue-typescript" style="font-size: 14px">Source Code</a></h1>'
-const RemoveSpace: RegExp = /^\s{5}/gmi
+const DefaultReadme: string =
+  '<h1 align="center">日常技术摘录 👋<a href="https://snippets.loadingmore.com">Online</a></h1>'
+const RemoveSpace: RegExp = /^\s{5}/gim
 
 export async function generateReadme() {
   const README = []
   const issues: Array<Issues> = await fetchIssues()
-  
+
   if (!issues) {
     console.log('Get the issue faild. Please check.')
     process.exit(1)
@@ -29,7 +30,7 @@ export async function generateReadme() {
         - [${data.name}](${data.issueUrl})
       `)
     })
-    
+
     const template = `
       <details>
         <summary>${name}<sup>${cateGoryData.length}</sup></summary>
@@ -47,9 +48,12 @@ export async function generateReadme() {
     fs.mkdirSync(path.resolve(cwd, 'dist'))
   }
   try {
-    fs.writeFileSync(path.resolve(cwd, 'dist/README.md'), README.join('\n').replace(RemoveSpace, ''))
+    fs.writeFileSync(
+      path.resolve(cwd, 'dist/README.md'),
+      README.join('\n').replace(RemoveSpace, '')
+    )
     fs.writeFileSync(path.resolve(cwd, 'dist/snippets.json'), JSON.stringify(result))
   } catch (error) {
     console.log(error)
   }
-}
\ No newline at end of file
+}
diff --git a/src/index.ts b/src/index.ts
index 238b38f..9d4f357 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,3 +1,3 @@
 import { generateReadme } from './generateReadme'
 
-generateReadme()
\ No newline at end of file
+generateReadme()
diff --git a/src/refactoringData.ts b/src/refactoringData.ts
index 6c7078d..111b693 100644
--- a/src/refactoringData.ts
+++ b/src/refactoringData.ts
@@ -2,9 +2,9 @@ import { simplifyIssue, Issues } from './simplifyIssue'
 
 export function refactoringData(issues: Array<Issues>) {
   return simplifyIssue(issues).reduce((result, issue) => {
-    const {id, name} = issue.labels
+    const { id, name } = issue.labels
     issue['displayLabel'] = name
-    result[id] ? result[id].push(issue) : result[id] = [issue]
+    result[id] ? result[id].push(issue) : (result[id] = [issue])
     return result
   }, {})
-}
\ No newline at end of file
+}
diff --git a/src/simplifyIssue.ts b/src/simplifyIssue.ts
index 2ab455a..69bdab4 100644
--- a/src/simplifyIssue.ts
+++ b/src/simplifyIssue.ts
@@ -23,7 +23,7 @@ const defaultLabel: Labels = {
   name: '未分类'
 }
 
-function extractUrl (issueContent: IssueContent) {
+function extractUrl(issueContent: IssueContent) {
   const match = issueContent.content.match(extractLinkReg)
   if (match) {
     return match[1]
diff --git a/src/snippets.ts b/src/snippets.ts
index b5ac6de..d23cf3e 100644
--- a/src/snippets.ts
+++ b/src/snippets.ts
@@ -28,7 +28,7 @@ class Snippets {
   renderList(id) {
     const issueList = this.Github_Issues[id]
     const list = []
-    issueList.forEach(({issueUrl, name}) => {
+    issueList.forEach(({ issueUrl, name }) => {
       list.push(`
       <li><a href="${issueUrl}">${name}</a></li>
       `)

From ad17216d23090a20f3bda88ac5cfda5b7e579eac Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Thu, 26 Mar 2020 12:19:15 +0800
Subject: [PATCH 50/56] chore: update template

---
 public/index.html | 23 ++++++++++++++++++-----
 1 file changed, 18 insertions(+), 5 deletions(-)

diff --git a/public/index.html b/public/index.html
index 75e81cd..f8d53bd 100644
--- a/public/index.html
+++ b/public/index.html
@@ -9,18 +9,26 @@
       max-width: 1200px;
       margin: 0 auto;
     }
+
     .snippets-label {
+      margin 30px auto;
     }
+
     .snippets-label span {
       position: relative;
       display: inline-block;
-      padding: 6px 14px;
+      padding: 6px 18px;
       margin: 4px;
       font-size: 14px;
-      background: #1aafb1;
+      background: #5eba7d;
       border-radius: 10px;
       color: #fff;
       cursor: pointer;
+      transtion: background .3s;
+    }
+
+    .snippets-label span:hover {
+      background: #af1275;
     }
 
     .snippets-label span.active {
@@ -38,15 +46,20 @@
 
     .snippets-list {
       padding: 6px;
-      list-style: none;
+      list-style: decimal-leading-zero;
       margin-top: 30px;
     }
 
     .snippets-list li {
-      margin-bottom: 6px
+      margin-bottom: 10px;
+    }
+
+    .snippets-list li:hover a {
+      color: #18afb1;
     }
+
     .snippets-list a {
-      color: #333f48
+      color: #333f48;
     }
   </style>
 </head>

From 663d1e09aafeb34f11a1c9ac92e3e6d3a1789d94 Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Thu, 26 Mar 2020 17:27:12 +0800
Subject: [PATCH 51/56] chore: update meta info

---
 public/index.html     | 10 ++++++----
 src/generateReadme.ts |  2 +-
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/public/index.html b/public/index.html
index f8d53bd..e84a006 100644
--- a/public/index.html
+++ b/public/index.html
@@ -3,7 +3,9 @@
 <head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
-  <title>Code Snippets</title>
+  <meta data-vue-meta="true" data-vmid="keywords" name="keywords" content="JavaScript, 前端">
+  <meta data-vue-meta="true" data-vmid="description" name="description" content="前端开发, 前端面试, 前端技术, NodeJs, React, Vuejs, Flutter, Typescript">
+  <title>日常技术归档</title>
   <style type="text/css" rel="stylesheet">
     .snippets-wrapper {
       max-width: 1200px;
@@ -20,7 +22,7 @@
       padding: 6px 18px;
       margin: 4px;
       font-size: 14px;
-      background: #5eba7d;
+      background: #18afb1;
       border-radius: 10px;
       color: #fff;
       cursor: pointer;
@@ -28,11 +30,11 @@
     }
 
     .snippets-label span:hover {
-      background: #af1275;
+      background: #333f48;
     }
 
     .snippets-label span.active {
-      background: #af1275;
+      background: #333f48;
     }
 
     .snippets-label i {
diff --git a/src/generateReadme.ts b/src/generateReadme.ts
index 8d29bc3..97175d6 100644
--- a/src/generateReadme.ts
+++ b/src/generateReadme.ts
@@ -5,7 +5,7 @@ import { fetchIssues } from './fetchIssues'
 import { Issues } from './simplifyIssue'
 
 const DefaultReadme: string =
-  '<h1 align="center">日常技术摘录 👋<a href="https://snippets.loadingmore.com">Online</a></h1>'
+  '<h1 align="center">日常技术文档归档 👋<a href="https://snippets.loadingmore.com">Online</a></h1>'
 const RemoveSpace: RegExp = /^\s{5}/gim
 
 export async function generateReadme() {

From bfc041a33552f47b4c2a18d7e7e03b3e1932fe9f Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Thu, 26 Mar 2020 20:26:28 +0800
Subject: [PATCH 52/56] chore: set the max amount article display

---
 public/index.html |  4 ++--
 src/snippets.ts   | 10 +++++-----
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/public/index.html b/public/index.html
index e84a006..1bcb58e 100644
--- a/public/index.html
+++ b/public/index.html
@@ -13,7 +13,7 @@
     }
 
     .snippets-label {
-      margin 30px auto;
+      margin: 30px auto;
     }
 
     .snippets-label span {
@@ -26,7 +26,7 @@
       border-radius: 10px;
       color: #fff;
       cursor: pointer;
-      transtion: background .3s;
+      transition: background .3s;
     }
 
     .snippets-label span:hover {
diff --git a/src/snippets.ts b/src/snippets.ts
index d23cf3e..46295a0 100644
--- a/src/snippets.ts
+++ b/src/snippets.ts
@@ -17,9 +17,11 @@ class Snippets {
     Object.keys(this.Github_Issues).forEach(id => {
       const issue = this.Github_Issues[id]
       const displayLabel = issue[0].displayLabel
-      const className = this.defautlLabel === displayLabel ? 'active' : ''
+      const activeClassName = this.defautlLabel === displayLabel ? 'class="active"' : ''
+      const articleAmount = issue.length > 99 ? '99+' : issue.length
+
       labels.push(
-        `<span data-id="${id}" data-display="${displayLabel}" class="${className}">${displayLabel}<i>${issue.length}</i></span>`
+        `<span data-id="${id}" data-display="${displayLabel}" ${activeClassName}>${displayLabel}<i>${articleAmount}</i></span>`
       )
     })
     return labels
@@ -29,9 +31,7 @@ class Snippets {
     const issueList = this.Github_Issues[id]
     const list = []
     issueList.forEach(({ issueUrl, name }) => {
-      list.push(`
-      <li><a href="${issueUrl}">${name}</a></li>
-      `)
+      list.push(`<li><a href="${issueUrl}">${name}</a></li>`)
     })
     return list
   }

From 49a0917a8b32169cd762c2aaf08f029a5bc6b38d Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Fri, 27 Mar 2020 23:06:08 +0800
Subject: [PATCH 53/56] chore: update index.html

---
 public/index.html | 41 ++++++++++++++++++++++++++++++++++++++---
 1 file changed, 38 insertions(+), 3 deletions(-)

diff --git a/public/index.html b/public/index.html
index 1bcb58e..665d47f 100644
--- a/public/index.html
+++ b/public/index.html
@@ -7,6 +7,27 @@
   <meta data-vue-meta="true" data-vmid="description" name="description" content="前端开发, 前端面试, 前端技术, NodeJs, React, Vuejs, Flutter, Typescript">
   <title>日常技术归档</title>
   <style type="text/css" rel="stylesheet">
+     * {
+      margin: 0;
+      padding: 0;
+      box-sizing: border-box;
+    }
+
+    body, html {
+      width: 100%;
+      height: 100%;
+    }
+
+    body {
+      width: 100%;
+      height: 100%;
+      background-image: url('https://mdppt-1254319003.cos.ap-chengdu.myqcloud.com/sea1.jpg'); 
+      -webkit-background-size: cover;
+      -moz-background-size: cover;
+      -o-background-size: cover;
+      background-size: cover;
+    }
+
     .snippets-wrapper {
       max-width: 1200px;
       margin: 0 auto;
@@ -48,20 +69,34 @@
 
     .snippets-list {
       padding: 6px;
-      list-style: decimal-leading-zero;
+      list-style: none;
       margin-top: 30px;
+      margin-left: 15px;
     }
 
     .snippets-list li {
       margin-bottom: 10px;
+      position: relative;
+    }
+
+    .snippets-list li::before {
+      position: absolute;
+      top: 50%;
+      margin-top: -4px;
+      left: -18px;
+      width: 8px;
+      height: 8px;
+      border-radius: 50%;
+      content: '';
+      background: #1ed3d6;
     }
 
     .snippets-list li:hover a {
-      color: #18afb1;
+      color: #71cfff;
     }
 
     .snippets-list a {
-      color: #333f48;
+      color: #f1f9ff;
     }
   </style>
 </head>

From 814d4d81fbaa60b96c9ad9af4baf48c9fa2187f7 Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Mon, 6 Apr 2020 16:51:12 +0800
Subject: [PATCH 54/56] chore: remove background image

---
 public/index.html | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/public/index.html b/public/index.html
index 665d47f..bf99298 100644
--- a/public/index.html
+++ b/public/index.html
@@ -21,7 +21,6 @@
     body {
       width: 100%;
       height: 100%;
-      background-image: url('https://mdppt-1254319003.cos.ap-chengdu.myqcloud.com/sea1.jpg'); 
       -webkit-background-size: cover;
       -moz-background-size: cover;
       -o-background-size: cover;
@@ -88,15 +87,16 @@
       height: 8px;
       border-radius: 50%;
       content: '';
-      background: #1ed3d6;
+      background: #18afb1;
     }
 
     .snippets-list li:hover a {
-      color: #71cfff;
+      color: #18afb1;
     }
 
     .snippets-list a {
-      color: #f1f9ff;
+      color: #666;
+      text-decoration: none;
     }
   </style>
 </head>

From 13b2743608d437b825c879329bb0f6230493ea04 Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Thu, 16 Jul 2020 10:40:49 +0800
Subject: [PATCH 55/56] remove CNAME

---
 .travis.yml | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 7f3174d..cee8f62 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -18,14 +18,13 @@ script:
 
 after_script:
   - cd ./dist
-  - echo 'snippets.loadingmore.com' > CNAME
   - git init
   - git config user.name "BiYuqi"
   - git config user.email "biyuqiwan@163.com"
   - git add README.md
   - git commit -m "Travis CI Auto Generate at `date +"%Y-%m-%d %H:%M"`"
   - git push --force --quiet "https://${GITHUB_SNIPPET}@${GH_REF}" master:master
-  - git add index.html CNAME snippets.js
+  - git add index.html snippets.js
   - git commit -m "Travis CI Auto Generate at `date +"%Y-%m-%d %H:%M"`"
   - git push --force --quiet "https://${GITHUB_SNIPPET}@${GH_REF}" master:gh-pages
 

From 6ef5a5af46e430e8ed9841f0ae5a6304c6ba1d33 Mon Sep 17 00:00:00 2001
From: BiYuqi <biyuqiwan@163.com>
Date: Tue, 11 Aug 2020 09:06:20 +0800
Subject: [PATCH 56/56] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=B5=84=E6=BA=90?=
 =?UTF-8?q?=E8=B7=AF=E5=BE=84=E9=94=99=E8=AF=AF?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/generatePage.ts   | 2 +-
 src/generateReadme.ts | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/generatePage.ts b/src/generatePage.ts
index e2628a4..168c914 100644
--- a/src/generatePage.ts
+++ b/src/generatePage.ts
@@ -15,7 +15,7 @@ function generateRenderLogic() {
 
   return `
     <script>window.Github_Issues = ${Github_Issues}</script>
-    <script src="/snippets.js"></script>
+    <script src="/snippets/snippets.js"></script>
   `
 }
 replacePlaceholderAndFillHtml()
diff --git a/src/generateReadme.ts b/src/generateReadme.ts
index 97175d6..cbef042 100644
--- a/src/generateReadme.ts
+++ b/src/generateReadme.ts
@@ -5,7 +5,7 @@ import { fetchIssues } from './fetchIssues'
 import { Issues } from './simplifyIssue'
 
 const DefaultReadme: string =
-  '<h1 align="center">日常技术文档归档 👋<a href="https://snippets.loadingmore.com">Online</a></h1>'
+  '<h1 align="center">日常技术文档归档 👋<a href="https://biyuqi.github.io/snippets/">Online</a></h1>'
 const RemoveSpace: RegExp = /^\s{5}/gim
 
 export async function generateReadme() {
