Skip to content
This repository was archived by the owner on Sep 12, 2019. It is now read-only.

Update dependencies and linting + testing setup. #86

Merged
merged 15 commits into from
May 16, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.cache-loader
2 changes: 1 addition & 1 deletion .lintstagedrc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"*.ts?(x)": [
"prettier-tslint fix \"src/**/*.ts?(x)\"",
"yarn run codestyle",
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unified command to run tslint + Prettier and fix all codestyle issues.

"git add"
],
"*.css": [
Expand Down
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8.9
10
8 changes: 8 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"printWidth": 85,
"semi": false,
"singleQuote": true,
"bracketSpacing": true,
"jsxBracketSameLine": true,
"arrowParens": "always"
}
29 changes: 23 additions & 6 deletions .stylelintrc
Original file line number Diff line number Diff line change
@@ -1,16 +1,33 @@
{
"extends": "stylelint-config-standard",
"rules": {
"comment-empty-line-before": false,
"comment-whitespace-inside": false,
"no-descending-specificity": false,
"declaration-colon-newline-after": false,
"selector-pseudo-element-colon-notation": "single",
"at-rule-no-vendor-prefix": true,
"declaration-empty-line-before": null,
"font-family-name-quotes": "always-where-recommended",
"function-url-quotes": "never",
"string-quotes": "single",
"selector-pseudo-class-no-unknown": [true, {
"ignorePseudoClasses": ["global", "root"]
}],
"property-no-unknown": [true, {
"ignoreProperties": ["composes"]
}]
"number-leading-zero": "never",
"selector-pseudo-class-no-unknown": [
true,
{
"ignorePseudoClasses": [
"global",
"root"
]
}
],
'property-no-unknown': [
true,
{
ignoreProperties: [
'composes'
]
}
]
}
}
22 changes: 22 additions & 0 deletions config/WatchTimesPlugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
let fs = require('fs');
module.exports = WatchTimestampsPlugin;

function WatchTimestampsPlugin(patterns) {
this.patterns = patterns;
}

