From 5b1536cc024e4a18ca9746b85d5563c9ecc8da15 Mon Sep 17 00:00:00 2001 From: Chris Svenningsen Date: Mon, 31 Aug 2020 17:09:28 -0700 Subject: [PATCH] Initial move towards new ESLint config supporting TS Co-authored-by: Sidney Keese --- .eslintignore | 28 + .eslintrc.js | 47 +- _locales/en/messages.json | 40 + app/spell_check.js | 1 - js/modules/i18n.d.ts | 6 + js/modules/link_previews.js | 2 +- js/notifications.js | 1 - js/read_receipts.js | 1 - libtextsecure/test/_test.js | 2 +- package.json | 17 +- test/backup_test.js | 2 +- ts/components/emoji/Emoji.stories.tsx | 8 +- ts/components/emoji/Emoji.tsx | 12 +- ts/components/emoji/EmojiButton.stories.tsx | 9 +- ts/components/emoji/EmojiButton.tsx | 2 + ts/components/emoji/EmojiPicker.stories.tsx | 9 +- ts/components/emoji/EmojiPicker.tsx | 23 +- ts/components/emoji/lib.ts | 38 +- ts/util/lint/exceptions.json | 2500 +++++++++++++++++-- tslint.json | 7 +- webpack.config.ts | 4 +- yarn.lock | 1138 ++++++--- 22 files changed, 3300 insertions(+), 597 deletions(-) create mode 100644 js/modules/i18n.d.ts diff --git a/.eslintignore b/.eslintignore index 805f9aafd..22a42f698 100644 --- a/.eslintignore +++ b/.eslintignore @@ -27,3 +27,31 @@ test/blanket_mocha.js # TypeScript generated files ts/**/*.js +**/*.d.ts +webpack.config.ts + +# Temporarily ignored during TSLint transition +# JIRA: DESKTOP-304 +ts/*.ts +ts/backbone/** +ts/build/** +ts/components/*.ts +ts/components/*.tsx +ts/components/conversation/** +ts/components/stickers/** +ts/notifications/** +ts/protobuf/** +ts/scripts/** +ts/services/** +ts/shims/** +ts/sql/** +ts/state/** +ts/storybook/** +ts/styleguide/** +ts/test/** +ts/textsecure/** +ts/types/** +ts/updater/** +ts/util/** +sticker-creator/**/*.ts +sticker-creator/**/*.tsx diff --git a/.eslintrc.js b/.eslintrc.js index 9bc431d91..895847997 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,7 +1,11 @@ // For reference: https://github.com/airbnb/javascript module.exports = { + root: true, settings: { + react: { + version: 'detect', + }, 'import/core-modules': ['electron'], }, @@ -9,6 +13,35 @@ module.exports = { plugins: ['mocha', 'more'], + overrides: [ + { + files: ['*.ts', '*.tsx'], + parser: '@typescript-eslint/parser', + parserOptions: { + project: 'tsconfig.json', + ecmaFeatures: { + jsx: true, + }, + ecmaVersion: 2018, + sourceType: 'module', + }, + plugins: ['@typescript-eslint'], + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:react/recommended', + 'airbnb-typescript-prettier', + ], + }, + { + files: ['**/*.stories.tsx'], + rules: { + 'import/no-extraneous-dependencies': 'off', + 'react/jsx-props-no-spreading': 'off', + }, + }, + ], + rules: { 'comma-dangle': [ 'error', @@ -37,7 +70,19 @@ module.exports = { 'no-console': 'error', // consistently place operators at end of line except ternaries - 'operator-linebreak': 'error', + 'operator-linebreak': [ + 'error', + 'after', + { overrides: { '?': 'ignore', ':': 'ignore' } }, + ], + + // Temporarily turned off during transition from TSLint + // JIRA: DESKTOP-623 + 'import/order': 'off', + 'no-else-return': 'off', + 'no-async-promise-executor': 'off', + 'prefer-object-spread': 'off', + strict: 'off', quotes: [ 'error', diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 5100bbff6..9fda6af0b 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -1910,6 +1910,42 @@ }, "description": "Shown as a tooltip over the emoji tone buttons." }, + "EmojiPicker__button--recents": { + "message": "Recents", + "description": "Label for recents emoji picker button" + }, + "EmojiPicker__button--emoji": { + "message": "Emoji", + "description": "Label for emoji emoji picker button" + }, + "EmojiPicker__button--animal": { + "message": "Animal", + "description": "Label for animal emoji picker button" + }, + "EmojiPicker__button--food": { + "message": "Food", + "description": "Label for food emoji picker button" + }, + "EmojiPicker__button--activity": { + "message": "Activity", + "description": "Label for activity emoji picker button" + }, + "EmojiPicker__button--travel": { + "message": "Travel", + "description": "Label for travel emoji picker button" + }, + "EmojiPicker__button--object": { + "message": "Object", + "description": "Label for object emoji picker button" + }, + "EmojiPicker__button--symbol": { + "message": "Symbol", + "description": "Label for symbol emoji picker button" + }, + "EmojiPicker__button--flag": { + "message": "Flag", + "description": "Label for flag emoji picker button" + }, "confirmation-dialog--Cancel": { "message": "Cancel", "description": "Appears on the cancel button in confirmation dialogs." @@ -2783,5 +2819,9 @@ "example": "10/23/2023, 7:10 PM" } } + }, + "EmojiButton__label": { + "message": "Emoji", + "description": "Label for emoji button" } } diff --git a/app/spell_check.js b/app/spell_check.js index 36a7e8e41..07f1208b9 100644 --- a/app/spell_check.js +++ b/app/spell_check.js @@ -1,4 +1,3 @@ -/* global exports, require */ /* eslint-disable strict */ const { Menu, clipboard } = require('electron'); diff --git a/js/modules/i18n.d.ts b/js/modules/i18n.d.ts new file mode 100644 index 000000000..7a6853c7c --- /dev/null +++ b/js/modules/i18n.d.ts @@ -0,0 +1,6 @@ +import { LocalizerType } from '../../ts/types/Util'; + +export const setup: ( + language: string, + messages: Record +) => LocalizerType; diff --git a/js/modules/link_previews.js b/js/modules/link_previews.js index 5ee8d53e9..f4232128b 100644 --- a/js/modules/link_previews.js +++ b/js/modules/link_previews.js @@ -239,7 +239,7 @@ function assembleChunks(chunkDescriptors) { return concatenateBytes(...chunks); } -const ASCII_PATTERN = new RegExp('[\\u0000-\\u007F]', 'g'); +const ASCII_PATTERN = new RegExp('[\\u0020-\\u007F]', 'g'); function isLinkSneaky(link) { // Any links which contain auth are considered sneaky diff --git a/js/notifications.js b/js/notifications.js index a63676886..36c8a2080 100644 --- a/js/notifications.js +++ b/js/notifications.js @@ -3,7 +3,6 @@ /* global drawAttention: false */ /* global i18n: false */ -/* global Signal: false */ /* global storage: false */ /* global Whisper: false */ /* global _: false */ diff --git a/js/read_receipts.js b/js/read_receipts.js index 38ed106e8..dc7fa1da1 100644 --- a/js/read_receipts.js +++ b/js/read_receipts.js @@ -4,7 +4,6 @@ _, ConversationController, MessageController, - window */ /* eslint-disable more/no-then */ diff --git a/libtextsecure/test/_test.js b/libtextsecure/test/_test.js index b18a48dda..f5d68d555 100644 --- a/libtextsecure/test/_test.js +++ b/libtextsecure/test/_test.js @@ -1,4 +1,4 @@ -/* global mocha, chai, assert */ +/* global chai */ mocha.setup('bdd'); window.assert = chai.assert; diff --git a/package.json b/package.json index 917ac4ad7..9a1cfefc1 100644 --- a/package.json +++ b/package.json @@ -195,6 +195,8 @@ "@types/webpack": "4.39.0", "@types/webpack-dev-server": "3.1.7", "@types/websocket": "1.0.0", + "@typescript-eslint/eslint-plugin": "3.10.1", + "@typescript-eslint/parser": "3.10.1", "arraybuffer-loader": "1.0.3", "asar": "0.14.0", "babel-core": "7.0.0-bridge.0", @@ -209,12 +211,13 @@ "electron-builder": "22.3.6", "electron-mocha": "8.1.1", "electron-notarize": "0.1.1", - "eslint": "4.18.2", - "eslint-config-airbnb-base": "12.1.0", - "eslint-config-prettier": "2.9.0", - "eslint-plugin-import": "2.8.0", - "eslint-plugin-mocha": "4.12.1", - "eslint-plugin-more": "0.3.1", + "eslint": "7.7.0", + "eslint-config-airbnb-typescript-prettier": "3.1.0", + "eslint-config-prettier": "6.11.0", + "eslint-plugin-import": "2.22.0", + "eslint-plugin-mocha": "8.0.0", + "eslint-plugin-more": "1.0.0", + "eslint-plugin-react": "7.20.6", "file-loader": "4.2.0", "grunt": "1.0.1", "grunt-cli": "1.2.0", @@ -242,7 +245,7 @@ "style-loader": "1.0.0", "ts-loader": "4.1.0", "ts-node": "8.3.0", - "tslint": "5.13.0", + "tslint": "6", "tslint-microsoft-contrib": "6.2.0", "tslint-react": "3.6.0", "typed-scss-modules": "0.0.11", diff --git a/test/backup_test.js b/test/backup_test.js index 943e2b3ba..e8d4971a3 100644 --- a/test/backup_test.js +++ b/test/backup_test.js @@ -1,4 +1,4 @@ -/* global Signal, Whisper, assert, textsecure, _, libsignal */ +/* global Signal, Whisper, textsecure, _, libsignal */ /* eslint-disable no-console */ diff --git a/ts/components/emoji/Emoji.stories.tsx b/ts/components/emoji/Emoji.stories.tsx index 93a5f820a..ef4ce0132 100644 --- a/ts/components/emoji/Emoji.stories.tsx +++ b/ts/components/emoji/Emoji.stories.tsx @@ -1,13 +1,7 @@ import * as React from 'react'; -import { Emoji, EmojiSizes, Props } from './Emoji'; - -// @ts-ignore -import { setup as setupI18n } from '../../js/modules/i18n'; - -// @ts-ignore -import enMessages from '../../_locales/en/messages.json'; import { storiesOf } from '@storybook/react'; import { boolean, select, text } from '@storybook/addon-knobs'; +import { Emoji, EmojiSizes, Props } from './Emoji'; const story = storiesOf('Components/Emoji/Emoji', module); diff --git a/ts/components/emoji/Emoji.tsx b/ts/components/emoji/Emoji.tsx index ba9ab5696..f9910cd5e 100644 --- a/ts/components/emoji/Emoji.tsx +++ b/ts/components/emoji/Emoji.tsx @@ -33,11 +33,13 @@ export const Emoji = React.memo( }: Props, ref ) => { - const image = shortName - ? getImagePath(shortName, skinTone) - : emoji - ? emojiToImage(emoji) - : ''; + let image = ''; + if (shortName) { + image = getImagePath(shortName, skinTone); + } else if (emoji) { + image = emojiToImage(emoji) || ''; + } + const backgroundStyle = inline ? { backgroundImage: `url('${image}')` } : {}; diff --git a/ts/components/emoji/EmojiButton.stories.tsx b/ts/components/emoji/EmojiButton.stories.tsx index 3555b15f2..99ec184f4 100644 --- a/ts/components/emoji/EmojiButton.stories.tsx +++ b/ts/components/emoji/EmojiButton.stories.tsx @@ -1,12 +1,11 @@ import * as React from 'react'; -// @ts-ignore -import { setup as setupI18n } from '../../../js/modules/i18n'; -// @ts-ignore -import enMessages from '../../../_locales/en/messages.json'; - import { storiesOf } from '@storybook/react'; import { action } from '@storybook/addon-actions'; + +import { setup as setupI18n } from '../../../js/modules/i18n'; +import enMessages from '../../../_locales/en/messages.json'; + import { EmojiButton } from './EmojiButton'; const i18n = setupI18n('en', enMessages); diff --git a/ts/components/emoji/EmojiButton.tsx b/ts/components/emoji/EmojiButton.tsx index d8df446f2..60d87afce 100644 --- a/ts/components/emoji/EmojiButton.tsx +++ b/ts/components/emoji/EmojiButton.tsx @@ -105,12 +105,14 @@ export const EmojiButton = React.memo( {({ ref }) => (