diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index a8ca8520..00000000 --- a/.eslintrc.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/eslintrc.json", - "root": true, - "extends": ["@cnblogs/typescript"], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "ecmaVersion": 6, - "sourceType": "module", - "project": ["./tsconfig.json", "./ui/tsconfig.json", "./test/tsconfig.json"] - }, - "rules": { - "prettier/prettier": [ - "error", - { - "endOfLine": "auto", - "semi": false - } - ], - "@typescript-eslint/strict-boolean-expressions": [ - "warn", - { - "allowString": false, - "allowNumber": false, - "allowNullableObject": false, - "allowNullableBoolean": false - } - ] - }, - "ignorePatterns": [ - "rs", - "out", - "pkg", - "dist", - "**/*.d.ts", - "src/test/**", - "src/wasm/**", - "src/assets/**", - "__mocks__/vscode.ts" - ], - "overrides": [ - { - "files": ["*.config.js"], - "env": { - "node": true - } - } - ] -} diff --git a/.prettierrc.js b/.prettierrc.js deleted file mode 100644 index 767c7f06..00000000 --- a/.prettierrc.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = { - ...require('@cnblogs/prettier-config'), - tabWidth: 4, - semi: false, -} diff --git a/.prettierrc.mjs b/.prettierrc.mjs new file mode 100644 index 00000000..9b6dba21 --- /dev/null +++ b/.prettierrc.mjs @@ -0,0 +1,6 @@ +/** @type {import("prettier").Config} */ +export default { + tabWidth: 4, + semi: false, + quotes: "single", +} diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 00000000..d08fac16 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,54 @@ +import eslintJS from "@eslint/js" +import tsEslint from "typescript-eslint" + +export default tsEslint.config({ + files: ["**/*.ts"], + ignores: [ + "**/rs", + "**/out", + "**/pkg", + "**/dist", + "**/*.d.ts", + "src/test/**/*", + "src/wasm/**/*", + "src/assets/**/*", + "__mocks__/vscode.ts", + ], + languageOptions: { + parserOptions: { + project: true, + tsconfigRootDir: import.meta.dirname, + }, + }, + extends: [ + eslintJS.configs.recommended, + ...tsEslint.configs.recommended, + ...tsEslint.configs.stylistic, + ], + rules: { + "@typescript-eslint/explicit-member-accessibility": [ + "off", + { + accessibility: "explicit", + }, + ], + "arrow-parens": ["off", "always"], + "import/order": "off", + "@typescript-eslint/member-ordering": "off", + "no-underscore-dangle": "off", + "@typescript-eslint/naming-convention": "off", + "jsdoc/newline-after-description": 0, + "@typescript-eslint/consistent-indexed-object-style": "off", + "@typescript-eslint/array-type": "off", + "no-extra-boolean-cast": "off", + "@typescript-eslint/no-empty-function": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-inferrable-types": "off", + "@typescript-eslint/no-unused-vars": "off", + "@typescript-eslint/ban-ts-comment": "off", + "no-case-declarations": "off", + "no-prototype-builtins": "off", + "@typescript-eslint/consistent-type-definitions": "off", + "@typescript-eslint/adjacent-overload-signatures": "off", + }, +}) diff --git a/package-lock.json b/package-lock.json index a49cd6ba..8a1fc8b7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38,6 +38,7 @@ "mime-types": "^3.0.1", "node-abort-controller": "^3.1.1", "node-fetch": "^3.3.2", + "prettier": "^3.6.2", "puppeteer-core": "^24.15.0", "randomstring": "^1.3.1", "react": "^18.2.0", @@ -47,8 +48,6 @@ "sqlite3": "^5.1.7" }, "devDependencies": { - "@cnblogs/eslint-config-typescript": "^1.0.4", - "@cnblogs/prettier-config": "^2.0.3", "@types/adm-zip": "^0.5.7", "@types/express": "^5.0.3", "@types/glob": "^9.0.0", @@ -73,7 +72,7 @@ "esbuild": "^0.25.8", "eslint": "^9.32.0", "eslint-config-prettier": "^10.1.8", - "eslint-plugin-prettier": "^5.5.3", + "eslint-plugin-prettier": "^5.5.4", "glob": "^11.0.3", "i": "^0.3.7", "jest": "^30.0.5", @@ -87,7 +86,6 @@ "postcss": "^8.5.6", "postcss-loader": "^8.1.1", "postcss-preset-env": "^10.2.4", - "prettier": "^3.6.2", "style-loader": "^4.0.0", "tailwindcss": "^4.1.11", "terser-webpack-plugin": "^5.3.14", @@ -96,6 +94,7 @@ "ts-node": "^10.9.2", "tsconfig-paths-webpack-plugin": "^4.2.0", "typescript": "^5.9.2", + "typescript-eslint": "^8.39.0", "utility-types": "^3.11.0", "webpack": "^5.101.0", "webpack-cli": "^6.0.1" @@ -648,21 +647,6 @@ "resolved": "https://registry.npmjs.org/@cnblogs/code-quality/-/code-quality-2.0.2.tgz", "integrity": "sha512-B6JM3lhaA2HEQ9lYHWcdT2MqqvmQwO/mBGwQWyWX7COeduMHT4zzZzDv+1+sF12ImX2GaY8oWzAZSw9MbCWgHQ==" }, - "node_modules/@cnblogs/eslint-config-typescript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@cnblogs/eslint-config-typescript/-/eslint-config-typescript-1.0.4.tgz", - "integrity": "sha512-dw2jDC5C8J1A6TxFoHGT6fAWMaanRg0Up3Q1tXR16b/n0HsBmLRcMFDw8zH+d4kuifKhxzVXlib17jAeQdQNXA==", - "dev": true, - "peerDependencies": { - "@typescript-eslint/eslint-plugin": ">= 4.0.0", - "@typescript-eslint/parser": ">= 5.0.0", - "eslint": ">= 7.5.0", - "eslint-config-prettier": ">= 7.0.0", - "eslint-plugin-prettier": ">= 3.0.0", - "prettier": ">= 2.0.0", - "typescript": ">= 4.0.0" - } - }, "node_modules/@cnblogs/load-script-css": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@cnblogs/load-script-css/-/load-script-css-1.6.0.tgz", @@ -713,15 +697,6 @@ "highlight.js": ">=11.0.0 < 12.0.0" } }, - "node_modules/@cnblogs/prettier-config": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@cnblogs/prettier-config/-/prettier-config-2.0.3.tgz", - "integrity": "sha512-ziC6JXSqeZEYLPglHGXtW16ycpdre2AFi1bgyzFLsKpNCApgXwWcXsHH5P87g0MUUvNWl+f181Z8mVrA3f429A==", - "dev": true, - "peerDependencies": { - "prettier": ">= 2.0.0" - } - }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", @@ -5636,6 +5611,19 @@ "node": ">= 8" } }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", @@ -7862,9 +7850,9 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.3.tgz", - "integrity": "sha512-NAdMYww51ehKfDyDhv59/eIItUVzU0Io9H2E8nHNGKEeeqlnci+1gCvrHib6EmZdf6GxF+LCV5K7UC65Ezvw7w==", + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.4.tgz", + "integrity": "sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg==", "dev": true, "license": "MIT", "dependencies": { @@ -10376,19 +10364,6 @@ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest-util/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/jest-validate": { "version": "30.0.5", "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.0.5.tgz", @@ -11124,6 +11099,19 @@ "node": ">=8.6" } }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -15033,12 +15021,13 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8.6" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" @@ -16082,7 +16071,6 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", - "dev": true, "license": "MIT", "bin": { "prettier": "bin/prettier.cjs" @@ -17693,19 +17681,6 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -18047,6 +18022,30 @@ "node": ">=14.17" } }, + "node_modules/typescript-eslint": { + "version": "8.39.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.39.0.tgz", + "integrity": "sha512-lH8FvtdtzcHJCkMOKnN73LIn6SLTpoojgJqDAxPm1jCR14eWSGPX8ul/gggBdPMk/d5+u9V854vTYQ8T5jF/1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.39.0", + "@typescript-eslint/parser": "8.39.0", + "@typescript-eslint/typescript-estree": "8.39.0", + "@typescript-eslint/utils": "8.39.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, "node_modules/uc.micro": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", @@ -19194,12 +19193,6 @@ "resolved": "https://registry.npmjs.org/@cnblogs/code-quality/-/code-quality-2.0.2.tgz", "integrity": "sha512-B6JM3lhaA2HEQ9lYHWcdT2MqqvmQwO/mBGwQWyWX7COeduMHT4zzZzDv+1+sF12ImX2GaY8oWzAZSw9MbCWgHQ==" }, - "@cnblogs/eslint-config-typescript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@cnblogs/eslint-config-typescript/-/eslint-config-typescript-1.0.4.tgz", - "integrity": "sha512-dw2jDC5C8J1A6TxFoHGT6fAWMaanRg0Up3Q1tXR16b/n0HsBmLRcMFDw8zH+d4kuifKhxzVXlib17jAeQdQNXA==", - "dev": true - }, "@cnblogs/load-script-css": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@cnblogs/load-script-css/-/load-script-css-1.6.0.tgz", @@ -19242,12 +19235,6 @@ "markdown-it-task-lists": "npm:@cnblogs/markdown-it-task-lists@^2.1.4" } }, - "@cnblogs/prettier-config": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@cnblogs/prettier-config/-/prettier-config-2.0.3.tgz", - "integrity": "sha512-ziC6JXSqeZEYLPglHGXtW16ycpdre2AFi1bgyzFLsKpNCApgXwWcXsHH5P87g0MUUvNWl+f181Z8mVrA3f429A==", - "dev": true - }, "@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", @@ -22196,6 +22183,14 @@ "requires": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" + }, + "dependencies": { + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + } } }, "aproba": { @@ -23686,9 +23681,9 @@ "dev": true }, "eslint-plugin-prettier": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.3.tgz", - "integrity": "sha512-NAdMYww51ehKfDyDhv59/eIItUVzU0Io9H2E8nHNGKEeeqlnci+1gCvrHib6EmZdf6GxF+LCV5K7UC65Ezvw7w==", + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.4.tgz", + "integrity": "sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg==", "dev": true, "requires": { "prettier-linter-helpers": "^1.0.0", @@ -25373,14 +25368,6 @@ "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", "picomatch": "^4.0.2" - }, - "dependencies": { - "picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true - } } }, "jest-validate": { @@ -25916,6 +25903,14 @@ "requires": { "braces": "^3.0.3", "picomatch": "^2.3.1" + }, + "dependencies": { + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + } } }, "mime": { @@ -28519,9 +28514,9 @@ "dev": true }, "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true }, "pify": { @@ -29052,8 +29047,7 @@ "prettier": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", - "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", - "dev": true + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==" }, "prettier-linter-helpers": { "version": "1.0.0", @@ -30104,14 +30098,6 @@ "requires": { "fdir": "^6.4.4", "picomatch": "^4.0.2" - }, - "dependencies": { - "picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true - } } }, "tmpl": { @@ -30326,6 +30312,18 @@ "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", "dev": true }, + "typescript-eslint": { + "version": "8.39.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.39.0.tgz", + "integrity": "sha512-lH8FvtdtzcHJCkMOKnN73LIn6SLTpoojgJqDAxPm1jCR14eWSGPX8ul/gggBdPMk/d5+u9V854vTYQ8T5jF/1Q==", + "dev": true, + "requires": { + "@typescript-eslint/eslint-plugin": "8.39.0", + "@typescript-eslint/parser": "8.39.0", + "@typescript-eslint/typescript-estree": "8.39.0", + "@typescript-eslint/utils": "8.39.0" + } + }, "uc.micro": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", diff --git a/package.json b/package.json index 5f52b2b5..fc43e4fd 100644 --- a/package.json +++ b/package.json @@ -1315,8 +1315,6 @@ ] }, "devDependencies": { - "@cnblogs/eslint-config-typescript": "^1.0.4", - "@cnblogs/prettier-config": "^2.0.3", "@types/adm-zip": "^0.5.7", "@types/express": "^5.0.3", "@types/glob": "^9.0.0", @@ -1341,7 +1339,7 @@ "esbuild": "^0.25.8", "eslint": "^9.32.0", "eslint-config-prettier": "^10.1.8", - "eslint-plugin-prettier": "^5.5.3", + "eslint-plugin-prettier": "^5.5.4", "glob": "^11.0.3", "i": "^0.3.7", "jest": "^30.0.5", @@ -1355,7 +1353,6 @@ "postcss": "^8.5.6", "postcss-loader": "^8.1.1", "postcss-preset-env": "^10.2.4", - "prettier": "^3.6.2", "style-loader": "^4.0.0", "tailwindcss": "^4.1.11", "terser-webpack-plugin": "^5.3.14", @@ -1364,6 +1361,7 @@ "ts-node": "^10.9.2", "tsconfig-paths-webpack-plugin": "^4.2.0", "typescript": "^5.9.2", + "typescript-eslint": "^8.39.0", "utility-types": "^3.11.0", "webpack": "^5.101.0", "webpack-cli": "^6.0.1" @@ -1398,6 +1396,7 @@ "mime-types": "^3.0.1", "node-abort-controller": "^3.1.1", "node-fetch": "^3.3.2", + "prettier": "^3.6.2", "puppeteer-core": "^24.15.0", "randomstring": "^1.3.1", "react": "^18.2.0", diff --git a/src/auth/auth-manager.ts b/src/auth/auth-manager.ts index 8c60ffe1..dfea208e 100644 --- a/src/auth/auth-manager.ts +++ b/src/auth/auth-manager.ts @@ -27,38 +27,38 @@ authProvider.onDidChangeSessions(async e => { await BlogExportProvider.optionalInstance?.refreshRecords({ force: false, clearCache: true }) }) -export namespace AuthManager { - export async function isAuthed() { +export class AuthManager { + static async isAuthed() { const sessionJsonList = await LocalState.getSecret(ExtConst.EXT_SESSION_STORAGE_KEY) const sessionList = JSON.parse(sessionJsonList ?? '[]') as AuthSession[] return sessionList.length > 0 } - export function ensureSession(opt?: AuthGetSessionOpt) { + static ensureSession(opt?: AuthGetSessionOpt) { try { return authentication.getSession(authProvider.providerId, [], opt) } catch (e) { - throw Error(`创建/获取 Session 失败: ${e}`) + throw Error(`创建/获取 Session 失败: ${e as string}`) } } - export async function webLogin() { + static async webLogin() { authProvider.useBrowser() - await login() + await AuthManager.login() } - export async function patLogin() { + static async patLogin() { authProvider.usePat() - await login() + await AuthManager.login() } - export async function login() { - const session = await ensureSession({ createIfNone: false, forceNewSession: true }) + static async login() { + const session = await AuthManager.ensureSession({ createIfNone: false, forceNewSession: true }) if (session !== undefined) await LocalState.setSecret(ExtConst.EXT_SESSION_STORAGE_KEY, JSON.stringify([session])) } - export async function logout() { + static async logout() { if (!(await AuthManager.isAuthed())) return try { @@ -68,24 +68,24 @@ export namespace AuthManager { await authProvider.removeSession(session.id) await Oauth.revokeToken(token) } catch (e) { - void Alert.err(`登出发生错误: ${e}`) + void Alert.err(`登出发生错误: ${e as string}`) throw e } } - export async function acquireToken() { - const session = await ensureSession({ createIfNone: false }) + static async acquireToken() { + const session = await AuthManager.ensureSession({ createIfNone: false }) if (session === undefined) Alert.throwWithWarn('未授权') if (isAuthSessionExpired(session)) { void Alert.warn('授权已过期,请重新登录') - await logout() + await AuthManager.logout() } return session?.accessToken } - export async function updateAuthStatus() { + static async updateAuthStatus() { const isAuthed = await AuthManager.isAuthed() await setCtx('isAuthed', isAuthed) await setCtx('isUnauthorized', !isAuthed) diff --git a/src/auth/auth-provider.ts b/src/auth/auth-provider.ts index e9477a32..4e9eca86 100644 --- a/src/auth/auth-provider.ts +++ b/src/auth/auth-provider.ts @@ -1,4 +1,4 @@ -import { AuthenticationSession as AuthSession, AuthenticationSession } from 'vscode' +import { AuthenticationSession as AuthSession, AuthenticationProviderSessionOptions, AuthenticationSession } from 'vscode' import { genVerifyChallengePair } from '@/service/code-challenge' import { authentication, @@ -22,7 +22,7 @@ import { LocalState } from '@/ctx/local-state' import { ExtConst } from '@/ctx/ext-const' import { UserService } from '@/service/user.service' -async function browserSignIn(challengeCode: string, scopes: string[]) { +async function browserSignIn(challengeCode: string, scopes: readonly string[]) { const para = consUrlPara( ['client_id', ExtConst.CLIENT_ID], ['client_secret', ExtConst.CLIENT_SEC], @@ -39,7 +39,7 @@ async function browserSignIn(challengeCode: string, scopes: string[]) { try { await env.openExternal(uri) } catch (e) { - void Alert.err(`重定向失败: ${e}`) + void Alert.err(`重定向失败: ${e as string}`) } } @@ -73,10 +73,10 @@ export class AuthProvider implements AuthenticationProvider, Disposable { this._usePat = true } - async getSessions(scopes?: string[]): Promise { + async getSessions(scopes: readonly string[] | undefined, options: AuthenticationProviderSessionOptions): + Promise { const sessions = await this.getAllSessions() const parsedScopes = this.ensureScopes(scopes) - return sessions.filter(({ scopes: sessionScopes }) => parsedScopes.every(x => sessionScopes.includes(x))) } @@ -84,7 +84,7 @@ export class AuthProvider implements AuthenticationProvider, Disposable { return this._usePat ? this.createSessionFromPat(scopes) : this.createSessionFromBrowser(scopes) } - // eslint-disable-next-line @typescript-eslint/no-unused-vars + async createSessionFromPat(scopes: string[]) { const validateInput = (value: string) => { if (value.trim().length === 0) @@ -181,7 +181,7 @@ export class AuthProvider implements AuthenticationProvider, Disposable { else keep.push(s) return { remove, keep } }, - { remove: [], keep: [] } + { remove: [] as AuthSession[], keep: [] as AuthSession[] } ) await LocalState.setSecret(ExtConst.EXT_SESSION_STORAGE_KEY, JSON.stringify(data.keep)) this._sessionChangeEmitter.fire({ removed: data.remove, added: undefined, changed: undefined }) @@ -204,15 +204,15 @@ export class AuthProvider implements AuthenticationProvider, Disposable { const { accountId, displayName } = userInfo - const session = { + const session = { account: { id: new Number(accountId).toString(), label: displayName, }, id: `${this.providerId}-${userInfo.accountId}`, accessToken: token, - scopes: this.ensureScopes(null), - } + scopes: this.ensureScopes(undefined), + } as AuthenticationSession await LocalState.setSecret(ExtConst.EXT_SESSION_STORAGE_KEY, JSON.stringify([session])) @@ -239,9 +239,9 @@ export class AuthProvider implements AuthenticationProvider, Disposable { } private ensureScopes( - scopes: string[] | null | undefined, + scopes: readonly string[] | undefined, { default: defaultScopes = ExtConst.OAUTH_SCOPES } = {} - ): string[] { + ): readonly string[] { return scopes == null || scopes.length <= 0 ? defaultScopes : scopes } } diff --git a/src/auth/is-auth-session-expired.ts b/src/auth/is-auth-session-expired.ts index 3efedf76..e34e243f 100644 --- a/src/auth/is-auth-session-expired.ts +++ b/src/auth/is-auth-session-expired.ts @@ -8,6 +8,6 @@ export function isAuthSessionExpired(authSession: AuthSession) { const accessTokenPart2 = accessToken.split('.')[1] const buf = Buffer.from(accessTokenPart2, 'base64') - const exp = JSON.parse(buf.toString()).exp + const exp = JSON.parse(buf.toString()).exp as number return exp * 1000 < Date.now() } diff --git a/src/auth/oauth.ts b/src/auth/oauth.ts index 4ba12739..47fa385a 100644 --- a/src/auth/oauth.ts +++ b/src/auth/oauth.ts @@ -7,23 +7,23 @@ function getAuthedOauthReq() { return new OauthReq(ExtConst.CLIENT_ID, ExtConst.CLIENT_SEC) } -export namespace Oauth { - export function getToken(verifyCode: string, authCode: string) { +export class Oauth { + static getToken(verifyCode: string, authCode: string) { const req = getAuthedOauthReq() try { return req.getToken(authCode, verifyCode, globalCtx.extUrl) } catch (e) { - void Alert.err(`获取 Token 失败: ${e}`) + void Alert.err(`获取 Token 失败: ${e as string}`) throw e } } - export function revokeToken(token: string) { + static revokeToken(token: string) { try { const req = getAuthedOauthReq() return req.revokeToken(token) } catch (e) { - void Alert.err(`撤销 Token 失败: ${e}`) + void Alert.err(`撤销 Token 失败: ${e as string}`) } } } diff --git a/src/cmd/blog-export/create.ts b/src/cmd/blog-export/create.ts index f7e13bfd..140dade9 100644 --- a/src/cmd/blog-export/create.ts +++ b/src/cmd/blog-export/create.ts @@ -17,7 +17,7 @@ export async function createBlogExport() { await BlogExportApi.create() await BlogExportProvider.optionalInstance?.refreshRecords() } catch (e) { - void Alert.err(`创建备份失败: ${e}`) + void Alert.err(`创建备份失败: ${e as string}`) return false } } diff --git a/src/cmd/blog-export/delete.ts b/src/cmd/blog-export/delete.ts index b2a89089..2ecd89bd 100644 --- a/src/cmd/blog-export/delete.ts +++ b/src/cmd/blog-export/delete.ts @@ -48,7 +48,7 @@ async function deleteExportRecordItem(item: BlogExportRecordTreeItem) { const hasDeleted = await BlogExportApi.del(record.id) .then(() => true) .catch(e => { - void Alert.err(`删除博客备份失败: ${e}`) + void Alert.err(`删除博客备份失败: ${e as string}`) return false }) if (hasDeleted) if (downloaded !== undefined) await removeDownloadedBlogExport(downloaded, { shouldDeleteLocal }) diff --git a/src/cmd/blog-export/download.ts b/src/cmd/blog-export/download.ts index 790c83cd..10e3db9a 100644 --- a/src/cmd/blog-export/download.ts +++ b/src/cmd/blog-export/download.ts @@ -9,7 +9,6 @@ import { Progress } from 'got' import path from 'path' import { promisify } from 'util' import { WorkspaceCfg } from '@/ctx/cfg/workspace' -// eslint-disable-next-line @typescript-eslint/naming-convention import AdmZip from 'adm-zip' import { setCtx } from '@/ctx/global-ctx' import { fsUtil } from '@/infra/fs/fsUtil' @@ -46,7 +45,7 @@ export async function downloadBlogExport(treeItem?: BlogExportRecordTreeItem) { treeItem.reportDownloadingProgress({ percentage, transferred, total: total ?? transferred }) blogExportProvider?.refreshItem(treeItem) }) - .on('error', e => { + .on('error', (e: { toString: () => string }) => { treeItem.reportDownloadingProgress(null) void onError('下载博客备份失败' + ', ' + e.toString()) }) diff --git a/src/cmd/blog-export/open-local.ts b/src/cmd/blog-export/open-local.ts index 029df51a..e69445a0 100644 --- a/src/cmd/blog-export/open-local.ts +++ b/src/cmd/blog-export/open-local.ts @@ -18,9 +18,7 @@ export async function openLocalExport(opts: Partial = def canSelectFolders: false, canSelectMany: false, filters: { - // eslint-disable-next-line @typescript-eslint/naming-convention Sqlite: ['db', 'zip'], - // eslint-disable-next-line @typescript-eslint/naming-convention // ZipSqlite: ['zip'], }, })) ?? [] @@ -44,7 +42,7 @@ export async function openLocalExport(opts: Partial = def // } if (isConfirmedToUnzip) { - // eslint-disable-next-line @typescript-eslint/naming-convention + const AdmZip = (await import('adm-zip')).default const zip = new AdmZip(filePath) zip.extractEntryTo(`${fileName}.db`, dirname, false, true) diff --git a/src/cmd/browser.ts b/src/cmd/browser.ts index ac0601d2..44903b55 100644 --- a/src/cmd/browser.ts +++ b/src/cmd/browser.ts @@ -3,38 +3,40 @@ import { execCmd } from '@/infra/cmd' import { UserService } from '@/service/user.service' import { Alert } from '@/infra/alert' -export namespace Browser.Open { - export function open(url: string) { - return execCmd('vscode.open', Uri.parse(url)) - } -} +export class Browser { + static Open = class { + static open(url: string) { + return execCmd('vscode.open', Uri.parse(url)) + } -export namespace Browser.Open.Cnb { - export const home = () => open('https://www.cnblogs.com') - export const news = () => open('https://news.cnblogs.com') - export const ing = () => open('https://ing.cnblogs.com') - export const q = () => open('https://q.cnblogs.com') -} + static Cnb = class { + static home = () => Browser.Open.open('https://www.cnblogs.com') + static news = () => Browser.Open.open('https://news.cnblogs.com') + static ing = () => Browser.Open.open('https://ing.cnblogs.com') + static q = () => Browser.Open.open('https://q.cnblogs.com') + } -export namespace Browser.Open.User { - export const accountSetting = () => open('https://account.cnblogs.com/settings/account') - export const buyVip = () => open('https://cnblogs.vip/') + User = class { + static accountSetting = () => Browser.Open.open('https://account.cnblogs.com/settings/account') + static buyVip = () => Browser.Open.open('https://cnblogs.vip/') - export async function blog() { - const blogApp = (await UserService.getUserInfo())?.blogApp + static async blog() { + const blogApp = (await UserService.getUserInfo())?.blogApp - if (blogApp == null) return void Alert.warn('未开通博客') + if (blogApp == null) return void Alert.warn('未开通博客') - void open(`https://www.cnblogs.com/${blogApp}`) - } + void Browser.Open.open(`https://www.cnblogs.com/${blogApp}`) + } - export const blogConsole = () => open('https://write.cnblogs.com') + static blogConsole = () => Browser.Open.open('https://write.cnblogs.com') - export async function home() { - const accountId = (await UserService.getUserInfo())?.accountId - if (accountId !== undefined) { - const url = `https://home.cnblogs.com/u/${accountId}` - return open(url) + static async home() { + const accountId = (await UserService.getUserInfo())?.accountId + if (accountId !== undefined) { + const url = `https://home.cnblogs.com/u/${accountId}` + return Browser.Open.open(url) + } + } } } } diff --git a/src/cmd/ing/ing-page-list.ts b/src/cmd/ing/ing-page-list.ts index da78cd60..e519d2d2 100644 --- a/src/cmd/ing/ing-page-list.ts +++ b/src/cmd/ing/ing-page-list.ts @@ -2,60 +2,62 @@ import { getIngListWebviewProvider } from '@/service/ing/ing-list-webview-provid import { QuickPickItem, window } from 'vscode' import { IngType, IngTypesMetadata } from '@/model/ing' -export namespace Ing.ListView { - export const refresh = () => getIngListWebviewProvider().reload() - - export function goNext() { - const provider = getIngListWebviewProvider() - const { pageIndex } = provider - return provider.reload({ pageIndex: pageIndex + 1 }) - } - - export function goPrev() { - const provider = getIngListWebviewProvider() - const { pageIndex } = provider - if (pageIndex > 1) return provider.reload({ pageIndex: pageIndex - 1 }) - return Promise.resolve() - } - - export function goFirst(): Promise { - return getIngListWebviewProvider().reload({ pageIndex: 1 }) - } - - export function switchType() { - const options: (QuickPickItem & { ingType: IngType })[] = IngTypesMetadata.map( - ([ingType, { displayName, description }]) => ({ - label: displayName, - ingType: ingType, - description: description, - picked: ingType === getIngListWebviewProvider().ingType, - }) - ) - const quickPick = window.createQuickPick<(typeof options)[0]>() - - quickPick.title = '选择闪存类型' - quickPick.items = options - quickPick.canSelectMany = false - quickPick.activeItems = options.filter(x => x.picked) - quickPick.selectedItems = quickPick.activeItems - quickPick.ignoreFocusOut = false - - const disposables = [quickPick] - - quickPick.onDidChangeSelection( - ([selectedItem]) => { - quickPick.hide() - return getIngListWebviewProvider().reload({ - pageIndex: 1, - ingType: selectedItem.ingType, +export class Ing { + static ListView = class { + static refresh = () => getIngListWebviewProvider().reload() + + static goNext() { + const provider = getIngListWebviewProvider() + const { pageIndex } = provider + return provider.reload({ pageIndex: pageIndex + 1 }) + } + + static goPrev() { + const provider = getIngListWebviewProvider() + const { pageIndex } = provider + if (pageIndex > 1) return provider.reload({ pageIndex: pageIndex - 1 }) + return Promise.resolve() + } + + static goFirst(): Promise { + return getIngListWebviewProvider().reload({ pageIndex: 1 }) + } + + static switchType() { + const options: (QuickPickItem & { ingType: IngType })[] = IngTypesMetadata.map( + ([ingType, { displayName, description }]) => ({ + label: displayName, + ingType: ingType, + description: description, + picked: ingType === getIngListWebviewProvider().ingType, }) - }, - undefined, - disposables - ) - quickPick.onDidHide(() => disposables.forEach(d => d.dispose()), undefined, disposables) - quickPick.show() - - return Promise.resolve() + ) + const quickPick = window.createQuickPick<(typeof options)[0]>() + + quickPick.title = '选择闪存类型' + quickPick.items = options + quickPick.canSelectMany = false + quickPick.activeItems = options.filter(x => x.picked) + quickPick.selectedItems = quickPick.activeItems + quickPick.ignoreFocusOut = false + + const disposables = [quickPick] + + quickPick.onDidChangeSelection( + ([selectedItem]) => { + quickPick.hide() + return getIngListWebviewProvider().reload({ + pageIndex: 1, + ingType: selectedItem.ingType, + }) + }, + undefined, + disposables + ) + quickPick.onDidHide(() => disposables.forEach(d => d.dispose()), undefined, disposables) + quickPick.show() + + return Promise.resolve() + } } } diff --git a/src/cmd/ing/pub-ing-with-input.ts b/src/cmd/ing/pub-ing-with-input.ts index 5fe2ae3f..01f96128 100644 --- a/src/cmd/ing/pub-ing-with-input.ts +++ b/src/cmd/ing/pub-ing-with-input.ts @@ -77,7 +77,6 @@ class InteractiveState { } private async showConfirm() { - // eslint-disable-next-line no-constant-condition while (true) { const items = [ ['确定', () => Promise.resolve(true)], diff --git a/src/cmd/pdf/export-pdf.ts b/src/cmd/pdf/export-pdf.ts index b3be9a44..8b2e19a2 100644 --- a/src/cmd/pdf/export-pdf.ts +++ b/src/cmd/pdf/export-pdf.ts @@ -1,4 +1,3 @@ -import type puppeteer from 'puppeteer-core' import fs from 'fs' import path from 'path' import os from 'os' @@ -14,6 +13,7 @@ import { PostEditDto } from '@/model/post-edit-dto' import { PostPdfTemplateBuilder } from '@/cmd/pdf/post-pdf-template-builder' import { ChromiumCfg } from '@/ctx/cfg/chromium' import { UserService } from '@/service/user.service' +import { Page } from 'puppeteer-core' async function launchBrowser(chromiumPath: string) { try { @@ -37,7 +37,7 @@ const exportOne = async ( idx: number, total: number, post: Post, - page: puppeteer.Page, + page: Page, targetFileUri: Uri, progress: Progress<{ message: string; increment: number }>, blogApp: string @@ -70,7 +70,7 @@ const exportOne = async ( report(-100) } -const createPdfBuffer = (page: puppeteer.Page) => +const createPdfBuffer = (page: Page) => page.pdf({ format: 'a4', printBackground: true, @@ -82,7 +82,7 @@ const createPdfBuffer = (page: puppeteer.Page) => }, }) -const writePdfToFile = (dir: Uri, post: Post, buffer: Buffer) => +const writePdfToFile = (dir: Uri, post: Post, buffer: Uint8Array) => new Promise(resolve => { fs.writeFile(path.join(dir.fsPath, `${post.title}.pdf`), buffer, () => { resolve() @@ -202,7 +202,7 @@ export async function exportPostToPdf(input?: Post | PostTreeItem | Uri): Promis try { await exportOne(idx++, total, post, page, dir, progress, blogApp) } catch (e) { - void Alert.err(`导出 ${post.title} 失败: ${e}`) + void Alert.err(`导出 ${post.title} 失败: ${e as string}`) } } await page.close() diff --git a/src/cmd/pdf/post-pdf-template-builder.ts b/src/cmd/pdf/post-pdf-template-builder.ts index 108b6b26..7bb29d35 100644 --- a/src/cmd/pdf/post-pdf-template-builder.ts +++ b/src/cmd/pdf/post-pdf-template-builder.ts @@ -1,4 +1,3 @@ -/* eslint-disable prettier/prettier */ import { Post } from '@/model/post' import { PostFileMapManager } from '@/service/post/post-file-map' import fs from 'fs' @@ -8,10 +7,10 @@ import { markdownItFactory } from '@cnblogs/markdown-it-presets' import { UserService } from '@/service/user.service' import { PostCateStore } from '@/stores/post-cate-store' -export namespace PostPdfTemplateBuilder { - export const HighlightedMessage = 'markdown-highlight-finished' +export class PostPdfTemplateBuilder { + static HighlightedMessage = 'markdown-highlight-finished' - export async function build(post: Post, blogApp: string): Promise { + static async build(post: Post, blogApp: string): Promise { let { postBody } = post const { isMarkdown, id: postId } = post @@ -127,7 +126,7 @@ export namespace PostPdfTemplateBuilder { diff --git a/src/cmd/post-cat/del-selected-cat.ts b/src/cmd/post-cat/del-selected-cat.ts index 839c8595..3c2ee40d 100644 --- a/src/cmd/post-cat/del-selected-cat.ts +++ b/src/cmd/post-cat/del-selected-cat.ts @@ -51,7 +51,7 @@ export async function delSelectedCat(input?: PostCatTreeItem | PostCat) { await PostCatService.del(category.categoryId) idx++ } catch (e) { - void Alert.err(`删除失败: ${e}`) + void Alert.err(`删除失败: ${e as string}`) } } diff --git a/src/cmd/post-cat/input-post-cat.ts b/src/cmd/post-cat/input-post-cat.ts index d4eddcc9..b8882977 100644 --- a/src/cmd/post-cat/input-post-cat.ts +++ b/src/cmd/post-cat/input-post-cat.ts @@ -44,11 +44,11 @@ export async function inputPostCat(parentTitle: string, cat?: PostCat) { const title = await setupTitle(parentTitle, cat?.title ?? '') const isVisible = await setupVisible(title) const description = await setupDescription(title, cat?.description ?? '') - return { + return { title, visible: isVisible, description, - } + } as PostCatAddDto } catch (_) { // input canceled, do nothing } diff --git a/src/cmd/post-cat/update-post-cat-treeview.ts b/src/cmd/post-cat/update-post-cat-treeview.ts index be16095a..cf61a9d7 100644 --- a/src/cmd/post-cat/update-post-cat-treeview.ts +++ b/src/cmd/post-cat/update-post-cat-treeview.ts @@ -35,7 +35,7 @@ export async function updatePostCatTreeView(arg?: PostCat | PostCatTreeItem) { await postCategoryDataProvider.refreshAsync() p.report({ increment: 100 }) } catch (e) { - void Alert.err(`更新博文失败: ${e}`) + void Alert.err(`更新博文失败: ${e as string}`) p.report({ increment: 100 }) } }) diff --git a/src/cmd/post-list/del-post.ts b/src/cmd/post-list/del-post.ts index e5e47053..f4c53f7c 100644 --- a/src/cmd/post-list/del-post.ts +++ b/src/cmd/post-list/del-post.ts @@ -84,7 +84,7 @@ export async function delSelectedPost(arg: unknown) { postIds: selectedPost.map(({ id }) => id), }) } catch (e) { - void Alert.err(`删除博文失败: ${e}`) + void Alert.err(`删除博文失败: ${e as string}`) } progress.report({ increment: 100 }) diff --git a/src/cmd/post-list/post-list-view.ts b/src/cmd/post-list/post-list-view.ts index 2627ebc0..f72a41c9 100644 --- a/src/cmd/post-list/post-list-view.ts +++ b/src/cmd/post-list/post-list-view.ts @@ -49,14 +49,14 @@ function updatePostListViewTitle() { } } -export namespace PostListView { - export async function refresh({ queue = false, pageIndex = 1 } = {}): Promise { +export class PostListView { + static async refresh({ queue = false, pageIndex = 1 } = {}): Promise { if (isLoading && !queue) { await refreshTask return false } else if (isLoading && refreshTask != null) { await refreshTask - return refresh() + return PostListView.refresh() } const fut = async () => { @@ -77,7 +77,7 @@ export namespace PostListView { refreshTask = fut() .then(() => true) .catch(async e => { - if (await UserService.hasBlog()) void Alert.err(`刷新随笔列表失败: ${e}`) + if (await UserService.hasBlog()) void Alert.err(`刷新随笔列表失败: ${e as string}`) return false }) .finally(() => (refreshTask = null)) @@ -85,11 +85,11 @@ export namespace PostListView { return refreshTask } - export const goNext = () => goPage(i => i + 1) + static goNext = () => goPage(i => i + 1) - export const goPrev = () => goPage(i => i - 1) + static goPrev = () => goPage(i => i - 1) - export async function seek() { + static async seek() { const input = await window.showInputBox({ placeHolder: '请输入页码', validateInput: i => { @@ -108,8 +108,8 @@ export namespace PostListView { if (pageIndex > 0 && !isNaN(pageIndex)) await goPage(() => pageIndex) } - export namespace Search { - export async function search() { + static Search = class { + static async search() { const searchKey = await window.showInputBox({ ignoreFocusOut: true, title: '搜索随笔', @@ -122,8 +122,8 @@ export namespace PostListView { await postDataProvider.search(searchKey) } - export const clear = () => postDataProvider.clearSearch() + static clear = () => postDataProvider.clearSearch() - export const refresh = () => postDataProvider.refreshSearch() + static refresh = () => postDataProvider.refreshSearch() } } diff --git a/src/cmd/post-list/post-pull.ts b/src/cmd/post-list/post-pull.ts index 3a60abd6..919f3c64 100644 --- a/src/cmd/post-list/post-pull.ts +++ b/src/cmd/post-list/post-pull.ts @@ -61,7 +61,6 @@ export async function postPull(input: InputType, showConfirm = true, mute = fals uriPath = fileUri.path const fsPath = fileUri.fsPath const fileName = path.basename(fsPath) - // eslint-disable-next-line @typescript-eslint/naming-convention const fileExists = await fsUtil.exists(fsPath) if (fileExists) { diff --git a/src/cmd/post-list/upload-post.ts b/src/cmd/post-list/upload-post.ts index dc4192b9..3be0700d 100644 --- a/src/cmd/post-list/upload-post.ts +++ b/src/cmd/post-list/upload-post.ts @@ -172,7 +172,7 @@ export async function uploadPost(input?: Post | PostTreeItem | PostEditDto, conf await PostListView.refresh() } catch (e) { progress.report({ increment: 100 }) - void Alert.err(`上传失败: ${e}`) + void Alert.err(`上传失败: ${e as string}`) } return isSaved diff --git a/src/cmd/show-local-file-to-post-info.ts b/src/cmd/show-local-file-to-post-info.ts index ae2fd144..6089d867 100644 --- a/src/cmd/show-local-file-to-post-info.ts +++ b/src/cmd/show-local-file-to-post-info.ts @@ -1,4 +1,3 @@ -/* eslint-disable prettier/prettier */ import path from 'path' import { Uri } from 'vscode' import { Alert } from '@/infra/alert' @@ -6,7 +5,7 @@ import { PostService } from '@/service/post/post' import { PostFileMapManager } from '@/service/post/post-file-map' import { searchPostByTitle } from '@/service/post/search-post-by-title' import { viewPostOnline } from './view-post-online' -import format from 'date-fns/format' +import { format } from 'date-fns/format' import { PostCateStore } from '@/stores/post-cate-store' /** diff --git a/src/cmd/upload-img/upload-img-from-path.ts b/src/cmd/upload-img/upload-img-from-path.ts index 4c8309f5..b6ca51e3 100644 --- a/src/cmd/upload-img/upload-img-from-path.ts +++ b/src/cmd/upload-img/upload-img-from-path.ts @@ -7,7 +7,7 @@ export function uploadImgFromPath(path: string) { const readStream = fs.createReadStream(path) return imageService.upload(readStream) } catch (e) { - console.log(`上传图片失败: ${e}`) - void Alert.err(`上传图片失败: ${e}`) + console.log(`上传图片失败: ${e as string}`) + void Alert.err(`上传图片失败: ${e as string}`) } } diff --git a/src/cmd/workspace.ts b/src/cmd/workspace.ts index 585310ae..1837c2b1 100644 --- a/src/cmd/workspace.ts +++ b/src/cmd/workspace.ts @@ -3,8 +3,8 @@ import { Alert } from '@/infra/alert' import { WorkspaceCfg } from '@/ctx/cfg/workspace' import { TextDocument, WorkspaceEdit, window, Range } from 'vscode' -export namespace Workspace { - export function resetTextDoc(doc: TextDocument, text: string) { +export class Workspace { + static resetTextDoc(doc: TextDocument, text: string) { const firstLine = doc.lineAt(0) const lastLine = doc.lineAt(doc.lineCount - 1) const range = new Range(firstLine.range.start, lastLine.range.end) @@ -16,7 +16,7 @@ export namespace Workspace { return we } - export async function codeOpen() { + static async codeOpen() { const uri = WorkspaceCfg.getWorkspaceUri() const options = ['在当前窗口中打开', '在新窗口中打开'] const msg = `即将打开 ${uri.fsPath}` @@ -28,11 +28,11 @@ export namespace Workspace { await execCmd('vscode.openFolder', uri, shouldOpenInNewWindow) } - export function osOpen() { + static osOpen() { void execCmd('revealFileInOS', WorkspaceCfg.getWorkspaceUri()) } - export async function set() { + static async set() { const uris = await window.showOpenDialog({ title: '选择工作空间', canSelectFolders: true, diff --git a/src/ctx/cfg/chromium.ts b/src/ctx/cfg/chromium.ts index 7ed55b19..1cb7a222 100644 --- a/src/ctx/cfg/chromium.ts +++ b/src/ctx/cfg/chromium.ts @@ -1,14 +1,13 @@ import { PlatformCfg } from '@/ctx/cfg/platform' -import getPlatformCfg = PlatformCfg.getPlatformCfg import { ConfigurationTarget } from 'vscode' -export namespace ChromiumCfg { - export function getChromiumPath(): string { - return getPlatformCfg().get('chromiumPath') ?? '' +export class ChromiumCfg { + static getChromiumPath(): string { + return PlatformCfg.getPlatformCfg().get('chromiumPath') ?? '' } - export function setChromiumPath(path: string) { + static setChromiumPath(path: string) { const cfgTarget = ConfigurationTarget.Global - return getPlatformCfg().update('chromiumPath', path, cfgTarget) + return PlatformCfg.getPlatformCfg().update('chromiumPath', path, cfgTarget) } } diff --git a/src/ctx/cfg/icon-theme.ts b/src/ctx/cfg/icon-theme.ts index 3cb6227b..bfa186c0 100644 --- a/src/ctx/cfg/icon-theme.ts +++ b/src/ctx/cfg/icon-theme.ts @@ -1,7 +1,7 @@ import { workspace } from 'vscode' -export namespace IconThemeCfg { - export function getIconTheme(): string { +export class IconThemeCfg { + static getIconTheme(): string { return workspace.getConfiguration('workbench').get('iconTheme') ?? 'unknown' } } diff --git a/src/ctx/cfg/markdown.ts b/src/ctx/cfg/markdown.ts index a006a527..5805ff01 100644 --- a/src/ctx/cfg/markdown.ts +++ b/src/ctx/cfg/markdown.ts @@ -1,41 +1,40 @@ import { LocalState } from '@/ctx/local-state' -import getExtCfg = LocalState.getExtCfg import { ImgSrc } from '@/service/extract-img/get-replace-list' -export namespace MarkdownCfg { - const cfgGet = (key: string) => getExtCfg().get(`markdown.${key}`) +export class MarkdownCfg { + static cfgGet = (key: string) => LocalState.getExtCfg().get(`markdown.${key}`) - export function isShowConfirmMsgWhenUploadPost(): boolean { - return cfgGet('showConfirmMsgWhenUploadPost') ?? true + static isShowConfirmMsgWhenUploadPost(): boolean { + return MarkdownCfg.cfgGet('showConfirmMsgWhenUploadPost') ?? true } - export function isIgnoreYfmWhenUploadPost(): boolean { - return cfgGet('ignoreYfmWhenUploadPost') ?? false + static isIgnoreYfmWhenUploadPost(): boolean { + return MarkdownCfg.cfgGet('ignoreYfmWhenUploadPost') ?? false } - export function isShowConfirmMsgWhenPullPost(): boolean { - return cfgGet('showConfirmMsgWhenPullPost') ?? true + static isShowConfirmMsgWhenPullPost(): boolean { + return MarkdownCfg.cfgGet('showConfirmMsgWhenPullPost') ?? true } - export function isEnableMarkdownEnhancement(): boolean { - return cfgGet('enableEnhancement') ?? true + static isEnableMarkdownEnhancement(): boolean { + return MarkdownCfg.cfgGet('enableEnhancement') ?? true } - export function isEnableMarkdownFenceBlockquote(): boolean { - return cfgGet('enableFenceQuote') ?? true + static isEnableMarkdownFenceBlockquote(): boolean { + return MarkdownCfg.cfgGet('enableFenceQuote') ?? true } - export function isEnableMarkdownImageSizing(): boolean { - return cfgGet('enableImageSizing') ?? true + static isEnableMarkdownImageSizing(): boolean { + return MarkdownCfg.cfgGet('enableImageSizing') ?? true } - export function isEnableMarkdownHighlightCodeLines(): boolean { - return cfgGet('enableHighlightCodeLines') ?? true + static isEnableMarkdownHighlightCodeLines(): boolean { + return MarkdownCfg.cfgGet('enableHighlightCodeLines') ?? true } - export function getAutoExtractImgSrc(): ImgSrc | undefined { + static getAutoExtractImgSrc(): ImgSrc | undefined { type T = 'disable' | 'web' | 'dataUrl' | 'fs' | 'any' - const cfg = cfgGet('autoExtractImages') ?? 'disable' + const cfg = MarkdownCfg.cfgGet('autoExtractImages') ?? 'disable' if (cfg === 'disable') return if (cfg === 'fs') return ImgSrc.fs @@ -44,7 +43,7 @@ export namespace MarkdownCfg { if (cfg === 'any') return ImgSrc.any } - export function getApplyAutoExtractImgToLocal(): boolean { - return cfgGet('applyAutoExtractImageToLocal') ?? true + static getApplyAutoExtractImgToLocal(): boolean { + return MarkdownCfg.cfgGet('applyAutoExtractImageToLocal') ?? true } } diff --git a/src/ctx/cfg/platform.ts b/src/ctx/cfg/platform.ts index 53dc39d7..ae2227eb 100644 --- a/src/ctx/cfg/platform.ts +++ b/src/ctx/cfg/platform.ts @@ -12,8 +12,8 @@ function getPlatformPrefix() { return 'windows' } -export namespace PlatformCfg { - export function getPlatformCfg() { +export class PlatformCfg { + static getPlatformCfg() { const entry = `cnblogsClient.${getPlatformPrefix()}` return workspace.getConfiguration(entry) } diff --git a/src/ctx/cfg/post-list.ts b/src/ctx/cfg/post-list.ts index e671bd73..464075b7 100644 --- a/src/ctx/cfg/post-list.ts +++ b/src/ctx/cfg/post-list.ts @@ -1,7 +1,7 @@ import { LocalState } from '@/ctx/local-state' -export namespace PostListCfg { - export function getListPageSize() { +export class PostListCfg { + static getListPageSize() { return LocalState.getExtCfg().get('pageSize.postList') ?? 30 } } diff --git a/src/ctx/cfg/ui.ts b/src/ctx/cfg/ui.ts index dbfb8e0d..88a2da4c 100644 --- a/src/ctx/cfg/ui.ts +++ b/src/ctx/cfg/ui.ts @@ -1,14 +1,13 @@ import { LocalState } from '@/ctx/local-state' -import getExtCfg = LocalState.getExtCfg -export namespace UiCfg { - const cfgGet = (key: string) => getExtCfg().get(`ui.${key}`) +export class UiCfg { + static cfgGet = (key: string) => LocalState.getExtCfg().get(`ui.${key}`) - export function isEnableTextIngStar() { - return cfgGet('textIngStar') ?? false + static isEnableTextIngStar() { + return UiCfg.cfgGet('textIngStar') ?? false } - export function isDisableIngUserAvatar() { - return cfgGet('disableIngUserAvatar') ?? false + static isDisableIngUserAvatar() { + return UiCfg.cfgGet('disableIngUserAvatar') ?? false } } diff --git a/src/ctx/cfg/workspace.ts b/src/ctx/cfg/workspace.ts index 73f0d088..b3b7cb87 100644 --- a/src/ctx/cfg/workspace.ts +++ b/src/ctx/cfg/workspace.ts @@ -1,18 +1,17 @@ import { PlatformCfg } from '@/ctx/cfg/platform' -import getPlatformCfg = PlatformCfg.getPlatformCfg import os from 'os' import { ConfigurationTarget, Uri, workspace } from 'vscode' import { Alert } from '@/infra/alert' import { PostFileMapManager } from '@/service/post/post-file-map' -export namespace WorkspaceCfg { - export function getWorkspaceUri() { - const path = getPlatformCfg().get('workspace') ?? '~/Documents/Cnblogs' +export class WorkspaceCfg { + static getWorkspaceUri() { + const path = PlatformCfg.getPlatformCfg().get('workspace') ?? '~/Documents/Cnblogs' const absPath = path.replace('~', os.homedir()) return Uri.file(absPath) } - export async function setWorkspaceUri(uri: Uri): Promise { + static async setWorkspaceUri(uri: Uri): Promise { const fsPath = uri.fsPath if (uri.scheme !== 'file') throw Error(`Invalid Uri: ${uri.path}`) @@ -26,7 +25,7 @@ export namespace WorkspaceCfg { const oldWorkspaceUri = WorkspaceCfg.getWorkspaceUri() const cfgTarget = ConfigurationTarget.Global - await getPlatformCfg()?.update('workspace', fsPath, cfgTarget) + await PlatformCfg.getPlatformCfg()?.update('workspace', fsPath, cfgTarget) PostFileMapManager.updateWithWorkspace(oldWorkspaceUri) } } diff --git a/src/ctx/ext-const.ts b/src/ctx/ext-const.ts index 838f27df..e627f101 100644 --- a/src/ctx/ext-const.ts +++ b/src/ctx/ext-const.ts @@ -1,24 +1,24 @@ declare const CNBLOGS_CLIENTID: string declare const CNBLOGS_CLIENTSECRET: string -export const isDevEnv = () => process.env.NODE_ENV === 'Development' +const isDevEnv = () => process.env.NODE_ENV === 'Development' -export namespace ExtConst { - export const EXT_NAME = 'vscode-cnb' - export const EXT_PUBLISHER = 'cnblogs' +export class ExtConst { + static EXT_NAME = 'vscode-cnb' + static EXT_PUBLISHER = 'cnblogs' - export const EXT_SESSION_STORAGE_KEY = 'cnblogs.sessions' + static EXT_SESSION_STORAGE_KEY = 'cnblogs.sessions' - export const CLIENT_ID = CNBLOGS_CLIENTID - export const CLIENT_SEC = CNBLOGS_CLIENTSECRET + static CLIENT_ID = CNBLOGS_CLIENTID + static CLIENT_SEC = CNBLOGS_CLIENTSECRET - export namespace ApiBase { - export const BLOG_BACKEND = 'https://write.cnblogs.com/api' - export const OPENAPI = 'https://api.cnblogs.com/api' - export const OAUTH = 'https://oauth.cnblogs.com' + static ApiBase = class { + static BLOG_BACKEND = 'https://write.cnblogs.com/api' + static OPENAPI = 'https://api.cnblogs.com/api' + static OAUTH = 'https://oauth.cnblogs.com' } - export const OAUTH_SCOPES = ['openid', 'profile', 'CnBlogsApi', 'CnblogsAdminApi'] + static OAUTH_SCOPES = ['openid', 'profile', 'CnBlogsApi', 'CnblogsAdminApi'] } export function extName(tail: any) { diff --git a/src/ctx/local-state.ts b/src/ctx/local-state.ts index 6bfb8533..4537cdcb 100644 --- a/src/ctx/local-state.ts +++ b/src/ctx/local-state.ts @@ -1,32 +1,32 @@ import { workspace } from 'vscode' import { globalCtx } from '@/ctx/global-ctx' -export namespace LocalState { - export function getExtCfg() { +export class LocalState { + static getExtCfg() { return workspace.getConfiguration('cnblogsClient') } - export function getState(key: string) { + static getState(key: string) { return globalCtx.extCtx.globalState.get(key) } - export function setState(key: string, val: any) { + static setState(key: string, val: any) { return globalCtx.extCtx.globalState.update(key, val) } - export function delState(key: string) { - return setState(key, undefined) + static delState(key: string) { + return LocalState.setState(key, undefined) } - export function getSecret(key: string) { + static getSecret(key: string) { return globalCtx.extCtx.secrets.get(key) } - export function setSecret(key: string, val: string) { + static setSecret(key: string, val: string) { return globalCtx.extCtx.secrets.store(key, val) } - export function delSecret(key: string) { + static delSecret(key: string) { return globalCtx.extCtx.secrets.delete(key) } } diff --git a/src/extension.ts b/src/extension.ts index 4b29c237..cbbb77d0 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -24,7 +24,7 @@ export async function activate(ctx: ExtensionContext) { setupCmd() setupExtTreeView() } catch (e) { - void Alert.err(`扩展激活失败,[立即反馈](https://github.com/cnblogs/vscode-cnb/issues),错误信息:${e}`) + void Alert.err(`扩展激活失败,[立即反馈](https://github.com/cnblogs/vscode-cnb/issues),错误信息:${e as string}`) throw e } diff --git a/src/infra/alert.ts b/src/infra/alert.ts index cf7c30c7..caaf8519 100644 --- a/src/infra/alert.ts +++ b/src/infra/alert.ts @@ -1,14 +1,14 @@ import path from 'path' import { ProgressLocation, Uri, window } from 'vscode' -export namespace Alert { - export const err = window.showErrorMessage +export class Alert { + public static err = window.showErrorMessage - export const info = window.showInformationMessage + public static info = window.showInformationMessage - export const warn = window.showWarningMessage + public static warn = window.showWarningMessage - export function infoWithTimeout(info: string, sec: number) { + infoWithTimeout(info: string, sec: number) { return window.withProgress( { title: info, @@ -26,14 +26,14 @@ export namespace Alert { * @param file the file path, could be a string or {@link Uri} object * @param trimExt */ - export function fileNotLinkedToPost(file: string | Uri, { trimExt = true } = {}) { + static fileNotLinkedToPost(file: string | Uri, { trimExt = true } = {}) { file = file instanceof Uri ? file.fsPath : file file = trimExt ? path.basename(file, path.extname(file)) : file void Alert.warn(`本地文件 ${file} 未关联博客园博文`) } - export function throwWithWarn(message: string): never { - void warn(message) + static throwWithWarn(message: string): never { + void Alert.warn(message) throw Error(message) } } diff --git a/src/infra/chromium-path-provider.ts b/src/infra/chromium-path-provider.ts index ff857fae..98917123 100644 --- a/src/infra/chromium-path-provider.ts +++ b/src/infra/chromium-path-provider.ts @@ -3,17 +3,22 @@ import fs from 'fs' import os from 'os' import path from 'path' import { Alert } from '@/infra/alert' -// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires +// eslint-disable-next-line @typescript-eslint/no-require-imports const download: (arg: Record) => Promise = require('download-chromium') -export namespace ChromiumPathProvider { - export const defaultChromiumPath = { - osx: [`${os.homedir()}/Applications/Google Chrome.app`, '/Applications/Google Chrome.app'], - win: ['C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe'], - } - export type ChromiumProviderFunc = () => Promise - const selectFromLocalTitle = '选择本地Chromium' - export const lookupExecutableFromMacApp = (path?: string) => { +export type ChromiumProviderFunc = () => Promise + +const selectFromLocalTitle = '选择本地Chromium' + +const defaultChromiumPath = { + osx: [`${os.homedir()}/Applications/Google Chrome.app`, '/Applications/Google Chrome.app'], + win: ['C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe'], +} + +const downloadFromInternetTitle = '帮我下载Chromium' + +export class ChromiumPathProvider { + static lookupExecutableFromMacApp = (path?: string) => { if (path === undefined) return if (path.endsWith('.app')) { @@ -28,7 +33,8 @@ export namespace ChromiumPathProvider { } return path } - export const selectFromLocal: ChromiumProviderFunc = async (): Promise => { + + static selectFromLocal: ChromiumProviderFunc = async (): Promise => { const platform = os.platform() const path = ( await window.showOpenDialog({ @@ -37,7 +43,6 @@ export namespace ChromiumPathProvider { canSelectFolders: false, canSelectFiles: true, filters: { - // eslint-disable-next-line @typescript-eslint/naming-convention Program: [ ...(platform === 'darwin' ? ['app', 'exe'] : []), ...(platform === 'win32' ? ['exe'] : []), @@ -45,10 +50,10 @@ export namespace ChromiumPathProvider { }, }) )?.pop()?.fsPath - return lookupExecutableFromMacApp(path) + return ChromiumPathProvider.lookupExecutableFromMacApp(path) } - const downloadFromInternetTitle = '帮我下载Chromium' - export const downloadFromInternet: ChromiumProviderFunc = async (): Promise => { + + static downloadFromInternet: ChromiumProviderFunc = async (): Promise => { const installPath = path.join(os.homedir(), `Downloads`) fs.mkdirSync(installPath, { recursive: true }) const chromiumPath = await window.withProgress( @@ -81,7 +86,7 @@ export namespace ChromiumPathProvider { return chromiumPath } - export const Options: [string, ChromiumPathProvider.ChromiumProviderFunc][] = [ + static Options: [string, ChromiumProviderFunc][] = [ [selectFromLocalTitle, ChromiumPathProvider.selectFromLocal], [downloadFromInternetTitle, ChromiumPathProvider.downloadFromInternet], ] diff --git a/src/infra/convert/map-to-json.ts b/src/infra/convert/map-to-json.ts index 28df0682..66e5c872 100644 --- a/src/infra/convert/map-to-json.ts +++ b/src/infra/convert/map-to-json.ts @@ -1,5 +1,5 @@ -// eslint-disable-next-line @typescript-eslint/naming-convention + export function mapToJson(map: Map) { - const obj = Object.fromEntries(map) + const obj = Object.fromEntries(map) as unknown return JSON.stringify(obj) } diff --git a/src/infra/convert/readableToBuffer.ts b/src/infra/convert/readableToBuffer.ts index 7896c6f5..f1a8ff34 100644 --- a/src/infra/convert/readableToBuffer.ts +++ b/src/infra/convert/readableToBuffer.ts @@ -4,7 +4,7 @@ export function readableToBytes(readable: Readable): Promise { return new Promise(resolve => { const bufs: Buffer[] = [] readable.on('readable', () => { - const chunk = readable.read() + const chunk = readable.read() as Buffer | null if (chunk !== null) { bufs.push(chunk) diff --git a/src/infra/fp/pipe.ts b/src/infra/fp/pipe.ts index a05cb2de..4e6abf64 100644 --- a/src/infra/fp/pipe.ts +++ b/src/infra/fp/pipe.ts @@ -1,4 +1,3 @@ -// eslint-disable-next-line @typescript-eslint/naming-convention export function pipe(f1: (a: A) => B, f2: (b: B) => C) { return (a: A) => f2(f1(a)) } diff --git a/src/infra/fs/fsUtil.ts b/src/infra/fs/fsUtil.ts index d8afb196..0739b0f7 100644 --- a/src/infra/fs/fsUtil.ts +++ b/src/infra/fs/fsUtil.ts @@ -1,7 +1,7 @@ import { Uri, workspace } from 'vscode' -export namespace fsUtil { - export async function exists(fsPath: string) { +export class fsUtil { + static async exists(fsPath: string) { try { await workspace.fs.stat(Uri.file(fsPath)) return true diff --git a/src/infra/http/authed-req.ts b/src/infra/http/authed-req.ts index 708c6bc4..c3978883 100644 --- a/src/infra/http/authed-req.ts +++ b/src/infra/http/authed-req.ts @@ -14,23 +14,23 @@ async function makeAuthed(header: Header) { if (token.length === 64) header.set(ReqHeaderKey.AUTHORIZATION_TYPE, 'pat') } -export namespace AuthedReq { - export async function put(url: string, header: Header, body: string) { +export class AuthedReq { + static async put(url: string, header: Header, body: string) { await makeAuthed(header) return Req.put(url, header, body) } - export async function del(url: string, header: Header) { + static async del(url: string, header: Header) { await makeAuthed(header) return Req.del(url, header) } - export async function post(url: string, header: Header, body: string) { + static async post(url: string, header: Header, body: string) { await makeAuthed(header) return Req.post(url, header, body) } - export async function get(url: string, header: Header) { + static async get(url: string, header: Header) { await makeAuthed(header) return Req.get(url, header) } diff --git a/src/infra/http/infra/header.ts b/src/infra/http/infra/header.ts index 7485ef5f..a8f82e22 100644 --- a/src/infra/http/infra/header.ts +++ b/src/infra/http/infra/header.ts @@ -1,12 +1,12 @@ -export namespace ReqHeaderKey { - export const CONTENT_TYPE = 'Content-Type' - export const AUTHORIZATION = 'Authorization' - export const AUTHORIZATION_TYPE = 'Authorization-Type' +export class ReqHeaderKey { + static CONTENT_TYPE = 'Content-Type' + static AUTHORIZATION = 'Authorization' + static AUTHORIZATION_TYPE = 'Authorization-Type' +} - export enum ContentType { - appJson = 'application/json', - appX3wfu = 'application/x-www-form-urlencoded', - } +export enum ContentType { + appJson = 'application/json', + appX3wfu = 'application/x-www-form-urlencoded', } export function consHeader(...kvs: [string, string][]) { diff --git a/src/infra/http/req.ts b/src/infra/http/req.ts index 9badfd9e..d8e5361a 100644 --- a/src/infra/http/req.ts +++ b/src/infra/http/req.ts @@ -4,23 +4,23 @@ import { mapToJson } from '@/infra/convert/map-to-json' type Header = Map -export namespace Req { - export function put(url: string, header: Header, body: string) { +export class Req { + static put(url: string, header: Header, body: string) { const headerJson = mapToJson(header) return RsHttp.put(url, headerJson, body) } - export function del(url: string, header: Header) { + static del(url: string, header: Header) { const headerJson = mapToJson(header) return RsHttp.del(url, headerJson) } - export function post(url: string, header: Header, body: string) { + static post(url: string, header: Header, body: string) { const headerJson = mapToJson(header) return RsHttp.post(url, headerJson, body) } - export function get(url: string, header: Header) { + static get(url: string, header: Header) { const headerJson = mapToJson(header) return RsHttp.get(url, headerJson) } diff --git a/src/model/page.ts b/src/model/page.ts index 5f83a4b3..da003016 100644 --- a/src/model/page.ts +++ b/src/model/page.ts @@ -5,20 +5,20 @@ export type Page = { items: T[] } -export type PageList = { +export type PageListGeneric = { pages: Page[] } -export namespace PageList { - export function hasPrev(pageIndex: number) { +export class PageList { + static hasPrev(pageIndex: number) { return pageIndex > 1 } - export function hasNext(pageIndex: number, pageCount: number) { + static hasNext(pageIndex: number, pageCount: number) { return pageIndex < pageCount } - export function calcPageCount(pageCap: number, pageListItemCount: number) { + static calcPageCount(pageCap: number, pageListItemCount: number) { return Math.floor(pageListItemCount / pageCap) + (pageListItemCount % pageCap > 0 ? 1 : 0) } } diff --git a/src/model/post.ts b/src/model/post.ts index a225321d..f640e8c1 100644 --- a/src/model/post.ts +++ b/src/model/post.ts @@ -1,5 +1,5 @@ -import differenceInSeconds from 'date-fns/differenceInSeconds' -import parseISO from 'date-fns/parseISO' +import { differenceInSeconds } from 'date-fns/differenceInSeconds' +import { parseISO } from 'date-fns/parseISO' export class Post { id = -1 diff --git a/src/model/webview-cmd.ts b/src/model/webview-cmd.ts index 4a3eb729..cadcf329 100644 --- a/src/model/webview-cmd.ts +++ b/src/model/webview-cmd.ts @@ -1,5 +1,6 @@ import { PostCat } from '@/model/post-cat' +// eslint-disable-next-line @typescript-eslint/no-namespace export namespace Webview.Cmd { export enum Ui { editPostCfg = 'editPostCfg', @@ -27,6 +28,7 @@ export namespace Webview.Cmd { value: PostCat[] } + // eslint-disable-next-line @typescript-eslint/no-namespace export namespace Ing { export enum Ui { setAppState = 'setAppState', diff --git a/src/model/webview-msg.ts b/src/model/webview-msg.ts index 9a7fed7f..9906e1f8 100644 --- a/src/model/webview-msg.ts +++ b/src/model/webview-msg.ts @@ -6,6 +6,7 @@ import { PostCat } from '@/model/post-cat' import { SiteCat } from '@/model/site-category' import { PostTag } from '@/wasm' +// eslint-disable-next-line @typescript-eslint/no-namespace export namespace WebviewMsg { export type Msg = { command: Webview.Cmd.Ui | Webview.Cmd.Ext diff --git a/src/service/blog-export/blog-export-records.store.ts b/src/service/blog-export/blog-export-records.store.ts index 358df7b0..606ba61f 100644 --- a/src/service/blog-export/blog-export-records.store.ts +++ b/src/service/blog-export/blog-export-records.store.ts @@ -1,27 +1,26 @@ import { BlogExportRecordList } from '@/model/blog-export' import { BlogExportApi } from '@/service/blog-export/blog-export' -export namespace BlogExportRecordsStore { - let cacheList: Promise | null = null - let cache: BlogExportRecordList | null = null +export class BlogExportRecordsStore { + private static cacheList: Promise | null = null + private static cache: BlogExportRecordList | null = null - export function getCached() { - return cache + static getCached() { + return BlogExportRecordsStore.cache } - export async function refresh(options?: { pageIndex?: number; pageSize?: number; shouldRefresh?: boolean }) { - await clearCache() - return list(options) + static async refresh(options?: { pageIndex?: number; pageSize?: number; shouldRefresh?: boolean }) { + await BlogExportRecordsStore.clearCache() + return BlogExportRecordsStore.list(options) } - export async function clearCache(): Promise { - if (cacheList !== null) await cacheList - - cacheList = null - cache = null + static async clearCache(): Promise { + if (BlogExportRecordsStore.cacheList !== null) await BlogExportRecordsStore.cacheList + BlogExportRecordsStore.cacheList = null + BlogExportRecordsStore.cache = null } - export async function list({ + static async list({ pageIndex = 1, pageSize = 500, }: { @@ -29,9 +28,9 @@ export namespace BlogExportRecordsStore { pageSize?: number shouldRefresh?: boolean } = {}): Promise { - cacheList ??= BlogExportApi.list({ pageIndex, pageSize }) - cache = await cacheList + BlogExportRecordsStore.cacheList ??= BlogExportApi.list({ pageIndex, pageSize }) + BlogExportRecordsStore.cache = await BlogExportRecordsStore.cacheList - return cache + return BlogExportRecordsStore.cache } } diff --git a/src/service/blog-export/blog-export.ts b/src/service/blog-export/blog-export.ts index 967b84df..9ad6fab7 100644 --- a/src/service/blog-export/blog-export.ts +++ b/src/service/blog-export/blog-export.ts @@ -8,35 +8,35 @@ import { ExtConst } from '@/ctx/ext-const' const basePath = `${ExtConst.ApiBase.BLOG_BACKEND}/blogExports` const downloadOrigin = 'https://export.cnblogs.com' -export namespace BlogExportApi { - export async function list({ pageIndex, pageSize }: { pageIndex?: number; pageSize?: number }) { +export class BlogExportApi { + static async list({ pageIndex, pageSize }: { pageIndex?: number; pageSize?: number }) { const para = consUrlPara(['pageIndex', `${pageIndex ?? ''}`], ['pageSize', `${pageSize ?? ''}`]) const url = `${basePath}?${para}` const resp = await AuthedReq.get(url, consHeader()) - return JSON.parse(resp) + return JSON.parse(resp) as BlogExportRecordList } - export async function create() { + static async create() { const resp = await AuthedReq.post(basePath, consHeader(), '') - return JSON.parse(resp) + return JSON.parse(resp) as BlogExportRecord } - export async function del(id: number) { + static async del(id: number) { const url = `${basePath}/${id}` await AuthedReq.del(url, consHeader()) } - export async function getById(id: number) { + static async getById(id: number) { const resp = await AuthedReq.get(`${basePath}/${id}`, consHeader()) - return JSON.parse(resp) + return JSON.parse(resp) as BlogExportRecord } - export function download(blogId: number, exportId: number) { + static download(blogId: number, exportId: number) { const g = got.extend({ hooks: { beforeRedirect: [ - (opt, resp) => { + (_opt: any, resp: { headers: { location: any } }) => { const location = resp.headers.location if (location === undefined) return if (location.includes('account.cnblogs.com')) throw new Error('未授权') diff --git a/src/service/blog-setting.ts b/src/service/blog-setting.ts index 08927f48..7c0757b5 100644 --- a/src/service/blog-setting.ts +++ b/src/service/blog-setting.ts @@ -6,8 +6,8 @@ import { ExtConst } from '@/ctx/ext-const' let cache: BlogSetting | null = null -export namespace BlogSettingService { - export async function getBlogSetting(refresh = false) { +export class BlogSettingService { + static getBlogSetting = async (refresh = false) => { if (cache != null && !refresh) return cache const url = `${ExtConst.ApiBase.BLOG_BACKEND}/settings` @@ -19,7 +19,7 @@ export namespace BlogSettingService { cache ??= setting return setting } catch (e) { - void Alert.err(`获取博客设置失败: ${e}`) + void Alert.err(`获取博客设置失败: ${e as string}`) return cache } } diff --git a/src/service/downloaded-export.store.ts b/src/service/downloaded-export.store.ts index e76794f1..bada72b7 100644 --- a/src/service/downloaded-export.store.ts +++ b/src/service/downloaded-export.store.ts @@ -11,8 +11,8 @@ const updateList = (value?: DownloadedBlogExport[] | null) => LocalState.setStat const updateExport = (id: number, value?: DownloadedBlogExport | null) => LocalState.setState(`${metadataKey}${id}`, value) -export namespace DownloadedExportStore { - export async function add(filePath: string, id?: number | null) { +export class DownloadedExportStore { + static async add(filePath: string, id?: number | null) { const item: DownloadedBlogExport = { id, filePath } const list = await DownloadedExportStore.list() const oldIdx = list.findIndex(x => x.filePath === filePath) @@ -25,8 +25,8 @@ export namespace DownloadedExportStore { ]) } - export async function list({ prune = true } = {}) { - let items = LocalState.getState(listKey) ?? [] + static async list({ prune = true } = {}) { + let items = LocalState.getState(listKey) as DownloadedBlogExport[] ?? [] if (prune) { const prunedItems: DownloadedBlogExport[] = [] @@ -50,12 +50,12 @@ export namespace DownloadedExportStore { } } - return Promise.resolve(LocalState.getState(listKey) ?? []) + return Promise.resolve(LocalState.getState(listKey) as DownloadedBlogExport[] ?? []) } - export async function remove(downloaded: DownloadedBlogExport, { shouldRemoveExportRecordMap = true } = {}) { + static async remove(downloaded: DownloadedBlogExport, { shouldRemoveExportRecordMap = true } = {}) { const futList = [ - updateList((await list()).filter(x => x.filePath !== downloaded.filePath)), + updateList((await DownloadedExportStore.list()).filter(x => x.filePath !== downloaded.filePath)), shouldRemoveExportRecordMap && downloaded.id != null && downloaded.id > 0 ? updateExport(downloaded.id, undefined) : await Promise.resolve(), @@ -63,7 +63,7 @@ export namespace DownloadedExportStore { await Promise.all(futList) } - export async function findById(id: number, { prune = true } = {}) { + static async findById(id: number, { prune = true } = {}) { const key = `${metadataKey}${id}` let item = LocalState.getState(key) as DownloadedBlogExport | undefined diff --git a/src/service/extract-img/find-img-link.ts b/src/service/extract-img/find-img-link.ts index b5deba68..363d78a5 100644 --- a/src/service/extract-img/find-img-link.ts +++ b/src/service/extract-img/find-img-link.ts @@ -23,12 +23,12 @@ export const FILTER_BYTE_OFFSET = -9999 function getImagesWithTs(text: string) { return [...text.matchAll(markdownImages)].concat([...text.matchAll(wikilinkImages)]).map(m => { const uri = m.groups?.uri ?? '' - return { + return { byteOffset: FILTER_BYTE_OFFSET, data: uri, src: webUrlPrefix.test(uri) ? ImgSrc.web : ImgSrc.fs, prefix: m.groups?.prefix, - } + } as ImgInfo }) } @@ -43,11 +43,11 @@ export function findImgLink(text: string): ImgInfo[] { if (webUrlPrefix.test(data)) src = ImgSrc.web else src = ImgSrc.fs - return { + return { byteOffset, data, src, - } + } as ImgInfo }) const imgTagDataUrlImgMgs = RsRegex.matches(imgTagDataUrlImgPat, text) as RsMatch[] @@ -57,11 +57,11 @@ export function findImgLink(text: string): ImgInfo[] { const prefix = mg.groups[1] const byteOffset = mg.byte_offset + Buffer.from(prefix).length - return { + return { byteOffset, data, src: ImgSrc.dataUrl, - } + } as ImgInfo }) let images = urlImgInfo.concat(dataUrlImgInfo) diff --git a/src/service/extract-img/get-replace-list.ts b/src/service/extract-img/get-replace-list.ts index e7ddeb55..bdfb29e3 100644 --- a/src/service/extract-img/get-replace-list.ts +++ b/src/service/extract-img/get-replace-list.ts @@ -47,7 +47,7 @@ export async function getReplaceList(fileDir: string, infoList: ImgInfo[], befor result.push([src, newLink]) } catch (e) { - void Alert.err(`提取失败(${src.data}): ${e}`) + void Alert.err(`提取失败(${src.data}): ${e as string}`) } } @@ -83,7 +83,6 @@ async function getImgBytes(baseDirPath: string, info: ImgInfo) { // for fs img if (info.src === ImgSrc.fs) { const path = info.data - // eslint-disable-next-line return await caseFsImg(baseDirPath, path) } diff --git a/src/service/ing/ing-list-webview-provider.ts b/src/service/ing/ing-list-webview-provider.ts index 0e6128fe..310acdaa 100644 --- a/src/service/ing/ing-list-webview-provider.ts +++ b/src/service/ing/ing-list-webview-provider.ts @@ -45,7 +45,6 @@ export class IngListWebviewProvider implements WebviewViewProvider { return this._ingType } - // eslint-disable-next-line @typescript-eslint/no-unused-vars async resolveWebviewView(webviewView: WebviewView, context: WebviewViewResolveContext, token: CancellationToken) { if (this._view !== null && this._view === webviewView) return @@ -152,11 +151,11 @@ let _ingListWebviewProvider: any = null export function getIngListWebviewProvider(): IngListWebviewProvider { _ingListWebviewProvider ??= new IngListWebviewProvider() - return _ingListWebviewProvider + return _ingListWebviewProvider as IngListWebviewProvider } class IngWebviewMessageObserver { - constructor(private _provider: IngListWebviewProvider) {} + constructor(private _provider: IngListWebviewProvider) { } observer = ({ command, payload }: IngWebviewHostCmd) => { switch (command) { diff --git a/src/service/ing/ing.ts b/src/service/ing/ing.ts index 52a25bfb..b07b223a 100644 --- a/src/service/ing/ing.ts +++ b/src/service/ing/ing.ts @@ -17,43 +17,43 @@ async function getComment(id: number) { return list.map(IngComment.parse) } -export namespace IngService { - export async function pub(content: string, isPrivate: boolean) { +export class IngService { + static async pub(content: string, isPrivate: boolean) { try { const req = await getAuthedIngReq() await req.publish(content, isPrivate) return true } catch (e) { - void Alert.err(`闪存发布失败: ${e}`) + void Alert.err(`闪存发布失败: ${e as string}`) return false } } - export async function getList({ pageIndex = 1, pageSize = 30, type = IngType.all } = {}) { + static async getList({ pageIndex = 1, pageSize = 30, type = IngType.all } = {}) { try { const req = await getAuthedIngReq() const resp = await req.getList(pageIndex, pageSize, type) const arr = JSON.parse(resp) as unknown[] return arr.map(Ing.parse) } catch (e) { - void Alert.err(`获取闪存列表失败: ${e}`) + void Alert.err(`获取闪存列表失败: ${e as string}`) return [] } } - export async function getCommentList(...ingIds: number[]) { + static async getCommentList(...ingIds: number[]) { const futList = ingIds.map(async id => ({ [id]: await getComment(id) })) const resList = await Promise.all(futList) return resList.reduce((acc, it) => Object.assign(it, acc), {}) } - export async function comment(ingId: number, content: string, replyTo?: number, parentCommentId?: number) { + static async comment(ingId: number, content: string, replyTo?: number, parentCommentId?: number) { try { const req = await getAuthedIngReq() await req.comment(ingId, content, replyTo, parentCommentId) return true } catch (e) { - void Alert.err(`发表评论失败, ${e}`) + void Alert.err(`发表评论失败, ${e as string}`) return false } } diff --git a/src/service/post/post-cat.ts b/src/service/post/post-cat.ts index e7af2ec6..efe1d464 100644 --- a/src/service/post/post-cat.ts +++ b/src/service/post/post-cat.ts @@ -15,58 +15,58 @@ async function getAuthedPostCatReq() { return new PostCatReq(new Token(token, isPatToken)) } -export namespace PostCatService { - export async function getAll() { +export class PostCatService { + static async getAll() { const req = await getAuthedPostCatReq() try { const resp = await req.getAll() - const { categories } = <{ categories: PostCat[] }>JSON.parse(resp) + const { categories } = JSON.parse(resp) as { categories: PostCat[] } if (categories == null) return [] return categories } catch (e) { - if (await UserService.hasBlog()) void Alert.err(`查询随笔分类失败: ${e}`) + if (await UserService.hasBlog()) void Alert.err(`查询随笔分类失败: ${e as string}`) throw e } } - export async function create(dto: PostCatAddDto) { + static async create(dto: PostCatAddDto) { const req = await getAuthedPostCatReq() const body = JSON.stringify(dto) try { await req.create(body) } catch (e) { - void Alert.err(`创建分类失败: ${e}`) + void Alert.err(`创建分类失败: ${e as string}`) } } - export async function update(category: PostCat) { + static async update(category: PostCat) { const req = await getAuthedPostCatReq() const body = JSON.stringify(category) try { await req.update(category.categoryId, body) } catch (e) { - void Alert.err(`更新分类失败: ${e}`) + void Alert.err(`更新分类失败: ${e as string}`) } } - export async function del(categoryId: number) { + static async del(categoryId: number) { const req = await getAuthedPostCatReq() try { await req.del(categoryId) } catch (e) { - void Alert.err(`删除分类失败: ${e}`) + void Alert.err(`删除分类失败: ${e as string}`) } } - export async function getSitePresetList(forceRefresh = false) { + static async getSitePresetList(forceRefresh = false) { if (siteCategoryCache != null && !forceRefresh) return siteCategoryCache const req = await getAuthedPostCatReq() try { const resp = await req.getSitePresetList() - siteCategoryCache = JSON.parse(resp) + siteCategoryCache = JSON.parse(resp) as SiteCat[] } catch (e) { - void Alert.err(`获取随笔分类失败: ${e}`) + void Alert.err(`获取随笔分类失败: ${e as string}`) } return siteCategoryCache diff --git a/src/service/post/post-cfg-panel.ts b/src/service/post/post-cfg-panel.ts index 622eef0e..e4c0515e 100644 --- a/src/service/post/post-cfg-panel.ts +++ b/src/service/post/post-cfg-panel.ts @@ -35,8 +35,8 @@ type PostCfgPanelOpenOption = { beforeUpdate: (postToUpdate: Post, panel: WebviewPanel) => Promise } -export namespace PostCfgPanel { - export async function open(option: PostCfgPanelOpenOption) { +export class PostCfgPanel { + static async open(option: PostCfgPanelOpenOption) { const { post, breadcrumbs, localFileUri } = option const panelTitle = option.panelTitle !== undefined ? option.panelTitle : `博文设置 - ${post.title}` @@ -155,13 +155,13 @@ const observeWebviewMsg = (panel: WebviewPanel, options: PostCfgPanelOpenOption) panel.dispose() afterSuccess(Object.assign({}, post, postSavedModel)) } catch (e) { - void Alert.err(`操作失败: ${e}`) + void Alert.err(`操作失败: ${e as string}`) } return } else if (command === Webview.Cmd.Ext.disposePanel) { panel.dispose() } else if (command === Webview.Cmd.Ext.uploadImg) { - await doUploadImg(webview, message) + await doUploadImg(webview, (message as WebviewMsg.UploadImgMsg)) } else if (command === Webview.Cmd.Ext.getChildCategories) { const { payload } = message as WebviewCommonCmd const cateStore = await PostCateStore.createAsync() diff --git a/src/service/post/post-file-map.ts b/src/service/post/post-file-map.ts index 02ce27ff..36d4132b 100644 --- a/src/service/post/post-file-map.ts +++ b/src/service/post/post-file-map.ts @@ -12,21 +12,21 @@ export type PostFileMap = [postId: number, filePath: string] const storageKey = 'postFileMaps' function getMaps(): PostFileMap[] { - return LocalState.getState(storageKey) ?? [] + return LocalState.getState(storageKey) as PostFileMap[] ?? [] } function isUriPath(path: string) { return path.startsWith('/') } -export namespace PostFileMapManager { - export function ensurePostFileUri(post: Post) { +export class PostFileMapManager { + static ensurePostFileUri(post: Post) { let fileUri = PostFileMapManager.getFileUri(post.id) - if (fileUri == null || !isInWorkspace(fileUri.path)) fileUri = buildLocalPostFileUri(post) + if (fileUri == null || !PostFileMapManager.isInWorkspace(fileUri.path)) fileUri = PostFileMapManager.buildLocalPostFileUri(post) return fileUri } - export function buildLocalPostFileUri(post: Post, appendToFileName = ''): Uri { + static buildLocalPostFileUri(post: Post, appendToFileName = ''): Uri { const workspaceUri = WorkspaceCfg.getWorkspaceUri() const ext = `${post.isMarkdown ? 'md' : 'html'}` let postTitle = post.title.replace(/#/g, '#') @@ -35,12 +35,12 @@ export namespace PostFileMapManager { return Uri.joinPath(workspaceUri, `${postTitle}${appendToFileName}.${post.id}.${ext}`) } - export async function updateOrCreateMany( + static async updateOrCreateMany( arg: | { - emitEvent?: boolean - maps: PostFileMap[] - } + emitEvent?: boolean + maps: PostFileMap[] + } | PostFileMap[] ) { let maps: PostFileMap[] = [] @@ -53,10 +53,10 @@ export namespace PostFileMapManager { shouldEmitEvent = arg.emitEvent ?? true } - for (const map of maps) await updateOrCreate(map[0], map[1], { emitEvent: shouldEmitEvent }) + for (const map of maps) await PostFileMapManager.updateOrCreate(map[0], map[1], { emitEvent: shouldEmitEvent }) } - export async function updateOrCreate(postId: number, filePath: string, { emitEvent = true } = {}) { + static async updateOrCreate(postId: number, filePath: string, { emitEvent = true } = {}) { const validFileExt = ['.md', '.mkd', '.htm', '.html'] if (filePath !== '' && !validFileExt.some(x => filePath.endsWith(x))) throw Error('Invalid filepath, file must have type markdown or html') @@ -73,43 +73,43 @@ export namespace PostFileMapManager { } } - export function findByPostId(postId: number) { + static findByPostId(postId: number) { const maps = getMaps().filter(validatePostFileMap) return maps.find(x => x[0] === postId) } - export function findByFilePath(path: string) { + static findByFilePath(path: string) { const maps = getMaps().filter(validatePostFileMap) let map = maps.find(x => x[0] !== 0 && x[1] === path) if (map === undefined) map = maps.find(x => x[0] !== 0 && x[1] === Uri.parse(path).fsPath) return map } - export function getFilePath(postId: number): string | undefined { - return getFileUri(postId)?.fsPath + static getFilePath(postId: number): string | undefined { + return PostFileMapManager.getFileUri(postId)?.fsPath } - export function getFileUri(postId: number): Uri | undefined { - const map = findByPostId(postId) + static getFileUri(postId: number): Uri | undefined { + const map = PostFileMapManager.findByPostId(postId) if (map == null) return const path = map[1] if (path === '') return return isUriPath(path) ? Uri.parse(path) : Uri.file(path) } - export function getPostId(filePath: string): number | undefined { - const map = findByFilePath(filePath) + static getPostId(filePath: string): number | undefined { + const map = PostFileMapManager.findByFilePath(filePath) if (map == null) return return map[0] } - export function extractPostId(fileNameWithoutExt: string): number | undefined { + static extractPostId(fileNameWithoutExt: string): number | undefined { const match = /\.(\d+)$/g.exec(fileNameWithoutExt) if (match == null) return return Number(match[1]) } - export function updateWithWorkspace(oldWorkspaceUri: Uri) { + static updateWithWorkspace(oldWorkspaceUri: Uri) { const newWorkspaceUri = WorkspaceCfg.getWorkspaceUri() if (newWorkspaceUri.path === oldWorkspaceUri.path) return getMaps().forEach(x => { @@ -121,7 +121,7 @@ export namespace PostFileMapManager { }) } - export function isInWorkspace(fileUriPath: string) { + static isInWorkspace(fileUriPath: string) { return fileUriPath.indexOf(WorkspaceCfg.getWorkspaceUri().path) >= 0 } } diff --git a/src/service/post/post-list-view.ts b/src/service/post/post-list-view.ts index 98f7e0e5..f41d8831 100644 --- a/src/service/post/post-list-view.ts +++ b/src/service/post/post-list-view.ts @@ -32,7 +32,7 @@ export async function revealPostListItem( } export function getListState() { - return LocalState.getState('postListState') + return LocalState.getState('postListState') as PostListState | undefined } export async function updatePostListState( @@ -42,12 +42,12 @@ export async function updatePostListState( hasPrev: boolean, hasNext: boolean ): Promise { - const finalState = { + const finalState = { pageIndex, pageSize, pageCount, hasPrev, hasNext, - } + } as PostListState await LocalState.setState('postListState', finalState) } diff --git a/src/service/post/post.ts b/src/service/post/post.ts index 0282a510..7cc2b6a6 100644 --- a/src/service/post/post.ts +++ b/src/service/post/post.ts @@ -22,12 +22,12 @@ async function getAuthedPostReq() { return new PostReq(new Token(token, isPatToken)) } -export namespace PostService { - export async function search(pageIndex: number, pageCap: number, keyword?: string, catId?: number) { +export class PostService { + static async search(pageIndex: number, pageCap: number, keyword?: string, catId?: number) { const req = await getAuthedPostReq() try { const json = await req.search(pageIndex, pageCap, keyword, catId) - const listModel = JSON.parse(json) + const listModel = JSON.parse(json) as PostListModel const page = { index: listModel.pageIndex, size: listModel.pageSize, @@ -42,12 +42,12 @@ export namespace PostService { zzkResult: listModel.zzkSearchResult, } } catch (e) { - void Alert.err(`搜索失败: ${e}`) + void Alert.err(`搜索失败: ${e as string}`) throw e } } - export async function getPosts({ pageIndex = 1, pageSize = 30, categoryId = <'' | number>'', search = '' }) { + static async getPosts({ pageIndex = 1, pageSize = 30, categoryId = '' as '' | number, search = '' }) { const para = consUrlPara( ['t', '1'], ['p', pageIndex.toString()], @@ -57,33 +57,33 @@ export namespace PostService { ) const url = `${ExtConst.ApiBase.BLOG_BACKEND}/posts/list?${para}` const resp = await AuthedReq.get(url, consHeader()) - return JSON.parse(resp) + return JSON.parse(resp) as PostListModel } - export async function getList(pageIndex: number, pageCap: number) { + static async getList(pageIndex: number, pageCap: number) { const req = await getAuthedPostReq() try { const resp = await req.getList(pageIndex, pageCap) - return JSON.parse(resp) + return JSON.parse(resp) as PostListRespItem[] } catch (e) { - void Alert.err(`获取随笔列表失败: ${e}`) + void Alert.err(`获取随笔列表失败: ${e as string}`) return [] } } - export async function getCount() { + static async getCount() { const req = await getAuthedPostReq() try { return await req.getCount() } catch (e) { - void Alert.err(`获取随笔列表失败: ${e}`) + void Alert.err(`获取随笔列表失败: ${e as string}`) return 0 } } // TODO: need better impl - export async function* iterAll() { - const postCount = await getCount() + static async* iterAll() { + const postCount = await PostService.getCount() for (const i of Array(postCount).keys()) { const list = await PostService.getList(i + 1, 1) const id = list[0].id @@ -92,36 +92,36 @@ export namespace PostService { } } - export async function getPostEditDto(postId: number) { + static async getPostEditDto(postId: number) { const req = await getAuthedPostReq() try { const resp = await req.getOne(postId) // TODO: need better impl - const { blogPost, myConfig } = <{ blogPost?: Post; myConfig?: MyConfig }>JSON.parse(resp) + const { blogPost, myConfig } = JSON.parse(resp) as { blogPost?: Post; myConfig?: MyConfig } if (blogPost === undefined) throw Error('博文不存在') - return { + return { post: Object.assign(new Post(), blogPost), config: myConfig, - } + } as PostEditDto } catch (e) { - void Alert.err(`获取博文失败: ${e}`) + void Alert.err(`获取博文失败: ${e as string}`) throw e } } - export async function del(...postIds: number[]) { + static async del(...postIds: number[]) { const req = await getAuthedPostReq() try { if (postIds.length === 1) await req.delOne(postIds[0]) else await req.delSome(new Uint32Array(postIds)) } catch (e) { - void Alert.err(`删除博文失败: ${e}`) + void Alert.err(`删除博文失败: ${e as string}`) } } - export async function update(post: Post) { + static async update(post: Post) { if (MarkdownCfg.isIgnoreYfmWhenUploadPost()) post.postBody = rmYfm(post.postBody) if (post.postBody === '') void Alert.warn('博文内容不能为空(发生于 http post 请求之前)') @@ -130,24 +130,24 @@ export namespace PostService { const req = await getAuthedPostReq() const resp = await req.update(body) - return JSON.parse(resp) + return JSON.parse(resp) as PostUpdatedResp } // TODO: need caahe - export async function getTemplate() { + static async getTemplate() { const req = await getAuthedPostReq() try { const resp = await req.getTemplate() // TODO: need better impl - const template = <{ blogPost?: Post; myConfig?: MyConfig }>JSON.parse(resp) + const template = JSON.parse(resp) as { blogPost?: Post; myConfig?: MyConfig } - return { + return { post: Object.assign(new Post(), template.blogPost), config: template.myConfig, - } + } as PostEditDto } catch (e) { - void Alert.err(`获取模板失败: ${e}`) + void Alert.err(`获取模板失败: ${e as string}`) throw e } } diff --git a/src/service/upload-img/image.service.ts b/src/service/upload-img/image.service.ts index 1b9655ec..5a8f618e 100644 --- a/src/service/upload-img/image.service.ts +++ b/src/service/upload-img/image.service.ts @@ -8,7 +8,6 @@ class ImageService { async upload( file: T ): Promise { - // eslint-disable-next-line @typescript-eslint/naming-convention const FormData = (await import('form-data')).default const form = new FormData() const { name, fileName, filename, path: _path } = file diff --git a/src/service/user.service.ts b/src/service/user.service.ts index 9b6acc8a..a942348d 100644 --- a/src/service/user.service.ts +++ b/src/service/user.service.ts @@ -4,20 +4,20 @@ import { UserInfo } from '@/model/user-info' import { ExtConst } from '@/ctx/ext-const' import fetch, { Headers } from 'node-fetch' -export namespace UserService { - export async function getUserInfo(): Promise { +export class UserService { + static async getUserInfo(): Promise { const token = await AuthManager.acquireToken() // TODO: need better solution const isPatToken = token.length === 64 - return getUserInfoWithToken(token, isPatToken) + return UserService.getUserInfoWithToken(token, isPatToken) } - export async function hasBlog(): Promise { + static async hasBlog(): Promise { const userInfo = await UserService.getUserInfo() return userInfo?.blogApp != null } - export async function getUserInfoWithToken(token: string, isPat: boolean): Promise { + static async getUserInfoWithToken(token: string, isPat: boolean): Promise { const url = `${ExtConst.ApiBase.OPENAPI}/users/v2` const headers = new Headers() diff --git a/src/setup/setup-cmd.ts b/src/setup/setup-cmd.ts index 08137394..8b2156b2 100644 --- a/src/setup/setup-cmd.ts +++ b/src/setup/setup-cmd.ts @@ -65,9 +65,7 @@ export function setupCmd() { regCmd(extName`.post.create`, createPost), regCmd(extName`.post.upload`, uploadPost), regCmd(extName`.post.upload-file`, uploadPostFile), - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument regCmd(extName`.post.upload-no-confirm`, arg => uploadPost(arg, false)), - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument regCmd(extName`.post.upload-file-no-confirm`, arg => uploadPostFile(arg, false)), regCmd(extName`.post.pull`, postPull), regCmd(extName`.post.pull-all`, postPullAll), diff --git a/src/stores/post-cate-store.ts b/src/stores/post-cate-store.ts index 1140bf6a..54b83136 100644 --- a/src/stores/post-cate-store.ts +++ b/src/stores/post-cate-store.ts @@ -4,7 +4,6 @@ import { PostCatService } from '@/service/post/post-cat' const DEFAULT_ORDER: number = 999999 export class PostCateStore { - // eslint-disable-next-line prettier/prettier constructor(private categories: ReadonlyArray) { } get isNullOrEmpty() { diff --git a/src/tree-view/model/blog-export/record.ts b/src/tree-view/model/blog-export/record.ts index 0643ac7f..22617418 100644 --- a/src/tree-view/model/blog-export/record.ts +++ b/src/tree-view/model/blog-export/record.ts @@ -4,8 +4,8 @@ import { BaseTreeItemSource } from '@/tree-view/model/base-tree-item-source' import { BlogExportRecordMetadata } from './record-metadata' import { parseStatusIcon } from './parser' import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from 'vscode' -import format from 'date-fns/format' -import parseISO from 'date-fns/parseISO' +import { format } from 'date-fns/format' +import { parseISO } from 'date-fns/parseISO' import { DownloadedExportStore } from '@/service/downloaded-export.store' import { BlogExportTreeItem, DownloadedExportTreeItem } from '@/tree-view/model/blog-export' import os from 'os' @@ -60,7 +60,6 @@ export class BlogExportRecordTreeItem extends BaseTreeItemSource implements Base } private pollingStatus() { - // eslint-disable-next-line @typescript-eslint/no-misused-promises const timeoutId = setTimeout(async () => { clearTimeout(timeoutId) try { @@ -92,10 +91,9 @@ export class BlogExportRecordTreeItem extends BaseTreeItemSource implements Base new BlogExportRecordMetadata( this, id, - `博文数量: ${ - status === BlogExportStatus.done - ? record.postCount - : `${record.exportedPostCount}/${record.postCount}` + `博文数量: ${status === BlogExportStatus.done + ? record.postCount + : `${record.exportedPostCount}/${record.postCount}` }`, undefined, new ThemeIcon('layers') @@ -116,35 +114,35 @@ export class BlogExportRecordTreeItem extends BaseTreeItemSource implements Base ), ...(dateExported !== null && dateExported !== undefined ? [ - new BlogExportRecordMetadata( - this, - id, - `完成时间: ${format(parseISO(dateExported), dateTimeFormat)}`, - undefined, - new ThemeIcon('vscode-cnb-date') - ), - ] + new BlogExportRecordMetadata( + this, + id, + `完成时间: ${format(parseISO(dateExported), dateTimeFormat)}`, + undefined, + new ThemeIcon('vscode-cnb-date') + ), + ] : []), ...(localExport !== undefined && (_downloadingProgress === null || _downloadingProgress === undefined) ? [ - new DownloadedExportTreeItem(this, localExport, { - label: `本地文件: ${localExport.filePath.replace( - new RegExp('^' + escapeRegExp(os.homedir())), - '~' - )}`, - }), - ] + new DownloadedExportTreeItem(this, localExport, { + label: `本地文件: ${localExport.filePath.replace( + new RegExp('^' + escapeRegExp(os.homedir())), + '~' + )}`, + }), + ] : []), ...(_downloadingProgress !== undefined && _downloadingProgress !== null ? [ - new BlogExportRecordMetadata( - this, - id, - `${this.formatDownloadProgress(filesize)}`, - undefined, - new ThemeIcon('sync~spin') - ), - ] + new BlogExportRecordMetadata( + this, + id, + `${this.formatDownloadProgress(filesize)}`, + undefined, + new ThemeIcon('sync~spin') + ), + ] : []), ] } diff --git a/src/tree-view/model/post-metadata.ts b/src/tree-view/model/post-metadata.ts index 90033d57..b34456ca 100644 --- a/src/tree-view/model/post-metadata.ts +++ b/src/tree-view/model/post-metadata.ts @@ -1,9 +1,8 @@ -/* eslint-disable prettier/prettier */ -import differenceInSeconds from 'date-fns/differenceInSeconds' -import differenceInYears from 'date-fns/differenceInYears' -import format from 'date-fns/format' -import formatDistanceStrict from 'date-fns/formatDistanceStrict' -import zhCN from 'date-fns/locale/zh-CN' +import { differenceInSeconds } from 'date-fns/differenceInSeconds' +import { differenceInYears } from 'date-fns/differenceInYears' +import { format } from 'date-fns/format' +import { formatDistanceStrict } from 'date-fns/formatDistanceStrict' +import { zhCN } from 'date-fns/locale/zh-CN' import { TreeItem, TreeItemCollapsibleState, ThemeIcon } from 'vscode' import { AccessPermission, Post, formatAccessPermission } from '@/model/post' import { PostEditDto } from '@/model/post-edit-dto' @@ -82,7 +81,6 @@ export abstract class PostMetadata extends BaseTreeItemSource { export abstract class PostEntryMetadata extends PostMetadata - // eslint-disable-next-line prettier/prettier implements BaseEntryTreeItem { constructor( parent: Post, @@ -203,6 +201,7 @@ export abstract class PostDateMetadata extends PostMetadata { this.distance = this.toDistance() } + // eslint-disable-next-line @typescript-eslint/class-literal-property-style get enabled(): boolean { return true } @@ -217,7 +216,6 @@ export abstract class PostDateMetadata extends PostMetadata { toTreeItem = (): TreeItem => Object.assign( new TreeItem( - // eslint-disable-next-line prettier/prettier `${this.label}: ${this.shouldUseDistance() ? this.distance + `(${this.formattedDate})` : this.formattedDate }` ), diff --git a/src/tree-view/navi-view.ts b/src/tree-view/navi-view.ts index e4b84562..80d393e0 100644 --- a/src/tree-view/navi-view.ts +++ b/src/tree-view/navi-view.ts @@ -5,7 +5,6 @@ export class NaviViewDataProvider implements TreeDataProvider { return el } - // eslint-disable-next-line @typescript-eslint/no-unused-vars getChildren(el?: TreeItem): ProviderResult { return [ { diff --git a/src/tree-view/provider/blog-export-provider.ts b/src/tree-view/provider/blog-export-provider.ts index e2f5520b..304c5c61 100644 --- a/src/tree-view/provider/blog-export-provider.ts +++ b/src/tree-view/provider/blog-export-provider.ts @@ -47,8 +47,6 @@ export class BlogExportProvider implements TreeDataProvider el instanceof ExportPostEntryTreeItem || el instanceof DownloadedExportTreeItem ) { - // TODO: fix lint - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore return el.getChildrenAsync() } @@ -76,9 +74,9 @@ export class BlogExportProvider implements TreeDataProvider if (entry !== null && entry !== undefined) { const hasCacheRefreshed = force ? await entry.refresh().then( - () => true, - () => false - ) + () => true, + () => false + ) : true if (hasCacheRefreshed) this._treeDataChangedSource?.fire(this._downloadedExportEntry) @@ -111,18 +109,18 @@ export class BlogExportProvider implements TreeDataProvider // TODO: need refactor const hasCacheRefreshed = force ? await BlogExportRecordsStore?.refresh() - .then(() => true) - .catch(async e => { - if (notifyOnError && (await UserService.hasBlog())) - void Alert.err(`刷新备份记录失败: ${e}`) - return false - }) + .then(() => true) + .catch(async e => { + if (notifyOnError && (await UserService.hasBlog())) + void Alert.err(`刷新备份记录失败: ${e as string}`) + return false + }) : clearCache - ? await BlogExportRecordsStore.clearCache().then( + ? await BlogExportRecordsStore.clearCache().then( () => true, () => true ) - : true + : true if (hasCacheRefreshed) this._treeDataChangedSource?.fire(null) diff --git a/src/tree-view/provider/post-category-tree-data-provider.ts b/src/tree-view/provider/post-category-tree-data-provider.ts index 404f88ac..85edb85e 100644 --- a/src/tree-view/provider/post-category-tree-data-provider.ts +++ b/src/tree-view/provider/post-category-tree-data-provider.ts @@ -131,7 +131,7 @@ export class PostCatTreeDataProvider implements TreeDataProvider new PostCatTreeItem(x)) } catch (e) { - void Alert.err(`获取博文分类失败: ${e}`) + void Alert.err(`获取博文分类失败: ${e as string}`) await this.setIsRefreshing(false) throw e } diff --git a/src/tree-view/provider/post-data-provider.ts b/src/tree-view/provider/post-data-provider.ts index 086d3d5d..19928c4c 100644 --- a/src/tree-view/provider/post-data-provider.ts +++ b/src/tree-view/provider/post-data-provider.ts @@ -74,7 +74,7 @@ export class PostDataProvider implements TreeDataProvider { return this.page } catch (e) { - if (await UserService.hasBlog()) void Alert.err(`加载博文失败: ${e}`) + if (await UserService.hasBlog()) void Alert.err(`加载博文失败: ${e as string}`) throw e } } diff --git a/src/tree-view/tree-view-register.ts b/src/tree-view/tree-view-register.ts index 34e2f412..467be193 100644 --- a/src/tree-view/tree-view-register.ts +++ b/src/tree-view/tree-view-register.ts @@ -53,6 +53,7 @@ export function setupExtTreeView() { }) const disposables: IDisposable[] = [] + // eslint-disable-next-line @typescript-eslint/no-unused-expressions for (const [, item] of Object.entries(_views)) typeof item === 'function' ? undefined : disposables.push(item) globalCtx.extCtx.subscriptions.push(...disposables) diff --git a/tsconfig.json b/tsconfig.json index ee5b7cc8..5bb7371a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,6 +9,7 @@ "rootDir": "src", "esModuleInterop": true, "allowSyntheticDefaultImports": true, + "importHelpers": true, "baseUrl": "./", "paths": { "@/*": ["src/*"] diff --git a/ui/share/active-theme-provider.ts b/ui/share/active-theme-provider.ts index 78552eed..6ebbff3a 100644 --- a/ui/share/active-theme-provider.ts +++ b/ui/share/active-theme-provider.ts @@ -1,7 +1,7 @@ import { darkTheme, lightTheme } from 'share/theme' -export namespace ActiveThemeProvider { - export function activeTheme() { +export class ActiveThemeProvider { + static activeTheme() { if (document.body.classList.contains('vscode-dark')) return darkTheme else return lightTheme }