diff --git a/.eslintignore b/.eslintignore index 71f4f8a..7eee4d9 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1,4 @@ dist json/disks/index.js node_modules +tmp diff --git a/.eslintrc.json b/.eslintrc.json index f615dee..dca0508 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,6 +1,11 @@ { + // Global + "root": true, "parser": "@typescript-eslint/parser", - "plugins": ["@typescript-eslint/eslint-plugin"], + "extends": [ + "eslint:recommended", + "plugin:jest/recommended" + ], "rules": { "indent": [ "error", @@ -17,32 +22,15 @@ "error", "unix" ], + "eqeqeq": [ + "error", + "smart" + ], "prefer-const": [ "error" ], - "semi": [ - "error", - "always" - ], + "no-var": "error", "no-use-before-define": "off", - "@typescript-eslint/no-floating-promises": "error", - "@typescript-eslint/no-use-before-define": [ - "error", - { - "functions": false, - "classes": false - } - ], - "no-unused-vars": "off", - "@typescript-eslint/no-unused-vars": [ - "error", - { - "argsIgnorePattern": "^_" - } - ], - "no-redeclare": "off", - "@typescript-eslint/no-redeclare": ["error"], - "no-dupe-class-members": "off", "no-console": [ "error", { @@ -52,6 +40,17 @@ "error" ] } + ], + // Jest configuration + "jest/expect-expect": [ + "error", + { + "assertFunctionNames": [ + "expect*", + "checkImageData", + "testCode" + ] + } ] }, "env": { @@ -59,20 +58,101 @@ "browser": true, "es6": true }, - "parserOptions": { - "sourceType": "module", - "project": "./tsconfig.json" - }, - "extends": "eslint:recommended", "overrides": [ + // All overrides matching a file are applied in-order, with the last + // taking precedence. + // + // TypeScript/TSX-specific configuration { "files": [ - "**/*.ts" + "*.ts", + "*.tsx" + ], + "plugins": [ + "@typescript-eslint/eslint-plugin" + ], + "extends": [ + "plugin:react/recommended", + "plugin:react-hooks/recommended", + "plugin:@typescript-eslint/recommended", + "plugin:@typescript-eslint/recommended-requiring-type-checking" ], "rules": { - "no-var": "error" + // recommended is just "warn" + "@typescript-eslint/no-explicit-any": "error", + // enforce semicolons at ends of statements + "semi": "off", + "@typescript-eslint/semi": [ + "error", + "always" + ], + // enforce semicolons to separate members + "@typescript-eslint/member-delimiter-style": [ + "error", + { + "multiline": { + "delimiter": "semi", + "requireLast": true + }, + "singleline": { + "delimiter": "semi", + "requireLast": false + } + } + ], + // definitions must come before uses for variables + "@typescript-eslint/no-use-before-define": [ + "error", + { + "functions": false, + "classes": false + } + ], + // no used variables + "no-unused-vars": "off", + "@typescript-eslint/no-unused-vars": [ + "error", + { + "argsIgnorePattern": "^_" + } + ], + // no redeclaration of classes, members or variables + "no-redeclare": "off", + "@typescript-eslint/no-redeclare": [ + "error" + ], + // allow empty interface definitions and empty extends + "@typescript-eslint/no-empty-interface": "off", + // allow explicit type declaration + "@typescript-eslint/no-inferrable-types": "off", + // allow some non-string types in templates + "@typescript-eslint/restrict-template-expressions": [ + "error", + { + "allowNumber": true, + "allowBoolean": true + } + ], + // react rules + "react-hooks/rules-of-hooks": "error", + "react-hooks/exhaustive-deps": "error" + }, + "parserOptions": { + "sourceType": "module", + "project": "./tsconfig.json" } }, + // UI elements + { + "files": [ + "js/ui/**.ts" + ], + "rules": { + // allow non-null assertions since these classes reference the DOM + "@typescript-eslint/no-non-null-assertion": "off" + } + }, + // JS Node configuration { "files": [ "bin/*", @@ -88,6 +168,7 @@ "browser": false } }, + // Test configuration { "files": [ "test/**/*" @@ -101,16 +182,18 @@ "no-console": 0 } }, + // Entry point configuration { "files": [ - "js/entry2.js", - "js/entry2e.js", + "js/entry2.ts", + "js/entry2e.ts", "jest.config.js" ], "env": { "commonjs": true } }, + // Worker configuration { "files": [ "workers/*" @@ -120,5 +203,13 @@ } } ], - "ignorePatterns": ["coverage/**/*"] + "ignorePatterns": [ + "coverage/**/*" + ], + "settings": { + "react": { + "pragma": "h", + "version": "16" + } + } } diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 7cc77c0..755a8d0 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -9,7 +9,7 @@ jobs: strategy: matrix: - node-version: [12.x] + node-version: [14.x] steps: - uses: actions/checkout@v2 diff --git a/.stylelintignore b/.stylelintignore new file mode 100644 index 0000000..1c4b846 --- /dev/null +++ b/.stylelintignore @@ -0,0 +1,2 @@ +css/apple2.css +coverage diff --git a/.stylelintrc.json b/.stylelintrc.json new file mode 100644 index 0000000..a3c7063 --- /dev/null +++ b/.stylelintrc.json @@ -0,0 +1,10 @@ +{ + "extends": [ + "stylelint-config-standard", + "stylelint-config-css-modules" + ], + "rules": { + "indentation": 4, + "selector-class-pattern": "^[a-z][a-zA-Z0-9_-]+$" + } +} diff --git a/LICENSE b/LICENSE index 7a90e4c..b66f6b5 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2013-2019 Will Scullin +Copyright (c) 2010-2021 Will Scullin and contributors 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 diff --git a/apple2js.html b/apple2js.html index eef9fbf..c82318a 100644 --- a/apple2js.html +++ b/apple2js.html @@ -1,6 +1,6 @@