├── CHANGELOG.md ├── postcss.config.js ├── .babelrc ├── prettier.config.js ├── src ├── App.scss ├── modules │ └── app.module │ │ ├── fields.json │ │ ├── meta.json │ │ └── module.html ├── components │ ├── SpinningLogo.js │ ├── SpinningLogo.scss │ ├── ErrorBoundary.js │ ├── Card.js │ └── Card.scss ├── index.scss ├── index.js ├── images │ ├── sprocket.svg │ └── logo.svg └── App.js ├── .github └── workflows │ └── .lint-build.yml ├── .gitignore ├── LICENSE ├── package.json ├── webpack.config.js ├── README.md └── .eslintrc.js /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | Change Log 2 | ========== 3 | 4 | ## 0.0.10 5 | 6 | Initial version 7 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | autoprefixer: {}, 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | "useBuiltIns": "usage", 7 | "corejs": 3.6 8 | } 9 | ], 10 | "@babel/preset-react" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /prettier.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | bracketSpacing: true, 3 | bracketSameLine: false, 4 | printWidth: 80, 5 | proseWrap: 'never', 6 | semi: true, 7 | singleQuote: true, 8 | tabWidth: 2, 9 | trailingComma: 'all', 10 | useTabs: false, 11 | }; 12 | -------------------------------------------------------------------------------- /src/App.scss: -------------------------------------------------------------------------------- 1 | .cms-react-boilerplate__container { 2 | text-align: center; 3 | background-color: #282c34; 4 | display: flex; 5 | flex-direction: column; 6 | align-items: center; 7 | justify-content: center; 8 | font-size: calc(10px + 2vmin); 9 | color: white; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/app.module/fields.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "default": 0, 4 | "min": 0, 5 | "max": 100, 6 | "display": "slider", 7 | "label": "Starting number of reasons", 8 | "locked": false, 9 | "name": "initial_count", 10 | "required": false, 11 | "type": "number" 12 | } 13 | ] 14 | -------------------------------------------------------------------------------- /src/components/SpinningLogo.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './SpinningLogo.scss'; 3 | 4 | function SpinningLogo({ src, alt, isSprocket = false }) { 5 | const classNames = `spinning-logo ${ 6 | isSprocket ? 'spinning-logo--sprocket' : '' 7 | }`; 8 | return {alt}; 9 | } 10 | 11 | export default SpinningLogo; 12 | -------------------------------------------------------------------------------- /src/modules/app.module/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "css_assets": [], 3 | "external_js": [], 4 | "global": false, 5 | "help_text": "", 6 | "host_template_types": ["PAGE"], 7 | "icon": "react", 8 | "js_assets": [], 9 | "label": "React app boilerplate", 10 | "other_assets": [], 11 | "smart_type": "NOT_SMART", 12 | "tags": [], 13 | "is_available_for_new_content": true 14 | } 15 | -------------------------------------------------------------------------------- /src/modules/app.module/module.html: -------------------------------------------------------------------------------- 1 | {{ require_css(get_asset_url('../../main.css')) }} 2 | {{ require_js(get_asset_url('../../main.js'), 'footer') }} 3 | {%- set instance_id = name %} 4 | 5 |
6 | 11 | 12 |
13 |
14 | -------------------------------------------------------------------------------- /src/index.scss: -------------------------------------------------------------------------------- 1 | .cms-react-boilerplate { 2 | margin: 0; 3 | padding: 0; 4 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 5 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 6 | sans-serif; 7 | -webkit-font-smoothing: antialiased; 8 | -moz-osx-font-smoothing: grayscale; 9 | code { 10 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 11 | monospace; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /.github/workflows/.lint-build.yml: -------------------------------------------------------------------------------- 1 | on: [push] 2 | 3 | jobs: 4 | lint-build: 5 | runs-on: ubuntu-latest 6 | 7 | steps: 8 | - name: Check out repo 9 | uses: actions/checkout@v2 10 | - name: Use Node.js 11 | uses: actions/setup-node@v1 12 | with: 13 | node-version: 16.x 14 | - name: Install deps 15 | run: | 16 | yarn install 17 | - name: Lint and build project into dist 18 | run: | 19 | yarn lint 20 | yarn build 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | config.json 6 | /.pnp 7 | .pnp.js 8 | 9 | # testing 10 | /coverage 11 | 12 | # production 13 | /dist 14 | 15 | # misc 16 | .DS_Store 17 | .env.local 18 | .env.development.local 19 | .env.test.local 20 | .env.production.local 21 | 22 | # vscode settings 23 | /.vscode/settings.json 24 | 25 | npm-debug.log* 26 | yarn-debug.log* 27 | yarn-error.log* 28 | 29 | hubspot.config.yml 30 | hubspot.config.yaml 31 | -------------------------------------------------------------------------------- /src/components/SpinningLogo.scss: -------------------------------------------------------------------------------- 1 | .spinning-logo__container { 2 | flex-direction: row; 3 | .spinning-logo { 4 | animation: spinning-logo infinite 20s linear; 5 | height: 300px; 6 | &:nth-child(even) { 7 | animation-direction: reverse; 8 | } 9 | } 10 | .spinning-logo--sprocket { 11 | transform-origin: 64.8% 55.4%; 12 | left: -130px; 13 | position: relative; 14 | 15 | } 16 | } 17 | @keyframes spinning-logo { 18 | from { 19 | transform: rotate(0deg); 20 | } 21 | to { 22 | transform: rotate(360deg); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2019 HubSpot, Inc. 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | -------------------------------------------------------------------------------- /src/components/ErrorBoundary.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | export default class ErrorBoundary extends Component { 4 | constructor(props) { 5 | super(props); 6 | this.state = { hasError: false }; 7 | } 8 | 9 | static getDerivedStateFromError() { 10 | return { hasError: true }; 11 | } 12 | 13 | componentDidCatch(error, errorInfo) { 14 | console.error(error, errorInfo); // eslint-disable-line no-console 15 | } 16 | 17 | render() { 18 | if (this.state.hasError) { 19 | // You can render any custom fallback UI 20 | return

Something went wrong.

; 21 | } 22 | 23 | return this.props.children; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/components/Card.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import './Card.scss'; 3 | 4 | function Card({ initialClickCount }) { 5 | const [clickCount, setClickCount] = useState(initialClickCount); 6 | const pluralize = (n, noun, suffix) => 7 | `${n !== 1 ? 'are' : 'is'} ${n} ${noun + (n !== 1 ? suffix : '')}`; 8 | 9 | return ( 10 |
11 |

12 | {`There ${ 13 | clickCount > 0 14 | ? pluralize(clickCount, 'reason', 's') 15 | : 'are so many reasons' 16 | } to use HubSpot CMS + React!`} 17 |

18 | 21 |
22 | ); 23 | } 24 | 25 | export default Card; 26 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import 'core-js/stable'; 2 | import 'regenerator-runtime/runtime'; 3 | import React from 'react'; 4 | import ReactDOM from 'react-dom'; 5 | import './index.scss'; 6 | import App from './App'; 7 | import ErrorBoundary from './components/ErrorBoundary'; 8 | 9 | const targetModulesData = document.querySelectorAll( 10 | '.cms-react-boilerplate > script[type="application/json"]', 11 | ); 12 | targetModulesData.forEach(({ dataset, textContent }) => { 13 | const root = document.getElementById(`App--${dataset.moduleInstance}`); 14 | return ReactDOM.render( 15 | 16 | 21 | , 22 | root, 23 | ); 24 | }); 25 | -------------------------------------------------------------------------------- /src/components/Card.scss: -------------------------------------------------------------------------------- 1 | .cms-react-boilerplate__card { 2 | max-width: 500px; 3 | margin-bottom: 40px; 4 | padding: 0.5em 1em; 5 | background-color: rgba(255, 255, 255, 0.1); 6 | border-radius: 6px; 7 | .btn { 8 | border: 1px solid #ff7a59; 9 | background-color: #ff7a59; 10 | border-radius: 3px; 11 | color: #ffffff; 12 | font-size: 1rem; 13 | padding: 11px 24px; 14 | text-align: center; 15 | user-select: none; 16 | transition: all 0.15s ease-out; 17 | display: inline-block; 18 | max-width: 100%; 19 | overflow: hidden; 20 | text-overflow: ellipsis; 21 | vertical-align: middle; 22 | white-space: nowrap; 23 | &:hover { 24 | background-color: #ff8f73; 25 | border-color: #ff8f73; 26 | color: #ffffff; 27 | cursor: pointer; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/images/sprocket.svg: -------------------------------------------------------------------------------- 1 | sprocket-web-color_sprocket-black-web -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './App.scss'; 3 | import SpinningLogo from './components/SpinningLogo'; 4 | import Card from './components/Card'; 5 | import reactLogo from './images/logo.svg'; 6 | import sprocketLogo from './images/sprocket.svg'; 7 | 8 | function App({ moduleData }) { 9 | // eslint-disable-next-line no-console 10 | console.log( 11 | 'all of your data typically accessed via the "module" keyword in HubL is available as JSON here!', 12 | moduleData, 13 | ); 14 | return ( 15 |
16 |
17 | 18 | 23 |
24 |

25 | Edit src/App.js and save to reload. 26 |

27 | 28 |
29 | ); 30 | } 31 | 32 | export default App; 33 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cms-react-boilerplate", 3 | "version": "0.5.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "webpack --watch --env autoupload --mode production", 8 | "build": "rm -Rf dist && webpack --mode production", 9 | "deploy": "rm -Rf dist && webpack --mode production && hs upload dist cms-react-boilerplate", 10 | "lint": "eslint src && prettier --list-different 'src/**/*.js' 'src/**/*.json'", 11 | "prettier:write": "prettier --write 'src/**/*.js' 'src/**/*.json'" 12 | }, 13 | "author": "", 14 | "license": "Apache-2.0", 15 | "devDependencies": { 16 | "@babel/core": "^7.17.5", 17 | "@babel/preset-env": "^7.16.11", 18 | "@babel/preset-react": "^7.16.7", 19 | "@hubspot/cli": "^4.0.0", 20 | "@hubspot/webpack-cms-plugins": "^4.0.0", 21 | "autoprefixer": "^10.4.7", 22 | "babel-eslint": "^10.0.3", 23 | "babel-loader": "^8.0.6", 24 | "copy-webpack-plugin": "^11.0.0", 25 | "core-js": "^3.6.5", 26 | "css-loader": "^6.7.1", 27 | "eslint": "^6.5.1", 28 | "eslint-plugin-import": "^2.18.2", 29 | "eslint-plugin-react": "^7.29.2", 30 | "eslint-plugin-react-hooks": "^4.2.0", 31 | "mini-css-extract-plugin": "^2.6.0", 32 | "postcss-loader": "^7.0.0", 33 | "prettier": "^2.6.2", 34 | "sass": "^1.52.1", 35 | "sass-loader": "^13.0.0", 36 | "style-loader": "^3.3.1", 37 | "url-loader": "^4.1.1", 38 | "webpack": "^5.72.1", 39 | "webpack-cli": "^4.9.2" 40 | }, 41 | "dependencies": { 42 | "postcss": "^8.4.14", 43 | "react": "^17.0.2", 44 | "react-dom": "^17.0.2", 45 | "regenerator-runtime": "^0.13.3" 46 | }, 47 | "browserslist": { 48 | "production": [ 49 | ">0.2%", 50 | "last 2 versions", 51 | "not dead", 52 | "not op_mini all" 53 | ], 54 | "development": [ 55 | "last 1 chrome version", 56 | "last 1 firefox version", 57 | "last 1 safari version" 58 | ] 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const CopyWebpackPlugin = require('copy-webpack-plugin'); 2 | const HubSpotAutoUploadPlugin = require('@hubspot/webpack-cms-plugins/HubSpotAutoUploadPlugin'); 3 | const MiniCssExtractPlugin = require('mini-css-extract-plugin'); 4 | const path = require('path'); 5 | const autoprefixer = require('autoprefixer'); 6 | 7 | 8 | const hubspotConfig = ({ portal, autoupload } = {}) => { 9 | return { 10 | target: 'web', 11 | entry: { 12 | main: './src/index.js', 13 | }, 14 | output: { 15 | path: path.resolve(__dirname, 'dist'), 16 | filename: '[name].js', 17 | }, 18 | optimization: { 19 | minimize: false, 20 | }, 21 | module: { 22 | rules: [ 23 | { 24 | test: /\.js$/, 25 | exclude: /node_modules/, 26 | use: { 27 | loader: 'babel-loader', 28 | }, 29 | }, 30 | { 31 | test: /\.s[ac]ss$/i, 32 | use: [ 33 | MiniCssExtractPlugin.loader, 34 | { loader: 'css-loader', options: { url: false } }, 35 | { 36 | loader: 'postcss-loader', 37 | }, 38 | 'sass-loader', 39 | ], 40 | }, 41 | { 42 | test: /\.(svg)$/, 43 | use: [ 44 | { 45 | loader: 'url-loader', 46 | }, 47 | ], 48 | }, 49 | ], 50 | }, 51 | plugins: [ 52 | new HubSpotAutoUploadPlugin({ 53 | portal, 54 | autoupload, 55 | src: 'dist', 56 | dest: 'cms-react-boilerplate', 57 | }), 58 | new MiniCssExtractPlugin({ 59 | filename: '[name].css', 60 | }), 61 | new CopyWebpackPlugin({ 62 | patterns: [ 63 | { from: 'src/images', to: 'images' }, 64 | { 65 | from: 'src/modules', 66 | to: 'modules', 67 | }, 68 | ], 69 | }), 70 | ], 71 | }; 72 | }; 73 | 74 | module.exports = [hubspotConfig]; 75 | -------------------------------------------------------------------------------- /src/images/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cms-react-boilerplate [beta] 2 | 3 | Boilerplate [React](https://reactjs.org/) project for creating apps using modules on the HubSpot CMS. 4 | 5 | ## *NOTE:* 6 | 7 | The `cms-react-boilerplate` legacy repository is a starting place for building and running a SPA (single page application) style React App on a HubSpot page. The React build itself is not directly connected to HubSpot. 8 | 9 | Recently HubSpot has released "CMS JS Building Blocks" for general availability. Read documentation and [view examples here](https://github.com/HubSpot/cms-js-building-block-examples). The "building blocks" feature directly integrates React on the server and the client with HubSpot and enables building HubSpot modules in React. Further, it builds on the [HubSpot Developer Projects](https://developers.hubspot.com/docs/platform/create-a-project) system which provides CI/CD build and deploy functionality. 10 | 11 | ## Getting Started 12 | 13 | For more information on local development tools, see [Local Development Tooling: Getting Started](https://designers.hubspot.com/docs/tools/local-development) 14 | 15 | ### Configuration 16 | 17 | #### Set up HubSpot CMS CLI ([`@hubspot/cli`](https://www.npmjs.com/package/@hubspot/cli)) 18 | - A config file named `hubspot.config.yml` will also be needed. The config can be at the project level or higher up in the directory tree. 19 | - Be sure to set a `defaultPortal` in your `hubspot.config.yml` to which you'd like the built app files to sync. 20 | 21 | ### Install 22 | - Run `npm install` or `yarn install` to install needed dependencies. 23 | 24 | ### Running 25 | - Run `npm start` or `yarn start` to automatically upload your project to `defaultPortal`. 26 | - Create a page from default theme, or any drag-and-drop (`dnd_area`) enabled template in your portal, and add the `app (label: React app boilerplate)` module. 27 | 28 | ### package.json scripts 29 | - `start` : Builds project with webpack, uploads to your `defaultPortal` specified in `hubspot.config.yml` and watches for changes via [`@hubspot/webpack-cms-plugins/HubSpotAutoUploadPlugin`](https://www.npmjs.com/package/@hubspot/webpack-cms-plugins). 30 | - `build` : Clears `/dist` contents and builds project into `/dist`. 31 | - `deploy` : Clears `/dist` contents, builds project into `/dist`, and uploads to via [`@hubspot/cli`](https://www.npmjs.com/package/@hubspot/cli). 32 | - `lint` : Lints CSS, JS, and JSON files via `eslint` ([documentation](https://eslint.org/docs/user-guide/configuring)) and checks for formatting via `prettier`([documentation](https://prettier.io/docs/en/configuration.html)) in `src`. 33 | - For configs, see `prettier.config.js` and `eslintrc.js`. 34 | - `prettier:write` : Formats JS and JSON files in `src`. 35 | - For configs, see `prettier.config.js`. 36 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | 4 | parser: 'babel-eslint', 5 | 6 | plugins: ['import', 'react', 'react-hooks'], 7 | 8 | env: { 9 | browser: true, 10 | commonjs: true, 11 | es6: true, 12 | jest: true, 13 | node: true, 14 | }, 15 | 16 | parserOptions: { 17 | ecmaVersion: 2018, 18 | sourceType: 'module', 19 | ecmaFeatures: { 20 | jsx: true, 21 | }, 22 | }, 23 | 24 | settings: { 25 | react: { 26 | version: 'detect', 27 | }, 28 | }, 29 | 30 | rules: { 31 | 'accessor-pairs': 'off', 32 | 'array-bracket-newline': 'off', 33 | 'array-bracket-spacing': 'off', 34 | 'array-callback-return': 'off', 35 | 'array-element-newline': 'off', 36 | 'arrow-body-style': 'off', 37 | 'arrow-parens': 'off', 38 | 'arrow-spacing': 'off', 39 | 'block-scoped-var': 'off', 40 | 'block-spacing': 'off', 41 | 'brace-style': 'off', 42 | 'callback-return': 'off', 43 | camelcase: 'off', 44 | 'capitalized-comments': 'off', 45 | 'class-methods-use-this': 'off', 46 | 'comma-dangle': 'off', 47 | 'comma-spacing': 'off', 48 | 'comma-style': 'off', 49 | complexity: 'off', 50 | 'computed-property-spacing': 'off', 51 | 'consistent-return': 'off', 52 | 'consistent-this': 'off', 53 | 'constructor-super': 'error', 54 | curly: 'off', 55 | 'default-case': 'off', 56 | 'dot-location': 'off', 57 | 'dot-notation': 'off', 58 | 'eol-last': 'off', 59 | eqeqeq: 'off', 60 | 'for-direction': 'off', 61 | 'func-call-spacing': 'off', 62 | 'func-name-matching': 'off', 63 | 'func-names': 'off', 64 | 'func-style': 'off', 65 | 'function-paren-newline': 'off', 66 | 'generator-star': 'off', 67 | 'generator-star-spacing': 'off', 68 | 'getter-return': 'off', 69 | 'global-require': 'off', 70 | 'guard-for-in': 'off', 71 | 'handle-callback-err': 'off', 72 | 'id-blacklist': 'off', 73 | 'id-length': 'off', 74 | 'id-match': 'off', 75 | 'implicit-arrow-linebreak': 'off', 76 | indent: 'off', 77 | 'indent-legacy': 'off', 78 | 'init-declarations': 'off', 79 | 'jsx-quotes': 'off', 80 | 'key-spacing': 'off', 81 | 'keyword-spacing': 'off', 82 | 'line-comment-position': 'off', 83 | 'linebreak-style': 'off', 84 | 'lines-around-comment': 'off', 85 | 'lines-around-directive': 'off', 86 | 'lines-between-class-members': 'off', 87 | 'max-depth': 'off', 88 | 'max-len': 'off', 89 | 'max-lines': 'off', 90 | 'max-nested-callbacks': 'off', 91 | 'max-params': 'off', 92 | 'max-statements': 'off', 93 | 'max-statements-per-line': 'off', 94 | 'multiline-comment-style': 'off', 95 | 'multiline-ternary': 'off', 96 | 'new-cap': 'off', 97 | 'new-parens': 'off', 98 | 'newline-after-var': 'off', 99 | 'newline-before-return': 'off', 100 | 'newline-per-chained-call': 'off', 101 | 'no-alert': 'off', 102 | 'no-array-constructor': 'off', 103 | 'no-arrow-condition': 'off', 104 | 'no-await-in-loop': 'off', 105 | 'no-bitwise': 'off', 106 | 'no-buffer-constructor': 'off', 107 | 'no-caller': 'off', 108 | 'no-case-declarations': 'error', 109 | 'no-catch-shadow': 'off', 110 | 'no-class-assign': 'error', 111 | 'no-comma-dangle': 'off', 112 | 'no-compare-neg-zero': 'error', 113 | 'no-cond-assign': 'error', 114 | 'no-confusing-arrow': 'off', 115 | 'no-confusing-arrow': 0, 116 | 'no-console': 'warn', 117 | 'no-const-assign': 'error', 118 | 'no-constant-condition': 'error', 119 | 'no-continue': 'off', 120 | 'no-control-regex': 'error', 121 | 'no-debugger': 'error', 122 | 'no-delete-var': 'error', 123 | 'no-div-regex': 'off', 124 | 'no-dupe-args': 'error', 125 | 'no-dupe-class-members': 'error', 126 | 'no-dupe-keys': 'error', 127 | 'no-duplicate-case': 'error', 128 | 'no-duplicate-imports': 'off', 129 | 'no-else-return': 'off', 130 | 'no-empty': 'error', 131 | 'no-empty-character-class': 'error', 132 | 'no-empty-function': 'off', 133 | 'no-empty-pattern': 'error', 134 | 'no-eq-null': 'off', 135 | 'no-eval': 'off', 136 | 'no-ex-assign': 'error', 137 | 'no-extend-native': 'off', 138 | 'no-extra-bind': 'off', 139 | 'no-extra-boolean-cast': 'error', 140 | 'no-extra-label': 'off', 141 | 'no-extra-parens': 'off', 142 | 'no-extra-parens': 'off', 143 | 'no-extra-semi': 'error', 144 | 'no-extra-semi': 'off', 145 | 'no-fallthrough': 'error', 146 | 'no-floating-decimal': 'off', 147 | 'no-floating-decimal': 'off', 148 | 'no-func-assign': 'error', 149 | 'no-global-assign': 'error', 150 | 'no-implicit-coercion': 'off', 151 | 'no-implicit-globals': 'off', 152 | 'no-implied-eval': 'off', 153 | 'no-inline-comments': 'off', 154 | 'no-inner-declarations': 'error', 155 | 'no-invalid-regexp': 'error', 156 | 'no-invalid-this': 'off', 157 | 'no-irregular-whitespace': 'error', 158 | 'no-iterator': 'off', 159 | 'no-label-var': 'off', 160 | 'no-labels': 'off', 161 | 'no-lone-blocks': 'off', 162 | 'no-lonely-if': 'off', 163 | 'no-loop-func': 'off', 164 | 'no-magic-numbers': 'off', 165 | 'no-mixed-operators': 'off', 166 | 'no-mixed-operators': 0, 167 | 'no-mixed-requires': 'off', 168 | 'no-mixed-spaces-and-tabs': 'error', 169 | 'no-mixed-spaces-and-tabs': 'off', 170 | 'no-multi-assign': 'off', 171 | 'no-multi-spaces': 'off', 172 | 'no-multi-spaces': 'off', 173 | 'no-multi-str': 'off', 174 | 'no-multiple-empty-lines': 'off', 175 | 'no-multiple-empty-lines': 'off', 176 | 'no-native-reassign': 'off', 177 | 'no-negated-condition': 'off', 178 | 'no-negated-in-lhs': 'off', 179 | 'no-nested-ternary': 'off', 180 | 'no-new': 'off', 181 | 'no-new-func': 'off', 182 | 'no-new-object': 'off', 183 | 'no-new-require': 'off', 184 | 'no-new-symbol': 'error', 185 | 'no-new-wrappers': 'off', 186 | 'no-obj-calls': 'error', 187 | 'no-octal': 'error', 188 | 'no-octal-escape': 'off', 189 | 'no-param-reassign': 'off', 190 | 'no-path-concat': 'off', 191 | 'no-plusplus': 'off', 192 | 'no-process-env': 'off', 193 | 'no-process-exit': 'off', 194 | 'no-proto': 'off', 195 | 'no-prototype-builtins': 'off', 196 | 'no-redeclare': 'error', 197 | 'no-regex-spaces': 'error', 198 | 'no-reserved-keys': 'off', 199 | 'no-restricted-globals': 'off', 200 | 'no-restricted-imports': 'off', 201 | 'no-restricted-modules': 'off', 202 | 'no-restricted-properties': 'off', 203 | 'no-restricted-syntax': 'off', 204 | 'no-return-assign': 'off', 205 | 'no-return-await': 'off', 206 | 'no-script-url': 'off', 207 | 'no-self-assign': 'error', 208 | 'no-self-compare': 'off', 209 | 'no-sequences': 'off', 210 | 'no-shadow': 'off', 211 | 'no-shadow-restricted-names': 'off', 212 | 'no-space-before-semi': 'off', 213 | 'no-spaced-func': 'off', 214 | 'no-sparse-arrays': 'error', 215 | 'no-sync': 'off', 216 | 'no-tabs': 'off', 217 | 'no-template-curly-in-string': 'off', 218 | 'no-ternary': 'off', 219 | 'no-this-before-super': 'error', 220 | 'no-throw-literal': 'off', 221 | 'no-trailing-spaces': 'off', 222 | 'no-undef': 'error', 223 | 'no-undef-init': 'off', 224 | 'no-undefined': 'off', 225 | 'no-underscore-dangle': 'off', 226 | 'no-unexpected-multiline': 'error', 227 | 'no-unexpected-multiline': 0, 228 | 'no-unmodified-loop-condition': 'off', 229 | 'no-unneeded-ternary': 'off', 230 | 'no-unreachable': 'error', 231 | 'no-unsafe-finally': 'error', 232 | 'no-unsafe-negation': 'error', 233 | 'no-unused-expressions': 'off', 234 | 'no-unused-labels': 'error', 235 | 'no-unused-vars': 'error', 236 | 'no-use-before-define': 'off', 237 | 'no-useless-call': 'off', 238 | 'no-useless-computed-key': 'off', 239 | 'no-useless-concat': 'off', 240 | 'no-useless-constructor': 'off', 241 | 'no-useless-escape': 'error', 242 | 'no-useless-rename': 'off', 243 | 'no-useless-return': 'off', 244 | 'no-var': 'off', 245 | 'no-void': 'off', 246 | 'no-warning-comments': 'off', 247 | 'no-whitespace-before-property': 'off', 248 | 'no-with': 'off', 249 | 'no-wrap-func': 'off', 250 | 'nonblock-statement-body-position': 'off', 251 | 'object-curly-newline': 'off', 252 | 'object-curly-spacing': 'off', 253 | 'object-property-newline': 'off', 254 | 'object-shorthand': 'off', 255 | 'one-var': 'off', 256 | 'one-var-declaration-per-line': 'off', 257 | 'operator-assignment': 'off', 258 | 'operator-linebreak': 'off', 259 | 'padded-blocks': 'off', 260 | 'padding-line-between-statements': 'off', 261 | 'prefer-arrow-callback': 'off', 262 | 'prefer-const': 'off', 263 | 'prefer-destructuring': 'off', 264 | 'prefer-numeric-literals': 'off', 265 | 'prefer-promise-reject-errors': 'off', 266 | 'prefer-reflect': 'off', 267 | 'prefer-rest-params': 'off', 268 | 'prefer-spread': 'off', 269 | 'prefer-template': 'off', 270 | 'quote-props': 'off', 271 | quotes: 'off', 272 | radix: 'off', 273 | 'require-await': 'off', 274 | 'require-jsdoc': 'off', 275 | 'require-yield': 'error', 276 | 'rest-spread-spacing': 'off', 277 | semi: 'off', 278 | 'semi-spacing': 'off', 279 | 'semi-style': 'off', 280 | 'sort-imports': 'off', 281 | 'sort-keys': 'off', 282 | 'sort-vars': 'off', 283 | 'space-after-function-name': 'off', 284 | 'space-after-keywords': 'off', 285 | 'space-before-blocks': 'off', 286 | 'space-before-function-paren': 'off', 287 | 'space-before-function-parentheses': 'off', 288 | 'space-before-keywords': 'off', 289 | 'space-in-brackets': 'off', 290 | 'space-in-parens': 'off', 291 | 'space-infix-ops': 'off', 292 | 'space-return-throw-case': 'off', 293 | 'space-unary-ops': 'off', 294 | 'space-unary-word-ops': 'off', 295 | 'spaced-comment': 'off', 296 | strict: 'off', 297 | 'switch-colon-spacing': 'off', 298 | 'symbol-description': 'off', 299 | 'template-curly-spacing': 'off', 300 | 'template-tag-spacing': 'off', 301 | 'unicode-bom': 'off', 302 | 'use-isnan': 'error', 303 | 'valid-jsdoc': 'off', 304 | 'valid-typeof': 'error', 305 | 'vars-on-top': 'off', 306 | 'wrap-iife': 'off', 307 | 'wrap-regex': 'off', 308 | 'yield-star-spacing': 'off', 309 | yoda: 'off', 310 | 311 | // react rules 312 | 313 | 'react/forbid-foreign-prop-types': ['warn', { allowInPropTypes: true }], 314 | 'react/jsx-no-comment-textnodes': 'warn', 315 | 'react/jsx-no-duplicate-props': 'warn', 316 | 'react/jsx-no-target-blank': 'warn', 317 | 'react/jsx-no-undef': 'error', 318 | 'react/jsx-pascal-case': [ 319 | 'warn', 320 | { 321 | allowAllCaps: true, 322 | ignore: [], 323 | }, 324 | ], 325 | 'react/jsx-uses-react': 'warn', 326 | 'react/jsx-uses-vars': 'warn', 327 | 'react/no-danger-with-children': 'warn', 328 | // Disabled because of undesirable warnings 329 | // See https://github.com/facebook/create-react-app/issues/5204 for 330 | // blockers until its re-enabled 331 | // 'react/no-deprecated': 'warn', 332 | 'react/no-direct-mutation-state': 'warn', 333 | 'react/no-is-mounted': 'warn', 334 | 'react/no-typos': 'error', 335 | 'react/react-in-jsx-scope': 'error', 336 | 'react/require-render-return': 'error', 337 | 'react/style-prop-object': 'warn', 338 | 'react/no-direct-mutation-state': 'warn', 339 | 'react/no-is-mounted': 'warn', 340 | 'react/no-typos': 'error', 341 | 'react/react-in-jsx-scope': 'error', 342 | 'react/require-render-return': 'error', 343 | 'react/style-prop-object': 'warn', 344 | 'react-hooks/rules-of-hooks': 'error', 345 | }, 346 | }; 347 | 348 | 349 | --------------------------------------------------------------------------------