├── .gitignore ├── .eslintignore ├── src ├── assets │ ├── scss │ │ ├── app.scss │ │ └── partial │ │ │ └── reset.scss │ └── img │ │ └── welcome-page │ │ ├── github.svg │ │ ├── ts.svg │ │ ├── eslint.svg │ │ ├── tsx-logo.svg │ │ └── babel.svg ├── index.prod.tsx ├── Root.tsx ├── index.html ├── App.tsx ├── components │ └── Header │ │ ├── styles.scss │ │ └── index.tsx ├── index.dev.tsx └── screens │ └── Welcome │ ├── styles.scss │ └── index.tsx ├── .postcssrc.json ├── .prettierrc ├── types └── index.d.ts ├── tsconfig.json ├── .babelrc ├── webpack ├── prod.webpack.js └── common.webpack.js ├── .eslintrc ├── README.md └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | webpack -------------------------------------------------------------------------------- /src/assets/scss/app.scss: -------------------------------------------------------------------------------- 1 | @import "partial/reset.scss"; 2 | -------------------------------------------------------------------------------- /.postcssrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "map": false, 3 | "plugins": { 4 | "postcss-plugin": {} 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "parser": "typescript", 4 | "trailingComma": "none", 5 | "arrowParens": "avoid", 6 | "endOfLine": "auto" 7 | } 8 | -------------------------------------------------------------------------------- /src/index.prod.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import Root from './Root'; 4 | 5 | ReactDOM.render(, document.getElementById('root')); 6 | -------------------------------------------------------------------------------- /src/Root.tsx: -------------------------------------------------------------------------------- 1 | import React, { FunctionComponent } from 'react'; 2 | 3 | import App from './App'; 4 | import Welcome from './screens/Welcome'; 5 | 6 | const Root: FunctionComponent = () => ( 7 | 8 | 9 | 10 | ); 11 | 12 | export default Root; 13 | -------------------------------------------------------------------------------- /types/index.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/export */ 2 | declare module '*.scss' { 3 | const content: { [className: string]: string }; 4 | export default content; 5 | } 6 | 7 | declare module '*.css' { 8 | const css: any; 9 | export default css; 10 | } 11 | 12 | declare module 'react-hot-loader/patch'; 13 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | React Typescript Starter 10 | 11 | 12 | 13 |
14 | 15 | 16 | -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import React, { FunctionComponent, ReactNode } from 'react'; 2 | 3 | import s from './assets/scss/app.scss'; 4 | 5 | interface Props { 6 | children: ReactNode; 7 | } 8 | 9 | const App: FunctionComponent = ({ children }) => ( 10 |
11 |
{children}
12 |
13 | ); 14 | 15 | export default App; 16 | -------------------------------------------------------------------------------- /src/components/Header/styles.scss: -------------------------------------------------------------------------------- 1 | .header { 2 | padding: 20px; 3 | box-shadow: 0 1px 2px 0 rgba(212, 212, 212, 0.5); 4 | 5 | .container { 6 | display: flex; 7 | justify-content: space-between; 8 | align-items: center; 9 | } 10 | 11 | .title { 12 | font-size: 1.6em; 13 | } 14 | 15 | .githubLogo { 16 | display: block; 17 | width: 35px; 18 | height: 35px; 19 | 20 | img { 21 | width: 100%; 22 | max-width: 100%; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/components/Header/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { FunctionComponent } from 'react'; 2 | 3 | import s from './styles.scss'; 4 | 5 | const Header: FunctionComponent = () => ( 6 |
7 |
8 |

React Typescript Starter

9 | 13 | Github 14 | 15 |
16 |
17 | ); 18 | 19 | export default Header; 20 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowSyntheticDefaultImports": true, 4 | "outDir": "dist", 5 | "sourceMap": true, 6 | "skipLibCheck": true, 7 | "noImplicitAny": false, 8 | "noImplicitReturns": true, 9 | "noImplicitThis": true, 10 | "noUnusedLocals": true, 11 | "noUnusedParameters": true, 12 | "module": "esNext", 13 | "moduleResolution": "node", 14 | "target": "es2017", 15 | "jsx": "react", 16 | "typeRoots": ["node_modules/@types"] 17 | }, 18 | "include": ["src", "types/index.d.ts", "./typings.d.ts"], 19 | "exclude": ["node_modules", "dist", "compiled", "webpack"] 20 | } 21 | -------------------------------------------------------------------------------- /src/index.dev.tsx: -------------------------------------------------------------------------------- 1 | /* global module */ 2 | import 'react-hot-loader/patch'; 3 | import { AppContainer } from 'react-hot-loader'; 4 | import React, { ComponentClass, FunctionComponent } from 'react'; 5 | import ReactDOM from 'react-dom'; 6 | import Root from './Root'; 7 | 8 | const renderComponent = (Component: ComponentClass | FunctionComponent) => { 9 | ReactDOM.render( 10 | 11 | 12 | , 13 | document.getElementById('root') 14 | ); 15 | }; 16 | 17 | renderComponent(Root); 18 | 19 | if (module.hot) { 20 | module.hot.accept('./Root', () => { 21 | renderComponent(Root); 22 | }); 23 | } 24 | -------------------------------------------------------------------------------- /src/assets/img/welcome-page/github.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/img/welcome-page/ts.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/typescript", 4 | "@babel/preset-react", 5 | [ 6 | "@babel/preset-env", 7 | { 8 | "modules": false, 9 | "targets": { 10 | "browsers": ["last 2 versions"] 11 | }, 12 | "useBuiltIns": "entry", 13 | "corejs": "3.0.0" 14 | } 15 | ] 16 | ], 17 | "plugins": [ 18 | [ 19 | "react-css-modules", 20 | { 21 | "webpackHotModuleReloading": true, 22 | "filetypes": { 23 | ".scss": { 24 | "syntax": "postcss-scss" 25 | } 26 | }, 27 | "generateScopedName": "[path]___[name]__[local]" 28 | } 29 | ], 30 | "emotion", 31 | "@babel/plugin-syntax-dynamic-import", 32 | "@babel/plugin-proposal-class-properties", 33 | "@babel/plugin-proposal-throw-expressions", 34 | "@babel/plugin-proposal-function-bind", 35 | [ 36 | "react-hot-loader/babel", 37 | { 38 | "safetyNet": false 39 | } 40 | ] 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /src/screens/Welcome/styles.scss: -------------------------------------------------------------------------------- 1 | $welcome-page-text-color: #294E80; 2 | 3 | .welcome { 4 | min-height: calc(100vh - 75px); 5 | display: flex; 6 | align-items: center; 7 | overflow: auto; 8 | 9 | .wrapper { 10 | margin: 0 auto; 11 | } 12 | 13 | .container { 14 | display: flex; 15 | flex-direction: column; 16 | align-items: center; 17 | padding: 25px 0; 18 | } 19 | 20 | .logo { 21 | width: 300px; 22 | 23 | img { 24 | width: 100%; 25 | max-width: 100%; 26 | } 27 | } 28 | 29 | .instructionsTitle { 30 | font-size: 1.3em; 31 | color: $welcome-page-text-color; 32 | margin: 0 0 10px; 33 | align-self: flex-start; 34 | 35 | &:not(:first-child) { 36 | margin: 20px 0 10px; 37 | } 38 | } 39 | 40 | code { 41 | background: #f1f1f1; 42 | border-radius: 10px; 43 | padding: 25px; 44 | width: 100%; 45 | } 46 | } 47 | 48 | .logos { 49 | display: flex; 50 | justify-content: center; 51 | flex-flow: row wrap; 52 | align-items: center; 53 | } 54 | 55 | .eslint { 56 | margin-right: 20px; 57 | width: 100px; 58 | 59 | img { 60 | width: 100%; 61 | max-width: 100%; 62 | } 63 | } 64 | 65 | .typescript { 66 | composes: eslint; 67 | } 68 | 69 | .babel { 70 | composes: eslint; 71 | width: 300px; 72 | } -------------------------------------------------------------------------------- /src/assets/img/welcome-page/eslint.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/screens/Welcome/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { FunctionComponent, Fragment } from 'react'; 2 | 3 | import Header from '../../components/Header'; 4 | 5 | import s from './styles.scss'; 6 | 7 | const Welcome: FunctionComponent<{}> = () => ( 8 | 9 |
10 |
11 |
12 |
13 |
14 | Logo 15 |
16 | 17 |
18 |
19 | Logo 20 |
21 |
22 | Logo 23 |
24 |
25 | Logo 26 |
27 |
28 | 29 |

To start:

30 | 31 |

yarn

32 |

yarn dev

33 |
34 | 35 |

To build:

36 | 37 |

yarn build

38 |
39 | 40 |

To lint:

41 | 42 |

yarn lint

43 |

yarn lint-fix

44 |
45 |
46 |
47 |
48 | 49 | ); 50 | 51 | export default Welcome; 52 | -------------------------------------------------------------------------------- /webpack/prod.webpack.js: -------------------------------------------------------------------------------- 1 | /* global process */ 2 | 3 | const webpack = require('webpack'); 4 | const { resolve } = require('path'); 5 | const merge = require('webpack-merge'); 6 | const MiniCssExtractPlugin = require('mini-css-extract-plugin'); 7 | 8 | const commonClientConfig = require('./common.webpack'); 9 | 10 | module.exports = merge({ 11 | customizeArray(a, b, key) { 12 | if (key === 'module.rules') { 13 | const testList = b.map(item => item.test.toString()); 14 | return a 15 | .filter(item => !testList.includes(item.test.toString())) 16 | .concat(b); 17 | } 18 | } 19 | })(commonClientConfig, { 20 | entry: { main: ['babel-polyfill', './index.prod.tsx'] }, 21 | mode: 'production', 22 | devtool: false, 23 | output: { 24 | path: resolve(__dirname, '../dist'), 25 | filename: 'js/[name].[chunkhash].min.js', 26 | publicPath: '' 27 | }, 28 | module: { 29 | rules: [ 30 | { 31 | test: /\.scss$/, 32 | use: [ 33 | MiniCssExtractPlugin.loader, 34 | { 35 | loader: 'css-loader', 36 | options: { 37 | importLoaders: 1, 38 | modules: { 39 | localIdentName: 'src-[path]___[name]__[local]' 40 | } 41 | } 42 | }, 43 | 'postcss-loader', 44 | 'sass-loader' 45 | ] 46 | } 47 | ] 48 | }, 49 | optimization: { 50 | splitChunks: { 51 | cacheGroups: { 52 | commons: { 53 | test: /[\\/]node_modules[\\/]/, 54 | name: 'vendors', 55 | chunks: 'all' 56 | } 57 | } 58 | }, 59 | runtimeChunk: true 60 | }, 61 | plugins: [ 62 | new MiniCssExtractPlugin({ 63 | filename: `styles/[name].css` 64 | }), 65 | new webpack.SourceMapDevToolPlugin({ 66 | exclude: /node_modules/, 67 | columns: true, 68 | test: /\.tsx?|\.ts?|\.js?$/, 69 | filename: 'js/[name].[chunkhash].js.map' 70 | }) 71 | ] 72 | }); 73 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "airbnb", 4 | "plugin:@typescript-eslint/recommended", 5 | "prettier", 6 | "prettier/@typescript-eslint" 7 | ], 8 | "parser": "@typescript-eslint/parser", 9 | "plugins": [ 10 | "babel", 11 | "import", 12 | "react", 13 | "compat", 14 | "promise", 15 | "prettier", 16 | "@typescript-eslint" 17 | ], 18 | "env": { 19 | "node": false, 20 | "browser": true 21 | }, 22 | "parserOptions": { 23 | "ecmaVersion": 2017, 24 | "sourceType": "module", 25 | "jsx": true 26 | }, 27 | "settings": { 28 | "react": { 29 | "pragma": "React", 30 | "version": "16.8" 31 | }, 32 | "import/resolver": { 33 | "node": { 34 | "paths": ["."], 35 | "extensions": [".js", ".ts", ".tsx"] 36 | } 37 | } 38 | }, 39 | "rules": { 40 | "curly": [2, "all"], 41 | "indent": ["error", 2, { "SwitchCase": 1 }], 42 | "arrow-body-style": ["error", "as-needed"], 43 | "arrow-parens": 0, 44 | "no-underscore-dangle": 0, 45 | "comma-dangle": ["error", "never"], 46 | "no-use-before-define": "error", 47 | "no-console": "error", 48 | "no-plusplus": 0, 49 | "no-minusminus": 0, 50 | "no-unused-expressions": 0, 51 | "no-unused-vars": ["error", { "ignoreRestSiblings": true }], 52 | "object-curly-newline": 0, 53 | "function-paren-newline": 0, 54 | "no-return-await": 0, 55 | "max-params": ["error", 5], 56 | "max-depth": ["error", 3], 57 | "promise/always-return": "error", 58 | "promise/catch-or-return": "error", 59 | "promise/param-names": "error", 60 | "promise/no-return-wrap": "error", 61 | "@typescript-eslint/explicit-function-return-type": "off", 62 | "@typescript-eslint/explicit-member-accessibility": "off", 63 | "@typescript-eslint/no-explicit-any": 0, 64 | "@typescript-eslint/no-unused-vars": [ 65 | "error", 66 | { "ignoreRestSiblings": true } 67 | ], 68 | "prettier/prettier": ["error"], 69 | "react/prop-types": "off", 70 | "react/jsx-filename-extension": "off", 71 | "import/extensions": [ 72 | "error", 73 | "ignorePackages", 74 | { 75 | "js": "never", 76 | "jsx": "never", 77 | "ts": "never", 78 | "tsx": "never" 79 | } 80 | ] 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/assets/img/welcome-page/tsx-logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /webpack/common.webpack.js: -------------------------------------------------------------------------------- 1 | /* global process */ 2 | require('dotenv').config(); 3 | 4 | const webpack = require('webpack'); 5 | const path = require('path'); 6 | const { resolve } = require('path'); 7 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 8 | const CopyWebpackPlugin = require('copy-webpack-plugin'); 9 | const InlineSourcePlugin = require('html-webpack-inline-source-plugin'); 10 | 11 | module.exports = { 12 | mode: 'development', 13 | context: resolve(__dirname, '../src'), 14 | entry: ['babel-polyfill', '../src/index.dev.tsx'], 15 | output: { 16 | path: path.join(__dirname, 'dist'), 17 | filename: '[name].js', 18 | publicPath: '' 19 | }, 20 | resolve: { 21 | extensions: ['.ts', '.tsx', '.js', '.jsx'], 22 | alias: { 23 | 'react-dom': '@hot-loader/react-dom' 24 | } 25 | }, 26 | 27 | module: { 28 | rules: [ 29 | { 30 | test: /\.(js|ts|jsx|tsx)$/, 31 | use: [ 32 | 'react-hot-loader/webpack', 33 | { 34 | loader: 'babel-loader' 35 | } 36 | ], 37 | exclude: /node_modules/ 38 | }, 39 | { 40 | test: /\.css$/, 41 | use: ['style-loader', 'css-loader', 'postcss-loader'] 42 | }, 43 | { 44 | test: /\.scss$/, 45 | use: [ 46 | 'style-loader', 47 | { 48 | loader: 'css-loader', 49 | options: { 50 | importLoaders: 1, 51 | modules: { 52 | localIdentName: 'src-[path]___[name]__[local]' 53 | } 54 | } 55 | }, 56 | 'postcss-loader', 57 | 'sass-loader' 58 | ] 59 | }, 60 | { 61 | test: /\.svg$/, 62 | use: ['svgo-loader'] 63 | }, 64 | { 65 | test: /\.(jpe?g|png|gif)$/i, 66 | loaders: [ 67 | 'file-loader?hash=sha512&digest=hex&name=img/[hash].[ext]', 68 | 'image-webpack-loader?bypassOnDebug&optipng.optimizationLevel=7&gifsicle.interlaced=false' 69 | ] 70 | }, 71 | { 72 | test: /\.(woff|woff2|eot|ttf)$/, 73 | loader: ['file-loader?name=fonts/[name].[ext]'] 74 | } 75 | ] 76 | }, 77 | plugins: [ 78 | new CopyWebpackPlugin([ 79 | { 80 | from: 'assets/img', 81 | to: 'assets/img' 82 | } 83 | ]), 84 | new HtmlWebpackPlugin({ 85 | template: 'index.html', 86 | inlineSource: 'runtime~.+\\.js', 87 | chunksSortMode: 'none' 88 | }), 89 | new InlineSourcePlugin(HtmlWebpackPlugin), 90 | new webpack.NamedModulesPlugin() 91 | ] 92 | }; 93 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | Shield 3 | Shield 4 | Shield 5 |
6 | 7 | # React Typescript Starter with Eslint and Babel 8 | 9 |
10 | 11 | react 12 | 13 |
14 | 15 |
16 | eslint 17 | babel 18 | typescript 19 |
20 | 21 | ## Description 22 | The problem of typing has long been known to all Javascript developers. Someone resolves it with the help of a Flow, someone with the help of something else, and someone with the help of a TypeScript. This repository allows you to make quick in React Development using TypeScript. 23 | 24 | This boilerplate uses Webpack, Eslint, CSS Modules and Babel. 25 | 26 | You don't need Create React App 27 | 28 | Pull Requests are very welcome! 29 | 30 | ## Usage 31 | 32 | ```sh 33 | git clone git@github.com:vtereshyn/react-typescript-eslint-starter.git 34 | ``` 35 | or 36 | ```sh 37 | git clone https://github.com/vtereshyn/react-typescript-eslint-starter.git 38 | ``` 39 | 40 | ### Install 41 | 42 | With Yarn: 43 | 44 | ```sh 45 | yarn 46 | ``` 47 | 48 | With NPM: 49 | 50 | ```sh 51 | npm i 52 | ``` 53 | 54 | ### Development mode 55 | 56 | With Yarn: 57 | 58 | ```sh 59 | yarn dev 60 | ``` 61 | 62 | With NPM: 63 | 64 | ```sh 65 | npm run dev 66 | ``` 67 | 68 | ### Run linters 69 | 70 | With Yarn: 71 | 72 | ```sh 73 | yarn lint 74 | ``` 75 | 76 | With NPM: 77 | 78 | ```sh 79 | npm run lint 80 | ``` 81 | 82 | 83 | #### Fix lint issues 84 | 85 | With Yarn: 86 | 87 | ```sh 88 | yarn lint-fix 89 | ``` 90 | 91 | With NPM: 92 | 93 | ```sh 94 | npm run lint-fix 95 | ``` 96 | 97 | ### Build project 98 | With Yarn: 99 | 100 | ```sh 101 | yarn build 102 | ``` 103 | 104 | With NPM: 105 | 106 | ```sh 107 | npm run build 108 | ``` 109 | Dist folder will have a structure like: 110 | 111 | ```js 112 | dist 113 | - public 114 | -- assets 115 | -- js 116 | -- styles 117 | -- index.html 118 | ``` 119 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "npm", 3 | "version": "1.0.0", 4 | "description": "Quick start for React application using Typescript, Eslint and Webpack", 5 | "main": "index.js", 6 | "scripts": { 7 | "dev": "cross-env NODE_ENV=local webpack-dev-server --config webpack/common.webpack", 8 | "start": "cross-env serve -s ./dist/public", 9 | "build": "cross-env NODE_ENV=production webpack --config webpack/prod.webpack --progress", 10 | "lint": "eslint src/**/*.{ts,tsx}", 11 | "lint-fix": "eslint **/*/*.tsx --fix" 12 | }, 13 | "keywords": [ 14 | "react", 15 | "typescript", 16 | "eslint", 17 | "webpack", 18 | "babel" 19 | ], 20 | "author": "Vladyslav Tereshyn", 21 | "license": "ISC", 22 | "dependencies": { 23 | "core-js": "^3.6.5", 24 | "dotenv": "^8.2.0", 25 | "react": "^16.13.1", 26 | "react-dom": "^16.13.1", 27 | "react-hot-loader": "^4.12.20" 28 | }, 29 | "devDependencies": { 30 | "@babel/core": "^7.9.0", 31 | "@babel/plugin-proposal-class-properties": "^7.8.3", 32 | "@babel/plugin-proposal-function-bind": "^7.8.3", 33 | "@babel/plugin-proposal-throw-expressions": "^7.8.3", 34 | "@babel/plugin-syntax-dynamic-import": "^7.8.3", 35 | "@babel/polyfill": "^7.8.7", 36 | "@babel/preset-env": "^7.9.5", 37 | "@babel/preset-react": "^7.9.4", 38 | "@babel/preset-typescript": "^7.9.0", 39 | "@hot-loader/react-dom": "^16.13.0", 40 | "@types/react": "^16.9.34", 41 | "@types/react-css-modules": "^4.6.2", 42 | "@types/react-dom": "^16.9.7", 43 | "@types/react-redux": "^7.1.7", 44 | "@types/react-router-dom": "^5.1.5", 45 | "@types/react-text-mask": "^5.4.6", 46 | "@types/redux-logger": "^3.0.7", 47 | "@types/webpack-env": "^1.15.2", 48 | "@typescript-eslint/eslint-plugin": "^2.30.0", 49 | "@typescript-eslint/parser": "^2.30.0", 50 | "babel-loader": "^8.1.0", 51 | "babel-minify-webpack-plugin": "^0.3.1", 52 | "babel-plugin-emotion": "^10.0.33", 53 | "babel-plugin-react-css-modules": "^5.2.6", 54 | "babel-polyfill": "^6.26.0", 55 | "copy-webpack-plugin": "^5.1.1", 56 | "cross-env": "^7.0.2", 57 | "css-loader": "^3.5.3", 58 | "eslint": "^6.8.0", 59 | "eslint-config-airbnb": "^18.1.0", 60 | "eslint-config-prettier": "^6.11.0", 61 | "eslint-plugin-babel": "^5.3.0", 62 | "eslint-plugin-compat": "^3.5.1", 63 | "eslint-plugin-import": "^2.20.2", 64 | "eslint-plugin-jsx-a11y": "^6.2.3", 65 | "eslint-plugin-prettier": "^3.1.3", 66 | "eslint-plugin-promise": "^4.2.1", 67 | "eslint-plugin-react": "^7.19.0", 68 | "fork-ts-checker-webpack-plugin": "^4.1.3", 69 | "html-webpack-inline-source-plugin": "^1.0.0-beta.2", 70 | "html-webpack-plugin": "^4.2.1", 71 | "mini-css-extract-plugin": "^0.9.0", 72 | "node-sass": "^4.14.0", 73 | "postcss-load-config": "^2.1.0", 74 | "postcss-loader": "^3.0.0", 75 | "postcss-plugin": "^1.0.0", 76 | "postcss-scss": "^2.0.0", 77 | "prettier": "^2.0.5", 78 | "sass-loader": "^8.0.2", 79 | "style-loader": "^1.2.1", 80 | "typescript": "^3.8.3", 81 | "webpack": "^4.43.0", 82 | "webpack-cli": "^3.3.11", 83 | "webpack-dev-server": "^3.10.3", 84 | "webpack-merge": "^4.2.2" 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/assets/scss/partial/reset.scss: -------------------------------------------------------------------------------- 1 | /* Reset 2 | /* ----------------------------------- */ 3 | 4 | html, 5 | body, 6 | div, 7 | span, 8 | applet, 9 | object, 10 | iframe, 11 | h1, 12 | h2, 13 | h3, 14 | h4, 15 | h5, 16 | h6, 17 | p, 18 | blockquote, 19 | pre, 20 | a, 21 | abbr, 22 | acronym, 23 | address, 24 | big, 25 | cite, 26 | code, 27 | del, 28 | dfn, 29 | em, 30 | img, 31 | ins, 32 | kbd, 33 | q, 34 | s, 35 | samp, 36 | small, 37 | strike, 38 | strong, 39 | sub, 40 | sup, 41 | tt, 42 | var, 43 | dl, 44 | dt, 45 | dd, 46 | ol, 47 | ul, 48 | li, 49 | fieldset, 50 | form, 51 | label, 52 | legend, 53 | table, 54 | caption, 55 | tbody, 56 | tfoot, 57 | thead, 58 | tr, 59 | th, 60 | td, 61 | article, 62 | aside, 63 | canvas, 64 | details, 65 | embed, 66 | figure, 67 | figcaption, 68 | footer, 69 | header, 70 | hgroup, 71 | menu, 72 | nav, 73 | output, 74 | ruby, 75 | section, 76 | summary, 77 | time, 78 | mark, 79 | audio, 80 | video { 81 | margin: 0; 82 | padding: 0; 83 | border: 0; 84 | font: inherit; 85 | font-size: 100%; 86 | vertical-align: baseline; 87 | } 88 | 89 | ol, 90 | ul { 91 | list-style: none; 92 | margin: 0; 93 | padding: 0; 94 | } 95 | 96 | blockquote, 97 | q { 98 | quotes: none; 99 | } 100 | 101 | blockquote::before, 102 | blockquote::after, 103 | q::before, 104 | q::after { 105 | content: ''; 106 | content: none; 107 | } 108 | 109 | table { 110 | border-spacing: 0; 111 | border-collapse: collapse; 112 | } 113 | 114 | html { 115 | box-sizing: border-box; 116 | font-family: sans-serif; 117 | -ms-text-size-adjust: 100%; 118 | -webkit-text-size-adjust: 100%; 119 | overflow-x: hidden; 120 | overflow-y: scroll; 121 | font-size: 62.5%; 122 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 123 | } 124 | 125 | *, 126 | *::before, 127 | *::after { 128 | box-sizing: inherit; 129 | } 130 | 131 | a { 132 | color: black; 133 | background-color: transparent; 134 | text-decoration: none; 135 | } 136 | 137 | blockquote cite a { 138 | font-weight: normal; 139 | } 140 | 141 | a:active, 142 | a:hover { 143 | color: black; 144 | outline: 0; 145 | text-decoration: none; 146 | } 147 | 148 | b, 149 | strong { 150 | font-weight: bold; 151 | } 152 | 153 | i, 154 | em, 155 | dfn { 156 | font-style: italic; 157 | } 158 | 159 | h1 { 160 | margin: 0; 161 | font-size: 5rem; 162 | font-weight: 700; 163 | } 164 | 165 | small { 166 | font-size: 80%; 167 | } 168 | 169 | sub, 170 | sup { 171 | position: relative; 172 | font-size: 75%; 173 | line-height: 0; 174 | vertical-align: baseline; 175 | } 176 | 177 | sup { 178 | top: -0.5em; 179 | } 180 | 181 | sub { 182 | bottom: -0.25em; 183 | } 184 | 185 | img { 186 | border: 0; 187 | } 188 | 189 | audio, 190 | canvas, 191 | iframe, 192 | img, 193 | svg, 194 | video { 195 | vertical-align: middle; 196 | } 197 | 198 | svg:not(:root) { 199 | overflow: hidden; 200 | } 201 | 202 | mark { 203 | background-color: #fdffb6; 204 | } 205 | 206 | code, 207 | kbd, 208 | pre, 209 | samp { 210 | font-family: monospace; 211 | font-size: 1em; 212 | } 213 | 214 | button, 215 | input, 216 | optgroup, 217 | select, 218 | textarea { 219 | margin: 0; /* 3 */ 220 | color: inherit; /* 1 */ 221 | font: inherit; /* 2 */ 222 | } 223 | 224 | button { 225 | overflow: visible; 226 | border: none; 227 | } 228 | 229 | button, 230 | select { 231 | text-transform: none; 232 | } 233 | 234 | button, 235 | html input[type="button"], 236 | /* 1 */ 237 | input[type="reset"], 238 | input[type="submit"] { 239 | cursor: pointer; /* 3 */ 240 | -webkit-appearance: button; /* 2 */ 241 | } 242 | 243 | button[disabled], 244 | html input[disabled] { 245 | cursor: default; 246 | } 247 | 248 | input { 249 | line-height: normal; 250 | } 251 | 252 | button::-moz-focus-inner, 253 | input::-moz-focus-inner { 254 | padding: 0; 255 | border: 0; 256 | } 257 | 258 | input:focus { 259 | outline: none; 260 | } 261 | 262 | input[type='checkbox'], 263 | input[type='radio'] { 264 | box-sizing: border-box; /* 1 */ 265 | padding: 0; /* 2 */ 266 | } 267 | 268 | input[type='number']::-webkit-inner-spin-button, 269 | input[type='number']::-webkit-outer-spin-button { 270 | height: auto; 271 | } 272 | 273 | input[type='search'] { 274 | box-sizing: content-box; /* 2 */ 275 | -webkit-appearance: textfield; /* 1 */ 276 | } 277 | 278 | input[type='search']::-webkit-search-cancel-button, 279 | input[type='search']::-webkit-search-decoration { 280 | -webkit-appearance: none; 281 | } 282 | 283 | legend { 284 | padding: 0; /* 2 */ 285 | border: 0; /* 1 */ 286 | } 287 | 288 | textarea { 289 | overflow: auto; 290 | resize: vertical; 291 | } 292 | 293 | td, 294 | th { 295 | padding: 0; 296 | } 297 | 298 | /* Base Styles 299 | /* ----------------------------------- */ 300 | 301 | body { 302 | font-family: 303 | -apple-system, 304 | BlinkMacSystemFont, 305 | 'Segoe UI', 306 | Roboto, 307 | Helvetica, 308 | Arial, 309 | sans-serif, 310 | 'Apple Color Emoji', 311 | 'Segoe UI Emoji', 312 | 'Segoe UI Symbol'; 313 | font-size: 16px; 314 | font-weight: 200; 315 | line-height: 1.6em; 316 | font-style: normal; 317 | letter-spacing: 0; 318 | text-rendering: optimizeLegibility; 319 | background: #fff; 320 | -webkit-font-smoothing: antialiased; 321 | -moz-osx-font-smoothing: grayscale; 322 | -moz-font-feature-settings: 'liga' on; 323 | font-feature-settings: 'liga' on; 324 | } 325 | 326 | hr { 327 | position: relative; 328 | display: block; 329 | width: 100%; 330 | margin: 1em 0; 331 | padding: 0; 332 | height: 1px; 333 | border: 0; 334 | background-color: #ccc; 335 | } 336 | 337 | fieldset { 338 | margin: 0; 339 | padding: 0; 340 | border: 0; 341 | } 342 | 343 | p, 344 | ul, 345 | ol, 346 | dl, 347 | blockquote { 348 | margin: 0; 349 | } 350 | 351 | ul { 352 | list-style: none; 353 | } 354 | 355 | ol { 356 | list-style: decimal; 357 | } 358 | 359 | ol ol, 360 | ul ul, 361 | ul ol, 362 | ol ul { 363 | margin: 0; 364 | } 365 | 366 | li { 367 | margin: 0; 368 | } 369 | 370 | dt { 371 | margin: 0; 372 | padding: 0; 373 | } 374 | 375 | dd { 376 | margin: 0; 377 | padding: 0; 378 | } 379 | 380 | blockquote { 381 | margin: 1.5em 0; 382 | padding: 0 1.6em 0 1.6em; 383 | } 384 | 385 | blockquote p { 386 | margin: 0.8em 0; 387 | font-size: 1.2em; 388 | font-weight: 300; 389 | } 390 | 391 | blockquote small { 392 | display: inline-block; 393 | margin: 0.8em 0 0.8em 1.5em; 394 | font-size: 0.9em; 395 | opacity: 0.8; 396 | } 397 | 398 | /* Quotation marks */ 399 | blockquote small::before { 400 | content: '\2014 \00A0'; 401 | } 402 | 403 | blockquote cite { 404 | font-weight: bold; 405 | } 406 | 407 | h1, 408 | h2, 409 | h3, 410 | h4, 411 | h5, 412 | h6 { 413 | margin-top: 0; 414 | line-height: 1.15; 415 | font-weight: 700; 416 | text-rendering: optimizeLegibility; 417 | } 418 | 419 | @media (max-width: 500px) { 420 | h1 { 421 | font-size: 2.2rem; 422 | } 423 | } 424 | 425 | h2 { 426 | margin: 0; 427 | font-size: 2rem; 428 | } 429 | 430 | @media (max-width: 500px) { 431 | h2 { 432 | font-size: 1.8rem; 433 | } 434 | } 435 | 436 | h3 { 437 | margin: 0; 438 | font-size: 1.8rem; 439 | font-weight: 500; 440 | } 441 | 442 | @media (max-width: 500px) { 443 | h3 { 444 | font-size: 1.7rem; 445 | } 446 | } 447 | 448 | h4 { 449 | margin: 0; 450 | font-size: 1.6rem; 451 | font-weight: 500; 452 | } 453 | 454 | h5 { 455 | margin: 0; 456 | font-size: 1.4rem; 457 | font-weight: 500; 458 | } 459 | 460 | h6 { 461 | margin: 0; 462 | font-size: 1.4rem; 463 | font-weight: 500; 464 | } 465 | 466 | .hide { 467 | display: none; 468 | } 469 | -------------------------------------------------------------------------------- /src/assets/img/welcome-page/babel.svg: -------------------------------------------------------------------------------- 1 | --------------------------------------------------------------------------------