Explorar el Código

Merge branch 'master' into feat/tag-form-with-typeahead

# Conflicts:
#	yarn.lock
yusuketk hace 7 años
padre
commit
fb32582dbf

+ 7 - 3
.eslintrc.js

@@ -1,8 +1,13 @@
 module.exports = {
 module.exports = {
   parser: 'babel-eslint',
   parser: 'babel-eslint',
+  parserOptions: {
+    ecmaFeatures: {
+      jsx: true
+    }
+  },
   extends: [
   extends: [
-    'airbnb',
-    'plugin:react/recommended',
+    'airbnb-base',
+    'airbnb/rules/react',
   ],
   ],
   env: {
   env: {
     browser: true,
     browser: true,
@@ -113,7 +118,6 @@ module.exports = {
     'react/require-default-props': 'off',
     'react/require-default-props': 'off',
     'react/self-closing-comp': 'off',
     'react/self-closing-comp': 'off',
     'react/sort-comp': 'off',
     'react/sort-comp': 'off',
-    'jsx-a11y/img-redundant-alt': 'off',
     // eslint-plugin-import rules
     // eslint-plugin-import rules
     'import/no-extraneous-dependencies': 'off',
     'import/no-extraneous-dependencies': 'off',
     'import/no-dynamic-require': 'off',
     'import/no-dynamic-require': 'off',

+ 5 - 3
CHANGES.md

@@ -1,9 +1,11 @@
-CHANGES
-========
+# CHANGES
 
 
 ## 3.4.3-RC
 ## 3.4.3-RC
 
 
-* 
+* Support Apply eslint-config-airbnb based rules
+* Support Apply prettier and stylelint
+* Support: Upgrade libs
+    * eslint
 
 
 ## 3.4.2
 ## 3.4.2
 
 

+ 8 - 0
README.md

@@ -168,7 +168,9 @@ Environment Variables
       * `mongodb` : MongoDB GridFS (Setting-less)
       * `mongodb` : MongoDB GridFS (Setting-less)
       * `local` : Server's Local file system (Setting-less)
       * `local` : Server's Local file system (Setting-less)
       * `none` : Disable file uploading
       * `none` : Disable file uploading
+    * MAX_FILE_SIZE: The maximum file size limit for uploads (bytes). default: `Infinity`
     * MONGO_GRIDFS_TOTAL_LIMIT: Total capacity limit of MongoDB GridFS (bytes). default: `Infinity`
     * MONGO_GRIDFS_TOTAL_LIMIT: Total capacity limit of MongoDB GridFS (bytes). default: `Infinity`
+    * SAML_USES_ONLY_ENV_VARS_FOR_SOME_OPTIONS: If `true`, the system uses only the value of the environment variable as the value of the SAML option that can be set via the environment variable.
 * **Option to integrate with external systems**
 * **Option to integrate with external systems**
     * HACKMD_URI: URI to connect to [HackMD(CodiMD)](https://hackmd.io/) server.
     * HACKMD_URI: URI to connect to [HackMD(CodiMD)](https://hackmd.io/) server.
         * **This server must load the GROWI agent. [Here's how to prepare it](https://docs.growi.org/guide/admin-cookbook/integrate-with-hackmd.html).**
         * **This server must load the GROWI agent. [Here's how to prepare it](https://docs.growi.org/guide/admin-cookbook/integrate-with-hackmd.html).**
@@ -183,8 +185,14 @@ Environment Variables
     * OAUTH_GITHUB_CLIENT_SECRET: GitHub API client secret for OAuth login.
     * OAUTH_GITHUB_CLIENT_SECRET: GitHub API client secret for OAuth login.
     * OAUTH_TWITTER_CONSUMER_KEY: Twitter consumer key(API key) for OAuth login.
     * OAUTH_TWITTER_CONSUMER_KEY: Twitter consumer key(API key) for OAuth login.
     * OAUTH_TWITTER_CONSUMER_SECRET: Twitter consumer secret(API secret) for OAuth login.
     * OAUTH_TWITTER_CONSUMER_SECRET: Twitter consumer secret(API secret) for OAuth login.
+    * SAML_ENABLED: Enable or disable SAML
     * SAML_ENTRY_POINT: IdP entry point
     * SAML_ENTRY_POINT: IdP entry point
     * SAML_ISSUER: Issuer string to supply to IdP
     * SAML_ISSUER: Issuer string to supply to IdP
+    * SAML_ATTR_MAPPING_ID: Attribute map for id
+    * SAML_ATTR_MAPPING_USERNAME: Attribute map for username
+    * SAML_ATTR_MAPPING_MAIL: Attribute map for email
+    * SAML_ATTR_MAPPING_FIRST_NAME: Attribute map for first name
+    * SAML_ATTR_MAPPING_LAST_NAME:  Attribute map for last name
     * SAML_CERT: PEM-encoded X.509 signing certificate string to validate the response from IdP
     * SAML_CERT: PEM-encoded X.509 signing certificate string to validate the response from IdP
 
 
 
 

+ 3 - 9
package.json

@@ -32,8 +32,8 @@
     "clean:report": "rimraf -- report",
     "clean:report": "rimraf -- report",
     "clean": "npm-run-all -p clean:*",
     "clean": "npm-run-all -p clean:*",
     "heroku-postbuild": "sh bin/heroku/install-plugins.sh && npm run build:prod",
     "heroku-postbuild": "sh bin/heroku/install-plugins.sh && npm run build:prod",
-    "lint:js:fix": "eslint . --fix",
-    "lint:js": "eslint .",
+    "lint:js:fix": "eslint **/*.{js,jsx} --fix",
+    "lint:js": "eslint **/*.{js,jsx}",
     "lint:styles:fix": "prettier-stylelint --quiet --write src/client/styles/scss/**/*.scss",
     "lint:styles:fix": "prettier-stylelint --quiet --write src/client/styles/scss/**/*.scss",
     "lint:styles": "stylelint src/client/styles/scss/**/*.scss",
     "lint:styles": "stylelint src/client/styles/scss/**/*.scss",
     "lint": "npm-run-all -p lint:js lint:styles",
     "lint": "npm-run-all -p lint:js lint:styles",
@@ -154,11 +154,10 @@
     "date-fns": "^1.29.0",
     "date-fns": "^1.29.0",
     "diff2html": "^2.3.3",
     "diff2html": "^2.3.3",
     "eazy-logger": "^3.0.2",
     "eazy-logger": "^3.0.2",
-    "eslint": "^5.0.0",
+    "eslint": "^5.15.1",
     "eslint-config-airbnb": "^17.1.0",
     "eslint-config-airbnb": "^17.1.0",
     "eslint-plugin-chai-friendly": "^0.4.1",
     "eslint-plugin-chai-friendly": "^0.4.1",
     "eslint-plugin-import": "^2.16.0",
     "eslint-plugin-import": "^2.16.0",
-    "eslint-plugin-jsx-a11y": "^6.2.1",
     "eslint-plugin-react": "^7.12.4",
     "eslint-plugin-react": "^7.12.4",
     "file-loader": "^3.0.1",
     "file-loader": "^3.0.1",
     "handsontable": "^6.0.1",
     "handsontable": "^6.0.1",
@@ -233,10 +232,5 @@
     "node": ">=8.11.1 <11",
     "node": ">=8.11.1 <11",
     "npm": ">=5.6.0 <7",
     "npm": ">=5.6.0 <7",
     "yarn": ">=1.5.1 <2"
     "yarn": ">=1.5.1 <2"
-  },
-  "config": {
-    "blanket": {
-      "pattern": "./src/lib/**/*.js"
-    }
   }
   }
 }
 }

+ 1 - 0
src/client/js/components/BookmarkButton.jsx

@@ -74,6 +74,7 @@ export default class BookmarkButton extends React.Component {
 
 
     return (
     return (
       <button
       <button
+        type="button"
         href="#"
         href="#"
         title="Bookmark"
         title="Bookmark"
         onClick={this.handleClick}
         onClick={this.handleClick}

+ 0 - 1
src/client/js/components/Common/UserPictureList.jsx

@@ -20,7 +20,6 @@ export default class UserPictureList extends React.Component {
 
 
     this.state = {
     this.state = {
       users,
       users,
-      tooltipUsername: '',
     };
     };
 
 
   }
   }

+ 3 - 3
src/client/js/components/HeaderSearchBox.jsx

@@ -46,17 +46,17 @@ class HeaderSearchBox extends React.Component {
   }
   }
 
 
   search() {
   search() {
-    const url = new URL(location.href);
+    const url = new URL(window.location.href);
     url.pathname = '/_search';
     url.pathname = '/_search';
 
 
     // construct search query
     // construct search query
     let q = this.state.text;
     let q = this.state.text;
     if (this.state.isScopeChildren) {
     if (this.state.isScopeChildren) {
-      q += ` prefix:${location.pathname}`;
+      q += ` prefix:${window.location.pathname}`;
     }
     }
     url.searchParams.append('q', q);
     url.searchParams.append('q', q);
 
 
-    location.href = url.href;
+    window.location.href = url.href;
   }
   }
 
 
   render() {
   render() {

+ 4 - 1
src/client/js/components/InstallerForm.jsx

@@ -36,7 +36,10 @@ class InstallerForm extends React.Component {
 
 
   render() {
   render() {
     const hasErrorClass = this.state.isValidUserName ? '' : ' has-error';
     const hasErrorClass = this.state.isValidUserName ? '' : ' has-error';
-    const unavailableUserId = this.state.isValidUserName ? '' : <span><i className="icon-fw icon-ban" />{ this.props.t('installer.unavaliable_user_id') }</span>;
+    const unavailableUserId = this.state.isValidUserName
+      ? ''
+      : <span><i className="icon-fw icon-ban" />{ this.props.t('installer.unavaliable_user_id') }</span>;
+
     return (
     return (
       <div className={`login-dialog p-t-10 p-b-10 col-sm-offset-4 col-sm-4${hasErrorClass}`}>
       <div className={`login-dialog p-t-10 p-b-10 col-sm-offset-4 col-sm-4${hasErrorClass}`}>
         <p className="alert alert-success">
         <p className="alert alert-success">

+ 1 - 0
src/client/js/components/LikeButton.jsx

@@ -51,6 +51,7 @@ export default class LikeButton extends React.Component {
 
 
     return (
     return (
       <button
       <button
+        type="button"
         href="#"
         href="#"
         title="Like"
         title="Like"
         onClick={this.handleClick}
         onClick={this.handleClick}

+ 8 - 3
src/client/js/components/Page.jsx

@@ -31,11 +31,16 @@ export default class Page extends React.Component {
   launchHandsontableModal(beginLineNumber, endLineNumber) {
   launchHandsontableModal(beginLineNumber, endLineNumber) {
     const tableLines = this.state.markdown.split(/\r\n|\r|\n/).slice(beginLineNumber - 1, endLineNumber).join('\n');
     const tableLines = this.state.markdown.split(/\r\n|\r|\n/).slice(beginLineNumber - 1, endLineNumber).join('\n');
     this.setState({ currentTargetTableArea: { beginLineNumber, endLineNumber } });
     this.setState({ currentTargetTableArea: { beginLineNumber, endLineNumber } });
-    this.refs.handsontableModal.show(MarkdownTable.fromMarkdownString(tableLines));
+    this.handsontableModal.show(MarkdownTable.fromMarkdownString(tableLines));
   }
   }
 
 
   saveHandlerForHandsontableModal(markdownTable) {
   saveHandlerForHandsontableModal(markdownTable) {
-    const newMarkdown = mtu.replaceMarkdownTableInMarkdown(markdownTable, this.state.markdown, this.state.currentTargetTableArea.beginLineNumber, this.state.currentTargetTableArea.endLineNumber);
+    const newMarkdown = mtu.replaceMarkdownTableInMarkdown(
+      markdownTable,
+      this.state.markdown,
+      this.state.currentTargetTableArea.beginLineNumber,
+      this.state.currentTargetTableArea.endLineNumber,
+    );
     this.props.onSaveWithShortcut(newMarkdown);
     this.props.onSaveWithShortcut(newMarkdown);
     this.setState({ currentTargetTableArea: null });
     this.setState({ currentTargetTableArea: null });
   }
   }
@@ -51,7 +56,7 @@ export default class Page extends React.Component {
           markdown={this.state.markdown}
           markdown={this.state.markdown}
           pagePath={this.props.pagePath}
           pagePath={this.props.pagePath}
         />
         />
-        <HandsontableModal ref="handsontableModal" onSave={this.saveHandlerForHandsontableModal} />
+        <HandsontableModal ref={(c) => { this.handsontableModal = c }} onSave={this.saveHandlerForHandsontableModal} />
       </div>
       </div>
     );
     );
   }
   }

+ 1 - 1
src/client/js/components/Page/RevisionRenderer.jsx

@@ -77,7 +77,7 @@ export default class RevisionRenderer extends React.Component {
       .then(() => { return interceptorManager.process('postPostProcess', context) })
       .then(() => { return interceptorManager.process('postPostProcess', context) })
       .then(() => { return interceptorManager.process('preRenderHtml', context) })
       .then(() => { return interceptorManager.process('preRenderHtml', context) })
       .then(() => {
       .then(() => {
-        this.setState({ html: context.parsedHTML, markdown });
+        this.setState({ html: context.parsedHTML });
       })
       })
       // process interceptors for post rendering
       // process interceptors for post rendering
       .then(() => { return interceptorManager.process('postRenderHtml', context) });
       .then(() => { return interceptorManager.process('postRenderHtml', context) });

+ 14 - 10
src/client/js/components/PageComment/CommentForm.jsx

@@ -82,7 +82,7 @@ export default class CommentForm extends React.Component {
     const value = event.target.checked;
     const value = event.target.checked;
     this.setState({ isMarkdown: value });
     this.setState({ isMarkdown: value });
     // changeMode
     // changeMode
-    this.refs.editor.setGfmMode(value);
+    this.editor.setGfmMode(value);
   }
   }
 
 
   handleSelect(key) {
   handleSelect(key) {
@@ -132,7 +132,7 @@ export default class CommentForm extends React.Component {
           isSlackEnabled: false,
           isSlackEnabled: false,
         });
         });
         // reset value
         // reset value
-        this.refs.editor.setValue('');
+        this.editor.setValue('');
       })
       })
       .catch((err) => {
       .catch((err) => {
         const errorMessage = err.message || 'An unknown error occured when posting comment';
         const errorMessage = err.message || 'An unknown error occured when posting comment';
@@ -143,7 +143,7 @@ export default class CommentForm extends React.Component {
   getCommentHtml() {
   getCommentHtml() {
     return (
     return (
       <CommentPreview
       <CommentPreview
-        inputRef={(el) => { return this.previewElement = el }}
+        inputRef={(el) => { this.previewElement = el }}
         html={this.state.html}
         html={this.state.html}
       />
       />
     );
     );
@@ -205,12 +205,12 @@ export default class CommentForm extends React.Component {
           // modify to "![fileName](url)" syntax
           // modify to "![fileName](url)" syntax
           insertText = `!${insertText}`;
           insertText = `!${insertText}`;
         }
         }
-        this.refs.editor.insertText(insertText);
+        this.editor.insertText(insertText);
       })
       })
       .catch(this.apiErrorHandler)
       .catch(this.apiErrorHandler)
       // finally
       // finally
       .then(() => {
       .then(() => {
-        this.refs.editor.terminateUploadingState();
+        this.editor.terminateUploadingState();
       });
       });
   }
   }
 
 
@@ -271,7 +271,11 @@ export default class CommentForm extends React.Component {
                 {/* Add Comment Button */}
                 {/* Add Comment Button */}
                 { !this.state.isFormShown
                 { !this.state.isFormShown
                   && (
                   && (
-                  <button className={`btn btn-lg ${isLayoutTypeGrowi ? 'btn-link' : 'btn-primary'} center-block`} onClick={this.showCommentFormBtnClickHandler}>
+                  <button
+                    type="button"
+                    className={`btn btn-lg ${isLayoutTypeGrowi ? 'btn-link' : 'btn-primary'} center-block`}
+                    onClick={this.showCommentFormBtnClickHandler}
+                  >
                     <i className="icon-bubble"></i> Add Comment
                     <i className="icon-bubble"></i> Add Comment
                   </button>
                   </button>
                   )
                   )
@@ -284,7 +288,7 @@ export default class CommentForm extends React.Component {
                       <Tabs activeKey={this.state.key} id="comment-form-tabs" onSelect={this.handleSelect} animation={false}>
                       <Tabs activeKey={this.state.key} id="comment-form-tabs" onSelect={this.handleSelect} animation={false}>
                         <Tab eventKey={1} title="Write">
                         <Tab eventKey={1} title="Write">
                           <Editor
                           <Editor
-                            ref="editor"
+                            ref={(c) => { this.editor = c }}
                             value={this.state.comment}
                             value={this.state.comment}
                             isGfmMode={this.state.isMarkdown}
                             isGfmMode={this.state.isMarkdown}
                             editorOptions={this.props.editorOptions}
                             editorOptions={this.props.editorOptions}
@@ -298,7 +302,7 @@ export default class CommentForm extends React.Component {
                             onCtrlEnter={this.postComment}
                             onCtrlEnter={this.postComment}
                           />
                           />
                         </Tab>
                         </Tab>
-                        { this.state.isMarkdown == true
+                        { this.state.isMarkdown
                           && (
                           && (
                           <Tab eventKey={2} title="Preview">
                           <Tab eventKey={2} title="Preview">
                             <div className="comment-form-preview">
                             <div className="comment-form-preview">
@@ -312,7 +316,7 @@ export default class CommentForm extends React.Component {
                     <div className="comment-submit">
                     <div className="comment-submit">
                       <div className="d-flex">
                       <div className="d-flex">
                         <label style={{ flex: 1 }}>
                         <label style={{ flex: 1 }}>
-                          { isLayoutTypeGrowi && this.state.key == 1
+                          { isLayoutTypeGrowi && this.state.key === 1
                             && (
                             && (
                             <span>
                             <span>
                               <input
                               <input
@@ -323,7 +327,7 @@ export default class CommentForm extends React.Component {
                                 value="1"
                                 value="1"
                                 onChange={this.updateStateCheckbox}
                                 onChange={this.updateStateCheckbox}
                               />
                               />
-                              Markdown
+                              <span className="ml-2">Markdown</span>
                             </span>
                             </span>
                             )
                             )
                         }
                         }

+ 9 - 8
src/client/js/components/PageEditor/Editor.jsx

@@ -39,8 +39,8 @@ export default class Editor extends AbstractEditor {
 
 
   getEditorSubstance() {
   getEditorSubstance() {
     return this.props.isMobile
     return this.props.isMobile
-      ? this.refs.taEditor
-      : this.refs.cmEditor;
+      ? this.taEditor
+      : this.cmEditor;
   }
   }
 
 
   /**
   /**
@@ -161,7 +161,7 @@ export default class Editor extends AbstractEditor {
 
 
   dropHandler(accepted, rejected) {
   dropHandler(accepted, rejected) {
     // rejected
     // rejected
-    if (accepted.length != 1) { // length should be 0 or 1 because `multiple={false}` is set
+    if (accepted.length !== 1) { // length should be 0 or 1 because `multiple={false}` is set
       this.setState({ dropzoneActive: false });
       this.setState({ dropzoneActive: false });
       return;
       return;
     }
     }
@@ -213,7 +213,8 @@ export default class Editor extends AbstractEditor {
       <div className="m-0 navbar navbar-default navbar-editor" style={{ minHeight: 'unset' }}>
       <div className="m-0 navbar navbar-default navbar-editor" style={{ minHeight: 'unset' }}>
         <ul className="pl-2 nav nav-navbar">
         <ul className="pl-2 nav nav-navbar">
           { this.getNavbarItems() != null && this.getNavbarItems().map((item, idx) => {
           { this.getNavbarItems() != null && this.getNavbarItems().map((item, idx) => {
-            return <li key={idx}>{item}</li>;
+            // eslint-disable-next-line react/no-array-index-key
+            return <li key={`navbarItem-${idx}`}>{item}</li>;
           }) }
           }) }
         </ul>
         </ul>
       </div>
       </div>
@@ -240,7 +241,7 @@ export default class Editor extends AbstractEditor {
     return (
     return (
       <div style={flexContainer} className="editor-container">
       <div style={flexContainer} className="editor-container">
         <Dropzone
         <Dropzone
-          ref="dropzone"
+          ref={(c) => { this.dropzone = c }}
           disableClick
           disableClick
           accept={this.getAcceptableType()}
           accept={this.getAcceptableType()}
           className={this.getDropzoneClassName()}
           className={this.getDropzoneClassName()}
@@ -258,7 +259,7 @@ export default class Editor extends AbstractEditor {
           {/* for PC */}
           {/* for PC */}
           { !isMobile && (
           { !isMobile && (
             <CodeMirrorEditor
             <CodeMirrorEditor
-              ref="cmEditor"
+              ref={(c) => { this.cmEditor = c }}
               onPasteFiles={this.pasteFilesHandler}
               onPasteFiles={this.pasteFilesHandler}
               onDragEnter={this.dragEnterHandler}
               onDragEnter={this.dragEnterHandler}
               {...this.props}
               {...this.props}
@@ -269,7 +270,7 @@ export default class Editor extends AbstractEditor {
           {/* for mobile */}
           {/* for mobile */}
           { isMobile && (
           { isMobile && (
             <TextAreaEditor
             <TextAreaEditor
-              ref="taEditor"
+              ref={(c) => { this.taEditor = c }}
               onPasteFiles={this.pasteFilesHandler}
               onPasteFiles={this.pasteFilesHandler}
               onDragEnter={this.dragEnterHandler}
               onDragEnter={this.dragEnterHandler}
               {...this.props}
               {...this.props}
@@ -284,7 +285,7 @@ export default class Editor extends AbstractEditor {
           <button
           <button
             type="button"
             type="button"
             className="btn btn-default btn-block btn-open-dropzone"
             className="btn btn-default btn-block btn-open-dropzone"
-            onClick={() => { this.refs.dropzone.open() }}
+            onClick={() => { this.dropzone.open() }}
           >
           >
 
 
             <i className="icon-paper-clip" aria-hidden="true"></i>&nbsp;
             <i className="icon-paper-clip" aria-hidden="true"></i>&nbsp;

+ 12 - 11
src/client/js/components/PageEditor/HandsontableModal.jsx

@@ -153,7 +153,7 @@ export default class HandsontableModal extends React.PureComponent {
 
 
   save() {
   save() {
     const markdownTable = new MarkdownTable(
     const markdownTable = new MarkdownTable(
-      this.refs.hotTable.hotInstance.getData(),
+      this.hotTable.hotInstance.getData(),
       { align: [].concat(this.state.markdownTable.options.align) },
       { align: [].concat(this.state.markdownTable.options.align) },
     ).normalizeCells();
     ).normalizeCells();
 
 
@@ -180,7 +180,8 @@ export default class HandsontableModal extends React.PureComponent {
    * In detail, when the setState method is called with those state passed,
    * In detail, when the setState method is called with those state passed,
    * React will start re-render process for the HotTable of this component because the HotTable receives those state values by props.
    * React will start re-render process for the HotTable of this component because the HotTable receives those state values by props.
    * HotTable#shouldComponentUpdate is called in this re-render process and calls the updateSettings method for the Handsontable instance.
    * HotTable#shouldComponentUpdate is called in this re-render process and calls the updateSettings method for the Handsontable instance.
-   * In updateSettings method, the loadData method is called in some case. (refs: https://github.com/handsontable/handsontable/blob/6.2.0/src/core.js#L1652-L1657)
+   * In updateSettings method, the loadData method is called in some case.
+   *  (refs: https://github.com/handsontable/handsontable/blob/6.2.0/src/core.js#L1652-L1657)
    * The updateSettings method calls in the HotTable always lead to call the loadData method because the HotTable passes data source by settings.data.
    * The updateSettings method calls in the HotTable always lead to call the loadData method because the HotTable passes data source by settings.data.
    * After the loadData method is executed, afterLoadData hooks are called.
    * After the loadData method is executed, afterLoadData hooks are called.
    */
    */
@@ -215,7 +216,7 @@ export default class HandsontableModal extends React.PureComponent {
     // store column index
     // store column index
     this.manuallyResizedColumnIndicesSet.add(currentColumn);
     this.manuallyResizedColumnIndicesSet.add(currentColumn);
     // force re-render
     // force re-render
-    const hotInstance = this.refs.hotTable.hotInstance;
+    const hotInstance = this.hotTable.hotInstance;
     hotInstance.render();
     hotInstance.render();
   }
   }
 
 
@@ -319,12 +320,12 @@ export default class HandsontableModal extends React.PureComponent {
    * synchronize the handsontable alignment to the markdowntable alignment
    * synchronize the handsontable alignment to the markdowntable alignment
    */
    */
   synchronizeAlignment() {
   synchronizeAlignment() {
-    if (this.refs.hotTable == null) {
+    if (this.hotTable == null) {
       return;
       return;
     }
     }
 
 
     const align = this.state.markdownTable.options.align;
     const align = this.state.markdownTable.options.align;
-    const hotInstance = this.refs.hotTable.hotInstance;
+    const hotInstance = this.hotTable.hotInstance;
 
 
     for (let i = 0; i < align.length; i++) {
     for (let i = 0; i < align.length; i++) {
       for (let j = 0; j < hotInstance.countRows(); j++) {
       for (let j = 0; j < hotInstance.countRows(); j++) {
@@ -335,7 +336,7 @@ export default class HandsontableModal extends React.PureComponent {
   }
   }
 
 
   alignButtonHandler(direction) {
   alignButtonHandler(direction) {
-    const selectedRange = this.refs.hotTable.hotInstance.getSelectedRange();
+    const selectedRange = this.hotTable.hotInstance.getSelectedRange();
     if (selectedRange == null) return;
     if (selectedRange == null) return;
 
 
     let startCol;
     let startCol;
@@ -387,8 +388,8 @@ export default class HandsontableModal extends React.PureComponent {
    *  according to the height of this.refs.hotTableContainer
    *  according to the height of this.refs.hotTableContainer
    */
    */
   expandHotTableHeight() {
   expandHotTableHeight() {
-    if (this.state.isWindowExpanded && this.refs.hotTableContainer != null) {
-      const height = this.refs.hotTableContainer.getBoundingClientRect().height;
+    if (this.state.isWindowExpanded && this.hotTableContainer != null) {
+      const height = this.hotTableContainer.getBoundingClientRect().height;
       this.setState({ handsontableHeight: height });
       this.setState({ handsontableHeight: height });
     }
     }
   }
   }
@@ -396,7 +397,7 @@ export default class HandsontableModal extends React.PureComponent {
   renderExpandOrContractButton() {
   renderExpandOrContractButton() {
     const iconClassName = this.state.isWindowExpanded ? 'icon-size-actual' : 'icon-size-fullscreen';
     const iconClassName = this.state.isWindowExpanded ? 'icon-size-actual' : 'icon-size-fullscreen';
     return (
     return (
-      <button className="close mr-3" onClick={this.state.isWindowExpanded ? this.contractWindow : this.expandWindow}>
+      <button type="button" className="close mr-3" onClick={this.state.isWindowExpanded ? this.contractWindow : this.expandWindow}>
         <i className={iconClassName} style={{ fontSize: '0.8em' }} aria-hidden="true"></i>
         <i className={iconClassName} style={{ fontSize: '0.8em' }} aria-hidden="true"></i>
       </button>
       </button>
     );
     );
@@ -432,9 +433,9 @@ export default class HandsontableModal extends React.PureComponent {
               </div>
               </div>
             </Collapse>
             </Collapse>
           </div>
           </div>
-          <div ref="hotTableContainer" className="m-4 hot-table-container">
+          <div ref={(c) => { this.hotTableContainer = c }} className="m-4 hot-table-container">
             <HotTable
             <HotTable
-              ref="hotTable"
+              ref={(c) => { this.hotTable = c }}
               data={this.state.markdownTable.table}
               data={this.state.markdownTable.table}
               settings={this.handsontableSettings}
               settings={this.handsontableSettings}
               height={this.state.handsontableHeight}
               height={this.state.handsontableHeight}

+ 18 - 6
src/client/js/components/PageEditorByHackmd.jsx

@@ -44,7 +44,7 @@ export default class PageEditorByHackmd extends React.PureComponent {
       return Promise.reject(new Error('HackmdEditor component has not initialized'));
       return Promise.reject(new Error('HackmdEditor component has not initialized'));
     }
     }
 
 
-    return this.refs.hackmdEditor.getValue()
+    return this.hackmdEditor.getValue()
       .then((document) => {
       .then((document) => {
         this.setState({ markdown: document });
         this.setState({ markdown: document });
         return document;
         return document;
@@ -54,7 +54,7 @@ export default class PageEditorByHackmd extends React.PureComponent {
   setMarkdown(markdown, updateEditorValue = true) {
   setMarkdown(markdown, updateEditorValue = true) {
     this.setState({ markdown });
     this.setState({ markdown });
     if (this.state.isInitialized && updateEditorValue) {
     if (this.state.isInitialized && updateEditorValue) {
-      this.refs.hackmdEditor.setValue(markdown);
+      this.hackmdEditor.setValue(markdown);
     }
     }
   }
   }
 
 
@@ -73,7 +73,6 @@ export default class PageEditorByHackmd extends React.PureComponent {
       initialRevisionId: updatedRevisionId,
       initialRevisionId: updatedRevisionId,
       revisionId: updatedRevisionId,
       revisionId: updatedRevisionId,
       revisionIdHackmdSynced: updatedRevisionIdHackmdSynced,
       revisionIdHackmdSynced: updatedRevisionIdHackmdSynced,
-      isDraftUpdatingInRealtime: false,
     });
     });
   }
   }
 
 
@@ -202,7 +201,7 @@ export default class PageEditorByHackmd extends React.PureComponent {
     if (this.state.isInitialized) {
     if (this.state.isInitialized) {
       return (
       return (
         <HackmdEditor
         <HackmdEditor
-          ref="hackmdEditor"
+          ref={(c) => { this.hackmdEditor = c }}
           hackmdUri={hackmdUri}
           hackmdUri={hackmdUri}
           pageIdOnHackmd={this.state.pageIdOnHackmd}
           pageIdOnHackmd={this.state.pageIdOnHackmd}
           initializationMarkdown={isResume ? null : this.state.markdown}
           initializationMarkdown={isResume ? null : this.state.markdown}
@@ -259,7 +258,14 @@ export default class PageEditorByHackmd extends React.PureComponent {
           </div>
           </div>
           <p className="text-center">
           <p className="text-center">
             Click to edit from the previous continuation<br />
             Click to edit from the previous continuation<br />
-            or <button className="btn btn-link text-danger p-0 hackmd-discard-button" onClick={() => { return this.discardChanges() }}>Discard changes</button>.
+            or
+            <button
+              type="button"
+              className="btn btn-link text-danger p-0 hackmd-discard-button"
+              onClick={() => { return this.discardChanges() }}
+            >
+              Discard changes
+            </button>.
           </p>
           </p>
           { isHackmdDocumentOutdated
           { isHackmdDocumentOutdated
             && (
             && (
@@ -268,7 +274,13 @@ export default class PageEditorByHackmd extends React.PureComponent {
               <div className="panel-body text-center">
               <div className="panel-body text-center">
                 The current draft on HackMD is based on&nbsp;
                 The current draft on HackMD is based on&nbsp;
                 <a href={`?revision=${revisionIdHackmdSynced}`}><span className="label label-default">{revisionIdHackmdSynced.substr(-8)}</span></a>.<br />
                 <a href={`?revision=${revisionIdHackmdSynced}`}><span className="label label-default">{revisionIdHackmdSynced.substr(-8)}</span></a>.<br />
-                <button className="btn btn-link text-danger p-0 hackmd-discard-button" onClick={() => { return this.discardChanges() }}>Discard it</button> to start to edit with current revision.
+                <button
+                  type="button"
+                  className="btn btn-link text-danger p-0 hackmd-discard-button"
+                  onClick={() => { return this.discardChanges() }}
+                >
+                  Discard it
+                </button> to start to edit with current revision.
               </div>
               </div>
             </div>
             </div>
             )
             )

+ 2 - 2
src/client/js/components/PageEditorByHackmd/HackmdEditor.jsx

@@ -32,7 +32,7 @@ export default class HackmdEditor extends React.PureComponent {
 
 
     const connection = Penpal.connectToChild({
     const connection = Penpal.connectToChild({
       url,
       url,
-      appendTo: this.refs.iframeContainer,
+      appendTo: this.iframeContainer,
       methods: { // expose methods to HackMD
       methods: { // expose methods to HackMD
         notifyBodyChanges(document) {
         notifyBodyChanges(document) {
           _this.notifyBodyChangesHandler(document);
           _this.notifyBodyChangesHandler(document);
@@ -78,7 +78,7 @@ export default class HackmdEditor extends React.PureComponent {
   render() {
   render() {
     return (
     return (
       // will be rendered in componentDidMount
       // will be rendered in componentDidMount
-      <div id="iframe-hackmd-container" ref="iframeContainer"></div>
+      <div id="iframe-hackmd-container" ref={(c) => { this.iframeContainer = c }}></div>
     );
     );
   }
   }
 
 

+ 3 - 3
src/client/js/components/PagePathAutoComplete.jsx

@@ -11,8 +11,8 @@ export default class PagePathAutoComplete extends React.Component {
     super(props);
     super(props);
 
 
     this.state = {
     this.state = {
-      searchError: null,
     };
     };
+
     this.crowi = this.props.crowi;
     this.crowi = this.props.crowi;
 
 
     this.onSubmit = this.onSubmit.bind(this);
     this.onSubmit = this.onSubmit.bind(this);
@@ -27,7 +27,7 @@ export default class PagePathAutoComplete extends React.Component {
 
 
   onSubmit(query) {
   onSubmit(query) {
     // get the closest form element
     // get the closest form element
-    const elem = this.refs.rootDom;
+    const elem = this.rootDom;
     const form = elem.closest('form');
     const form = elem.closest('form');
     // submit with jQuery
     // submit with jQuery
     $(form).submit();
     $(form).submit();
@@ -41,7 +41,7 @@ export default class PagePathAutoComplete extends React.Component {
 
 
   render() {
   render() {
     return (
     return (
-      <div ref="rootDom">
+      <div ref={(c) => { this.rootDom = c }}>
         <SearchTypeahead
         <SearchTypeahead
           ref={this.searchTypeaheadDom}
           ref={this.searchTypeaheadDom}
           crowi={this.crowi}
           crowi={this.crowi}

+ 5 - 1
src/client/js/components/PageStatusAlert.jsx

@@ -58,6 +58,10 @@ class PageStatusAlert extends React.Component {
     });
     });
   }
   }
 
 
+  refreshPage() {
+    window.location.reload();
+  }
+
   renderSomeoneEditingAlert() {
   renderSomeoneEditingAlert() {
     return (
     return (
       <div className="alert-hackmd-someone-editing myadmin-alert alert-success myadmin-alert-bottom alertbottom2">
       <div className="alert-hackmd-someone-editing myadmin-alert alert-success myadmin-alert-bottom alertbottom2">
@@ -100,7 +104,7 @@ class PageStatusAlert extends React.Component {
         &nbsp;
         &nbsp;
         <i className="fa fa-angle-double-right"></i>
         <i className="fa fa-angle-double-right"></i>
         &nbsp;
         &nbsp;
-        <a href="javascript:location.reload();">
+        <a onClick={this.refreshPage}>
           {label2}
           {label2}
         </a>
         </a>
       </div>
       </div>

+ 2 - 2
src/client/js/components/RecentCreated/RecentCreated.jsx

@@ -92,7 +92,7 @@ export default class RecentCreated extends React.Component {
    */
    */
   generateFirstPrev(activePage) {
   generateFirstPrev(activePage) {
     const paginationItems = [];
     const paginationItems = [];
-    if (activePage != 1) {
+    if (activePage !== 1) {
       paginationItems.push(
       paginationItems.push(
         <Pagination.First key="first" onClick={() => { return this.getRecentCreatedList(1) }} />,
         <Pagination.First key="first" onClick={() => { return this.getRecentCreatedList(1) }} />,
       );
       );
@@ -134,7 +134,7 @@ export default class RecentCreated extends React.Component {
    */
    */
   generateNextLast(activePage, totalPage) {
   generateNextLast(activePage, totalPage) {
     const paginationItems = [];
     const paginationItems = [];
-    if (totalPage != activePage) {
+    if (totalPage !== activePage) {
       paginationItems.push(
       paginationItems.push(
         <Pagination.Next key="next" onClick={() => { return this.getRecentCreatedList(this.state.activePage + 1) }} />,
         <Pagination.Next key="next" onClick={() => { return this.getRecentCreatedList(this.state.activePage + 1) }} />,
       );
       );

+ 5 - 5
src/client/js/components/SavePageControls.jsx

@@ -27,8 +27,8 @@ class SavePageControls extends React.PureComponent {
   }
   }
 
 
   getCurrentOptionsToSave() {
   getCurrentOptionsToSave() {
-    const slackNotificationOptions = this.refs.slackNotification.getCurrentOptionsToSave();
-    const grantSelectorOptions = this.refs.grantSelector.getCurrentOptionsToSave();
+    const slackNotificationOptions = this.slackNotification.getCurrentOptionsToSave();
+    const grantSelectorOptions = this.grantSelector.getCurrentOptionsToSave();
     return Object.assign(slackNotificationOptions, grantSelectorOptions);
     return Object.assign(slackNotificationOptions, grantSelectorOptions);
   }
   }
 
 
@@ -60,7 +60,7 @@ class SavePageControls extends React.PureComponent {
       <div className="d-flex align-items-center form-inline">
       <div className="d-flex align-items-center form-inline">
         <div className="mr-2">
         <div className="mr-2">
           <SlackNotification
           <SlackNotification
-            ref="slackNotification"
+            ref={(c) => { this.slackNotification = c }}
             crowi={this.props.crowi}
             crowi={this.props.crowi}
             pageId={this.props.pageId}
             pageId={this.props.pageId}
             pagePath={this.props.pagePath}
             pagePath={this.props.pagePath}
@@ -75,8 +75,8 @@ class SavePageControls extends React.PureComponent {
             <GrantSelector
             <GrantSelector
               crowi={this.props.crowi}
               crowi={this.props.crowi}
               ref={(elem) => {
               ref={(elem) => {
-                  if (this.refs.grantSelector == null) {
-                    this.refs.grantSelector = elem.getWrappedInstance();
+                  if (this.grantSelector == null) {
+                    this.grantSelector = elem.getWrappedInstance();
                   }
                   }
                 }}
                 }}
               grant={this.props.grant}
               grant={this.props.grant}

+ 1 - 2
src/client/js/components/SavePageControls/GrantSelector.jsx

@@ -189,7 +189,6 @@ class GrantSelector extends React.Component {
     // add specified group option
     // add specified group option
     grantElems.push(
     grantElems.push(
       <option
       <option
-        ref="specifiedGroupOption"
         key="specifiedGroupKey"
         key="specifiedGroupKey"
         value={SPECIFIED_GROUP_VALUE}
         value={SPECIFIED_GROUP_VALUE}
         style={{ display: grantGroup ? 'inherit' : 'none' }}
         style={{ display: grantGroup ? 'inherit' : 'none' }}
@@ -209,7 +208,7 @@ class GrantSelector extends React.Component {
           bsClass={bsClassName}
           bsClass={bsClassName}
           className="btn-group-sm selectpicker"
           className="btn-group-sm selectpicker"
           onChange={this.changeGrantHandler}
           onChange={this.changeGrantHandler}
-          inputRef={(el) => { return this.grantSelectorInputEl = el }}
+          inputRef={(el) => { this.grantSelectorInputEl = el }}
         >
         >
 
 
           {grantElems}
           {grantElems}

+ 2 - 2
src/client/js/components/SlackNotification.jsx

@@ -56,8 +56,8 @@ export default class SlackNotification extends React.Component {
     return (
     return (
       <div className="input-group input-group-sm input-group-slack extended-setting">
       <div className="input-group input-group-sm input-group-slack extended-setting">
         <label className="input-group-addon">
         <label className="input-group-addon">
-          <img id="slack-mark-white" src="/images/icons/slack/mark-monochrome_white.svg" width="18" height="18" />
-          <img id="slack-mark-black" src="/images/icons/slack/mark-monochrome_black.svg" width="18" height="18" />
+          <img id="slack-mark-white" alt="slack-mark" src="/images/icons/slack/mark-monochrome_white.svg" width="18" height="18" />
+          <img id="slack-mark-black" alt="slack-mark" src="/images/icons/slack/mark-monochrome_black.svg" width="18" height="18" />
           <input type="checkbox" value="1" checked={this.state.isSlackEnabled} onChange={this.updateStateCheckbox} />
           <input type="checkbox" value="1" checked={this.state.isSlackEnabled} onChange={this.updateStateCheckbox} />
         </label>
         </label>
         <input
         <input

+ 2 - 2
src/client/js/components/User/User.js

@@ -32,8 +32,8 @@ export default class User extends React.Component {
 
 
 User.propTypes = {
 User.propTypes = {
   user: PropTypes.object.isRequired,
   user: PropTypes.object.isRequired,
-  name: PropTypes.bool.isRequired,
-  username: PropTypes.bool.isRequired,
+  name: PropTypes.bool,
+  username: PropTypes.bool,
 };
 };
 
 
 User.defaultProps = {
 User.defaultProps = {

+ 21 - 1
src/client/styles/scss/_editor-attachment.scss

@@ -1,6 +1,7 @@
 @import 'editor-overlay';
 @import 'editor-overlay';
 
 
 .editor-container {
 .editor-container {
+
   // for Dropzone
   // for Dropzone
   .dropzone {
   .dropzone {
     @mixin insertSimpleLineIcons($code) {
     @mixin insertSimpleLineIcons($code) {
@@ -26,6 +27,7 @@
         }
         }
       }
       }
     }
     }
+
     // uploading
     // uploading
     &.dropzone-uploading {
     &.dropzone-uploading {
       @include overlay-processing-style(overlay-dropzone-active, 2.5em, 0.5em);
       @include overlay-processing-style(overlay-dropzone-active, 2.5em, 0.5em);
@@ -37,14 +39,17 @@
         .overlay-content {
         .overlay-content {
           // insert content
           // insert content
           @include insertSimpleLineIcons('\e617'); // icon-exclamation
           @include insertSimpleLineIcons('\e617'); // icon-exclamation
+
           &:after {
           &:after {
             content: 'File uploading is disabled';
             content: 'File uploading is disabled';
           }
           }
         }
         }
       }
       }
     }
     }
+
     // uploadable
     // uploadable
     &.dropzone-uploadable {
     &.dropzone-uploadable {
+
       // accepted
       // accepted
       &.dropzone-accepted:not(.dropzone-rejected) {
       &.dropzone-accepted:not(.dropzone-rejected) {
         .overlay.overlay-dropzone-active {
         .overlay.overlay-dropzone-active {
@@ -53,33 +58,39 @@
           .overlay-content {
           .overlay-content {
             // insert content
             // insert content
             @include insertSimpleLineIcons('\e084'); // icon-cloud-upload
             @include insertSimpleLineIcons('\e084'); // icon-cloud-upload
+
             &:after {
             &:after {
               content: 'Drop here to upload';
               content: 'Drop here to upload';
             }
             }
+
             // style
             // style
             color: #666;
             color: #666;
             background: rgba(200, 200, 200, 0.8);
             background: rgba(200, 200, 200, 0.8);
           }
           }
         }
         }
       }
       }
+
       // file type mismatch
       // file type mismatch
       &.dropzone-rejected:not(.dropzone-uploadablefile) {
       &.dropzone-rejected:not(.dropzone-uploadablefile) {
         .overlay.overlay-dropzone-active {
         .overlay.overlay-dropzone-active {
           .overlay-content {
           .overlay-content {
             // insert content
             // insert content
             @include insertSimpleLineIcons('\e032'); // icon-picture
             @include insertSimpleLineIcons('\e032'); // icon-picture
+
             &:after {
             &:after {
               content: 'Only an image file is allowed';
               content: 'Only an image file is allowed';
             }
             }
           }
           }
         }
         }
       }
       }
+
       // multiple files
       // multiple files
       &.dropzone-accepted.dropzone-rejected {
       &.dropzone-accepted.dropzone-rejected {
         .overlay.overlay-dropzone-active {
         .overlay.overlay-dropzone-active {
           .overlay-content {
           .overlay-content {
             // insert content
             // insert content
             @include insertSimpleLineIcons('\e617'); // icon-exclamation
             @include insertSimpleLineIcons('\e617'); // icon-exclamation
+
             &:after {
             &:after {
               content: 'Only 1 file is allowed';
               content: 'Only 1 file is allowed';
             }
             }
@@ -87,7 +98,9 @@
         }
         }
       }
       }
     }
     }
-  } // end of.dropzone
+
+    /* end of.dropzone */
+  }
 
 
   .btn-open-dropzone {
   .btn-open-dropzone {
     z-index: 2;
     z-index: 2;
@@ -96,10 +109,17 @@
     font-size: small;
     font-size: small;
     border: none;
     border: none;
     border-top: 1px dotted #ccc;
     border-top: 1px dotted #ccc;
+    border-bottom: none;
     border-radius: 0;
     border-radius: 0;
+
     &:active {
     &:active {
       box-shadow: none;
       box-shadow: none;
     }
     }
+
+    &:hover,
+    &:focus {
+      border-bottom: none;
+    }
   }
   }
 }
 }
 
 

+ 40 - 5
src/client/styles/scss/_layout_kibela.scss

@@ -1,4 +1,5 @@
 body.kibela {
 body.kibela {
+
   .icon-link,
   .icon-link,
   .CodeMirror-hint-active,
   .CodeMirror-hint-active,
   .nav-main-left-tab,
   .nav-main-left-tab,
@@ -6,59 +7,73 @@ body.kibela {
   .active {
   .active {
     color: #5882fa;
     color: #5882fa;
   }
   }
+
   .bg-white {
   .bg-white {
     background: #fefffe !important;
     background: #fefffe !important;
   }
   }
+
   .logo {
   .logo {
     background: transparent;
     background: transparent;
+
     .logo-mark {
     .logo-mark {
       height: 50px;
       height: 50px;
       background-color: white;
       background-color: white;
       box-shadow: none;
       box-shadow: none;
+
       svg {
       svg {
         width: 60px;
         width: 60px;
       }
       }
     }
     }
   }
   }
+
   /* header */
   /* header */
   .background-t {
   .background-t {
     background-color: transparent;
     background-color: transparent;
   }
   }
+
   .authors {
   .authors {
     padding-top: 10px;
     padding-top: 10px;
+
     li {
     li {
       list-style: none !important;
       list-style: none !important;
     }
     }
   }
   }
+
   .search-input-group,
   .search-input-group,
   .search-typeahead {
   .search-typeahead {
     .btn {
     .btn {
       background-color: transparent;
       background-color: transparent;
     }
     }
   }
   }
+
   .panel-heading {
   .panel-heading {
     border-radius: 0 !important;
     border-radius: 0 !important;
   }
   }
+
   .btn-open-dropzone {
   .btn-open-dropzone {
     background: rgb(243, 245, 247);
     background: rgb(243, 245, 247);
-    border-bottom: 0px !important;
   }
   }
+
   /* page list */
   /* page list */
   .page-list {
   .page-list {
     background: white;
     background: white;
   }
   }
+
   .page-attachments-row {
   .page-attachments-row {
     background-color: #e5ecf1 !important;
     background-color: #e5ecf1 !important;
     border: 0px;
     border: 0px;
   }
   }
+
   .round-corner {
   .round-corner {
     border-radius: 0.35em;
     border-radius: 0.35em;
   }
   }
+
   .round-corner-top {
   .round-corner-top {
     z-index: absolute;
     z-index: absolute;
     border-top: solid 0.4em #5584e1;
     border-top: solid 0.4em #5584e1;
     border-radius: 0.35em;
     border-radius: 0.35em;
   }
   }
+
   .kibela-block {
   .kibela-block {
     position: absolute;
     position: absolute;
     top: 0px;
     top: 0px;
@@ -71,17 +86,21 @@ body.kibela {
     border-top: solid 0.4em #5584e1;
     border-top: solid 0.4em #5584e1;
     border-radius: 0.35em;
     border-radius: 0.35em;
   }
   }
+
   .bg-title {
   .bg-title {
     position: relative;
     position: relative;
     background: transparent;
     background: transparent;
     border: none;
     border: none;
+
     svg {
     svg {
       display: none;
       display: none;
     }
     }
+
     @media screen and (max-width: 765px) {
     @media screen and (max-width: 765px) {
       padding-top: 30px;
       padding-top: 30px;
     }
     }
   }
   }
+
   .revision-toc {
   .revision-toc {
     &.affix {
     &.affix {
       top: calc(60px + 5px);
       top: calc(60px + 5px);
@@ -89,9 +108,11 @@ body.kibela {
       min-width: calc(#{100 / 12 * 2%} - #{$grid-gutter-width}); // width of 2column - padding
       min-width: calc(#{100 / 12 * 2%} - #{$grid-gutter-width}); // width of 2column - padding
       margin-top: 40px;
       margin-top: 40px;
     }
     }
+
     .revision-toc-content {
     .revision-toc-content {
       padding: 0;
       padding: 0;
     }
     }
+
     @media screen and (max-width: 1400px) {
     @media screen and (max-width: 1400px) {
       &.affix {
       &.affix {
         right: 0rem !important;
         right: 0rem !important;
@@ -99,15 +120,19 @@ body.kibela {
       }
       }
     }
     }
   }
   }
+
   /* search page */
   /* search page */
   .search-result-list,
   .search-result-list,
   .page-list-li {
   .page-list-li {
     background: #f4f5f6;
     background: #f4f5f6;
   }
   }
+
   /* Tabs */
   /* Tabs */
   .nav.nav-tabs {
   .nav.nav-tabs {
     border-bottom-color: #f4f5f6;
     border-bottom-color: #f4f5f6;
-    > li > a {
+
+    >li>a {
+
       &,
       &,
       &:hover,
       &:hover,
       &:focus {
       &:focus {
@@ -117,33 +142,39 @@ body.kibela {
         border-left: none;
         border-left: none;
       }
       }
     }
     }
-    > li.active > a {
+
+    >li.active>a {
       background: transparent !important;
       background: transparent !important;
       border-top: none;
       border-top: none;
       border-right: none;
       border-right: none;
       border-bottom: solid 2.7px #5584e1;
       border-bottom: solid 2.7px #5584e1;
       border-left: none;
       border-left: none;
     }
     }
+
     .wiki {
     .wiki {
       h1 {
       h1 {
         border-bottom: solid 2px #5584e1 !important;
         border-bottom: solid 2px #5584e1 !important;
       }
       }
+
       h2 {
       h2 {
         border-color: solid 1px #5584e1;
         border-color: solid 1px #5584e1;
       }
       }
     }
     }
   }
   }
+
   /* user page */
   /* user page */
   .header-wrap {
   .header-wrap {
     padding: 0px;
     padding: 0px;
     margin-left: 2em;
     margin-left: 2em;
   }
   }
+
   /* edit */
   /* edit */
   .CodeMirror {
   .CodeMirror {
     border: solid 1.2px #d8d8d8;
     border: solid 1.2px #d8d8d8;
     border-top: solid 0.3em #5584e1 !important;
     border-top: solid 0.3em #5584e1 !important;
     border-radius: 0.35em;
     border-radius: 0.35em;
   }
   }
+
   &.on-edit {
   &.on-edit {
     $header-plus-footer: 42px //  .nav height
     $header-plus-footer: 42px //  .nav height
       + 5.5px //                  .kibela-block border-top
       + 5.5px //                  .kibela-block border-top
@@ -154,8 +185,8 @@ body.kibela {
     @include expand-editor($header-plus-footer);
     @include expand-editor($header-plus-footer);
 
 
     .main {
     .main {
-      > .row.page-content {
-        > .col-xs-12 {
+      >.row.page-content {
+        >.col-xs-12 {
           width: 100%;
           width: 100%;
           padding: 0;
           padding: 0;
         }
         }
@@ -164,22 +195,26 @@ body.kibela {
 
 
     .tab-content {
     .tab-content {
       padding-top: 15px;
       padding-top: 15px;
+
       #edit {
       #edit {
         margin-right: 1em;
         margin-right: 1em;
         margin-left: 1em;
         margin-left: 1em;
       }
       }
     }
     }
+
     .tab-pane {
     .tab-pane {
       .page-editor-editor-container {
       .page-editor-editor-container {
         margin: 0px;
         margin: 0px;
         border: none !important;
         border: none !important;
       }
       }
     }
     }
+
     .page-editor-preview-container {
     .page-editor-preview-container {
       padding-right: 0px !important;
       padding-right: 0px !important;
       padding-left: 2em;
       padding-left: 2em;
       background: white !important;
       background: white !important;
     }
     }
+
     .page-editor-footer {
     .page-editor-footer {
       min-height: 60px;
       min-height: 60px;
       padding: 13px;
       padding: 13px;

+ 72 - 52
src/server/service/passport.js

@@ -317,20 +317,25 @@ class PassportService {
     }
     }
 
 
     debug('GoogleStrategy: setting up..');
     debug('GoogleStrategy: setting up..');
-    passport.use(new GoogleStrategy({
-      clientId: config.crowi['security:passport-google:clientId'] || process.env.OAUTH_GOOGLE_CLIENT_ID,
-      clientSecret: config.crowi['security:passport-google:clientSecret'] || process.env.OAUTH_GOOGLE_CLIENT_SECRET,
-      callbackURL: (this.crowi.configManager.getConfig('crowi', 'app:siteUrl') != null)
-        ? urljoin(this.crowi.configManager.getSiteUrl(), '/passport/google/callback') // auto-generated with v3.2.4 and above
-        : config.crowi['security:passport-google:callbackUrl'] || process.env.OAUTH_GOOGLE_CALLBACK_URI, // DEPRECATED: backward compatible with v3.2.3 and below
-      skipUserProfile: false,
-    }, ((accessToken, refreshToken, profile, done) => {
-        if (profile) {
-          return done(null, profile);
-        }
+    passport.use(
+      new GoogleStrategy(
+        {
+          clientId: config.crowi['security:passport-google:clientId'] || process.env.OAUTH_GOOGLE_CLIENT_ID,
+          clientSecret: config.crowi['security:passport-google:clientSecret'] || process.env.OAUTH_GOOGLE_CLIENT_SECRET,
+          callbackURL: (this.crowi.configManager.getConfig('crowi', 'app:siteUrl') != null)
+            ? urljoin(this.crowi.configManager.getSiteUrl(), '/passport/google/callback') // auto-generated with v3.2.4 and above
+            : config.crowi['security:passport-google:callbackUrl'] || process.env.OAUTH_GOOGLE_CALLBACK_URI, // DEPRECATED: backward compatible with v3.2.3 and below
+          skipUserProfile: false,
+        },
+        (accessToken, refreshToken, profile, done) => {
+          if (profile) {
+            return done(null, profile);
+          }
 
 
-        return done(null, false);
-      })));
+          return done(null, false);
+        },
+      ),
+    );
 
 
     this.isGoogleStrategySetup = true;
     this.isGoogleStrategySetup = true;
     debug('GoogleStrategy: setup is done');
     debug('GoogleStrategy: setup is done');
@@ -363,20 +368,25 @@ class PassportService {
     }
     }
 
 
     debug('GitHubStrategy: setting up..');
     debug('GitHubStrategy: setting up..');
-    passport.use(new GitHubStrategy({
-      clientID: config.crowi['security:passport-github:clientId'] || process.env.OAUTH_GITHUB_CLIENT_ID,
-      clientSecret: config.crowi['security:passport-github:clientSecret'] || process.env.OAUTH_GITHUB_CLIENT_SECRET,
-      callbackURL: (this.crowi.configManager.getConfig('crowi', 'app:siteUrl') != null)
-        ? urljoin(this.crowi.configManager.getSiteUrl(), '/passport/github/callback') // auto-generated with v3.2.4 and above
-        : config.crowi['security:passport-github:callbackUrl'] || process.env.OAUTH_GITHUB_CALLBACK_URI, // DEPRECATED: backward compatible with v3.2.3 and below
-      skipUserProfile: false,
-    }, ((accessToken, refreshToken, profile, done) => {
-        if (profile) {
-          return done(null, profile);
-        }
+    passport.use(
+      new GitHubStrategy(
+        {
+          clientID: config.crowi['security:passport-github:clientId'] || process.env.OAUTH_GITHUB_CLIENT_ID,
+          clientSecret: config.crowi['security:passport-github:clientSecret'] || process.env.OAUTH_GITHUB_CLIENT_SECRET,
+          callbackURL: (this.crowi.configManager.getConfig('crowi', 'app:siteUrl') != null)
+            ? urljoin(this.crowi.configManager.getSiteUrl(), '/passport/github/callback') // auto-generated with v3.2.4 and above
+            : config.crowi['security:passport-github:callbackUrl'] || process.env.OAUTH_GITHUB_CALLBACK_URI, // DEPRECATED: backward compatible with v3.2.3 and below
+          skipUserProfile: false,
+        },
+        (accessToken, refreshToken, profile, done) => {
+          if (profile) {
+            return done(null, profile);
+          }
 
 
-        return done(null, false);
-      })));
+          return done(null, false);
+        },
+      ),
+    );
 
 
     this.isGitHubStrategySetup = true;
     this.isGitHubStrategySetup = true;
     debug('GitHubStrategy: setup is done');
     debug('GitHubStrategy: setup is done');
@@ -409,20 +419,25 @@ class PassportService {
     }
     }
 
 
     debug('TwitterStrategy: setting up..');
     debug('TwitterStrategy: setting up..');
-    passport.use(new TwitterStrategy({
-      consumerKey: config.crowi['security:passport-twitter:consumerKey'] || process.env.OAUTH_TWITTER_CONSUMER_KEY,
-      consumerSecret: config.crowi['security:passport-twitter:consumerSecret'] || process.env.OAUTH_TWITTER_CONSUMER_SECRET,
-      callbackURL: (this.crowi.configManager.getConfig('crowi', 'app:siteUrl') != null)
-        ? urljoin(this.crowi.configManager.getSiteUrl(), '/passport/twitter/callback') // auto-generated with v3.2.4 and above
-        : config.crowi['security:passport-twitter:callbackUrl'] || process.env.OAUTH_TWITTER_CALLBACK_URI, // DEPRECATED: backward compatible with v3.2.3 and below
-      skipUserProfile: false,
-    }, ((accessToken, refreshToken, profile, done) => {
-        if (profile) {
-          return done(null, profile);
-        }
+    passport.use(
+      new TwitterStrategy(
+        {
+          consumerKey: config.crowi['security:passport-twitter:consumerKey'] || process.env.OAUTH_TWITTER_CONSUMER_KEY,
+          consumerSecret: config.crowi['security:passport-twitter:consumerSecret'] || process.env.OAUTH_TWITTER_CONSUMER_SECRET,
+          callbackURL: (this.crowi.configManager.getConfig('crowi', 'app:siteUrl') != null)
+            ? urljoin(this.crowi.configManager.getSiteUrl(), '/passport/twitter/callback') // auto-generated with v3.2.4 and above
+            : config.crowi['security:passport-twitter:callbackUrl'] || process.env.OAUTH_TWITTER_CALLBACK_URI, // DEPRECATED: backward compatible with v3.2.3 and below
+          skipUserProfile: false,
+        },
+        (accessToken, refreshToken, profile, done) => {
+          if (profile) {
+            return done(null, profile);
+          }
 
 
-        return done(null, false);
-      })));
+          return done(null, false);
+        },
+      ),
+    );
 
 
     this.isTwitterStrategySetup = true;
     this.isTwitterStrategySetup = true;
     debug('TwitterStrategy: setup is done');
     debug('TwitterStrategy: setup is done');
@@ -454,20 +469,25 @@ class PassportService {
     }
     }
 
 
     debug('SamlStrategy: setting up..');
     debug('SamlStrategy: setting up..');
-    passport.use(new SamlStrategy({
-      entryPoint: configManager.getConfig('crowi', 'security:passport-saml:entryPoint'),
-      callbackUrl: (this.crowi.configManager.getConfig('crowi', 'app:siteUrl') != null)
-        ? urljoin(this.crowi.configManager.getSiteUrl(), '/passport/saml/callback') // auto-generated with v3.2.4 and above
-        : configManager.getConfig('crowi', 'security:passport-saml:callbackUrl'), // DEPRECATED: backward compatible with v3.2.3 and below
-      issuer: configManager.getConfig('crowi', 'security:passport-saml:issuer'),
-      cert: configManager.getConfig('crowi', 'security:passport-saml:cert'),
-    }, ((profile, done) => {
-        if (profile) {
-          return done(null, profile);
-        }
+    passport.use(
+      new SamlStrategy(
+        {
+          entryPoint: configManager.getConfig('crowi', 'security:passport-saml:entryPoint'),
+          callbackUrl: (this.crowi.configManager.getConfig('crowi', 'app:siteUrl') != null)
+            ? urljoin(this.crowi.configManager.getSiteUrl(), '/passport/saml/callback') // auto-generated with v3.2.4 and above
+            : configManager.getConfig('crowi', 'security:passport-saml:callbackUrl'), // DEPRECATED: backward compatible with v3.2.3 and below
+          issuer: configManager.getConfig('crowi', 'security:passport-saml:issuer'),
+          cert: configManager.getConfig('crowi', 'security:passport-saml:cert'),
+        },
+        (profile, done) => {
+          if (profile) {
+            return done(null, profile);
+          }
 
 
-        return done(null, false);
-      })));
+          return done(null, false);
+        },
+      ),
+    );
 
 
     this.isSamlStrategySetup = true;
     this.isSamlStrategySetup = true;
     debug('SamlStrategy: setup is done');
     debug('SamlStrategy: setup is done');

+ 192 - 163
yarn.lock

@@ -361,15 +361,9 @@ acorn-dynamic-import@^4.0.0:
   version "4.0.0"
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz#482210140582a36b83c3e342e1cfebcaa9240948"
   resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz#482210140582a36b83c3e342e1cfebcaa9240948"
 
 
-acorn-jsx@^4.1.1:
-  version "4.1.1"
-  resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-4.1.1.tgz#e8e41e48ea2fe0c896740610ab6a4ffd8add225e"
-  dependencies:
-    acorn "^5.0.3"
-
-acorn@^5.0.3, acorn@^5.6.0:
-  version "5.7.1"
-  resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.1.tgz#f095829297706a7c9776958c0afc8930a9b9d9d8"
+acorn-jsx@^5.0.0:
+  version "5.0.1"
+  resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.1.tgz#32a064fd925429216a09b141102bfdd185fae40e"
 
 
 acorn@^5.7.3:
 acorn@^5.7.3:
   version "5.7.3"
   version "5.7.3"
@@ -379,6 +373,10 @@ acorn@^6.0.5:
   version "6.1.0"
   version "6.1.0"
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.0.tgz#b0a3be31752c97a0f7013c5f4903b71a05db6818"
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.0.tgz#b0a3be31752c97a0f7013c5f4903b71a05db6818"
 
 
+acorn@^6.0.7:
+  version "6.1.1"
+  resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.1.tgz#7d25ae05bb8ad1f9b699108e1094ecd7884adc1f"
+
 after@0.8.2:
 after@0.8.2:
   version "0.8.2"
   version "0.8.2"
   resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
   resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
@@ -416,7 +414,7 @@ ajv@^5.1.0:
     fast-json-stable-stringify "^2.0.0"
     fast-json-stable-stringify "^2.0.0"
     json-schema-traverse "^0.3.0"
     json-schema-traverse "^0.3.0"
 
 
-ajv@^6.0.1, ajv@^6.5.0:
+ajv@^6.0.1:
   version "6.5.1"
   version "6.5.1"
   resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.1.tgz#88ebc1263c7133937d108b80c5572e64e1d9322d"
   resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.1.tgz#88ebc1263c7133937d108b80c5572e64e1d9322d"
   dependencies:
   dependencies:
@@ -442,6 +440,15 @@ ajv@^6.5.5:
     json-schema-traverse "^0.4.1"
     json-schema-traverse "^0.4.1"
     uri-js "^4.2.2"
     uri-js "^4.2.2"
 
 
+ajv@^6.9.1:
+  version "6.10.0"
+  resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1"
+  dependencies:
+    fast-deep-equal "^2.0.1"
+    fast-json-stable-stringify "^2.0.0"
+    json-schema-traverse "^0.4.1"
+    uri-js "^4.2.2"
+
 align-text@^0.1.1, align-text@^0.1.3:
 align-text@^0.1.1, align-text@^0.1.3:
   version "0.1.4"
   version "0.1.4"
   resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117"
   resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117"
@@ -468,9 +475,9 @@ ansi-colors@3.2.3:
   version "3.2.3"
   version "3.2.3"
   resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813"
   resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813"
 
 
-ansi-escapes@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.0.0.tgz#ec3e8b4e9f8064fc02c3ac9b65f1c275bda8ef92"
+ansi-escapes@^3.2.0:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b"
 
 
 ansi-regex@^2.0.0:
 ansi-regex@^2.0.0:
   version "2.1.1"
   version "2.1.1"
@@ -540,13 +547,6 @@ argparse@^1.0.7:
   dependencies:
   dependencies:
     sprintf-js "~1.0.2"
     sprintf-js "~1.0.2"
 
 
-aria-query@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-3.0.0.tgz#65b3fcc1ca1155a8c9ae64d6eee297f15d5133cc"
-  dependencies:
-    ast-types-flow "0.0.7"
-    commander "^2.11.0"
-
 arr-diff@^2.0.0:
 arr-diff@^2.0.0:
   version "2.0.0"
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf"
   resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf"
@@ -660,9 +660,9 @@ assign-symbols@^1.0.0:
   version "1.0.0"
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
   resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
 
 
-ast-types-flow@0.0.7, ast-types-flow@^0.0.7:
-  version "0.0.7"
-  resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad"
+astral-regex@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9"
 
 
 async-each-series@0.1.1:
 async-each-series@0.1.1:
   version "0.1.1"
   version "0.1.1"
@@ -788,12 +788,6 @@ axios@^0.18.0:
     follow-redirects "^1.3.0"
     follow-redirects "^1.3.0"
     is-buffer "^1.1.5"
     is-buffer "^1.1.5"
 
 
-axobject-query@^2.0.2:
-  version "2.0.2"
-  resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.0.2.tgz#ea187abe5b9002b377f925d8bf7d1c561adf38f9"
-  dependencies:
-    ast-types-flow "0.0.7"
-
 babel-code-frame@^6.26.0:
 babel-code-frame@^6.26.0:
   version "6.26.0"
   version "6.26.0"
   resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
   resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
@@ -1853,19 +1847,13 @@ cache-base@^1.0.1:
     union-value "^1.0.0"
     union-value "^1.0.0"
     unset-value "^1.0.0"
     unset-value "^1.0.0"
 
 
-caller-path@^0.1.0:
-  version "0.1.0"
-  resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f"
-  dependencies:
-    callsites "^0.2.0"
-
 callsite@1.0.0:
 callsite@1.0.0:
   version "1.0.0"
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20"
   resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20"
 
 
-callsites@^0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca"
+callsites@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.0.0.tgz#fb7eb569b72ad7a45812f93fd9430a3e410b3dd3"
 
 
 camelcase-keys@^2.0.0:
 camelcase-keys@^2.0.0:
   version "2.1.0"
   version "2.1.0"
@@ -2026,9 +2014,9 @@ character-reference-invalid@^1.0.0:
   version "1.1.2"
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.2.tgz#21e421ad3d84055952dab4a43a04e73cd425d3ed"
   resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.2.tgz#21e421ad3d84055952dab4a43a04e73cd425d3ed"
 
 
-chardet@^0.4.0:
-  version "0.4.2"
-  resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2"
+chardet@^0.7.0:
+  version "0.7.0"
+  resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
 
 
 charenc@~0.0.1:
 charenc@~0.0.1:
   version "0.0.2"
   version "0.0.2"
@@ -2826,10 +2814,6 @@ cyclist@~0.2.2:
   version "0.2.2"
   version "0.2.2"
   resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640"
   resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640"
 
 
-damerau-levenshtein@^1.0.4:
-  version "1.0.4"
-  resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz#03191c432cb6eea168bb77f3a55ffdccb8978514"
-
 dashdash@^1.12.0, dashdash@^1.14.0:
 dashdash@^1.12.0, dashdash@^1.14.0:
   version "1.14.1"
   version "1.14.1"
   resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
   resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
@@ -2881,7 +2865,7 @@ debug@3.2.6, debug@^3.0.0, debug@^3.0.1, debug@^3.2.6:
   dependencies:
   dependencies:
     ms "^2.1.1"
     ms "^2.1.1"
 
 
-debug@^4.1.0:
+debug@^4.0.1, debug@^4.1.0:
   version "4.1.1"
   version "4.1.1"
   resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
   resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
   dependencies:
   dependencies:
@@ -3079,6 +3063,12 @@ doctrine@^2.1.0:
   dependencies:
   dependencies:
     esutils "^2.0.2"
     esutils "^2.0.2"
 
 
+doctrine@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961"
+  dependencies:
+    esutils "^2.0.2"
+
 dom-helpers@^3.2.0, dom-helpers@^3.2.1:
 dom-helpers@^3.2.0, dom-helpers@^3.2.1:
   version "3.3.1"
   version "3.3.1"
   resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.3.1.tgz#fc1a4e15ffdf60ddde03a480a9c0fece821dd4a6"
   resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.3.1.tgz#fc1a4e15ffdf60ddde03a480a9c0fece821dd4a6"
@@ -3256,10 +3246,6 @@ emoji-regex@^7.0.1:
   version "7.0.1"
   version "7.0.1"
   resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.1.tgz#5a132b28ebf84a289ba692862f7d4206ebcd32d0"
   resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.1.tgz#5a132b28ebf84a289ba692862f7d4206ebcd32d0"
 
 
-emoji-regex@^7.0.2:
-  version "7.0.3"
-  resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
-
 emojis-list@^2.0.0:
 emojis-list@^2.0.0:
   version "2.1.0"
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
   resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
@@ -3408,16 +3394,6 @@ error-ex@^1.2.0, error-ex@^1.3.1:
   dependencies:
   dependencies:
     is-arrayish "^0.2.1"
     is-arrayish "^0.2.1"
 
 
-es-abstract@^1.10.0, es-abstract@^1.5.1, es-abstract@^1.6.1:
-  version "1.12.0"
-  resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165"
-  dependencies:
-    es-to-primitive "^1.1.1"
-    function-bind "^1.1.1"
-    has "^1.0.1"
-    is-callable "^1.1.3"
-    is-regex "^1.0.4"
-
 es-abstract@^1.11.0, es-abstract@^1.12.0:
 es-abstract@^1.11.0, es-abstract@^1.12.0:
   version "1.13.0"
   version "1.13.0"
   resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9"
   resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9"
@@ -3439,6 +3415,16 @@ es-abstract@^1.4.3:
     is-callable "^1.1.3"
     is-callable "^1.1.3"
     is-regex "^1.0.4"
     is-regex "^1.0.4"
 
 
+es-abstract@^1.5.1, es-abstract@^1.6.1:
+  version "1.12.0"
+  resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165"
+  dependencies:
+    es-to-primitive "^1.1.1"
+    function-bind "^1.1.1"
+    has "^1.0.1"
+    is-callable "^1.1.3"
+    is-regex "^1.0.4"
+
 es-abstract@^1.7.0:
 es-abstract@^1.7.0:
   version "1.10.0"
   version "1.10.0"
   resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.10.0.tgz#1ecb36c197842a00d8ee4c2dfd8646bb97d60864"
   resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.10.0.tgz#1ecb36c197842a00d8ee4c2dfd8646bb97d60864"
@@ -3547,19 +3533,6 @@ eslint-plugin-import@^2.16.0:
     read-pkg-up "^2.0.0"
     read-pkg-up "^2.0.0"
     resolve "^1.9.0"
     resolve "^1.9.0"
 
 
-eslint-plugin-jsx-a11y@^6.2.1:
-  version "6.2.1"
-  resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.2.1.tgz#4ebba9f339b600ff415ae4166e3e2e008831cf0c"
-  dependencies:
-    aria-query "^3.0.0"
-    array-includes "^3.0.3"
-    ast-types-flow "^0.0.7"
-    axobject-query "^2.0.2"
-    damerau-levenshtein "^1.0.4"
-    emoji-regex "^7.0.2"
-    has "^1.0.3"
-    jsx-ast-utils "^2.0.1"
-
 eslint-plugin-react@^7.12.4:
 eslint-plugin-react@^7.12.4:
   version "7.12.4"
   version "7.12.4"
   resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.12.4.tgz#b1ecf26479d61aee650da612e425c53a99f48c8c"
   resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.12.4.tgz#b1ecf26479d61aee650da612e425c53a99f48c8c"
@@ -3590,59 +3563,69 @@ eslint-scope@^4.0.0:
     esrecurse "^4.1.0"
     esrecurse "^4.1.0"
     estraverse "^4.1.1"
     estraverse "^4.1.1"
 
 
+eslint-scope@^4.0.2:
+  version "4.0.2"
+  resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.2.tgz#5f10cd6cabb1965bf479fa65745673439e21cb0e"
+  dependencies:
+    esrecurse "^4.1.0"
+    estraverse "^4.1.1"
+
+eslint-utils@^1.3.1:
+  version "1.3.1"
+  resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.3.1.tgz#9a851ba89ee7c460346f97cf8939c7298827e512"
+
 eslint-visitor-keys@^1.0.0:
 eslint-visitor-keys@^1.0.0:
   version "1.0.0"
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d"
   resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d"
 
 
-eslint@^5.0.0:
-  version "5.0.0"
-  resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.0.0.tgz#3576704f7377aca072da69c00862277c5fe57153"
+eslint@^5.15.1:
+  version "5.15.1"
+  resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.15.1.tgz#8266b089fd5391e0009a047050795b1d73664524"
   dependencies:
   dependencies:
-    ajv "^6.5.0"
-    babel-code-frame "^6.26.0"
+    "@babel/code-frame" "^7.0.0"
+    ajv "^6.9.1"
     chalk "^2.1.0"
     chalk "^2.1.0"
     cross-spawn "^6.0.5"
     cross-spawn "^6.0.5"
-    debug "^3.1.0"
-    doctrine "^2.1.0"
-    eslint-scope "^4.0.0"
+    debug "^4.0.1"
+    doctrine "^3.0.0"
+    eslint-scope "^4.0.2"
+    eslint-utils "^1.3.1"
     eslint-visitor-keys "^1.0.0"
     eslint-visitor-keys "^1.0.0"
-    espree "^4.0.0"
+    espree "^5.0.1"
     esquery "^1.0.1"
     esquery "^1.0.1"
     esutils "^2.0.2"
     esutils "^2.0.2"
-    file-entry-cache "^2.0.0"
+    file-entry-cache "^5.0.1"
     functional-red-black-tree "^1.0.1"
     functional-red-black-tree "^1.0.1"
     glob "^7.1.2"
     glob "^7.1.2"
-    globals "^11.5.0"
-    ignore "^3.3.3"
+    globals "^11.7.0"
+    ignore "^4.0.6"
+    import-fresh "^3.0.0"
     imurmurhash "^0.1.4"
     imurmurhash "^0.1.4"
-    inquirer "^5.2.0"
-    is-resolvable "^1.1.0"
-    js-yaml "^3.11.0"
+    inquirer "^6.2.2"
+    js-yaml "^3.12.0"
     json-stable-stringify-without-jsonify "^1.0.1"
     json-stable-stringify-without-jsonify "^1.0.1"
     levn "^0.3.0"
     levn "^0.3.0"
-    lodash "^4.17.5"
+    lodash "^4.17.11"
     minimatch "^3.0.4"
     minimatch "^3.0.4"
     mkdirp "^0.5.1"
     mkdirp "^0.5.1"
     natural-compare "^1.4.0"
     natural-compare "^1.4.0"
     optionator "^0.8.2"
     optionator "^0.8.2"
     path-is-inside "^1.0.2"
     path-is-inside "^1.0.2"
-    pluralize "^7.0.0"
     progress "^2.0.0"
     progress "^2.0.0"
-    regexpp "^1.1.0"
-    require-uncached "^1.0.3"
-    semver "^5.5.0"
-    string.prototype.matchall "^2.0.0"
+    regexpp "^2.0.1"
+    semver "^5.5.1"
     strip-ansi "^4.0.0"
     strip-ansi "^4.0.0"
     strip-json-comments "^2.0.1"
     strip-json-comments "^2.0.1"
-    table "^4.0.3"
+    table "^5.2.3"
     text-table "^0.2.0"
     text-table "^0.2.0"
 
 
-espree@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/espree/-/espree-4.0.0.tgz#253998f20a0f82db5d866385799d912a83a36634"
+espree@^5.0.1:
+  version "5.0.1"
+  resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a"
   dependencies:
   dependencies:
-    acorn "^5.6.0"
-    acorn-jsx "^4.1.1"
+    acorn "^6.0.7"
+    acorn-jsx "^5.0.0"
+    eslint-visitor-keys "^1.0.0"
 
 
 esprima@^4.0.0:
 esprima@^4.0.0:
   version "4.0.0"
   version "4.0.0"
@@ -3918,12 +3901,12 @@ extend@^3.0.2, extend@~3.0.2:
   version "3.0.2"
   version "3.0.2"
   resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
   resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
 
 
-external-editor@^2.1.0:
-  version "2.2.0"
-  resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5"
+external-editor@^3.0.3:
+  version "3.0.3"
+  resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.0.3.tgz#5866db29a97826dbe4bf3afd24070ead9ea43a27"
   dependencies:
   dependencies:
-    chardet "^0.4.0"
-    iconv-lite "^0.4.17"
+    chardet "^0.7.0"
+    iconv-lite "^0.4.24"
     tmp "^0.0.33"
     tmp "^0.0.33"
 
 
 extglob@^0.3.1:
 extglob@^0.3.1:
@@ -4022,6 +4005,12 @@ file-entry-cache@^2.0.0:
     flat-cache "^1.2.1"
     flat-cache "^1.2.1"
     object-assign "^4.0.1"
     object-assign "^4.0.1"
 
 
+file-entry-cache@^5.0.1:
+  version "5.0.1"
+  resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c"
+  dependencies:
+    flat-cache "^2.0.1"
+
 file-loader@^3.0.1:
 file-loader@^3.0.1:
   version "3.0.1"
   version "3.0.1"
   resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-3.0.1.tgz#f8e0ba0b599918b51adfe45d66d1e771ad560faa"
   resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-3.0.1.tgz#f8e0ba0b599918b51adfe45d66d1e771ad560faa"
@@ -4139,12 +4128,24 @@ flat-cache@^1.2.1:
     graceful-fs "^4.1.2"
     graceful-fs "^4.1.2"
     write "^0.2.1"
     write "^0.2.1"
 
 
+flat-cache@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0"
+  dependencies:
+    flatted "^2.0.0"
+    rimraf "2.6.3"
+    write "1.0.3"
+
 flat@^4.1.0:
 flat@^4.1.0:
   version "4.1.0"
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.0.tgz#090bec8b05e39cba309747f1d588f04dbaf98db2"
   resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.0.tgz#090bec8b05e39cba309747f1d588f04dbaf98db2"
   dependencies:
   dependencies:
     is-buffer "~2.0.3"
     is-buffer "~2.0.3"
 
 
+flatted@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.0.tgz#55122b6536ea496b4b44893ee2608141d10d9916"
+
 flatten@^1.0.2:
 flatten@^1.0.2:
   version "1.0.2"
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782"
   resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782"
@@ -4477,14 +4478,10 @@ global-prefix@^1.0.1:
     is-windows "^1.0.1"
     is-windows "^1.0.1"
     which "^1.2.14"
     which "^1.2.14"
 
 
-globals@^11.1.0:
+globals@^11.1.0, globals@^11.7.0:
   version "11.11.0"
   version "11.11.0"
   resolved "https://registry.yarnpkg.com/globals/-/globals-11.11.0.tgz#dcf93757fa2de5486fbeed7118538adf789e9c2e"
   resolved "https://registry.yarnpkg.com/globals/-/globals-11.11.0.tgz#dcf93757fa2de5486fbeed7118538adf789e9c2e"
 
 
-globals@^11.5.0:
-  version "11.7.0"
-  resolved "https://registry.yarnpkg.com/globals/-/globals-11.7.0.tgz#a583faa43055b1aca771914bf68258e2fc125673"
-
 globals@^9.18.0:
 globals@^9.18.0:
   version "9.18.0"
   version "9.18.0"
   resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
   resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
@@ -5006,7 +5003,7 @@ i18next@=12.1.0:
   version "12.1.0"
   version "12.1.0"
   resolved "https://registry.yarnpkg.com/i18next/-/i18next-12.1.0.tgz#387bf4b94d05b0160b6a41d001a6b360e384bdb1"
   resolved "https://registry.yarnpkg.com/i18next/-/i18next-12.1.0.tgz#387bf4b94d05b0160b6a41d001a6b360e384bdb1"
 
 
-iconv-lite@0.4.19, iconv-lite@^0.4.17, iconv-lite@~0.4.13:
+iconv-lite@0.4.19, iconv-lite@~0.4.13:
   version "0.4.19"
   version "0.4.19"
   resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
   resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
 
 
@@ -5016,6 +5013,12 @@ iconv-lite@0.4.23, iconv-lite@^0.4.4:
   dependencies:
   dependencies:
     safer-buffer ">= 2.1.2 < 3"
     safer-buffer ">= 2.1.2 < 3"
 
 
+iconv-lite@^0.4.24:
+  version "0.4.24"
+  resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
+  dependencies:
+    safer-buffer ">= 2.1.2 < 3"
+
 icss-replace-symbols@^1.1.0:
 icss-replace-symbols@^1.1.0:
   version "1.1.0"
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded"
   resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded"
@@ -5052,6 +5055,10 @@ ignore@^3.3.5:
   version "3.3.10"
   version "3.3.10"
   resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043"
   resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043"
 
 
+ignore@^4.0.6:
+  version "4.0.6"
+  resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
+
 immutable@^3:
 immutable@^3:
   version "3.8.2"
   version "3.8.2"
   resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.8.2.tgz#c2439951455bb39913daf281376f1530e104adf3"
   resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.8.2.tgz#c2439951455bb39913daf281376f1530e104adf3"
@@ -5062,6 +5069,13 @@ import-cwd@^2.0.0:
   dependencies:
   dependencies:
     import-from "^2.1.0"
     import-from "^2.1.0"
 
 
+import-fresh@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.0.0.tgz#a3d897f420cab0e671236897f75bc14b4885c390"
+  dependencies:
+    parent-module "^1.0.0"
+    resolve-from "^4.0.0"
+
 import-from@^2.1.0:
 import-from@^2.1.0:
   version "2.1.0"
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/import-from/-/import-from-2.1.0.tgz#335db7f2a7affd53aaa471d4b8021dee36b7f3b1"
   resolved "https://registry.yarnpkg.com/import-from/-/import-from-2.1.0.tgz#335db7f2a7affd53aaa471d4b8021dee36b7f3b1"
@@ -5138,22 +5152,22 @@ ini@^1.3.4, ini@~1.3.0:
   version "1.3.5"
   version "1.3.5"
   resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
   resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
 
 
-inquirer@^5.2.0:
-  version "5.2.0"
-  resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-5.2.0.tgz#db350c2b73daca77ff1243962e9f22f099685726"
+inquirer@^6.2.2:
+  version "6.2.2"
+  resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.2.tgz#46941176f65c9eb20804627149b743a218f25406"
   dependencies:
   dependencies:
-    ansi-escapes "^3.0.0"
-    chalk "^2.0.0"
+    ansi-escapes "^3.2.0"
+    chalk "^2.4.2"
     cli-cursor "^2.1.0"
     cli-cursor "^2.1.0"
     cli-width "^2.0.0"
     cli-width "^2.0.0"
-    external-editor "^2.1.0"
+    external-editor "^3.0.3"
     figures "^2.0.0"
     figures "^2.0.0"
-    lodash "^4.3.0"
+    lodash "^4.17.11"
     mute-stream "0.0.7"
     mute-stream "0.0.7"
     run-async "^2.2.0"
     run-async "^2.2.0"
-    rxjs "^5.5.2"
+    rxjs "^6.4.0"
     string-width "^2.1.0"
     string-width "^2.1.0"
-    strip-ansi "^4.0.0"
+    strip-ansi "^5.0.0"
     through "^2.3.6"
     through "^2.3.6"
 
 
 interpret@^1.1.0:
 interpret@^1.1.0:
@@ -5471,7 +5485,7 @@ is-regexp@^1.0.0:
   version "1.0.0"
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069"
   resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069"
 
 
-is-resolvable@^1.0.0, is-resolvable@^1.1.0:
+is-resolvable@^1.0.0:
   version "1.1.0"
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88"
   resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88"
 
 
@@ -5628,6 +5642,13 @@ js-yaml@^3.11.0:
     argparse "^1.0.7"
     argparse "^1.0.7"
     esprima "^4.0.0"
     esprima "^4.0.0"
 
 
+js-yaml@^3.12.0:
+  version "3.12.2"
+  resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.2.tgz#ef1d067c5a9d9cb65bd72f285b5d8105c77f14fc"
+  dependencies:
+    argparse "^1.0.7"
+    esprima "^4.0.0"
+
 js-yaml@~3.10.0:
 js-yaml@~3.10.0:
   version "3.10.0"
   version "3.10.0"
   resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc"
   resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc"
@@ -6078,7 +6099,7 @@ lodash@^4.0.0, lodash@^4.14.0, lodash@^4.17.2, lodash@^4.17.4, lodash@~4.17.4:
   version "4.17.4"
   version "4.17.4"
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
 
 
-lodash@^4.15.0, lodash@^4.2.0, lodash@^4.3.0:
+lodash@^4.15.0, lodash@^4.2.0:
   version "4.17.5"
   version "4.17.5"
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511"
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511"
 
 
@@ -7420,6 +7441,12 @@ parallel-transform@^1.1.0:
     inherits "^2.0.3"
     inherits "^2.0.3"
     readable-stream "^2.1.5"
     readable-stream "^2.1.5"
 
 
+parent-module@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.0.tgz#df250bdc5391f4a085fb589dad761f5ad6b865b5"
+  dependencies:
+    callsites "^3.0.0"
+
 parse-asn1@^5.0.0:
 parse-asn1@^5.0.0:
   version "5.1.0"
   version "5.1.0"
   resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.0.tgz#37c4f9b7ed3ab65c74817b5f2480937fbf97c712"
   resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.0.tgz#37c4f9b7ed3ab65c74817b5f2480937fbf97c712"
@@ -7724,10 +7751,6 @@ platform@1.3.5:
   version "1.3.5"
   version "1.3.5"
   resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.5.tgz#fb6958c696e07e2918d2eeda0f0bc9448d733444"
   resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.5.tgz#fb6958c696e07e2918d2eeda0f0bc9448d733444"
 
 
-pluralize@^7.0.0:
-  version "7.0.0"
-  resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777"
-
 popper.js@^1.14.4:
 popper.js@^1.14.4:
   version "1.14.7"
   version "1.14.7"
   resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.7.tgz#e31ec06cfac6a97a53280c3e55e4e0c860e7738e"
   resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.7.tgz#e31ec06cfac6a97a53280c3e55e4e0c860e7738e"
@@ -8752,15 +8775,9 @@ regexp-clone@0.0.1:
   version "0.0.1"
   version "0.0.1"
   resolved "https://registry.yarnpkg.com/regexp-clone/-/regexp-clone-0.0.1.tgz#a7c2e09891fdbf38fbb10d376fb73003e68ac589"
   resolved "https://registry.yarnpkg.com/regexp-clone/-/regexp-clone-0.0.1.tgz#a7c2e09891fdbf38fbb10d376fb73003e68ac589"
 
 
-regexp.prototype.flags@^1.2.0:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz#6b30724e306a27833eeb171b66ac8890ba37e41c"
-  dependencies:
-    define-properties "^1.1.2"
-
-regexpp@^1.1.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-1.1.0.tgz#0e3516dd0b7904f413d2d4193dce4618c3a689ab"
+regexpp@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f"
 
 
 regexpu-core@^1.0.0:
 regexpu-core@^1.0.0:
   version "1.0.0"
   version "1.0.0"
@@ -8980,13 +8997,6 @@ require-package-name@^2.0.1:
   version "2.0.1"
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/require-package-name/-/require-package-name-2.0.1.tgz#c11e97276b65b8e2923f75dabf5fb2ef0c3841b9"
   resolved "https://registry.yarnpkg.com/require-package-name/-/require-package-name-2.0.1.tgz#c11e97276b65b8e2923f75dabf5fb2ef0c3841b9"
 
 
-require-uncached@^1.0.3:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3"
-  dependencies:
-    caller-path "^0.1.0"
-    resolve-from "^1.0.0"
-
 require_optional@^1.0.1, require_optional@~1.0.0:
 require_optional@^1.0.1, require_optional@~1.0.0:
   version "1.0.1"
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/require_optional/-/require_optional-1.0.1.tgz#4cf35a4247f64ca3df8c2ef208cc494b1ca8fc2e"
   resolved "https://registry.yarnpkg.com/require_optional/-/require_optional-1.0.1.tgz#4cf35a4247f64ca3df8c2ef208cc494b1ca8fc2e"
@@ -9011,10 +9021,6 @@ resolve-dir@^1.0.0, resolve-dir@^1.0.1:
     expand-tilde "^2.0.0"
     expand-tilde "^2.0.0"
     global-modules "^1.0.0"
     global-modules "^1.0.0"
 
 
-resolve-from@^1.0.0:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226"
-
 resolve-from@^2.0.0:
 resolve-from@^2.0.0:
   version "2.0.0"
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57"
   resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57"
@@ -9085,6 +9091,12 @@ rimraf@2, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2:
   dependencies:
   dependencies:
     glob "^7.0.5"
     glob "^7.0.5"
 
 
+rimraf@2.6.3:
+  version "2.6.3"
+  resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
+  dependencies:
+    glob "^7.1.3"
+
 rimraf@~2.4.0:
 rimraf@~2.4.0:
   version "2.4.5"
   version "2.4.5"
   resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.4.5.tgz#ee710ce5d93a8fdb856fb5ea8ff0e2d75934b2da"
   resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.4.5.tgz#ee710ce5d93a8fdb856fb5ea8ff0e2d75934b2da"
@@ -9122,18 +9134,18 @@ rx@4.1.0:
   version "4.1.0"
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782"
   resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782"
 
 
-rxjs@^5.5.2:
-  version "5.5.11"
-  resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.11.tgz#f733027ca43e3bec6b994473be4ab98ad43ced87"
-  dependencies:
-    symbol-observable "1.0.1"
-
 rxjs@^5.5.6:
 rxjs@^5.5.6:
   version "5.5.12"
   version "5.5.12"
   resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.12.tgz#6fa61b8a77c3d793dbaf270bee2f43f652d741cc"
   resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.12.tgz#6fa61b8a77c3d793dbaf270bee2f43f652d741cc"
   dependencies:
   dependencies:
     symbol-observable "1.0.1"
     symbol-observable "1.0.1"
 
 
+rxjs@^6.4.0:
+  version "6.4.0"
+  resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.4.0.tgz#f3bb0fe7bda7fb69deac0c16f17b50b0b8790504"
+  dependencies:
+    tslib "^1.9.0"
+
 safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
 safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
   version "5.1.1"
   version "5.1.1"
   resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
   resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
@@ -9241,6 +9253,10 @@ semver@^5.5.0:
   version "5.5.0"
   version "5.5.0"
   resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
   resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
 
 
+semver@^5.5.1:
+  version "5.6.0"
+  resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
+
 semver@~5.3.0:
 semver@~5.3.0:
   version "5.3.0"
   version "5.3.0"
   resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
   resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
@@ -9441,6 +9457,14 @@ slice-ansi@1.0.0:
   dependencies:
   dependencies:
     is-fullwidth-code-point "^2.0.0"
     is-fullwidth-code-point "^2.0.0"
 
 
+slice-ansi@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636"
+  dependencies:
+    ansi-styles "^3.2.0"
+    astral-regex "^1.0.0"
+    is-fullwidth-code-point "^2.0.0"
+
 sliced@1.0.1:
 sliced@1.0.1:
   version "1.0.1"
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/sliced/-/sliced-1.0.1.tgz#0b3a662b5d04c3177b1926bea82b03f837a2ef41"
   resolved "https://registry.yarnpkg.com/sliced/-/sliced-1.0.1.tgz#0b3a662b5d04c3177b1926bea82b03f837a2ef41"
@@ -9818,16 +9842,6 @@ string-width@^3.0.0:
     is-fullwidth-code-point "^2.0.0"
     is-fullwidth-code-point "^2.0.0"
     strip-ansi "^5.0.0"
     strip-ansi "^5.0.0"
 
 
-string.prototype.matchall@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-2.0.0.tgz#2af8fe3d2d6dc53ca2a59bd376b089c3c152b3c8"
-  dependencies:
-    define-properties "^1.1.2"
-    es-abstract "^1.10.0"
-    function-bind "^1.1.1"
-    has-symbols "^1.0.0"
-    regexp.prototype.flags "^1.2.0"
-
 string.prototype.padend@^3.0.0:
 string.prototype.padend@^3.0.0:
   version "3.0.0"
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/string.prototype.padend/-/string.prototype.padend-3.0.0.tgz#f3aaef7c1719f170c5eab1c32bf780d96e21f2f0"
   resolved "https://registry.yarnpkg.com/string.prototype.padend/-/string.prototype.padend-3.0.0.tgz#f3aaef7c1719f170c5eab1c32bf780d96e21f2f0"
@@ -10106,7 +10120,7 @@ symbol-observable@1.0.1:
   version "1.0.1"
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4"
   resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4"
 
 
-table@^4.0.1, table@^4.0.3:
+table@^4.0.1:
   version "4.0.3"
   version "4.0.3"
   resolved "https://registry.yarnpkg.com/table/-/table-4.0.3.tgz#00b5e2b602f1794b9acaf9ca908a76386a7813bc"
   resolved "https://registry.yarnpkg.com/table/-/table-4.0.3.tgz#00b5e2b602f1794b9acaf9ca908a76386a7813bc"
   dependencies:
   dependencies:
@@ -10117,6 +10131,15 @@ table@^4.0.1, table@^4.0.3:
     slice-ansi "1.0.0"
     slice-ansi "1.0.0"
     string-width "^2.1.1"
     string-width "^2.1.1"
 
 
+table@^5.2.3:
+  version "5.2.3"
+  resolved "https://registry.yarnpkg.com/table/-/table-5.2.3.tgz#cde0cc6eb06751c009efab27e8c820ca5b67b7f2"
+  dependencies:
+    ajv "^6.9.1"
+    lodash "^4.17.11"
+    slice-ansi "^2.1.0"
+    string-width "^3.0.0"
+
 tapable@^1.0.0:
 tapable@^1.0.0:
   version "1.0.0"
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.0.0.tgz#cbb639d9002eed9c6b5975eb20598d7936f1f9f2"
   resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.0.0.tgz#cbb639d9002eed9c6b5975eb20598d7936f1f9f2"
@@ -10966,6 +10989,12 @@ write-file-atomic@^2.0.0:
     imurmurhash "^0.1.4"
     imurmurhash "^0.1.4"
     signal-exit "^3.0.2"
     signal-exit "^3.0.2"
 
 
+write@1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3"
+  dependencies:
+    mkdirp "^0.5.1"
+
 write@^0.2.1:
 write@^0.2.1:
   version "0.2.1"
   version "0.2.1"
   resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757"
   resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757"