Initial commit

This commit is contained in:
Jan Tuomi
2018-06-20 09:35:41 +03:00
commit 19ed49ae3d
27 changed files with 21606 additions and 0 deletions
+17
View File
@@ -0,0 +1,17 @@
{
"presets": [
["env", {"modules": false}],
"react"
],
"plugins": [
"react-hot-loader/babel"
],
"env": {
"production": {
"presets": ["minify"]
},
"test": {
"presets": ["env", "react"]
}
}
}
+8
View File
@@ -0,0 +1,8 @@
.idea/
dist/
node_modules/
src/**/*.jsx
tests/jest/__coverage__/
tests/jest/**/*.jsx
tests/testcafe/screenshots
.vscode/
+3
View File
@@ -0,0 +1,3 @@
{
"extends": "stylelint-config-standard"
}
+48
View File
@@ -0,0 +1,48 @@
Aalto-yliopiston Sähköinsinöörikilta Website 2018
MIT License
Copyright (c) 2017 Aalto-yliopiston Sähköinsinöörikilta ry
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
React Webpack Typescript Starter
MIT License
Copyright (c) 2017 Viktor Persson
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+58
View File
@@ -0,0 +1,58 @@
# Web 2.0 Frontend
Minimal starter kit with hot module replacement (HMR) for rapid development.
* **[React](https://facebook.github.io/react/)** (16.x)
* **[Webpack](https://webpack.js.org/)** (4.x)
* **[Typescript](https://www.typescriptlang.org/)** (2.x)
* **[Hot Module Replacement (HMR)](https://webpack.js.org/concepts/hot-module-replacement/)** using [React Hot Loader](https://github.com/gaearon/react-hot-loader) (4.x)
* [Babel](http://babeljs.io/) (6.x)
* [SASS](http://sass-lang.com/)
* [Jest](https://facebook.github.io/jest/) - Testing framework for React applications
* Production build script
* Image loading/minification using [Image Webpack Loader](https://github.com/tcoopman/image-webpack-loader)
* Typescript compiling using [Awesome Typescript Loader](https://github.com/s-panferov/awesome-typescript-loader) (5.x)
* Code quality (linting) for Typescript and SASS/CSS.
## Installation
1. Clone/download repo
2. `npm install`
## Usage
**Development**
`npm start`
* Build app continously (HMR enabled)
* App served @ `http://localhost:8080`
**Production**
`npm run start-prod`
* Build app once (HMR disabled)
* App served @ `http://localhost:3000`
---
**All commands**
Command | Description
--- | ---
`npm run start-dev` | Build app continously (HMR enabled) and serve @ `http://localhost:8080`
`npm run start-prod` | Build app once (HMR disabled) and serve @ `http://localhost:3000`
`npm run build` | Build app to `/dist/`
`npm run test` | Run e2e and unit tests
`npm run test:unit` | Run unit tests with Jest
`npm run test:e2e` | Run end-to-end tests with TestCafé
`npm run lint` | Run Typescript and SASS linter
`npm run lint:ts` | Run Typescript linter
`npm run lint:sass` | Run SASS linter
`npm run start` | (alias of `npm run start-dev`)
## See also
* [React Webpack Babel Starter](https://github.com/vikpe/react-webpack-babel-starter)
* [Isomorphic Webapp Starter](https://github.com/vikpe/isomorphic-webapp-starter)
## Copyright
Aalto-yliopiston Sähköinsinöörikilta ry
+30
View File
@@ -0,0 +1,30 @@
{
"rootDir": "..",
"coverageDirectory": "<rootDir>/tests/jest/__coverage__/",
"setupFiles": [
"<rootDir>/tests/jest/__mocks__/shim.js"
],
"roots": [
"<rootDir>/src/",
"<rootDir>/tests/jest/"
],
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/tests/jest/__mocks__/fileMock.js",
"\\.(css|scss|less)$": "<rootDir>/tests/jest/__mocks__/styleMock.js"
},
"moduleFileExtensions": ["ts", "tsx", "js", "jsx"],
"transform": {
"^.+\\.(ts|tsx)$": "<rootDir>/configs/jest.preprocessor.js"
},
"transformIgnorePatterns": [
"/node_modules/"
],
"testRegex": "/tests/jest/.*\\.(ts|tsx)$",
"moduleDirectories": [
"node_modules"
],
"globals": {
"DEVELOPMENT": false,
"FAKE_SERVER": false
}
}
+25
View File
@@ -0,0 +1,25 @@
const tsc = require('typescript');
const tsConfig = require('./../tsconfig.json');
module.exports = {
process(src, path) {
const isTs = path.endsWith('.ts');
const isTsx = path.endsWith('.tsx');
const isTypescriptFile = (isTs || isTsx);
if ( isTypescriptFile ) {
src = tsc.transpileModule(
src,
{
compilerOptions: tsConfig.compilerOptions,
fileName: path
}
).outputText;
// update the path so babel can try and process the output
path = path.substr(0, path.lastIndexOf('.')) + (isTs ? '.js' : '.jsx') || path;
}
return src;
},
};
+57
View File
@@ -0,0 +1,57 @@
// shared config (dev and prod)
const {resolve} = require('path');
const {CheckerPlugin} = require('awesome-typescript-loader');
const StyleLintPlugin = require('stylelint-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx'],
},
context: resolve(__dirname, '../../src'),
module: {
rules: [
{
test: /\.js$/,
use: ['babel-loader', 'source-map-loader'],
exclude: /node_modules/,
},
{
test: /\.tsx?$/,
use: ['babel-loader', 'awesome-typescript-loader'],
},
{
test: /\.css$/,
use: ['style-loader', { loader: 'css-loader', options: { importLoaders: 1 } }, 'postcss-loader',],
},
{
test: /\.scss$/,
loaders: [
'style-loader',
{ loader: 'css-loader', options: { importLoaders: 1 } },
'postcss-loader',
'sass-loader',
],
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
loaders: [
'file-loader?hash=sha512&digest=hex&name=img/[hash].[ext]',
'image-webpack-loader?bypassOnDebug&optipng.optimizationLevel=7&gifsicle.interlaced=false',
],
},
],
},
plugins: [
new CheckerPlugin(),
new StyleLintPlugin(),
new HtmlWebpackPlugin({template: 'index.html.ejs',}),
],
externals: {
'react': 'React',
'react-dom': 'ReactDOM',
},
performance: {
hints: false,
},
};
+22
View File
@@ -0,0 +1,22 @@
// development config
const merge = require('webpack-merge');
const webpack = require('webpack');
const commonConfig = require('./common');
module.exports = merge(commonConfig, {
mode: 'development',
entry: [
'react-hot-loader/patch', // activate HMR for React
'webpack-dev-server/client?http://localhost:8080',// bundle the client for webpack-dev-server and connect to the provided endpoint
'webpack/hot/only-dev-server', // bundle the client for hot reloading, only- means to only hot reload for successful updates
'./index.tsx' // the entry point of our app
],
devServer: {
hot: true, // enable HMR on the server
},
devtool: 'cheap-module-eval-source-map',
plugins: [
new webpack.HotModuleReplacementPlugin(), // enable HMR globally
new webpack.NamedModulesPlugin(), // prints more readable module names in the browser console on HMR updates
],
});
+17
View File
@@ -0,0 +1,17 @@
// production config
const merge = require('webpack-merge');
const {resolve} = require('path');
const commonConfig = require('./common');
module.exports = merge(commonConfig, {
mode: 'production',
entry: './index.tsx',
output: {
filename: 'js/bundle.[hash].min.js',
path: resolve(__dirname, '../../dist'),
publicPath: '/',
},
devtool: 'source-map',
plugins: [],
});
+11
View File
@@ -0,0 +1,11 @@
const express = require('express');
const app = express();
const portNumber = 3000;
const sourceDir = 'dist';
app.use(express.static(sourceDir));
app.listen(portNumber, () => {
console.log(`Express web server started: http://localhost:${portNumber}`);
console.log(`Serving content from /${sourceDir}/`);
});
+20967
View File
File diff suppressed because it is too large Load Diff
+75
View File
@@ -0,0 +1,75 @@
{
"name": "web2.0-frontend",
"version": "0.1.0",
"description": "Web 2.0 Frontend. React, Typescript.",
"keywords": [
"react",
"webpack",
"typescript",
"babel",
"sass",
"hmr",
"starter",
"boilerplate"
],
"author": "Jan Tuomi",
"license": "MIT",
"homepage": "https://sik.ayy.fi",
"scripts": {
"build": "npm run clean-dist && webpack -p --config=configs/webpack/prod.js",
"clean-dist": "rm -f -r -d dist",
"lint": "npm run lint:ts && npm run lint:sass",
"lint:ts": "tslint './src/**/*.ts*' --format stylish --force",
"lint:sass": "stylelint ./src/**/*.scss",
"start": "npm run start-dev",
"start-dev": "webpack-dev-server --config=configs/webpack/dev.js",
"test": "npm-run-all test:unit test:e2e",
"serve": "node express.js",
"start-prod": "npm run build && npm run serve",
"test:unit": "jest --watch --coverage --config=configs/jest.json",
"test:e2e": "npm-run-all -s build -p -r serve test:e2e:run",
"test:e2e:run": "testcafe -S -s 'tests/testcafe/screenshots' --app-init-delay 2000 chrome tests/testcafe"
},
"devDependencies": {
"@types/jest": "^23.0.0",
"@types/node": "^10.3.1",
"@types/react": "^16.3.16",
"@types/react-dom": "^16.0.6",
"awesome-typescript-loader": "^5.0.0",
"babel-cli": "^6.26.0",
"babel-core": "^6.26.3",
"babel-loader": "^7.1.4",
"babel-preset-env": "^1.7.0",
"babel-preset-react": "^6.24.1",
"css-loader": "^0.28.11",
"express": "^4.16.3",
"file-loader": "^1.1.11",
"html-webpack-plugin": "^3.2.0",
"image-webpack-loader": "^4.3.0",
"jest": "^23.1.0",
"node-sass": "^4.9.0",
"npm-run-all": "^4.1.3",
"postcss-loader": "^2.1.5",
"react": "^16.4.0",
"react-addons-test-utils": "^15.6.2",
"react-dom": "^16.4.0",
"react-hot-loader": "^4.3.0",
"sass-loader": "^7.0.3",
"serve": "^9.1.0",
"style-loader": "^0.21.0",
"stylelint": "^9.2.1",
"stylelint-config-standard": "^18.2.0",
"stylelint-webpack-plugin": "^0.10.5",
"testcafe": "^0.20.3",
"tslint": "^5.10.0",
"typescript": "^2.9.1",
"uglifyjs-webpack-plugin": "^1.2.5",
"webpack": "^4.11.1",
"webpack-cli": "^3.0.3",
"webpack-dev-middleware": "^3.1.3",
"webpack-dev-server": "^3.1.4",
"webpack-merge": "^4.1.2"
},
"dependencies": {},
"postcss": {}
}
+7
View File
@@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3">
<g fill="#61DAFB">
<path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/>
<circle cx="420.9" cy="296.5" r="45.7"/>
<path d="M520.5 78.1z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

+5
View File
@@ -0,0 +1,5 @@
.app {
&__landing {
text-align: center;
}
}
+18
View File
@@ -0,0 +1,18 @@
import * as React from "react";
import "./App.scss";
const reactLogo = require("../../assets/img/react_logo.svg");
export interface AppProps {
}
export default class App extends React.Component<AppProps, undefined> {
render() {
return (
<div className="app__landing">
<h1>Aalto-yliopiston sähköinsinöörikilta!</h1>
<p>Sähköä, viinaa, naisia.</p>
</div>
);
}
}
+2
View File
@@ -0,0 +1,2 @@
import App from "./App";
export default App;
+15
View File
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Aalto-yliopiston Sähköinsinoorikilta ry</title>
</head>
<body>
<div id="root"></div>
<!-- Dependencies -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.2.0/umd/react.production.min.js" integrity="sha256-wouRkivKKXA3y6AuyFwcDcF50alCNV8LbghfYCH6Z98=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.2.0/umd/react-dom.production.min.js" integrity="sha256-9hrJxD4IQsWHdNpzLkJKYGiY/SEZFJJSUqyeZPNKd8g=" crossorigin="anonymous"></script>
</body>
</html>
+30
View File
@@ -0,0 +1,30 @@
$white: #f4f7fc;
$blue: #2f6c76;
$dark-blue: #193b41;
$font-helvetica: helvetica, arial, sans-serif;
html,
body {
font-size: 16px;
margin-top: 2rem;
background-color: $white;
height: 100%;
font-family: $font-helvetica;
color: $blue;
}
body {
max-width: 1200px;
padding: 0 0.5rem;
margin: auto;
}
h1 {
font-size: 3rem;
}
p {
color: $dark-blue;
font-size: 1.5rem;
}
+30
View File
@@ -0,0 +1,30 @@
import * as React from "react";
import {render} from "react-dom";
import {AppContainer} from "react-hot-loader";
import App from "./components/App";
import "./index.scss";
const rootEl = document.getElementById("root");
render(
<AppContainer>
<App/>
</AppContainer>,
rootEl
);
// Hot Module Replacement API
declare const module: { hot: any };
if (module.hot) {
module.hot.accept("./components/App", () => {
const NewApp = require("./components/App").default;
render(
<AppContainer>
<NewApp/>
</AppContainer>,
rootEl
);
});
}
+16
View File
@@ -0,0 +1,16 @@
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import * as TestUtils from 'react-dom/test-utils';
import App from '../../src/components/App';
it('App is rendered', () => {
// Render App in the document
const appElement: any = TestUtils.renderIntoDocument(
<App/>
);
const appNode = ReactDOM.findDOMNode(appElement);
// Verify text content
expect(appNode.textContent).toEqual('Aalto-yliopiston sähköinsinöörikilta!Sähköä, viinaa, naisia.');
});
+1
View File
@@ -0,0 +1 @@
module.exports = 'test-file-stub';
+3
View File
@@ -0,0 +1,3 @@
global.requestAnimationFrame = (callback) => {
setTimeout(callback, 0);
};
+1
View File
@@ -0,0 +1 @@
module.exports = {};
+25
View File
@@ -0,0 +1,25 @@
/**
* TestCafé test fixtures.
* This file is used by TestCafé to run end-to-end tests with chrome against the site.
* Tests are grouped into fixtures and fixtures into files.
*/
import { Selector } from 'testcafe';
fixture`Page renders correctly`.page('http://localhost:3000');
test('Paragraph exists and is visible', async t => {
/**
* Test if there is a paragraph on the page.
*/
const p = Selector('p');
await t.expect(await p.exists && await p.visible);
});
test('Header contains text "Aalto-yliopiston sähköinsinöörikilta!"', async t => {
/**
* Test if the header contains the text.
*/
const header = Selector('h1');
const text = await header.textContent;
await t.expect(text.includes('Aalto-yliopiston sähköinsinöörikilta!'));
});
+14
View File
@@ -0,0 +1,14 @@
{
"compilerOptions": {
"outDir": "./dist/",
"sourceMap": true,
"noImplicitAny": false,
"module": "commonjs",
"target": "es5",
"jsx": "react",
"lib": ["es5", "es6", "dom"]
},
"include": [
"./src/**/*"
]
}
+101
View File
@@ -0,0 +1,101 @@
{
"jsRules": {
"class-name": true,
"comment-format": [
true,
"check-space"
],
"indent": [
true,
"spaces"
],
"no-duplicate-variable": true,
"no-eval": true,
"no-trailing-whitespace": true,
"no-unsafe-finally": true,
"one-line": [
true,
"check-open-brace",
"check-whitespace"
],
"quotemark": [
true,
"double"
],
"semicolon": [
true,
"always"
],
"triple-equals": [
true,
"allow-null-check"
],
"variable-name": [
true,
"ban-keywords"
],
"whitespace": [
true,
"check-branch",
"check-decl",
"check-operator",
"check-separator",
"check-type"
]
},
"rules": {
"class-name": true,
"comment-format": [
true,
"check-space"
],
"indent": [
true,
"spaces"
],
"no-eval": true,
"no-internal-module": true,
"no-trailing-whitespace": true,
"no-unsafe-finally": true,
"no-var-keyword": true,
"one-line": [
true,
"check-open-brace",
"check-whitespace"
],
"quotemark": [
true,
"double"
],
"semicolon": [
true,
"always"
],
"triple-equals": [
true,
"allow-null-check"
],
"typedef-whitespace": [
true,
{
"call-signature": "nospace",
"index-signature": "nospace",
"parameter": "nospace",
"property-declaration": "nospace",
"variable-declaration": "nospace"
}
],
"variable-name": [
true,
"ban-keywords"
],
"whitespace": [
true,
"check-branch",
"check-decl",
"check-operator",
"check-separator",
"check-type"
]
}
}