瀏覽代碼

lint: configure eslint for typescript, fix a few linting warnings

sschmid 4 年之前
父節點
當前提交
d6f51d88f8

+ 207 - 0
.eslintrc.js

@@ -0,0 +1,207 @@
+/*
+👋 Hi! This file was autogenerated by tslint-to-eslint-config.
+https://github.com/typescript-eslint/tslint-to-eslint-config
+
+It represents the closest reasonable ESLint configuration to this
+project's original TSLint configuration.
+
+We recommend eventually switching this configuration to extend from
+the recommended rulesets in typescript-eslint. 
+https://github.com/typescript-eslint/tslint-to-eslint-config/blob/master/docs/FAQs.md
+
+Happy linting! 💖
+*/
+module.exports = {
+    "env": {
+        "browser": true,
+        "es6": true,
+        "node": true
+    },
+    "parser": "@typescript-eslint/parser",
+    "parserOptions": {
+        "project": "tsconfig.json",
+        "sourceType": "module"
+    },
+    "plugins": [
+        "eslint-plugin-jsdoc",
+        "eslint-plugin-no-null",
+        "@typescript-eslint",
+        "@typescript-eslint/tslint"
+    ],
+    "rules": {
+        "@typescript-eslint/dot-notation": "error",
+        "@typescript-eslint/explicit-member-accessibility": [
+            "off",
+            {
+                "accessibility": "explicit"
+            }
+        ],
+        "@typescript-eslint/indent": [
+            "off",
+            2,
+            {
+                "CallExpression": {
+                    "arguments": "first"
+                },
+                "FunctionDeclaration": {
+                    "parameters": "first"
+                },
+                "FunctionExpression": {
+                    "parameters": "first"
+                }
+            }
+        ],
+        "@typescript-eslint/member-delimiter-style": [
+            "error",
+            {
+                "multiline": {
+                    "delimiter": "none",
+                    "requireLast": true
+                },
+                "singleline": {
+                    "delimiter": "comma",
+                    "requireLast": false
+                }
+            }
+        ],
+        "@typescript-eslint/member-ordering": "off",
+        "@typescript-eslint/naming-convention": "off",
+        "@typescript-eslint/no-empty-function": "error",
+        "@typescript-eslint/no-explicit-any": "off",
+        "@typescript-eslint/no-inferrable-types": "off",
+        "@typescript-eslint/no-parameter-properties": "error",
+        "@typescript-eslint/no-require-imports": "off",
+        "@typescript-eslint/no-shadow": [
+            "error",
+            {
+                "hoist": "all"
+            }
+        ],
+        "@typescript-eslint/no-unused-expressions": "error",
+        "@typescript-eslint/no-var-requires": "error",
+        "@typescript-eslint/prefer-namespace-keyword": "error",
+        "@typescript-eslint/quotes": [
+            "error",
+            "double",
+            {
+                "avoidEscape": true
+            }
+        ],
+        "@typescript-eslint/semi": [
+            "error"
+        ],
+        "@typescript-eslint/type-annotation-spacing": "error",
+        "brace-style": [
+            "off",
+            "1tbs"
+        ],
+        "comma-dangle": "off",
+        "curly": "error",
+        "default-case": "error",
+        "eol-last": "error",
+        "eqeqeq": [
+            "error",
+            "smart"
+        ],
+        "guard-for-in": "error",
+        // this misfires in Typescript
+        /*"id-blacklist": [
+            "error",
+            "any",
+            "Number",
+            "number",
+            "String",
+            "string",
+            "Boolean",
+            "boolean",
+            //"Undefined",
+            //"undefined"
+        ],*/
+        "id-match": "error",
+        "jsdoc/check-alignment": "error",
+        "jsdoc/check-indentation": "error",
+        "jsdoc/newline-after-description": "off",
+        "max-len": [
+            "error",
+            {
+                "code": 160
+            }
+        ],
+        "no-bitwise": "error",
+        "no-caller": "error",
+        "no-cond-assign": "error",
+        "no-console": [
+            "error",
+            {
+                "allow": [
+                    "log",
+                    "warn",
+                    "dir",
+                    "timeLog",
+                    "assert",
+                    "clear",
+                    "count",
+                    "countReset",
+                    "group",
+                    "groupEnd",
+                    "table",
+                    "dirxml",
+                    "error",
+                    "groupCollapsed",
+                    "Console",
+                    "profile",
+                    "profileEnd",
+                    "timeStamp",
+                    "context"
+                ]
+            }
+        ],
+        "no-debugger": "error",
+        "no-empty": "error",
+        "no-eval": "error",
+        "no-fallthrough": "error",
+        "no-multiple-empty-lines": "off",
+        "no-new-wrappers": "error",
+        "no-null/no-null": "error",
+        "no-redeclare": "error",
+        "no-trailing-spaces": "error",
+        "no-underscore-dangle": "error",
+        "no-unused-labels": "error",
+        "no-var": "error",
+        "prefer-const": "error",
+        "radix": "error",
+        "spaced-comment": [
+            "off",
+            "always",
+            {
+                "markers": [
+                    "/"
+                ]
+            }
+        ],
+        "@typescript-eslint/tslint/config": [
+            "error",
+            {
+                "rules": {
+                    "object-literal-sort-keys": true,
+                    "typedef": [
+                        true,
+                        "call-signature",
+                        "parameter",
+                        "property-declaration",
+                        "variable-declaration",
+                        "member-variable-declaration"
+                    ],
+                    "whitespace": [
+                        true,
+                        "check-branch",
+                        "check-decl",
+                        "check-operator",
+                        "check-separator",
+                        "check-type"
+                    ]
+                }
+            }
+        ]
+    }
+};

