diff --git a/ts/styleguide/StyleGuideUtil.ts b/ts/styleguide/StyleGuideUtil.ts
index 8d57014c9..511b55fe6 100644
--- a/ts/styleguide/StyleGuideUtil.ts
+++ b/ts/styleguide/StyleGuideUtil.ts
@@ -1,11 +1,10 @@
import React from 'react';
import ReactDOM from 'react-dom';
-import { padStart, sample } from 'lodash';
+import { default as _, padStart, sample } from 'lodash';
import libphonenumber from 'google-libphonenumber';
-import _ from 'lodash';
import moment from 'moment';
-import qs from 'qs';
+import QueryString from 'qs';
export { _ };
@@ -57,6 +56,7 @@ function makeObjectUrl(data: ArrayBuffer, contentType: string): string {
const blob = new Blob([data], {
type: contentType,
});
+
return URL.createObjectURL(blob);
}
@@ -90,7 +90,7 @@ export {
const parent = window as any;
const query = window.location.search.replace(/^\?/, '');
-const urlOptions = qs.parse(query);
+const urlOptions = QueryString.parse(query);
const theme = urlOptions.theme || 'android';
const locale = urlOptions.locale || 'en';
@@ -99,11 +99,11 @@ import localeMessages from '../../_locales/en/messages.json';
// @ts-ignore
import { setup } from '../../js/modules/i18n';
-import filesize from 'filesize';
+import fileSize from 'filesize';
const i18n = setup(locale, localeMessages);
-parent.filesize = filesize;
+parent.filesize = fileSize;
parent.i18n = i18n;
parent.React = React;
@@ -137,6 +137,7 @@ const Attachments = {
parent.Signal = Signal.setup({
Attachments,
userDataPath: '/',
+ // tslint:disable-next-line:no-backbone-get-set-outside-model
getRegionCode: () => parent.storage.get('regionCode'),
});
parent.SignalService = SignalService;
diff --git a/ts/styleguide/tslint.json b/ts/styleguide/tslint.json
new file mode 100644
index 000000000..4645335d0
--- /dev/null
+++ b/ts/styleguide/tslint.json
@@ -0,0 +1,11 @@
+{
+ "defaultSeverity": "error",
+ "extends": ["../../tslint.json"],
+ "rules": {
+ // To allow the use of devDependencies here
+ "no-implicit-dependencies": false,
+
+ // All tests use arrow functions, and they can be long
+ "max-func-body-length": false
+ }
+}
diff --git a/ts/test/components/media-gallery/groupMessagesByDate.ts b/ts/test/components/media-gallery/groupMessagesByDate_test.ts
similarity index 99%
rename from ts/test/components/media-gallery/groupMessagesByDate.ts
rename to ts/test/components/media-gallery/groupMessagesByDate_test.ts
index 84f9b6fb5..57cb113d9 100644
--- a/ts/test/components/media-gallery/groupMessagesByDate.ts
+++ b/ts/test/components/media-gallery/groupMessagesByDate_test.ts
@@ -1,5 +1,3 @@
-import 'mocha';
-
import { assert } from 'chai';
import { shuffle } from 'lodash';
diff --git a/ts/test/html/index_test.ts b/ts/test/html/index_test.ts
index 87ffc84a9..cefd9469a 100644
--- a/ts/test/html/index_test.ts
+++ b/ts/test/html/index_test.ts
@@ -1,4 +1,3 @@
-import 'mocha';
import { assert } from 'chai';
import * as HTML from '../../html';
@@ -52,6 +51,7 @@ describe('HTML', () => {
{
name: 'URLs without protocols',
input: 'github.com',
+ // tslint:disable-next-line:no-http-string
outputHref: 'http://github.com',
outputLabel: 'github.com',
},
diff --git a/ts/test/tslint.json b/ts/test/tslint.json
new file mode 100644
index 000000000..4645335d0
--- /dev/null
+++ b/ts/test/tslint.json
@@ -0,0 +1,11 @@
+{
+ "defaultSeverity": "error",
+ "extends": ["../../tslint.json"],
+ "rules": {
+ // To allow the use of devDependencies here
+ "no-implicit-dependencies": false,
+
+ // All tests use arrow functions, and they can be long
+ "max-func-body-length": false
+ }
+}
diff --git a/ts/test/types/Attachment_test.ts b/ts/test/types/Attachment_test.ts
index b7ef5f754..a7d251697 100644
--- a/ts/test/types/Attachment_test.ts
+++ b/ts/test/types/Attachment_test.ts
@@ -1,7 +1,3 @@
-/**
- * @prettier
- */
-import 'mocha';
import { assert } from 'chai';
import * as Attachment from '../../types/Attachment';
diff --git a/ts/test/types/Contact_test.ts b/ts/test/types/Contact_test.ts
index 775429adc..40a5d63c6 100644
--- a/ts/test/types/Contact_test.ts
+++ b/ts/test/types/Contact_test.ts
@@ -1,4 +1,3 @@
-import 'mocha';
import { assert } from 'chai';
import { getName } from '../../types/Contact';
diff --git a/ts/test/types/Conversation_test.ts b/ts/test/types/Conversation_test.ts
index 67187f10a..7ff2330bf 100644
--- a/ts/test/types/Conversation_test.ts
+++ b/ts/test/types/Conversation_test.ts
@@ -1,4 +1,3 @@
-import 'mocha';
import { assert } from 'chai';
import * as Conversation from '../../types/Conversation';
diff --git a/ts/test/types/Settings_test.ts b/ts/test/types/Settings_test.ts
index 6b23aca22..d54f9107b 100644
--- a/ts/test/types/Settings_test.ts
+++ b/ts/test/types/Settings_test.ts
@@ -1,11 +1,11 @@
import os from 'os';
-import sinon from 'sinon';
+import Sinon from 'sinon';
import { assert } from 'chai';
import * as Settings from '../../../ts/types/Settings';
describe('Settings', () => {
- const sandbox = sinon.createSandbox();
+ const sandbox = Sinon.createSandbox();
describe('isAudioNotificationSupported', () => {
context('on macOS', () => {
diff --git a/ts/test/types/message/initializeAttachmentMetadata_test.ts b/ts/test/types/message/initializeAttachmentMetadata_test.ts
index 16ba687e3..207012db4 100644
--- a/ts/test/types/message/initializeAttachmentMetadata_test.ts
+++ b/ts/test/types/message/initializeAttachmentMetadata_test.ts
@@ -1,4 +1,3 @@
-import 'mocha';
import { assert } from 'chai';
import * as Message from '../../../../ts/types/message/initializeAttachmentMetadata';
diff --git a/ts/types/Attachment.ts b/ts/types/Attachment.ts
index 3599f184f..b2451420d 100644
--- a/ts/types/Attachment.ts
+++ b/ts/types/Attachment.ts
@@ -121,6 +121,7 @@ export const getSuggestedFilename = ({
: '';
const fileType = getFileExtension(attachment);
const extension = fileType ? `.${fileType}` : '';
+
return `${prefix}${suffix}${extension}`;
};
@@ -133,7 +134,6 @@ export const getFileExtension = (attachment: Attachment): string | null => {
case 'video/quicktime':
return 'mov';
default:
- // TODO: Use better MIME --> file extension mapping:
return attachment.contentType.split('/')[1];
}
};
diff --git a/ts/types/Contact.ts b/ts/types/Contact.ts
index 4ff4f1027..bdc7badfa 100644
--- a/ts/types/Contact.ts
+++ b/ts/types/Contact.ts
@@ -85,6 +85,7 @@ export function contactSelector(
},
};
}
+
return {
...contact,
avatar,
diff --git a/ts/types/Message.ts b/ts/types/Message.ts
index ea5417de0..1a2a6baad 100644
--- a/ts/types/Message.ts
+++ b/ts/types/Message.ts
@@ -100,5 +100,6 @@ export const hasExpiration = (message: Message): boolean => {
}
const { expireTimer } = message;
+
return typeof expireTimer === 'number' && expireTimer > 0;
};
diff --git a/ts/types/backbone/Collection.ts b/ts/types/backbone/Collection.ts
index 078538c42..d5a4df388 100644
--- a/ts/types/backbone/Collection.ts
+++ b/ts/types/backbone/Collection.ts
@@ -4,5 +4,5 @@ export interface Collection
{
models: Array>;
// tslint:disable-next-line no-misused-new
new (): Collection;
- fetch(options: object): JQuery.Deferred;
+ fetch(options: object): JQuery.Deferred;
}
diff --git a/ts/util/arrayBufferToObjectURL.ts b/ts/util/arrayBufferToObjectURL.ts
index 8375faa3b..760193c09 100644
--- a/ts/util/arrayBufferToObjectURL.ts
+++ b/ts/util/arrayBufferToObjectURL.ts
@@ -14,5 +14,6 @@ export const arrayBufferToObjectURL = ({
}
const blob = new Blob([data], { type });
+
return URL.createObjectURL(blob);
};
diff --git a/ts/util/emoji.ts b/ts/util/emoji.ts
index 3aa3dd708..f15e75282 100644
--- a/ts/util/emoji.ts
+++ b/ts/util/emoji.ts
@@ -29,6 +29,7 @@ export function replaceColons(str: string) {
if (code) {
return instance.data[code][0][0];
}
+
return m;
});
}
@@ -51,6 +52,7 @@ function getCountOfAllMatches(str: string, regex: RegExp) {
function hasNormalCharacters(str: string) {
const noEmoji = str.replace(instance.rx_unified, '').trim();
+
return noEmoji.length > 0;
}
@@ -96,6 +98,7 @@ export function getReplacementData(
variation,
};
}
+
return {
value: unified,
};
diff --git a/tslint.json b/tslint.json
index 01efd4298..3e15ab7ad 100644
--- a/tslint.json
+++ b/tslint.json
@@ -1,6 +1,6 @@
{
"defaultSeverity": "error",
- "extends": ["tslint:recommended", "tslint-react"],
+ "extends": ["tslint:recommended", "tslint-react", "tslint-microsoft-contrib"],
"jsRules": {},
"rules": {
"align": [
@@ -35,6 +35,9 @@
"mocha-no-side-effect-code": false,
"mocha-unneeded-done": true,
+ // We always want 'as Type'
+ "no-angle-bracket-type-assertion": true,
+
"no-consecutive-blank-lines": [true, 2],
"object-literal-key-quotes": [true, "as-needed"],
"object-literal-sort-keys": false,
@@ -73,7 +76,54 @@
},
"esSpecCompliant": true
}
- ]
+ ],
+
+ // Disabling a large set of Microsoft-recommended rules
+
+ // Modifying:
+
+ // React components and namespaces are Pascal case
+ "variable-name": [true, "allow-pascal-case"],
+
+ // Maybe will turn on:
+
+ // We're not trying to be comprehensive with JSDoc right now. We have the style guide.
+ "completed-docs": false,
+ // Today we have files with a single named export which isn't the filename. Eventually.
+ "export-name": false,
+ // We have a lot of 'any' in our code today
+ "no-any": false,
+ // We use this today, could get rid of it
+ "no-increment-decrement": false,
+ // This seems to detect false positives: any multi-level object literal, for example
+ "no-object-literal-type-assertion": false,
+ // I like relative references to the current dir, or absolute. Maybe can do this?
+ "no-relative-imports": false,
+ // We have a lot of 'any' in our code today
+ "no-unsafe-any": false,
+ // Not everything needs to be typed right now
+ "typedef": false,
+
+ // Probably won't turn on:
+
+ // We want to import a capitalized React, for example
+ "import-name": false,
+ // We have the styleguide for better docs
+ "missing-jsdoc": false,
+ // 'type' and 'number' are just too common
+ "no-reserved-keywords": false,
+ // The style guide needs JSDoc-style block comments to extract proptype documentation
+ "no-single-line-block-comment": false,
+ // Out-of-order functions can improve readability
+ "no-use-before-declare": false,
+ // We use Array syntax
+ "prefer-array-literal": false,
+ // We prefer key: () => void syntax, because it suggests an object instead of a class
+ "prefer-method-signature": false,
+ // 'as' is nicer than angle brackets.
+ "prefer-type-cast": false,
+ // We use || and && shortcutting because we're javascript programmers
+ "strict-boolean-expressions": false
},
"rulesDirectory": ["node_modules/tslint-microsoft-contrib"]
}