WatchTimestampsPlugin.prototype.apply = function(compiler) {
compiler.plugin('watch-run', (watch, callback) => {
let patterns = this.patterns;
let timestamps = watch.fileTimestamps || watch.compiler.fileTimestamps;

Object.keys(timestamps).forEach(filepath => {
if (patterns.some(pat => pat instanceof RegExp ? pat.test(filepath) : !~filepath.indexOf(pat))) {
let time = fs.statSync(filepath).mtime;
if (timestamps instanceof Map) timestamps.set(filepath, time);
else timestamps[filepath] = time;
}
});
callback();
});
};
11 changes: 7 additions & 4 deletions config/env.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,16 @@ var dotenvFiles = [

// Load environment variables from .env* files. Suppress warnings using silent
// if this file is missing. dotenv will never modify any environment variables
// that have already been set.
// that have already been set. Variable expansion is supported in .env files.
// https://github.com/motdotla/dotenv
// https://github.com/motdotla/dotenv-expand
dotenvFiles.forEach(dotenvFile => {
if (fs.existsSync(dotenvFile)) {
require('dotenv').config({
path: dotenvFile,
});
require('dotenv-expand')(
require('dotenv').config({
path: dotenvFile,
})
);
}
});

Expand Down
15 changes: 10 additions & 5 deletions config/jest/typescriptTransform.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
// Copyright 2004-present Facebook. All Rights Reserved.
const tsc = require('typescript');
const tsConfig = require('../../tsconfig.test.json');

'use strict';

const tsJestPreprocessor = require('ts-jest/preprocessor');

module.exports = tsJestPreprocessor;
module.exports = {
process(src, path) {
if (path.endsWith('.ts') || path.endsWith('.tsx')) {
return tsc.transpile(src, tsConfig.compilerOptions, path, []);
}
return src;
},
};
6 changes: 6 additions & 0 deletions config/polyfills.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,9 @@ require('whatwg-fetch');
// Object.assign() is commonly used with React.
// It will use the native implementation if it's present and isn't buggy.
Object.assign = require('object-assign');

// In tests, polyfill requestAnimationFrame since jsdom doesn't provide it yet.
// We don't polyfill it in the browser--this is user's responsibility.
if (process.env.NODE_ENV === 'test') {
require('raf').polyfill(global);
}
149 changes: 149 additions & 0 deletions config/react-dev-utils/FileSizeReporter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var fs = require('fs');
var path = require('path');
var chalk = require('chalk');
var filesize = require('filesize');
var recursive = require('recursive-readdir');
var stripAnsi = require('strip-ansi');
var gzipSize = require('gzip-size').sync;

// Prints a detailed summary of build files.
function printFileSizesAfterBuild(
webpackStats,
previousSizeMap,
buildFolder,
maxBundleGzipSize,
maxChunkGzipSize
) {
var root = previousSizeMap.root;
var sizes = previousSizeMap.sizes;
var assets = (webpackStats.stats || [webpackStats])
.map(stats =>
stats
.toJson()
.assets.filter(asset => /\.(js|css)$/.test(asset.name))
.map(asset => {
var fileContents = fs.readFileSync(path.join(root, asset.name));
var size = gzipSize(fileContents);
var previousSize = sizes[removeFileNameHash(root, asset.name)];
var difference = getDifferenceLabel(size, previousSize);
return {
folder: path.join(
path.basename(buildFolder),
path.dirname(asset.name)
),
name: path.basename(asset.name),
size: size,
sizeLabel:
filesize(size) + (difference ? ' (' + difference + ')' : '')
};
})
)
.reduce((single, all) => all.concat(single), []);
assets.sort((a, b) => b.size - a.size);
var longestSizeLabelLength = Math.max.apply(
null,
assets.map(a => stripAnsi(a.sizeLabel).length)
);
var suggestBundleSplitting = false;
assets.forEach(asset => {
var sizeLabel = asset.sizeLabel;
var sizeLength = stripAnsi(sizeLabel).length;
if (sizeLength < longestSizeLabelLength) {
var rightPadding = ' '.repeat(longestSizeLabelLength - sizeLength);
sizeLabel += rightPadding;
}
var isMainBundle = asset.name.indexOf('main.') === 0;
var maxRecommendedSize = isMainBundle
? maxBundleGzipSize
: maxChunkGzipSize;
var isLarge = maxRecommendedSize && asset.size > maxRecommendedSize;
if (isLarge && path.extname(asset.name) === '.js') {
suggestBundleSplitting = true;
}
console.log(
' ' +
(isLarge ? chalk.yellow(sizeLabel) : sizeLabel) +
' ' +
chalk.dim(asset.folder + path.sep) +
chalk.cyan(asset.name)
);
});
if (suggestBundleSplitting) {
console.log();
console.log(
chalk.yellow('The bundle size is significantly larger than recommended.')
);
console.log(
chalk.yellow(
'Consider reducing it with code splitting: https://goo.gl/9VhYWB'
)
);
console.log(
chalk.yellow(
'You can also analyze the project dependencies: https://goo.gl/LeUzfb'
)
);
}
}

function removeFileNameHash(buildFolder, fileName) {
return fileName
.replace(buildFolder, '')
.replace(
/\/?(.*)(\.[0-9a-f]+)(\.chunk)?(\.js|\.css)/,
(match, p1, p2, p3, p4) => p1 + p4
);
}

// Input: 1024, 2048
// Output: "(+1 KB)"
function getDifferenceLabel(currentSize, previousSize) {
var FIFTY_KILOBYTES = 1024 * 50;
var difference = currentSize - previousSize;
var fileSize = !Number.isNaN(difference) ? filesize(difference) : 0;
if (difference >= FIFTY_KILOBYTES) {
return chalk.red('+' + fileSize);
} else if (difference < FIFTY_KILOBYTES && difference > 0) {
return chalk.yellow('+' + fileSize);
} else if (difference < 0) {
return chalk.green(fileSize);
} else {
return '';
}
}

function measureFileSizesBeforeBuild(buildFolder) {
return new Promise(resolve => {
recursive(buildFolder, (err, fileNames) => {
var sizes;
if (!err && fileNames) {
sizes = fileNames
.filter(fileName => /\.(js|css)$/.test(fileName))
.reduce((memo, fileName) => {
var contents = fs.readFileSync(fileName);
var key = removeFileNameHash(buildFolder, fileName);
memo[key] = gzipSize(contents);
return memo;
}, {});
}
resolve({
root: buildFolder,
sizes: sizes || {},
});
});
});
}

module.exports = {
measureFileSizesBeforeBuild: measureFileSizesBeforeBuild,
printFileSizesAfterBuild: printFileSizesAfterBuild,
};
43 changes: 43 additions & 0 deletions config/react-dev-utils/InterpolateHtmlPlugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

// This Webpack plugin lets us interpolate custom variables into `index.html`.
// Usage: `new InterpolateHtmlPlugin({ 'MY_VARIABLE': 42 })`
// Then, you can use %MY_VARIABLE% in your `index.html`.

// It works in tandem with HtmlWebpackPlugin.
// Learn more about creating plugins like this:
// https://github.com/ampedandwired/html-webpack-plugin#events

'use strict';
const escapeStringRegexp = require('escape-string-regexp');

class InterpolateHtmlPlugin {
constructor(replacements) {
this.replacements = replacements;
}

apply(compiler) {
compiler.hooks.compilation.tap('InterpolateHtmlPlugin', compilation => {
compilation.hooks.htmlWebpackPluginBeforeHtmlProcessing.tap(
'InterpolateHtmlPlugin',
data => {
// Run HTML through a series of user-specified string replacements.
Object.keys(this.replacements).forEach(key => {
const value = this.replacements[key];
data.html = data.html.replace(
new RegExp('%' + escapeStringRegexp(key) + '%', 'g'),
value
);
});
}
);
});
}
}

module.exports = InterpolateHtmlPlugin;
Loading