+ 6 - 2
package.json

@@ -7,8 +7,7 @@
   "scripts": {
     "docs": "typedoc --out ./build/docs --name OpenSheetMusicDisplay --module commonjs --target ES2017 --ignoreCompilerErrors --mode file ./src",
     "eslint": "eslint .",
-    "tslint": "tslint --project tsconfig.json \"src/**/*.ts\" \"test/**/*.ts\"",
-    "lint": "npm-run-all tslint eslint",
+    "lint": "eslint -c .eslintrc.js --ext .ts src/",
     "test": "karma start --single-run --no-auto-watch",
     "test:watch": "karma start --no-single-run --auto-watch --browsers ChromeNoSecurity",
     "prebuild": "ncp src/VexFlowPatch/src/ node_modules/vexflow/src/",
@@ -74,6 +73,9 @@
     "@types/chai": "^4.2.11",
     "@types/mocha": "^7.0.2",
     "@types/node": "^14.0.9",
+    "@typescript-eslint/eslint-plugin": "^4.14.0",
+    "@typescript-eslint/eslint-plugin-tslint": "^4.14.0",
+    "@typescript-eslint/parser": "^4.14.0",
     "canvas": "^2.6.1",
     "chai": "^4.1.0",
     "clean-webpack-plugin": "^3.0.0",
@@ -83,6 +85,8 @@
     "eslint": "^6.8.0",
     "eslint-config-standard": "14.1.1",
     "eslint-plugin-import": "^2.20.2",
+    "eslint-plugin-jsdoc": "^31.0.8",
+    "eslint-plugin-no-null": "^1.0.2",
     "eslint-plugin-node": "^11.0.0",
     "eslint-plugin-promise": "^4.2.1",
     "eslint-plugin-standard": "^4.0.0",

+ 1 - 2
src/MusicalScore/Graphical/MusicSystemBuilder.ts

@@ -892,9 +892,8 @@ export class MusicSystemBuilder {
         if (Math.abs(systemVarWidth - 0) < 0.00001 || Math.abs(systemFixWidth - 0) < 0.00001) {
             return 1.0;
         }
-        let systemEndX: number;
         const currentSystem: MusicSystem = this.currentSystemParams.currentSystem;
-        systemEndX = currentSystem.StaffLines[0].PositionAndShape.Size.width;
+        const systemEndX: number = currentSystem.StaffLines[0].PositionAndShape.Size.width;
         const scalingFactor: number = (systemEndX - systemFixWidth) / systemVarWidth;
         return scalingFactor;
     }

+ 4 - 4
src/MusicalScore/Graphical/VexFlow/VexFlowConverter.ts

@@ -40,7 +40,7 @@ export class VexFlowConverter {
      * Mapping from numbers of alterations on the key signature to major keys
      * @type {[alterationsNo: number]: string; }
      */
-    private static majorMap: {[_: number]: string; } = {
+    private static majorMap: {[_: number]: string } = {
         "-1": "F", "-2": "Bb", "-3": "Eb", "-4": "Ab", "-5": "Db", "-6": "Gb", "-7": "Cb", "-8": "Fb",
         "0": "C", "1": "G", "2": "D", "3": "A", "4": "E", "5": "B", "6": "F#", "7": "C#", "8": "G#"
     };
@@ -48,7 +48,7 @@ export class VexFlowConverter {
      * Mapping from numbers of alterations on the key signature to minor keys
      * @type {[alterationsNo: number]: string; }
      */
-    private static minorMap: {[_: number]: string; } = {
+    private static minorMap: {[_: number]: string } = {
         "-1": "D", "-2": "G", "-3": "C", "-4": "F", "-5": "Bb", "-6": "Eb", "-7": "Ab", "-8": "Db",
         "0": "A", "1": "E", "2": "B", "3": "F#", "4": "C#", "5": "G#", "6": "D#", "7": "A#", "8": "E#"
     };
@@ -703,8 +703,8 @@ export class VexFlowConverter {
      * Convert a ClefInstruction to a string represention of a clef type in VexFlow.
      *
      * @param clef The OSMD object to be converted representing the clef
-     * @param size The VexFlow size to be used. Can be `default` or `small`. As soon as
-     *             #118 is done, this parameter will be dispensable.
+     * @param size The VexFlow size to be used. Can be `default` or `small`.
+     * As soon as #118 is done, this parameter will be dispensable.
      * @returns    A string representation of a VexFlow clef
      * @see        https://github.com/0xfe/vexflow/blob/master/src/clef.js
      * @see        https://github.com/0xfe/vexflow/blob/master/tests/clef_tests.js

+ 1 - 1
src/MusicalScore/ScoreIO/MusicSymbolModules/SlurReader.ts

@@ -8,7 +8,7 @@ import { PlacementEnum } from "../../VoiceData/Expressions";
 
 export class SlurReader {
     private musicSheet: MusicSheet;
-    private openSlurDict: { [_: number]: Slur; } = {};
+    private openSlurDict: { [_: number]: Slur } = {};
     constructor(musicSheet: MusicSheet) {
         this.musicSheet = musicSheet;
     }

+ 6 - 6
src/MusicalScore/ScoreIO/VoiceGenerator.ts

@@ -58,9 +58,9 @@ export class VoiceGenerator {
   // private lastBeamTag: string = "";
   private openBeams: Beam[] = []; // works like a stack, with push and pop
   private beamNumberOffset: number = 0;
-  private openTieDict: { [_: number]: Tie; } = {};
+  private openTieDict: { [_: number]: Tie } = {};
   private currentOctaveShift: number = 0;
-  private tupletDict: { [_: number]: Tuplet; } = {};
+  private tupletDict: { [_: number]: Tuplet } = {};
   private openTupletNumber: number = 0;
 
   public get GetVoice(): Voice {
@@ -169,7 +169,7 @@ export class VoiceGenerator {
             if (!arpeggioAlreadyExists) {
                 let arpeggioType: ArpeggioType = ArpeggioType.ARPEGGIO_DIRECTIONLESS;
                 const directionAttr: Attr = arpeggioNode.attribute("direction");
-                if (directionAttr !== null) {
+                if (directionAttr) {
                   switch (directionAttr.value) {
                     case "up":
                       arpeggioType = ArpeggioType.ROLL_UP;
@@ -212,7 +212,7 @@ export class VoiceGenerator {
         }
 
         // remove open ties, if there is already a gap between the last tie note and now.
-        const openTieDict: { [_: number]: Tie; } = this.openTieDict;
+        const openTieDict: { [_: number]: Tie } = this.openTieDict;
         for (const key in openTieDict) {
           if (openTieDict.hasOwnProperty(key)) {
             const tie: Tie = openTieDict[key];
@@ -398,7 +398,7 @@ export class VoiceGenerator {
           }
         } else if (noteElement.name === "notehead") {
           noteheadShapeXml = noteElement.value;
-          if (noteElement.attribute("filled") !== null) {
+          if (noteElement.attribute("filled")) {
             noteheadFilledXml = noteElement.attribute("filled").value === "yes";
           }
         }
@@ -875,7 +875,7 @@ export class VoiceGenerator {
    * @returns {number}
    */
   private findCurrentNoteInTieDict(candidateNote: Note): number {
-    const openTieDict: { [_: number]: Tie; } = this.openTieDict;
+    const openTieDict: { [_: number]: Tie } = this.openTieDict;
     for (const key in openTieDict) {
       if (openTieDict.hasOwnProperty(key)) {
         const tie: Tie = openTieDict[key];

+ 1 - 1
src/MusicalScore/SubInstrument.ts

@@ -12,7 +12,7 @@ export class SubInstrument {
         this.volume = 1.0;
     }
 
-    private static midiInstrument: { [key: string]: MidiInstrument; } = {
+    private static midiInstrument: { [key: string]: MidiInstrument } = {
         "alt": MidiInstrument.Synth_Voice,
         "alto": MidiInstrument.Synth_Voice,
         "banjo": MidiInstrument.Banjo,