diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..a007fea --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +build/* diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..991aab5 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,80 @@ +module.exports = { + 'env': { + 'browser': true, + 'es2020': true, + 'node': true + }, + 'extends': [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended' + ], + 'parser': '@typescript-eslint/parser', + 'parserOptions': { + 'ecmaVersion': 6, + 'sourceType': 'module' + // 'project': './tsconfig.json', + }, + 'plugins': [ + '@typescript-eslint' + ], + + /** + * 规则写法 + * 1、'quotes': 0; -- 0关闭,1警告,2错误 + * 2、'quotes': 'off'; -- off关闭,warn警告,error错误 + * 3、'quotes': ['error', 'single']; 'error'是提示类型,'single'是参数。参数不止一个的时候写成{} + */ + 'rules': { + // 是否检查变量已申明但未使用:警告。 + '@typescript-eslint/no-unused-vars': ['warn'], + // 强制单引号:开启,自动修正 + 'quotes': 0, + // 强制分号:js 关闭,ts 强制分号。 + 'semi': ['off'], + // 'semi': ['off'], + // 定义变量时自动类型推断:关闭 + '@typescript-eslint/no-inferrable-types': ['off'], + // 强制const:关闭 + 'prefer-const': ['off'], + // 不允许空函数:关闭 + '@typescript-eslint/no-empty-function': ['off'], + // 禁止特定类型:关闭。 PS:如果打开 Function 类型会报错 + '@typescript-eslint/ban-types': ['off'], + // 禁止多余的分号:关闭。 PS:打开后,某些大括号结束加分号会报错 + '@typescript-eslint/no-extra-semi': ['off'], + // 检查函数是否有返回值:警告。 PS:有些老代码没有返回值,历史包袱重,暂时不强制报错 + '@typescript-eslint/explicit-module-boundary-types': ['warn'], + // 禁止给变量赋值为 this:关闭。 + '@typescript-eslint/no-this-alias': ['off'], + // 禁止使用 requires:关闭。 + '@typescript-eslint/no-var-requires': ['off'], + // 检测无法访问的代码:关闭。 PS:有时候需要用 return 注释掉后面的代码 + 'no-unreachable': ['off'], + /** + * 是否可以直接调用对象方法:关闭。 + * PS:暂时关闭。目前写法:myObject.hasOwnProperty('name') ,推荐写法:Object.prototype.hasOwnProperty.call(foo, "bar") + */ + 'no-prototype-builtins': ['off'], + // 是否允许函数内定义函数:关闭。 + 'no-inner-declarations': ['off'], + // 不允许判断条件写死:关闭。 PS:打开后,if(false){} 这种判断语句会报错 + 'no-constant-condition': ['off'], + // get 和 set 是否必须放在一起:关闭。 + '@typescript-eslint/adjacent-overload-signatures': ['off'], + "no-async-promise-executor": ['off'] + }, + // 如果有 js 和 ts 需要分开指定的规则,就 js 写 rules 里,ts 写 overrides 里 + 'overrides': [{ + // enable the rule specifically for TypeScript files + 'files': ['*.ts', '*.tsx'], + 'rules': { + // 强制分号:开启,自动修正 + 'semi': ['error', 'always'], + // '@typescript-eslint/explicit-module-boundary-types': ['error'] + } + }], + // 定义全局变量 + 'globals': { + 'Global': true + } +}; diff --git a/CHANGELOG.md b/CHANGELOG.md index ff4ebaf..cc3928a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## version 2.0.0 +- 重构 + ## version 1.1.9 - BWC90 & WC317 数据 diff --git a/LICENSE b/LICENSE index 9bde961..50e6cda 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020-present ccagml +Copyright (c) 2022-present ccagml Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/_config.yml b/_config.yml index c419263..277f1f2 100644 --- a/_config.yml +++ b/_config.yml @@ -1 +1 @@ -theme: jekyll-theme-cayman \ No newline at end of file +theme: jekyll-theme-cayman diff --git a/package-lock.json b/package-lock.json index 888f16e..6cdb985 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "vscode-leetcode-problem-rating", - "version": "1.1.8", + "version": "1.1.9", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "vscode-leetcode-problem-rating", - "version": "1.1.8", + "version": "1.1.9", "license": "MIT", "dependencies": { "ansi-styles": "3.2.1", @@ -22,7 +22,6 @@ "ora": "3.0.0", "prompt": "^1.2.0", "request": "2.88.0", - "require-from-string": "^2.0.2", "underscore": "1.12.1", "unescape-js": "^1.1.4", "wordwrap": "1.0.0" @@ -32,11 +31,13 @@ "@types/lodash": "^4.14.170", "@types/markdown-it": "0.0.7", "@types/node": "^14.14.33", - "@types/require-from-string": "^1.2.0", "@types/vscode": "1.57.0", + "@typescript-eslint/eslint-plugin": "^5.42.1", + "@typescript-eslint/parser": "^5.42.1", "chai": "4.2.0", + "eslint": "^8.27.0", "tslint": "^5.20.1", - "typescript": "^4.3.2" + "typescript": "^4.8.4" }, "engines": { "vscode": "^1.57.0" @@ -85,6 +86,109 @@ "node": ">=0.1.90" } }, + "node_modules/@eslint/eslintrc": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", + "integrity": "sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.4.0", + "globals": "^13.15.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.7", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.7.tgz", + "integrity": "sha512-kBbPWzN8oVMLb0hOUYXhmxggL/1cJE6ydvjDIGi9EnAGUyA7cLVKQg+d/Dsm+KZwx2czGHrCmMVLiyg8s5JPKw==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/@types/fs-extra": { "version": "9.0.13", "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", @@ -94,6 +198,12 @@ "@types/node": "*" } }, + "node_modules/@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, "node_modules/@types/linkify-it": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz", @@ -121,10 +231,10 @@ "integrity": "sha512-qelS/Ra6sacc4loe/3MSjXNL1dNQ/GjxNHVzuChwMfmk7HuycRLVQN2qNY3XahK+fZc5E2szqQSKUyAF0E+2bg==", "dev": true }, - "node_modules/@types/require-from-string": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@types/require-from-string/-/require-from-string-1.2.1.tgz", - "integrity": "sha512-mIDK7lTHc0uW67SxPIqkwCrxmdKBV5aAET560hyZnT8c6Ekp9Aah3GPqe8Pl1Yzn/i2NMYmYv+HiMLwjGDCIAQ==", + "node_modules/@types/semver": { + "version": "7.3.13", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", + "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", "dev": true }, "node_modules/@types/vscode": { @@ -133,6 +243,304 @@ "integrity": "sha512-FeznBFtIDCWRluojTsi9c3LLcCHOXP5etQfBK42+ixo1CoEAchkw39tuui9zomjZuKfUVL33KZUDIwHZ/xvOkQ==", "dev": true }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.42.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.42.1.tgz", + "integrity": "sha512-LyR6x784JCiJ1j6sH5Y0K6cdExqCCm8DJUTcwG5ThNXJj/G8o5E56u5EdG4SLy+bZAwZBswC+GYn3eGdttBVCg==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.42.1", + "@typescript-eslint/type-utils": "5.42.1", + "@typescript-eslint/utils": "5.42.1", + "debug": "^4.3.4", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "regexpp": "^3.2.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.42.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.42.1.tgz", + "integrity": "sha512-kAV+NiNBWVQDY9gDJDToTE/NO8BHi4f6b7zTsVAJoTkmB/zlfOpiEVBzHOKtlgTndCKe8vj9F/PuolemZSh50Q==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.42.1", + "@typescript-eslint/types": "5.42.1", + "@typescript-eslint/typescript-estree": "5.42.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.42.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.42.1.tgz", + "integrity": "sha512-QAZY/CBP1Emx4rzxurgqj3rUinfsh/6mvuKbLNMfJMMKYLRBfweus8brgXF8f64ABkIZ3zdj2/rYYtF8eiuksQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.42.1", + "@typescript-eslint/visitor-keys": "5.42.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.42.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.42.1.tgz", + "integrity": "sha512-WWiMChneex5w4xPIX56SSnQQo0tEOy5ZV2dqmj8Z371LJ0E+aymWD25JQ/l4FOuuX+Q49A7pzh/CGIQflxMVXg==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "5.42.1", + "@typescript-eslint/utils": "5.42.1", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.42.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.42.1.tgz", + "integrity": "sha512-Qrco9dsFF5lhalz+lLFtxs3ui1/YfC6NdXu+RAGBa8uSfn01cjO7ssCsjIsUs484vny9Xm699FSKwpkCcqwWwA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.42.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.42.1.tgz", + "integrity": "sha512-qElc0bDOuO0B8wDhhW4mYVgi/LZL+igPwXtV87n69/kYC/7NG3MES0jHxJNCr4EP7kY1XVsRy8C/u3DYeTKQmw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.42.1", + "@typescript-eslint/visitor-keys": "5.42.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.42.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.42.1.tgz", + "integrity": "sha512-Gxvf12xSp3iYZd/fLqiQRD4uKZjDNR01bQ+j8zvhPjpsZ4HmvEFL/tC4amGNyxN9Rq+iqvpHLhlqx6KTxz9ZyQ==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.42.1", + "@typescript-eslint/types": "5.42.1", + "@typescript-eslint/typescript-estree": "5.42.1", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.42.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.42.1.tgz", + "integrity": "sha512-LOQtSF4z+hejmpUvitPlc4hA7ERGoj2BVkesOcG91HCn8edLGUXbTrErmutmPbl8Bo9HjAvOO/zBKQHExXNA2A==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.42.1", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/acorn": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", + "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -172,6 +580,15 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/asn1": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", @@ -249,6 +666,18 @@ "concat-map": "0.0.1" } }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/builtin-modules": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", @@ -258,6 +687,15 @@ "node": ">=0.10.0" } }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -443,6 +881,20 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/css-select": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", @@ -488,6 +940,23 @@ "node": ">=0.10" } }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, "node_modules/deep-eql": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", @@ -500,6 +969,12 @@ "node": ">=0.12" } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, "node_modules/defaults": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", @@ -528,6 +1003,30 @@ "node": ">=0.3.1" } }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -620,19 +1119,338 @@ "node": ">=0.8.0" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "node_modules/eslint": { + "version": "8.27.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.27.0.tgz", + "integrity": "sha512-0y1bfG2ho7mty+SiILVf9PfuRA49ek4Nc60Wmmu62QlobNR+CeXa4xXIJgcuwSQgZiWaPH+5BDsctpIW0PR/wQ==", "dev": true, + "dependencies": { + "@eslint/eslintrc": "^1.3.3", + "@humanwhocodes/config-array": "^0.11.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.4.0", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.15.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/eslint/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz", + "integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==", + "dev": true, + "dependencies": { + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" }, "engines": { "node": ">=4" } }, + "node_modules/esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -659,11 +1477,113 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, + "node_modules/fast-glob": { + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, "node_modules/forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -755,11 +1675,64 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "13.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", + "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, "node_modules/har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -845,8 +1818,42 @@ "sshpk": "^1.7.0" }, "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" } }, "node_modules/inflight": { @@ -885,6 +1892,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -893,16 +1909,58 @@ "node": ">=8" } }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, "node_modules/isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" }, + "node_modules/js-sdsl": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", + "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==", + "dev": true + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -946,6 +2004,12 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -976,6 +2040,19 @@ "node": ">=0.6.0" } }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/linkify-it": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", @@ -984,11 +2061,32 @@ "uc.micro": "^1.0.1" } }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, "node_modules/log-symbols": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", @@ -1000,6 +2098,18 @@ "node": ">=4" } }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/markdown-it": { "version": "12.3.2", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", @@ -1028,6 +2138,28 @@ "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==" }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -1095,11 +2227,29 @@ "node": "*" } }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, "node_modules/mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, "node_modules/nconf": { "version": "0.11.4", "resolved": "https://registry.npmjs.org/nconf/-/nconf-0.11.4.tgz", @@ -1153,6 +2303,23 @@ "node": ">=4" } }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/ora": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ora/-/ora-3.0.0.tgz", @@ -1169,6 +2336,48 @@ "node": ">=6" } }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/parse5": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.1.tgz", @@ -1192,6 +2401,15 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -1201,12 +2419,30 @@ "node": ">=0.10.0" } }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", @@ -1221,6 +2457,27 @@ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/prompt": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/prompt/-/prompt-1.3.0.tgz", @@ -1259,6 +2516,26 @@ "node": ">=0.6" } }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/read": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", @@ -1270,6 +2547,18 @@ "node": ">=0.8" } }, + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, "node_modules/request": { "version": "2.88.0", "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", @@ -1309,14 +2598,6 @@ "node": ">=0.10.0" } }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/resolve": { "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", @@ -1334,6 +2615,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/restore-cursor": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", @@ -1346,6 +2636,16 @@ "node": ">=4" } }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, "node_modules/revalidator": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz", @@ -1354,6 +2654,44 @@ "node": ">= 0.4.0" } }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -1392,11 +2730,41 @@ "semver": "bin/semver" } }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -1483,6 +2851,18 @@ "node": ">=4" } }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -1499,11 +2879,29 @@ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, - "engines": { - "node": ">= 0.4" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=8.0" } }, "node_modules/tough-cookie": { @@ -1594,6 +2992,18 @@ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -1603,6 +3013,18 @@ "node": ">=4" } }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/typescript": { "version": "4.8.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", @@ -1688,6 +3110,21 @@ "defaults": "^1.0.3" } }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/winston": { "version": "2.4.6", "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.6.tgz", @@ -1709,6 +3146,15 @@ "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -1793,6 +3239,12 @@ "node": ">=10" } }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", @@ -1817,6 +3269,18 @@ "engines": { "node": ">=10" } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } }, "dependencies": { @@ -1851,6 +3315,83 @@ "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==" }, + "@eslint/eslintrc": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", + "integrity": "sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.4.0", + "globals": "^13.15.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + } + } + }, + "@humanwhocodes/config-array": { + "version": "0.11.7", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.7.tgz", + "integrity": "sha512-kBbPWzN8oVMLb0hOUYXhmxggL/1cJE6ydvjDIGi9EnAGUyA7cLVKQg+d/Dsm+KZwx2czGHrCmMVLiyg8s5JPKw==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + } + }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true + }, + "@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, "@types/fs-extra": { "version": "9.0.13", "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", @@ -1860,6 +3401,12 @@ "@types/node": "*" } }, + "@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, "@types/linkify-it": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz", @@ -1887,10 +3434,10 @@ "integrity": "sha512-qelS/Ra6sacc4loe/3MSjXNL1dNQ/GjxNHVzuChwMfmk7HuycRLVQN2qNY3XahK+fZc5E2szqQSKUyAF0E+2bg==", "dev": true }, - "@types/require-from-string": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@types/require-from-string/-/require-from-string-1.2.1.tgz", - "integrity": "sha512-mIDK7lTHc0uW67SxPIqkwCrxmdKBV5aAET560hyZnT8c6Ekp9Aah3GPqe8Pl1Yzn/i2NMYmYv+HiMLwjGDCIAQ==", + "@types/semver": { + "version": "7.3.13", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", + "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", "dev": true }, "@types/vscode": { @@ -1899,6 +3446,179 @@ "integrity": "sha512-FeznBFtIDCWRluojTsi9c3LLcCHOXP5etQfBK42+ixo1CoEAchkw39tuui9zomjZuKfUVL33KZUDIwHZ/xvOkQ==", "dev": true }, + "@typescript-eslint/eslint-plugin": { + "version": "5.42.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.42.1.tgz", + "integrity": "sha512-LyR6x784JCiJ1j6sH5Y0K6cdExqCCm8DJUTcwG5ThNXJj/G8o5E56u5EdG4SLy+bZAwZBswC+GYn3eGdttBVCg==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "5.42.1", + "@typescript-eslint/type-utils": "5.42.1", + "@typescript-eslint/utils": "5.42.1", + "debug": "^4.3.4", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "regexpp": "^3.2.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "dependencies": { + "semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + } + } + }, + "@typescript-eslint/parser": { + "version": "5.42.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.42.1.tgz", + "integrity": "sha512-kAV+NiNBWVQDY9gDJDToTE/NO8BHi4f6b7zTsVAJoTkmB/zlfOpiEVBzHOKtlgTndCKe8vj9F/PuolemZSh50Q==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "5.42.1", + "@typescript-eslint/types": "5.42.1", + "@typescript-eslint/typescript-estree": "5.42.1", + "debug": "^4.3.4" + } + }, + "@typescript-eslint/scope-manager": { + "version": "5.42.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.42.1.tgz", + "integrity": "sha512-QAZY/CBP1Emx4rzxurgqj3rUinfsh/6mvuKbLNMfJMMKYLRBfweus8brgXF8f64ABkIZ3zdj2/rYYtF8eiuksQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.42.1", + "@typescript-eslint/visitor-keys": "5.42.1" + } + }, + "@typescript-eslint/type-utils": { + "version": "5.42.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.42.1.tgz", + "integrity": "sha512-WWiMChneex5w4xPIX56SSnQQo0tEOy5ZV2dqmj8Z371LJ0E+aymWD25JQ/l4FOuuX+Q49A7pzh/CGIQflxMVXg==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "5.42.1", + "@typescript-eslint/utils": "5.42.1", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "dependencies": { + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + } + } + }, + "@typescript-eslint/types": { + "version": "5.42.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.42.1.tgz", + "integrity": "sha512-Qrco9dsFF5lhalz+lLFtxs3ui1/YfC6NdXu+RAGBa8uSfn01cjO7ssCsjIsUs484vny9Xm699FSKwpkCcqwWwA==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.42.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.42.1.tgz", + "integrity": "sha512-qElc0bDOuO0B8wDhhW4mYVgi/LZL+igPwXtV87n69/kYC/7NG3MES0jHxJNCr4EP7kY1XVsRy8C/u3DYeTKQmw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.42.1", + "@typescript-eslint/visitor-keys": "5.42.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "dependencies": { + "semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + } + } + }, + "@typescript-eslint/utils": { + "version": "5.42.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.42.1.tgz", + "integrity": "sha512-Gxvf12xSp3iYZd/fLqiQRD4uKZjDNR01bQ+j8zvhPjpsZ4HmvEFL/tC4amGNyxN9Rq+iqvpHLhlqx6KTxz9ZyQ==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.42.1", + "@typescript-eslint/types": "5.42.1", + "@typescript-eslint/typescript-estree": "5.42.1", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0", + "semver": "^7.3.7" + }, + "dependencies": { + "semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.42.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.42.1.tgz", + "integrity": "sha512-LOQtSF4z+hejmpUvitPlc4hA7ERGoj2BVkesOcG91HCn8edLGUXbTrErmutmPbl8Bo9HjAvOO/zBKQHExXNA2A==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.42.1", + "eslint-visitor-keys": "^3.3.0" + } + }, + "acorn": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", + "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -1928,6 +3648,12 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, "asn1": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", @@ -1996,12 +3722,27 @@ "concat-map": "0.0.1" } }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, "builtin-modules": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", "integrity": "sha512-wxXCdllwGhI2kCC0MnvTGYTMvnVZTvqgypkiTI8Pa5tcz2i6VqsqwYGgqwXji+4RgCzms6EajE4IxiUH6HH8nQ==", "dev": true }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -2150,6 +3891,17 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, "css-select": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", @@ -2180,6 +3932,15 @@ "assert-plus": "^1.0.0" } }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, "deep-eql": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", @@ -2189,6 +3950,12 @@ "type-detect": "^4.0.0" } }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, "defaults": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", @@ -2208,6 +3975,24 @@ "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, "dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -2250,25 +4035,213 @@ "safer-buffer": "^2.1.0" } }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "entities": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", + "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==" + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + }, + "eslint": { + "version": "8.27.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.27.0.tgz", + "integrity": "sha512-0y1bfG2ho7mty+SiILVf9PfuRA49ek4Nc60Wmmu62QlobNR+CeXa4xXIJgcuwSQgZiWaPH+5BDsctpIW0PR/wQ==", + "dev": true, + "requires": { + "@eslint/eslintrc": "^1.3.3", + "@humanwhocodes/config-array": "^0.11.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.4.0", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.15.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } }, - "entities": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", - "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==" + "eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^2.0.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + } + } }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + "eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "dev": true }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + "espree": { + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz", + "integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==", + "dev": true, + "requires": { + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" + } }, "esprima": { "version": "4.0.1", @@ -2276,6 +4249,52 @@ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, + "esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -2296,11 +4315,94 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, + "fast-glob": { + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -2371,11 +4473,49 @@ "path-is-absolute": "^1.0.0" } }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "globals": { + "version": "13.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", + "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, "graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, + "grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -2435,6 +4575,28 @@ "sshpk": "^1.7.0" } }, + "ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -2465,21 +4627,60 @@ "has": "^1.0.3" } }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" }, + "js-sdsl": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", + "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==", + "dev": true + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -2522,6 +4723,12 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -2547,6 +4754,16 @@ "verror": "1.10.0" } }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, "linkify-it": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", @@ -2555,11 +4772,26 @@ "uc.micro": "^1.0.1" } }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, "lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, "log-symbols": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", @@ -2568,6 +4800,15 @@ "chalk": "^2.0.1" } }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, "markdown-it": { "version": "12.3.2", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", @@ -2592,6 +4833,22 @@ "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==" }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, "mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -2635,11 +4892,29 @@ "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, "mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, "nconf": { "version": "0.11.4", "resolved": "https://registry.npmjs.org/nconf/-/nconf-0.11.4.tgz", @@ -2681,6 +4956,20 @@ "mimic-fn": "^1.0.0" } }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, "ora": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ora/-/ora-3.0.0.tgz", @@ -2694,6 +4983,33 @@ "wcwidth": "^1.0.1" } }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, "parse5": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.1.tgz", @@ -2711,18 +5027,36 @@ "parse5": "^7.0.0" } }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, "path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, "pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", @@ -2734,6 +5068,18 @@ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, "prompt": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/prompt/-/prompt-1.3.0.tgz", @@ -2768,6 +5114,12 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==" }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, "read": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", @@ -2776,6 +5128,12 @@ "mute-stream": "~0.0.4" } }, + "regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true + }, "request": { "version": "2.88.0", "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", @@ -2808,11 +5166,6 @@ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" - }, "resolve": { "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", @@ -2824,6 +5177,12 @@ "supports-preserve-symlinks-flag": "^1.0.0" } }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, "restore-cursor": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", @@ -2833,11 +5192,35 @@ "signal-exit": "^3.0.2" } }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, "revalidator": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz", "integrity": "sha512-xcBILK2pA9oh4SiinPEZfhP8HfrB/ha+a2fTMyl7Om2WjlDVrOQy99N2MXXlUHqGJz4qEu2duXxHJjDWuK/0xg==" }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -2859,11 +5242,32 @@ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, "signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -2929,6 +5333,12 @@ "ansi-regex": "^3.0.0" } }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -2943,6 +5353,21 @@ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, "tough-cookie": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", @@ -3012,12 +5437,27 @@ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + }, "typescript": { "version": "4.8.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", @@ -3085,6 +5525,15 @@ "defaults": "^1.0.3" } }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, "winston": { "version": "2.4.6", "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.6.tgz", @@ -3105,6 +5554,12 @@ } } }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -3167,6 +5622,12 @@ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", @@ -3185,6 +5646,12 @@ "version": "20.2.9", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==" + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true } } } diff --git a/package.json b/package.json index 488a488..ceb8cdb 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "vscode-leetcode-problem-rating", "displayName": "LeetCode problem rating", "description": "为LeetCode题目难度进行打分。避免只有简单、中等、困难三种难度", - "version": "1.1.9", + "version": "2.0.0", "author": "ccagml", "publisher": "ccagml", "license": "MIT", @@ -29,7 +29,6 @@ "onCommand:leetcode.toggleLeetCodeCn", "onCommand:leetcode.signin", "onCommand:leetcode.signout", - "onCommand:leetcode.manageSessions", "onCommand:leetcode.refreshExplorer", "onCommand:leetcode.pickOne", "onCommand:leetcode.deleteAllCache", @@ -67,11 +66,6 @@ "title": "Sign Out", "category": "LeetCode" }, - { - "command": "leetcode.manageSessions", - "title": "Manage Sessions", - "category": "LeetCode" - }, { "command": "leetcode.refreshExplorer", "title": "Refresh", @@ -773,22 +767,22 @@ "@types/lodash": "^4.14.170", "@types/markdown-it": "0.0.7", "@types/node": "^14.14.33", - "@types/require-from-string": "^1.2.0", "@types/vscode": "1.57.0", + "@typescript-eslint/eslint-plugin": "^5.42.1", + "@typescript-eslint/parser": "^5.42.1", + "chai": "4.2.0", + "eslint": "^8.27.0", "tslint": "^5.20.1", - "typescript": "^4.3.2", - "chai": "4.2.0" + "typescript": "^4.8.4" }, "dependencies": { + "ansi-styles": "3.2.1", + "cheerio": "1.0.0-rc.12", "fs-extra": "^10.0.0", + "he": "1.2.0", "highlight.js": "^10.7.2", "lodash": "^4.17.21", "markdown-it": "12.3.2", - "require-from-string": "^2.0.2", - "unescape-js": "^1.1.4", - "ansi-styles": "3.2.1", - "cheerio": "1.0.0-rc.12", - "he": "1.2.0", "mkdirp": "^1.0.4", "moment": "^2.29.1", "nconf": "^0.11.2", @@ -796,6 +790,7 @@ "prompt": "^1.2.0", "request": "2.88.0", "underscore": "1.12.1", + "unescape-js": "^1.1.4", "wordwrap": "1.0.0" } } diff --git a/resources/bin/leetcode b/resources/bin/leetcode index 719ac70..eab3991 100755 --- a/resources/bin/leetcode +++ b/resources/bin/leetcode @@ -1,3 +1,3 @@ #!/usr/bin/env node -require('../../out/src/vsc-leetcode-cli/new_lib/cli'); +require('../../out/src/childProcessCall/cli'); diff --git a/src/vsc-leetcode-cli/new_lib/cache.ts b/src/childProcessCall/cache.ts similarity index 75% rename from src/vsc-leetcode-cli/new_lib/cache.ts rename to src/childProcessCall/cache.ts index 331574b..ad1a972 100644 --- a/src/vsc-leetcode-cli/new_lib/cache.ts +++ b/src/childProcessCall/cache.ts @@ -1,4 +1,14 @@ -var path = require('path'); +/* + * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/cache.ts + * Path: https://github.com/ccagml/vscode-leetcode-problem-rating + * Created Date: Thursday, October 27th 2022, 7:43:29 pm + * Author: ccagml + * + * Copyright (c) 2022 ccagml . All rights reserved. + */ + + +let path = require('path'); import { file } from "./file"; @@ -11,7 +21,7 @@ class Cache { public deleteAll() { this.list().forEach(value => { this.del(value.name); - }) + }); }; public get(k) { diff --git a/src/vsc-leetcode-cli/new_lib/cli.ts b/src/childProcessCall/cli.ts similarity index 62% rename from src/vsc-leetcode-cli/new_lib/cli.ts rename to src/childProcessCall/cli.ts index a582108..89239c8 100644 --- a/src/vsc-leetcode-cli/new_lib/cli.ts +++ b/src/childProcessCall/cli.ts @@ -1,4 +1,12 @@ +/* + * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/cli.ts + * Path: https://github.com/ccagml/vscode-leetcode-problem-rating + * Created Date: Thursday, October 27th 2022, 7:43:29 pm + * Author: ccagml + * + * Copyright (c) 2022 ccagml . All rights reserved. + */ // var h = require('./helper'); @@ -8,7 +16,7 @@ import { log } from "./log"; import { file } from "./file"; class NewCli { constructor() { - this.run() + this.run(); } public run() { process.stdout.on('error', function (e) { @@ -16,7 +24,7 @@ class NewCli { }); config.init(); this.initLogLevel(); - this.initDir() + this.initDir(); this.initPlugins((e) => { if (e) return log.fatal(e); require('./cache').cache.init(); @@ -30,7 +38,7 @@ class NewCli { private initDir() { file.init(); - file.mkdir(file.homeDir()) + file.mkdir(file.homeDir()); } private initPlugins(cb) { @@ -41,9 +49,9 @@ class NewCli { } private runCommand_new() { - var com_str = process.argv[2] - var auto_js = require("./commands/" + com_str)[com_str + "Command"] - auto_js.handler(auto_js.process_argv(process.argv)) + let com_str = process.argv[2]; + let auto_js = require("./commands/" + com_str)[com_str + "Command"]; + auto_js.handler(auto_js.process_argv(process.argv)); } } diff --git a/src/vsc-leetcode-cli/new_lib/commands/cache.ts b/src/childProcessCall/commands/cache.ts similarity index 73% rename from src/vsc-leetcode-cli/new_lib/commands/cache.ts rename to src/childProcessCall/commands/cache.ts index fe408e8..d2b8119 100644 --- a/src/vsc-leetcode-cli/new_lib/commands/cache.ts +++ b/src/childProcessCall/commands/cache.ts @@ -1,4 +1,14 @@ -var underscore = require('underscore'); +/* + * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/commands/cache.ts + * Path: https://github.com/ccagml/vscode-leetcode-problem-rating + * Created Date: Thursday, October 27th 2022, 7:43:29 pm + * Author: ccagml + * + * Copyright (c) 2022 ccagml . All rights reserved. + */ + + +let underscore = require('underscore'); import { helper } from "../helper"; @@ -11,7 +21,7 @@ class CacheCommand { } process_argv = function (argv) { - var argv_config = helper.base_argv().option('d', { + let argv_config = helper.base_argv().option('d', { alias: 'delete', type: 'boolean', describe: 'Delete cache by keyword', @@ -21,11 +31,11 @@ class CacheCommand { type: 'string', describe: 'Cache name or question id', default: '' - }) - argv_config.process_argv(argv) + }); + argv_config.process_argv(argv); - return argv_config.get_result() - } + return argv_config.get_result(); + }; handler = function (argv) { diff --git a/src/vsc-leetcode-cli/new_lib/commands/config.ts b/src/childProcessCall/commands/config.ts similarity index 78% rename from src/vsc-leetcode-cli/new_lib/commands/config.ts rename to src/childProcessCall/commands/config.ts index 50267f4..97053d9 100644 --- a/src/vsc-leetcode-cli/new_lib/commands/config.ts +++ b/src/childProcessCall/commands/config.ts @@ -1,5 +1,15 @@ -var underscore = require('underscore'); -var nconf = require('nconf'); +/* + * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/commands/config.ts + * Path: https://github.com/ccagml/vscode-leetcode-problem-rating + * Created Date: Thursday, October 27th 2022, 7:43:29 pm + * Author: ccagml + * + * Copyright (c) 2022 ccagml . All rights reserved. + */ + + +let underscore = require('underscore'); +let nconf = require('nconf'); import { config } from "../config"; @@ -15,7 +25,7 @@ class ConfigCommand { process_argv(argv) { - var argv_config = helper.base_argv().option('a', { + let argv_config = helper.base_argv().option('a', { alias: 'all', type: 'boolean', describe: 'Show all config', @@ -36,10 +46,10 @@ class ConfigCommand { type: 'string', describe: 'Config value', default: '' - }) - argv_config.process_argv(argv) + }); + argv_config.process_argv(argv); - return argv_config.get_result() + return argv_config.get_result(); } diff --git a/src/vsc-leetcode-cli/new_lib/commands/list.ts b/src/childProcessCall/commands/list.ts similarity index 72% rename from src/vsc-leetcode-cli/new_lib/commands/list.ts rename to src/childProcessCall/commands/list.ts index 7e95189..9a43cb3 100644 --- a/src/vsc-leetcode-cli/new_lib/commands/list.ts +++ b/src/childProcessCall/commands/list.ts @@ -1,4 +1,14 @@ +/* + * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/commands/list.ts + * Path: https://github.com/ccagml/vscode-leetcode-problem-rating + * Created Date: Thursday, October 27th 2022, 7:43:29 pm + * Author: ccagml + * + * Copyright (c) 2022 ccagml . All rights reserved. + */ + + import { helper } from "../helper"; import { log } from "../log"; import { corePlugin } from "../core"; @@ -10,7 +20,7 @@ class ListCommand { } process_argv(argv) { - var argv_config = helper.base_argv().option('q', corePlugin.filters.query) + let argv_config = helper.base_argv().option('q', corePlugin.filters.query) .option('s', { alias: 'stat', type: 'boolean', @@ -34,11 +44,11 @@ class ListCommand { type: 'string', default: '', describe: 'Filter questions by keyword' - }) + }); - argv_config.process_argv(argv) + argv_config.process_argv(argv); - return argv_config.get_result() + return argv_config.get_result(); } handler(argv) { @@ -47,10 +57,10 @@ class ListCommand { if (e) return log.info(e); let new_objcet: Array = []; problems.forEach(element => { - let temp_ele: any = {} + let temp_ele: any = {}; for (const key in element) { if (key != "link") { - temp_ele[key] = element[key] + temp_ele[key] = element[key]; } } new_objcet.push(temp_ele); diff --git a/src/vsc-leetcode-cli/new_lib/commands/plugin.ts b/src/childProcessCall/commands/plugin.ts similarity index 66% rename from src/vsc-leetcode-cli/new_lib/commands/plugin.ts rename to src/childProcessCall/commands/plugin.ts index 11b9168..7f187e4 100644 --- a/src/vsc-leetcode-cli/new_lib/commands/plugin.ts +++ b/src/childProcessCall/commands/plugin.ts @@ -1,3 +1,11 @@ +/* + * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/commands/plugin.ts + * Path: https://github.com/ccagml/vscode-leetcode-problem-rating + * Created Date: Thursday, October 27th 2022, 7:43:29 pm + * Author: ccagml + * + * Copyright (c) 2022 ccagml . All rights reserved. + */ import { helper } from "../helper"; @@ -13,7 +21,7 @@ class PluginCommand { } process_argv = function (argv) { - var argv_config = helper.base_argv().option('d', { + let argv_config = helper.base_argv().option('d', { alias: 'disable', type: 'boolean', describe: 'Disable plugin', @@ -32,17 +40,17 @@ class PluginCommand { type: 'string', describe: 'Filter plugin by name', default: '' - }) + }); - argv_config.process_argv(argv) + argv_config.process_argv(argv); - return argv_config.get_result() - } + return argv_config.get_result(); + }; handler = function (argv) { session.argv = argv; - let plugins = myPluginBase.plugins; + let all_plugin = myPluginBase.installed; const name = argv.name; // if (argv.install) { @@ -56,13 +64,14 @@ class PluginCommand { // return; // } - if (name) plugins = plugins.filter(x => x.name === name); - if (plugins.length === 0) return log.fatal('Plugin not found!'); - - const p = plugins[0]; - if (p.missing && (argv.enable || argv.disable)) - return log.fatal('Plugin missing, install it first'); + if (name) { + all_plugin = all_plugin.filter(x => x.name === name); + }; + if (all_plugin.length === 0) { + return log.fatal('Plugin not found!'); + } + const p = all_plugin[0]; if (argv.enable) { p.enabled = true; p.save(); @@ -70,12 +79,11 @@ class PluginCommand { p.enabled = false; p.save(); } else if (argv.delete) { - p.delete(); + // p.delete(); p.save(); myPluginBase.init(); } else if (argv.config) { log.info(JSON.stringify(config.plugins[name] || {}, null, 2)); - } else { } }; } diff --git a/src/vsc-leetcode-cli/new_lib/commands/query.ts b/src/childProcessCall/commands/query.ts similarity index 77% rename from src/vsc-leetcode-cli/new_lib/commands/query.ts rename to src/childProcessCall/commands/query.ts index ce3f63d..984400c 100644 --- a/src/vsc-leetcode-cli/new_lib/commands/query.ts +++ b/src/childProcessCall/commands/query.ts @@ -1,3 +1,12 @@ +/* + * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/commands/query.ts + * Path: https://github.com/ccagml/vscode-leetcode-problem-rating + * Created Date: Thursday, October 27th 2022, 7:43:29 pm + * Author: ccagml + * + * Copyright (c) 2022 ccagml . All rights reserved. + */ + import { helper } from "../helper"; import { log } from "../log"; @@ -11,7 +20,7 @@ class QueryCommand { process_argv = function (argv) { - var argv_config = helper.base_argv().option('T', { + let argv_config = helper.base_argv().option('T', { alias: 'dontTranslate', type: 'boolean', default: false, @@ -33,12 +42,12 @@ class QueryCommand { type: 'string', default: "", describe: 'test', - }) + }); - argv_config.process_argv(argv) + argv_config.process_argv(argv); - return argv_config.get_result() - } + return argv_config.get_result(); + }; handler = function (argv) { session.argv = argv; diff --git a/src/vsc-leetcode-cli/new_lib/commands/session.ts b/src/childProcessCall/commands/session.ts similarity index 85% rename from src/vsc-leetcode-cli/new_lib/commands/session.ts rename to src/childProcessCall/commands/session.ts index 9a4c2f3..bc2dd71 100644 --- a/src/vsc-leetcode-cli/new_lib/commands/session.ts +++ b/src/childProcessCall/commands/session.ts @@ -1,3 +1,13 @@ +/* + * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/commands/session.ts + * Path: https://github.com/ccagml/vscode-leetcode-problem-rating + * Created Date: Thursday, October 27th 2022, 7:43:29 pm + * Author: ccagml + * + * Copyright (c) 2022 ccagml . All rights reserved. + */ + + import { helper } from "../helper"; import { corePlugin } from "../core"; @@ -43,7 +53,7 @@ class SessionCommand { if (argv.create) return corePlugin.createSession(argv.keyword, this.printSessions); - var that = this; + let that = this; corePlugin.getSessions(function (e, sessions) { if (e) return log.info(e); diff --git a/src/vsc-leetcode-cli/new_lib/commands/show.ts b/src/childProcessCall/commands/show.ts similarity index 88% rename from src/vsc-leetcode-cli/new_lib/commands/show.ts rename to src/childProcessCall/commands/show.ts index f9d3ac1..90ce7e3 100644 --- a/src/vsc-leetcode-cli/new_lib/commands/show.ts +++ b/src/childProcessCall/commands/show.ts @@ -1,6 +1,15 @@ +/* + * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/commands/show.ts + * Path: https://github.com/ccagml/vscode-leetcode-problem-rating + * Created Date: Thursday, October 27th 2022, 7:43:29 pm + * Author: ccagml + * + * Copyright (c) 2022 ccagml . All rights reserved. + */ -var util = require('util'); -var childProcess = require('child_process'); + +let util = require('util'); +let childProcess = require('child_process'); import { helper } from "../helper"; @@ -18,7 +27,7 @@ class ShowCommand { process_argv = function (argv) { - var argv_config = helper.base_argv().option('c', { + let argv_config = helper.base_argv().option('c', { alias: 'codeonly', type: 'boolean', default: false, @@ -66,13 +75,13 @@ class ShowCommand { type: 'string', default: '', describe: 'Show question by name or id' - }) + }); - argv_config.process_argv(argv) + argv_config.process_argv(argv); - return argv_config.get_result() - } + return argv_config.get_result(); + }; genFileName(problem, opts) { @@ -165,7 +174,7 @@ class ShowCommand { if (problem.totalSubmit) log.info(`* Total Submissions: ${problem.totalSubmit}`); if (problem.testable && problem.testcase) { - var testcase_value = util.inspect(problem.testcase) + let testcase_value = util.inspect(problem.testcase); log.info(`* Testcase Example: ${testcase_value}`); } if (filename) @@ -176,7 +185,7 @@ class ShowCommand { } handler(argv) { - var that = this + let that = this; session.argv = argv; if (argv.keyword.length > 0) { // show specific one diff --git a/src/vsc-leetcode-cli/new_lib/commands/star.ts b/src/childProcessCall/commands/star.ts similarity index 69% rename from src/vsc-leetcode-cli/new_lib/commands/star.ts rename to src/childProcessCall/commands/star.ts index c43d6b1..f9a2176 100644 --- a/src/vsc-leetcode-cli/new_lib/commands/star.ts +++ b/src/childProcessCall/commands/star.ts @@ -1,4 +1,14 @@ +/* + * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/commands/star.ts + * Path: https://github.com/ccagml/vscode-leetcode-problem-rating + * Created Date: Thursday, October 27th 2022, 7:43:29 pm + * Author: ccagml + * + * Copyright (c) 2022 ccagml . All rights reserved. + */ + + import { helper } from "../helper"; import { log } from "../log"; import { corePlugin } from "../core"; @@ -10,7 +20,7 @@ class StarCommand { } process_argv(argv) { - var argv_config = helper.base_argv().option('d', { + let argv_config = helper.base_argv().option('d', { alias: 'delete', type: 'boolean', describe: 'Unstar question', @@ -20,12 +30,12 @@ class StarCommand { type: 'string', describe: 'Question name or id', default: '' - }) + }); - argv_config.process_argv(argv) + argv_config.process_argv(argv); - return argv_config.get_result() + return argv_config.get_result(); } handler(argv) { diff --git a/src/vsc-leetcode-cli/new_lib/commands/stat.ts b/src/childProcessCall/commands/stat.ts similarity index 90% rename from src/vsc-leetcode-cli/new_lib/commands/stat.ts rename to src/childProcessCall/commands/stat.ts index 2096667..3c2c64e 100644 --- a/src/vsc-leetcode-cli/new_lib/commands/stat.ts +++ b/src/childProcessCall/commands/stat.ts @@ -1,5 +1,15 @@ -var moment_out = require('moment'); -var underscore = require('underscore'); +/* + * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/commands/stat.ts + * Path: https://github.com/ccagml/vscode-leetcode-problem-rating + * Created Date: Thursday, October 27th 2022, 7:43:29 pm + * Author: ccagml + * + * Copyright (c) 2022 ccagml . All rights reserved. + */ + + +let moment_out = require('moment'); +let underscore = require('underscore'); import { helper } from "../helper"; import { log } from "../log"; @@ -12,7 +22,7 @@ class StatCommand { } process_argv(argv) { - var argv_config = helper.base_argv().option('c', { + let argv_config = helper.base_argv().option('c', { alias: 'cal', type: 'boolean', default: false, @@ -31,10 +41,10 @@ class StatCommand { describe: 'Include locked questions' }) .option('q', corePlugin.filters.query) - .option('t', corePlugin.filters.tag) - argv_config.process_argv(argv) + .option('t', corePlugin.filters.tag); + argv_config.process_argv(argv); - return argv_config.get_result() + return argv_config.get_result(); } printLine(key, done, all) { @@ -190,7 +200,7 @@ class StatCommand { handler(argv) { session.argv = argv; - var that = this; + let that = this; corePlugin.filterProblems(argv, function (e, problems) { if (e) return log.info(e); diff --git a/src/vsc-leetcode-cli/new_lib/commands/submission.ts b/src/childProcessCall/commands/submission.ts similarity index 88% rename from src/vsc-leetcode-cli/new_lib/commands/submission.ts rename to src/childProcessCall/commands/submission.ts index ca3ace0..112961d 100644 --- a/src/vsc-leetcode-cli/new_lib/commands/submission.ts +++ b/src/childProcessCall/commands/submission.ts @@ -1,7 +1,17 @@ +/* + * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/commands/submission.ts + * Path: https://github.com/ccagml/vscode-leetcode-problem-rating + * Created Date: Thursday, October 27th 2022, 7:43:29 pm + * Author: ccagml + * + * Copyright (c) 2022 ccagml . All rights reserved. + */ -var path = require('path'); -var _ = require('underscore'); + +let path = require('path'); + +let _ = require('underscore'); @@ -20,7 +30,7 @@ class SubMission { } process_argv = function (argv) { - var argv_config = helper.base_argv().option('a', { + let argv_config = helper.base_argv().option('a', { alias: 'all', type: 'boolean', default: false, @@ -54,15 +64,15 @@ class SubMission { type: 'string', default: '', describe: 'Download specific question by id' - }) - argv_config.process_argv(argv) + }); + argv_config.process_argv(argv); - return argv_config.get_result() - } + return argv_config.get_result(); + }; doTask(problem, queue, cb) { - var that = this; + let that = this; const argv = queue.ctx.argv; function onTaskDone(e, msg) { diff --git a/src/vsc-leetcode-cli/new_lib/commands/submit.ts b/src/childProcessCall/commands/submit.ts similarity index 73% rename from src/vsc-leetcode-cli/new_lib/commands/submit.ts rename to src/childProcessCall/commands/submit.ts index 5c07c34..be9c318 100644 --- a/src/vsc-leetcode-cli/new_lib/commands/submit.ts +++ b/src/childProcessCall/commands/submit.ts @@ -1,6 +1,16 @@ +/* + * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/commands/submit.ts + * Path: https://github.com/ccagml/vscode-leetcode-problem-rating + * Created Date: Thursday, October 27th 2022, 7:43:29 pm + * Author: ccagml + * + * Copyright (c) 2022 ccagml . All rights reserved. + */ -var util = require('util'); -var lodash = require('lodash'); + + +let util = require('util'); +let lodash = require('lodash'); import { helper } from "../helper"; @@ -18,14 +28,14 @@ class SubmitCommand { process_argv(argv) { - var argv_config = helper.base_argv().positional('filename', { + let argv_config = helper.base_argv().positional('filename', { type: 'string', describe: 'Code file to submit', default: '' - }) - argv_config.process_argv(argv) + }); + argv_config.process_argv(argv); - return argv_config.get_result() + return argv_config.get_result(); } @@ -37,12 +47,12 @@ class SubmitCommand { for (let line of lines) { if (k !== 'state') { if (!log_obj.hasOwnProperty(lodash.startCase(k))) { - log_obj[lodash.startCase(k)] = [line] + log_obj[lodash.startCase(k)] = [line]; } else { - log_obj[lodash.startCase(k)].push(line) + log_obj[lodash.startCase(k)].push(line); } } else { - log_obj.messages.push(line) + log_obj.messages.push(line); } } } @@ -50,7 +60,7 @@ class SubmitCommand { printLine(log_obj, ...ret: any[]) { const args = ret.slice(1); const line = util.format.apply(util, args); - log_obj.messages.push(line) + log_obj.messages.push(line); } handler(argv) { @@ -59,7 +69,7 @@ class SubmitCommand { return log.fatal('File ' + argv.filename + ' not exist!'); const meta = file.meta(argv.filename); - var that = this; + let that = this; // translation doesn't affect problem lookup corePlugin.getProblem(meta, true, function (e, problem) { if (e) return log.info(e); @@ -72,13 +82,13 @@ class SubmitCommand { const result = results[0]; - var log_obj: any = {} - log_obj.messages = [] - log_obj.system_message = {} - log_obj.system_message.fid = problem.fid - log_obj.system_message.id = problem.id - log_obj.system_message.qid = problem.id - log_obj.system_message.sub_type = "submit" + let log_obj: any = {}; + log_obj.messages = []; + log_obj.system_message = {}; + log_obj.system_message.fid = problem.fid; + log_obj.system_message.id = problem.id; + log_obj.system_message.qid = problem.id; + log_obj.system_message.sub_type = "submit"; log_obj.system_message.accepted = false; that.printResult(result, 'state', log_obj); @@ -110,7 +120,7 @@ class SubmitCommand { that.printResult(result, 'expected_answer', log_obj); that.printResult(result, 'stdout', log_obj); } - log.info(JSON.stringify(log_obj)) + log.info(JSON.stringify(log_obj)); corePlugin.updateProblem(problem, { state: (result.ok ? 'ac' : 'notac') }); }); }); diff --git a/src/vsc-leetcode-cli/new_lib/commands/test.ts b/src/childProcessCall/commands/test.ts similarity index 76% rename from src/vsc-leetcode-cli/new_lib/commands/test.ts rename to src/childProcessCall/commands/test.ts index 868fe65..354a80f 100644 --- a/src/vsc-leetcode-cli/new_lib/commands/test.ts +++ b/src/childProcessCall/commands/test.ts @@ -1,6 +1,16 @@ +/* + * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/commands/test.ts + * Path: https://github.com/ccagml/vscode-leetcode-problem-rating + * Created Date: Thursday, October 27th 2022, 7:43:29 pm + * Author: ccagml + * + * Copyright (c) 2022 ccagml . All rights reserved. + */ -var _ = require('underscore'); -var lodash = require('lodash'); + + +let _ = require('underscore'); +let lodash = require('lodash'); import { helper } from "../helper"; @@ -17,7 +27,7 @@ class TestCommand { process_argv(argv) { - var argv_config = helper.base_argv().option('i', { + let argv_config = helper.base_argv().option('i', { alias: 'interactive', type: 'boolean', default: false, @@ -39,11 +49,11 @@ class TestCommand { type: 'string', default: '', describe: 'Code file to test' - }) + }); - argv_config.process_argv(argv) + argv_config.process_argv(argv); - return argv_config.get_result() + return argv_config.get_result(); } @@ -59,20 +69,20 @@ class TestCommand { for (let line of lines) { const extraInfo = extra ? ` (${extra})` : ''; if (k !== 'state') { - var new_kk = lodash.startCase(k) + extraInfo; + let new_kk = lodash.startCase(k) + extraInfo; if (!log_obj.hasOwnProperty(new_kk)) { - log_obj[new_kk] = [line] + log_obj[new_kk] = [line]; } else { - log_obj[new_kk].push(line) + log_obj[new_kk].push(line); } } else { - log_obj.messages.push(line) + log_obj.messages.push(line); } } } runTest(argv) { - var that = this + let that = this; if (!file.exist(argv.filename)) return log.fatal('File ' + argv.filename + ' not exist!'); @@ -98,10 +108,10 @@ class TestCommand { // NOTE: wordwrap internally uses '\n' as EOL, so here we have to // remove all '\r' in the raw string. new_desc = new_desc.replace(/\r\n/g, '\n').replace(/^ /mg, '⁠'); - var input = (require('wordwrap')(120))(new_desc).split('\n'); - var temp_test: Array = [] - var start_flag = false; - var temp_collect = ""; + let input = (require('wordwrap')(120))(new_desc).split('\n'); + let temp_test: Array = []; + let start_flag = false; + let temp_collect = ""; for (let all_input = 0; all_input < input.length; all_input++) { const element = input[all_input]; var check_index = element.indexOf("输入"); @@ -109,7 +119,7 @@ class TestCommand { check_index = element.indexOf("Input:"); } if (check_index != -1) { - temp_collect += element.substring(check_index + 1) + temp_collect += element.substring(check_index + 1); start_flag = true; continue; } @@ -125,10 +135,10 @@ class TestCommand { temp_collect += element; } else { if (temp_collect.length > 0) { - var new_ele = temp_collect; - var temp_case: Array = [] - var wait_cur = "" - var no_need_flag = false + let new_ele = temp_collect; + let temp_case: Array = []; + let wait_cur = ""; + let no_need_flag = false; for (let index = new_ele.length - 1; index >= 0; index--) { if (no_need_flag) { if (new_ele[index] == ",") { @@ -136,16 +146,16 @@ class TestCommand { } } else { if (new_ele[index] == "=") { - temp_case.push(wait_cur.trim()) + temp_case.push(wait_cur.trim()); no_need_flag = true; - wait_cur = "" + wait_cur = ""; } else { - wait_cur = new_ele[index] + wait_cur + wait_cur = new_ele[index] + wait_cur; } } } for (let index = temp_case.length - 1; index >= 0; index--) { - temp_test.push(temp_case[index]) + temp_test.push(temp_case[index]); } temp_collect = ""; } @@ -156,8 +166,8 @@ class TestCommand { if (temp_test.length < 1) { return; } - var all_case = temp_test.join("\n") - problem.testcase = all_case + let all_case = temp_test.join("\n"); + problem.testcase = all_case; } if (!problem.testcase) @@ -172,13 +182,13 @@ class TestCommand { results = _.sortBy(results, x => x.type); - var log_obj: any = {} - log_obj.messages = [] - log_obj.system_message = {} - log_obj.system_message.fid = problem.fid - log_obj.system_message.id = problem.id - log_obj.system_message.qid = problem.id - log_obj.system_message.sub_type = "test" + let log_obj: any = {}; + log_obj.messages = []; + log_obj.system_message = {}; + log_obj.system_message.fid = problem.fid; + log_obj.system_message.id = problem.id; + log_obj.system_message.qid = problem.id; + log_obj.system_message.sub_type = "test"; log_obj.system_message.accepted = false; if (results[0].state === 'Accepted') { @@ -205,7 +215,7 @@ class TestCommand { } handler(argv) { - var that = this; + let that = this; session.argv = argv; if (!argv.i) return that.runTest(argv); diff --git a/src/vsc-leetcode-cli/new_lib/commands/user.ts b/src/childProcessCall/commands/user.ts similarity index 88% rename from src/vsc-leetcode-cli/new_lib/commands/user.ts rename to src/childProcessCall/commands/user.ts index 2341e69..71a5739 100644 --- a/src/vsc-leetcode-cli/new_lib/commands/user.ts +++ b/src/childProcessCall/commands/user.ts @@ -1,5 +1,14 @@ +/* + * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/commands/user.ts + * Path: https://github.com/ccagml/vscode-leetcode-problem-rating + * Created Date: Thursday, October 27th 2022, 7:43:29 pm + * Author: ccagml + * + * Copyright (c) 2022 ccagml . All rights reserved. + */ -var prompt_out = require('prompt'); + +let prompt_out = require('prompt'); import { helper } from "../helper"; import { log } from "../log"; import { corePlugin } from "../core"; @@ -11,7 +20,7 @@ class UserCommand { } process_argv(argv) { - var argv_config = helper.base_argv().option('l', { + let argv_config = helper.base_argv().option('l', { alias: 'login', type: 'boolean', default: false, @@ -40,11 +49,11 @@ class UserCommand { type: 'boolean', default: false, describe: 'Logout' - }) + }); - argv_config.process_argv(argv) + argv_config.process_argv(argv); - return argv_config.get_result() + return argv_config.get_result(); } diff --git a/src/vsc-leetcode-cli/new_lib/config.ts b/src/childProcessCall/config.ts similarity index 88% rename from src/vsc-leetcode-cli/new_lib/config.ts rename to src/childProcessCall/config.ts index 4f5529f..fcb4ebd 100644 --- a/src/vsc-leetcode-cli/new_lib/config.ts +++ b/src/childProcessCall/config.ts @@ -1,15 +1,25 @@ -var underscore = require('underscore'); +/* + * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/config.ts + * Path: https://github.com/ccagml/vscode-leetcode-problem-rating + * Created Date: Thursday, October 27th 2022, 7:43:29 pm + * Author: ccagml + * + * Copyright (c) 2022 ccagml . All rights reserved. + */ + + +let underscore = require('underscore'); class Config { - app - sys - autologin - code - file - color - icon - network - plugins + app; + sys; + autologin; + code; + file; + color; + icon; + network; + plugins; constructor() { this.sys = { categories: [ @@ -66,37 +76,36 @@ class Config { verify: 'https://leetcode.com/submissions/detail/$id/check/', favorites: 'https://leetcode.com/list/api/questions', favorite_delete: 'https://leetcode.com/list/api/questions/$hash/$id', - plugin: 'https://raw.githubusercontent.com/leetcode-tools/leetcode-cli/master/lib/plugins/$name.js', problem_detail: '', noj_go: '', u: '', }, - } + }; this.autologin = { enable: false, retry: 2 - } + }; this.code = { editor: 'vim', lang: 'cpp' - } + }; this.file = { show: '${fid}.${slug}', submission: '${fid}.${slug}.${sid}.${ac}' - } + }; this.color = { enable: true, theme: 'default' - } + }; this.icon = { theme: '' - } + }; this.network = { concurrency: 10, delay: 1 - } - this.plugins = {} + }; + this.plugins = {}; } init() { @@ -124,8 +133,8 @@ class Config { this.sys.urls.verify = 'https://leetcode.cn/submissions/detail/$id/check/'; this.sys.urls.favorites = 'https://leetcode.cn/list/api/questions'; this.sys.urls.favorite_delete = 'https://leetcode.cn/list/api/questions/$hash/$id'; - this.sys.urls.noj_go = 'https://leetcode.cn/graphql/noj-go/' - this.sys.urls.u = 'https://leetcode.cn/u/$username/' + this.sys.urls.noj_go = 'https://leetcode.cn/graphql/noj-go/'; + this.sys.urls.u = 'https://leetcode.cn/u/$username/'; this.sys.urls.github_login = 'https://leetcode.cn/accounts/github/login/?next=%2F'; this.sys.urls.linkedin_login = 'https://leetcode.cn/accounts/linkedin_oauth2/login/?next=%2F'; this.sys.urls.leetcode_redirect = 'https://leetcode.cn/'; diff --git a/src/vsc-leetcode-cli/new_lib/core.ts b/src/childProcessCall/core.ts similarity index 88% rename from src/vsc-leetcode-cli/new_lib/core.ts rename to src/childProcessCall/core.ts index 5f267be..9ea7d90 100644 --- a/src/vsc-leetcode-cli/new_lib/core.ts +++ b/src/childProcessCall/core.ts @@ -1,7 +1,17 @@ -var util = require('util'); +/* + * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/core.ts + * Path: https://github.com/ccagml/vscode-leetcode-problem-rating + * Created Date: Thursday, October 27th 2022, 7:43:29 pm + * Author: ccagml + * + * Copyright (c) 2022 ccagml . All rights reserved. + */ -var _ = require('underscore'); -var cheerio = require('cheerio'); + +let util = require('util'); + +let _ = require('underscore'); +let cheerio = require('cheerio'); // import { log } from "./log"; import { helper } from "./helper"; @@ -14,8 +24,8 @@ function hasTag(o, tag) { } class CorePlugin extends MyPluginBase { - id = 99999999 - name = 'core' + id = 99999999; + name = 'core'; builtin = true; filters = { query: { @@ -69,16 +79,16 @@ class CorePlugin extends MyPluginBase { }); }; public getProblem = (keyword, needTranslation, cb) => { - var that = this; + let that = this; this.getProblems(needTranslation, function (e, problems) { if (e) return cb(e); keyword = Number(keyword) || keyword; const metaFid = file.exist(keyword) ? file.meta(keyword).id : NaN; const problem = problems.find(function (x) { if (keyword?.fid) { - return x.fid + '' === keyword.fid + '' + return x.fid + '' === keyword.fid + ''; } else if (keyword?.qid) { - return x.id + '' === keyword.qid + '' + return x.id + '' === keyword.qid + ''; } else { return x.id + '' === keyword + '' || x.fid + '' === metaFid + '' || x.name === keyword || x.slug === keyword; } @@ -129,20 +139,20 @@ class CorePlugin extends MyPluginBase { if (e) return cb(e); return cb(null, result); }); - } + }; getQueryZ = (username, cb) => { this.getTestApi(username, function (e, result) { if (e) return cb(e); return cb(null, result); }); - } + }; getUserContest = (username, cb) => { this.getUserContestP(username, function (e, result) { if (e) return cb(e); return cb(null, result); }); - } + }; } diff --git a/src/vsc-leetcode-cli/new_lib/file.ts b/src/childProcessCall/file.ts similarity index 79% rename from src/vsc-leetcode-cli/new_lib/file.ts rename to src/childProcessCall/file.ts index e3ac287..d93e94d 100644 --- a/src/vsc-leetcode-cli/new_lib/file.ts +++ b/src/childProcessCall/file.ts @@ -1,11 +1,19 @@ -// import { FILE } from "dns"; +/* + * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/file.ts + * Path: https://github.com/ccagml/vscode-leetcode-problem-rating + * Created Date: Thursday, October 27th 2022, 7:43:29 pm + * Author: ccagml + * + * Copyright (c) 2022 ccagml . All rights reserved. + */ -var fs = require('fs'); -var os = require('os'); -var path = require('path'); -var _ = require('underscore'); -var mkdirp = require('mkdirp'); +let fs = require('fs'); +let os = require('os'); +let path = require('path'); + +let _ = require('underscore'); +let mkdirp = require('mkdirp'); export interface IMETA { id: string @@ -50,7 +58,7 @@ class File { }; public codeDir(dir) { - return path.join(__dirname, '..', dir || ''); + return path.join(__dirname, dir || ''); }; public cacheFile(k) { @@ -61,10 +69,6 @@ class File { return path.join(this.homeDir(), 'config.json'); }; - public pluginFile(name) { - return path.join(this.codeDir('lib/plugins'), path.basename(name)); - }; - public listCodeDir(dir) { dir = this.codeDir(dir); return this.list(dir).map(function (f) { @@ -137,7 +141,7 @@ class File { }; public render(tpl, data) { - const tplfile = path.join(__dirname, "..", "..", "..", "..", "resources", "templates", tpl + '.tpl') + const tplfile = path.join(__dirname, "..", "..", "..", "resources", "templates", tpl + '.tpl'); let result = _.template(this.data(tplfile).replace(/\r\n/g, '\n'))(data); if (this.isWindows()) { result = result.replace(/\n/g, '\r\n'); @@ -152,7 +156,7 @@ class File { }; public metaByName(filename) { - const m = Object.assign({}, defaultMETA, {}) + const m = Object.assign({}, defaultMETA, {}); m.id = file.name(filename).split('.')[0]; @@ -166,7 +170,7 @@ class File { }; public meta(filename) { - const m = Object.assign({}, defaultMETA, {}) + const m = Object.assign({}, defaultMETA, {}); const line = this.data(filename).split('\n') @@ -174,13 +178,13 @@ class File { // @lc app=leetcode.cn id=剑指 Offer II 116 lang=cpp - var id_right = line.split('id=')[1] - var lang_cat = id_right.split('lang=') - var id = lang_cat[0].trim(); - var lang = lang_cat[1].trim(); - m.id = id - m.fid = id - m.lang = lang + let id_right = line.split('id=')[1]; + let lang_cat = id_right.split('lang='); + let id = lang_cat[0].trim(); + let lang = lang_cat[1].trim(); + m.id = id; + m.fid = id; + m.lang = lang; return m; }; diff --git a/src/vsc-leetcode-cli/new_lib/helper.ts b/src/childProcessCall/helper.ts similarity index 87% rename from src/vsc-leetcode-cli/new_lib/helper.ts rename to src/childProcessCall/helper.ts index 267cbfe..fbae1c7 100644 --- a/src/vsc-leetcode-cli/new_lib/helper.ts +++ b/src/childProcessCall/helper.ts @@ -1,5 +1,14 @@ -// var underscore = require('underscore'); -var ora = require('ora'); +/* + * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/helper.ts + * Path: https://github.com/ccagml/vscode-leetcode-problem-rating + * Created Date: Thursday, October 27th 2022, 7:43:29 pm + * Author: ccagml + * + * Copyright (c) 2022 ccagml . All rights reserved. + */ + + +let ora = require('ora'); import { file } from "./file"; @@ -50,7 +59,7 @@ export const LANGS = [ ]; class HELPER { - KEYS + KEYS; constructor() { this.KEYS = { user: '../user', @@ -142,7 +151,7 @@ class HELPER { readStdin(cb) { const stdin = process.stdin; - var bufs: Array = []; + let bufs: Array = []; console.log('NOTE: to finish the input, press ' + (file.isWindows() ? ' and ' : '')); @@ -194,26 +203,26 @@ class HELPER { }; base_argv() { - var base = { + let base = { all_base_data: {}, positional_index: 0, positional_key: {}, option: function (key, value) { - this.all_base_data[key] = value.default - this.all_base_data[value.alias] = value.default - this[key] = value - return this + this.all_base_data[key] = value.default; + this.all_base_data[value.alias] = value.default; + this[key] = value; + return this; }, positional: function (key, value) { - this.positional_key[this.positional_index] = key + this.positional_key[this.positional_index] = key; this.positional_index = this.positional_index + 1; - this.all_base_data[key] = value.default - this.all_base_data[value.alias] = value.default - this[key] = value - return this + this.all_base_data[key] = value.default; + this.all_base_data[value.alias] = value.default; + this[key] = value; + return this; }, set_opt(key, temp_val?) { - var cfg = this[key] + let cfg = this[key]; if (cfg) { if (cfg.type == "boolean") { this.all_base_data[key] = true; @@ -234,8 +243,8 @@ class HELPER { return false; }, set_posi(value, index) { - var cfg_key = this.positional_key[index] - var cfg = this[cfg_key] + let cfg_key = this.positional_key[index]; + let cfg = this[cfg_key]; if (cfg) { this.all_base_data[cfg_key] = value; if (cfg.alias) { @@ -244,11 +253,11 @@ class HELPER { } }, process_argv(argv) { - var all_posi = 0 + let all_posi = 0; for (let index = 3; index < argv.length; index++) { - var con = argv[index] + let con = argv[index]; if (con[0] == '-' && con[1] == '-') { - this.set_opt(con.substring(2)) + this.set_opt(con.substring(2)); } else if (con[0] == '-') { for (let con_index = 1; con_index < con.length; con_index++) { @@ -263,9 +272,9 @@ class HELPER { } }, get_result: function () { - return this.all_base_data + return this.all_base_data; } - } + }; return base; } } diff --git a/src/vsc-leetcode-cli/new_lib/log.ts b/src/childProcessCall/log.ts similarity index 62% rename from src/vsc-leetcode-cli/new_lib/log.ts rename to src/childProcessCall/log.ts index 7db468a..37bea8d 100644 --- a/src/vsc-leetcode-cli/new_lib/log.ts +++ b/src/childProcessCall/log.ts @@ -1,14 +1,24 @@ -var _ = require('underscore'); +/* + * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/log.ts + * Path: https://github.com/ccagml/vscode-leetcode-problem-rating + * Created Date: Thursday, October 27th 2022, 7:43:29 pm + * Author: ccagml + * + * Copyright (c) 2022 ccagml . All rights reserved. + */ + + +let _ = require('underscore'); class LOG { - output = _.bind(console.log, console) - level + output = _.bind(console.log, console); + level; levels = new Map([ ['INFO', { value: 2 }], ['WARN', { value: 3 }], ['ERROR', { value: 4 }], - ]) + ]); setLevel(name) { this.level = this.levels.get(name) || this.levels.get('INFO'); }; @@ -31,19 +41,19 @@ class LOG { }; info(...rest: any[]) { - const args = rest //Array.from(arguments); + const args = rest; //Array.from(arguments); let s = args.map(x => x.toString()).join(' '); this.output(s); }; warn(...rest: any[]) { - const args = rest //Array.from(arguments); + const args = rest; //Array.from(arguments); args.unshift('[' + "warn" + ']'); let s = args.map(x => x.toString()).join(' '); this.output(s); }; error(...rest: any[]) { - const args = rest //Array.from(arguments); + const args = rest; //Array.from(arguments); args.unshift('[' + "error" + ']'); let s = args.map(x => x.toString()).join(' '); diff --git a/src/vsc-leetcode-cli/new_lib/my_plugin_base.ts b/src/childProcessCall/my_plugin_base.ts similarity index 79% rename from src/vsc-leetcode-cli/new_lib/my_plugin_base.ts rename to src/childProcessCall/my_plugin_base.ts index 81a9944..5de566b 100644 --- a/src/vsc-leetcode-cli/new_lib/my_plugin_base.ts +++ b/src/childProcessCall/my_plugin_base.ts @@ -1,4 +1,14 @@ -var underscore = require('underscore'); +/* + * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/my_plugin_base.ts + * Path: https://github.com/ccagml/vscode-leetcode-problem-rating + * Created Date: Thursday, October 27th 2022, 7:43:29 pm + * Author: ccagml + * + * Copyright (c) 2022 ccagml . All rights reserved. + */ + + +let underscore = require('underscore'); import { config as out_config } from "./config"; import { file } from "./file"; @@ -13,11 +23,11 @@ export class MyPluginBase { desc; enabled; deleted; - missing; builtin; deps; next; plugins: Array = []; + installed: Array = []; head; // 插件头 是core config; constructor() { @@ -27,7 +37,6 @@ export class MyPluginBase { const stats = cache.get(helper.KEYS.plugins) || {}; if (this.deleted) delete stats[this.name]; - else if (this.missing) return; else stats[this.name] = this.enabled; cache.set(helper.KEYS.plugins, stats); @@ -41,8 +50,8 @@ export class MyPluginBase { public base_init(head?) { head = head || require('./core').corePlugin; const stats = cache.get(helper.KEYS.plugins) || {}; - let installed: Array = []; - let file_plugin: Array = file.listCodeDir('new_lib/plugins') + let file_plugin: Array = file.listCodeDir('plugins'); + this.installed = []; for (let f of file_plugin) { const p = f.data; if (!p) continue; @@ -55,19 +64,19 @@ export class MyPluginBase { p.enabled = false; } } - installed.push(p); + this.installed.push(p); } // 根据id大小排序, 大的前面 - installed = underscore.sortBy(installed, x => -x.id); + this.installed = underscore.sortBy(this.installed, x => -x.id); // 从小的开始init - for (let i = installed.length - 1; i >= 0; --i) { - const p = installed[i]; + for (let i = this.installed.length - 1; i >= 0; --i) { + const p = this.installed[i]; if (p.enabled) { p.init(); } } // 连成链表状 - this.plugins = installed.filter(x => x.enabled); + this.plugins = this.installed.filter(x => x.enabled); let last = head; for (let p of this.plugins) { last.setNext(p); @@ -182,98 +191,98 @@ export class MyPluginBase { // } public getProblems(Translate: boolean, cb) { - this.next.getProblems(Translate, cb) + this.next.getProblems(Translate, cb); } public getQuestionOfToday(cb) { - this.next.getQuestionOfToday(cb) + this.next.getQuestionOfToday(cb); } public getTestApi(username, cb) { - this.next.getTestApi(username, cb) + this.next.getTestApi(username, cb); } public getUserContestP(username, cb) { - this.next.getUserContestP(username, cb) + this.next.getUserContestP(username, cb); } public getProblemsTitle(cb) { - this.next.getProblemsTitle(cb) + this.next.getProblemsTitle(cb); } public createSession(a, cb) { - this.next.createSession(a, cb) + this.next.createSession(a, cb); } public getSessions(cb) { - this.next.getSessions(cb) + this.next.getSessions(cb); } public activateSession(s, cb) { - this.next.activateSession(s, cb) + this.next.activateSession(s, cb); } public deleteSession(s, cb) { - this.next.deleteSession(s, cb) + this.next.deleteSession(s, cb); } public updateProblem(a, b) { - this.next.updateProblem(a, b) + this.next.updateProblem(a, b); } public getSubmissions(s, cb) { - this.next.getSubmissions(s, cb) + this.next.getSubmissions(s, cb); } public getSubmission(s, cb) { - this.next.getSubmission(s, cb) + this.next.getSubmission(s, cb); } public submitProblem(s, cb) { - this.next.submitProblem(s, cb) + this.next.submitProblem(s, cb); } public testProblem(s, cb) { - this.next.testProblem(s, cb) + this.next.testProblem(s, cb); } public login(user, cb) { - this.next.login(user, cb) + this.next.login(user, cb); } public logout(user, cb) { - this.next.logout(user, cb) + this.next.logout(user, cb); } public githubLogin(user, cb) { - this.next.githubLogin(user, cb) + this.next.githubLogin(user, cb); } public linkedinLogin(user, cb) { - this.next.linkedinLogin(user, cb) + this.next.linkedinLogin(user, cb); } public cookieLogin(user, cb) { - this.next.cookieLogin(user, cb) + this.next.cookieLogin(user, cb); } public filterProblems(opts, cb) { - this.next.filterProblems(opts, cb) + this.next.filterProblems(opts, cb); } public getProblem(keyword, needTranslation, cb) { - this.next.getProblem(keyword, needTranslation, cb) + this.next.getProblem(keyword, needTranslation, cb); } public starProblem(problem, starred, cb) { - this.next.starProblem(problem, starred, cb) + this.next.starProblem(problem, starred, cb); } public exportProblem(problem, opts) { - this.next.exportProblem(problem, opts) + this.next.exportProblem(problem, opts); } public getTodayQuestion(cb) { - this.next.getTodayQuestion(cb) + this.next.getTodayQuestion(cb); } public getQueryZ(username, cb) { - this.next.getQueryZ(username, cb) + this.next.getQueryZ(username, cb); } public getUserContest(username, cb) { - this.next.getUserContest(username, cb) + this.next.getUserContest(username, cb); } } diff --git a/src/vsc-leetcode-cli/new_lib/plugins/cache.ts b/src/childProcessCall/plugins/cache.ts similarity index 87% rename from src/vsc-leetcode-cli/new_lib/plugins/cache.ts rename to src/childProcessCall/plugins/cache.ts index c22f216..ed7b7d1 100644 --- a/src/vsc-leetcode-cli/new_lib/plugins/cache.ts +++ b/src/childProcessCall/plugins/cache.ts @@ -1,6 +1,16 @@ +/* + * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/plugins/cache.ts + * Path: https://github.com/ccagml/vscode-leetcode-problem-rating + * Created Date: Thursday, October 27th 2022, 7:43:29 pm + * Author: ccagml + * + * Copyright (c) 2022 ccagml . All rights reserved. + */ + + import { MyPluginBase } from "../my_plugin_base"; -var underscore = require('underscore'); +let underscore = require('underscore'); import { cache } from "../cache"; @@ -8,14 +18,14 @@ import { helper } from "../helper"; // import { log } from "../log"; import { session } from "../session"; -// const plugin = new Plugin(50, 'cache', '', 'Plugin to provide local cache.'); + class CachePlugin extends MyPluginBase { - id = 50 - name = 'cache' + id = 50; + name = 'cache'; builtin = true; constructor() { - super() + super(); } clearCacheIfTchanged = (needTranslation) => { @@ -25,7 +35,7 @@ class CachePlugin extends MyPluginBase { cache.set(helper.KEYS.translation, { useEndpointTranslation: needTranslation }); } - } + }; public getProblems = (needTranslation, cb) => { this.clearCacheIfTchanged(needTranslation); @@ -45,7 +55,7 @@ class CachePlugin extends MyPluginBase { this.clearCacheIfTchanged(needTranslation); const k = helper.KEYS.problem(problem); const _problem = cache.get(k); - var that = this; + let that = this; if (_problem) { if (!_problem.desc.includes('
')) {
 
diff --git a/src/vsc-leetcode-cli/new_lib/plugins/leetcode.cn.ts b/src/childProcessCall/plugins/leetcode.cn.ts
similarity index 90%
rename from src/vsc-leetcode-cli/new_lib/plugins/leetcode.cn.ts
rename to src/childProcessCall/plugins/leetcode.cn.ts
index 7682fbf..8248935 100644
--- a/src/vsc-leetcode-cli/new_lib/plugins/leetcode.cn.ts
+++ b/src/childProcessCall/plugins/leetcode.cn.ts
@@ -1,26 +1,34 @@
+/*
+ * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/plugins/leetcode.cn.ts
+ * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
+ * Created Date: Thursday, October 27th 2022, 7:43:29 pm
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
 
 
 import { MyPluginBase } from "../my_plugin_base";
 
-var request = require('request');
+let request = require('request');
 
 import { config } from "../config";
 
 import { session } from "../session";
 
 class LeetCodeCn extends MyPluginBase {
-  id = 15
-  name = 'leetcode.cn'
+  id = 15;
+  name = 'leetcode.cn';
   builtin = true;
   constructor() {
-    super()
+    super();
   }
   init() {
-    config.fix_cn()
+    config.fix_cn();
   };
 
   getProblems = (needTranslation, cb) => {
-    var that = this;
+    let that = this;
     this.next.getProblems(needTranslation, function (e, problems) {
       if (e) return cb(e);
 
@@ -120,12 +128,12 @@ class LeetCodeCn extends MyPluginBase {
 
       e = checkError(e, resp, 200);
       if (e) return cb(e);
-      var result: any = {}
-      result.titleSlug = body.data.todayRecord[0].question.titleSlug
-      result.questionId = body.data.todayRecord[0].question.questionId
-      result.fid = body.data.todayRecord[0].question.questionFrontendId
-      result.date = body.data.todayRecord[0].data
-      result.userStatus = body.data.todayRecord[0].userStatus
+      let result: any = {};
+      result.titleSlug = body.data.todayRecord[0].question.titleSlug;
+      result.questionId = body.data.todayRecord[0].question.questionId;
+      result.fid = body.data.todayRecord[0].question.questionFrontendId;
+      result.date = body.data.todayRecord[0].data;
+      result.userStatus = body.data.todayRecord[0].userStatus;
       return cb(null, result);
     });
   };
@@ -184,7 +192,7 @@ class LeetCodeCn extends MyPluginBase {
     const opts = makeOpts(config.sys.urls.graphql);
     opts.headers.Origin = config.sys.urls.base;
 
-    const value_array = value.split("-")
+    const value_array = value.split("-");
 
     opts.json = true;
     opts.body = {
@@ -220,13 +228,13 @@ class LeetCodeCn extends MyPluginBase {
 
       e = checkError(e, resp, 200);
       if (e) return cb(e);
-      let result = {}
+      let result = {};
       body.data.problemsetQuestionList.questions.forEach(element => {
         result[element.frontendQuestionId] = {
           topicTags: element.topicTags.map(function (p) { return p.slug; }),
           CompanyTags: element.extra.topCompanyTags.map(function (p) { return p.slug; }),
-        }
-      })
+        };
+      });
       return cb(null, result);
     });
   };
@@ -243,7 +251,7 @@ function signOpts(opts, user) {
 }
 
 function makeOpts(url) {
-  var opts: any = {};
+  let opts: any = {};
   opts.url = url;
   opts.headers = {};
 
diff --git a/src/vsc-leetcode-cli/new_lib/plugins/leetcode.ts b/src/childProcessCall/plugins/leetcode.ts
similarity index 95%
rename from src/vsc-leetcode-cli/new_lib/plugins/leetcode.ts
rename to src/childProcessCall/plugins/leetcode.ts
index b4de85a..a0c8873 100644
--- a/src/vsc-leetcode-cli/new_lib/plugins/leetcode.ts
+++ b/src/childProcessCall/plugins/leetcode.ts
@@ -1,9 +1,19 @@
+/*
+ * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/plugins/leetcode.ts
+ * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
+ * Created Date: Thursday, October 27th 2022, 7:43:29 pm
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
 
-var util = require('util');
 
-var underscore = require('underscore');
-var request = require('request');
-var prompt_out = require('prompt');
+
+let util = require('util');
+
+let underscore = require('underscore');
+let request = require('request');
+let prompt_out = require('prompt');
 
 import { config } from "../config";
 import { helper } from "../helper";
@@ -14,11 +24,11 @@ import { MyPluginBase } from "../my_plugin_base";
 import { Queue } from "../queue";
 
 class LeetCode extends MyPluginBase {
-  id = 10
-  name = 'leetcode'
+  id = 10;
+  name = 'leetcode';
   builtin = true;
   constructor() {
-    super()
+    super();
   }
 
   signOpts(opts, user) {
@@ -56,7 +66,7 @@ class LeetCode extends MyPluginBase {
   };
 
   getProblems = (_, cb) => {
-    var that = this;
+    let that = this;
     let problems = [];
     const getCategory = function (category, _, cb) {
       that.getCategoryProblems(category, function (e, _problems) {
@@ -82,7 +92,7 @@ class LeetCode extends MyPluginBase {
 
     const opts = this.makeOpts(config.sys.urls.problems.replace('$category', category));
 
-    var that = this
+    let that = this;
     request(opts, function (e, resp, body) {
       e = that.checkError(e, resp, 200);
       if (e) return cb(e);
@@ -148,7 +158,7 @@ class LeetCode extends MyPluginBase {
     };
 
 
-    var that = this
+    let that = this;
     request.post(opts, function (e, resp, body) {
 
       e = that.checkError(e, resp, 200);
@@ -190,7 +200,7 @@ class LeetCode extends MyPluginBase {
     });
 
 
-    var that = this
+    let that = this;
     request(opts, function (e, resp, body) {
 
       e = that.checkError(e, resp, 200);
@@ -212,7 +222,7 @@ class LeetCode extends MyPluginBase {
 
       return cb(null, body);
     });
-  }
+  };
 
 
   verifyResult = (task, queue, cb) => {
@@ -221,7 +231,7 @@ class LeetCode extends MyPluginBase {
     opts.url = config.sys.urls.verify.replace('$id', task.id);
 
 
-    var that = this;
+    let that = this;
     request(opts, function (e, resp, body) {
 
       e = that.checkError(e, resp, 200);
@@ -237,7 +247,7 @@ class LeetCode extends MyPluginBase {
       }
       return cb();
     });
-  }
+  };
 
   formatResult = (result) => {
     const x: any = {
@@ -281,13 +291,13 @@ class LeetCode extends MyPluginBase {
     if (x.error.length > 0) x.ok = false;
 
     return x;
-  }
+  };
 
   testProblem = (problem, cb) => {
 
     const opts = this.makeOpts(config.sys.urls.test.replace('$slug', problem.slug));
     opts.body = { data_input: problem.testcase };
-    var that = this
+    let that = this;
     this.runCode(opts, problem, function (e, task) {
       if (e) return cb(e);
 
@@ -310,7 +320,7 @@ class LeetCode extends MyPluginBase {
 
     const opts = this.makeOpts(config.sys.urls.submit.replace('$slug', problem.slug));
     opts.body = { judge_type: 'large' };
-    var that = this
+    let that = this;
     this.runCode(opts, problem, function (e, task) {
       if (e) return cb(e);
 
@@ -326,7 +336,7 @@ class LeetCode extends MyPluginBase {
 
     const opts = this.makeOpts(config.sys.urls.submissions.replace('$slug', problem.slug));
     opts.headers.Referer = config.sys.urls.problem.replace('$slug', problem.slug);
-    var that = this
+    let that = this;
     request(opts, function (e, resp, body) {
       e = that.checkError(e, resp, 200);
       if (e) return cb(e);
@@ -343,7 +353,7 @@ class LeetCode extends MyPluginBase {
   getSubmission = (submission, cb) => {
 
     const opts = this.makeOpts(config.sys.urls.submission.replace('$id', submission.id));
-    var that = this
+    let that = this;
     request(opts, function (e, resp, body) {
       e = that.checkError(e, resp, 200);
       if (e) return cb(e);
@@ -373,7 +383,7 @@ class LeetCode extends MyPluginBase {
     };
 
 
-    var that = this;
+    let that = this;
     request.post(opts, function (e, resp, _) {
 
       e = that.checkError(e, resp, 200);
@@ -387,7 +397,7 @@ class LeetCode extends MyPluginBase {
     const opts = this.makeOpts(config.sys.urls.favorites);
 
 
-    var that = this;
+    let that = this;
     request(opts, function (e, resp, body) {
 
       e = that.checkError(e, resp, 200);
@@ -399,7 +409,7 @@ class LeetCode extends MyPluginBase {
   };
 
   getUserInfo = (cb) => {
-    var that = this;
+    let that = this;
     const opts = this.makeOpts(config.sys.urls.graphql);
     opts.headers.Origin = config.sys.urls.base;
     opts.headers.Referer = config.sys.urls.base;
@@ -435,7 +445,7 @@ class LeetCode extends MyPluginBase {
     opts.body = data;
 
 
-    var that = this;
+    let that = this;
     request(opts, function (e, resp, body) {
 
       e = that.checkError(e, resp, 200);
@@ -443,7 +453,7 @@ class LeetCode extends MyPluginBase {
 
       return e ? cb(e) : cb(null, body.sessions);
     });
-  }
+  };
 
   getSessions = (cb) => {
 
@@ -470,7 +480,7 @@ class LeetCode extends MyPluginBase {
   signin = (user, cb) => {
     const isCN = config.app === 'leetcode.cn';
     const spin = isCN ? helper.spin('Signing in leetcode.cn') : helper.spin('Signing in leetcode.com');
-    var that = this;
+    let that = this;
     request(config.sys.urls.login, function (e, resp, _) {
       spin.stop();
       e = that.checkError(e, resp, 200);
@@ -504,7 +514,7 @@ class LeetCode extends MyPluginBase {
   };
 
   getUser = (user, cb) => {
-    var that = this;
+    let that = this;
     this.getFavorites(function (e, favorites) {
       if (!e) {
         const f = favorites.favorites.private_favorites.find((f) => f.name === 'Favorite');
@@ -530,7 +540,7 @@ class LeetCode extends MyPluginBase {
   };
 
   login = (user, cb) => {
-    var that = this;
+    let that = this;
     that.signin(user, function (e, user) {
       if (e) return cb(e);
       that.getUser(user, cb);
@@ -549,10 +559,10 @@ class LeetCode extends MyPluginBase {
       sessionId: reSessionResult[1],
       sessionCSRF: reCsrfResult[1],
     };
-  }
+  };
 
   requestLeetcodeAndSave = (request, leetcodeUrl, user, cb) => {
-    var that = this;
+    let that = this;
     request.get({ url: leetcodeUrl }, function (_, resp, __) {
       const redirectUri = resp.request.uri.href;
       if (redirectUri !== config.sys.urls.leetcode_redirect) {
@@ -564,7 +574,7 @@ class LeetCode extends MyPluginBase {
       session.saveUser(user);
       that.getUser(user, cb);
     });
-  }
+  };
 
   cookieLogin = (user, cb) => {
     const cookieData = this.parseCookie(user.cookie, cb);
@@ -578,7 +588,7 @@ class LeetCode extends MyPluginBase {
     const urls = config.sys.urls;
     const leetcodeUrl = urls.github_login;
     const _request = request.defaults({ jar: true });
-    var that = this;
+    let that = this;
     _request(urls.github_login_request, function (_, __, body) {
 
       const authenticityToken = body.match(/name="authenticity_token" value="(.*?)"/);
@@ -671,7 +681,7 @@ class LeetCode extends MyPluginBase {
         'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'
       }
     });
-    var that = this;
+    let that = this;
     _request(urls.linkedin_login_request, function (_, resp, body) {
 
       if (resp.statusCode !== 200) {
diff --git a/src/vsc-leetcode-cli/new_lib/plugins/retry.ts b/src/childProcessCall/plugins/retry.ts
similarity index 83%
rename from src/vsc-leetcode-cli/new_lib/plugins/retry.ts
rename to src/childProcessCall/plugins/retry.ts
index 2c2add7..dd89750 100644
--- a/src/vsc-leetcode-cli/new_lib/plugins/retry.ts
+++ b/src/childProcessCall/plugins/retry.ts
@@ -1,13 +1,22 @@
+/*
+ * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/plugins/retry.ts
+ * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
+ * Created Date: Thursday, October 27th 2022, 7:43:29 pm
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
+
+
 
 import { MyPluginBase } from "../my_plugin_base";
 import { config } from "../config";
 import { session } from "../session";
 
-// var plugin = new Plugin(30, 'retry', '',
-//   'Plugin to retry last failed request if autologin.enable is on.');
+
 class RetryPlugin extends MyPluginBase {
-  id = 30
-  name = 'retry'
+  id = 30;
+  name = 'retry';
   builtin = true;
   count = {};
 
@@ -15,7 +24,7 @@ class RetryPlugin extends MyPluginBase {
     return config.autologin.enable &&
       (e === session.errors.EXPIRED) &&
       (this.count[name] || 0) < config.autologin.retry;
-  }
+  };
   init = () => {
     const names = [
       'activateSession',
@@ -31,7 +40,7 @@ class RetryPlugin extends MyPluginBase {
       'submitProblem',
       'starProblem'
     ];
-    var that = this;
+    let that = this;
     for (let name of names) {
       that.count[name] = 0;
       this[name] = function () {
diff --git a/src/vsc-leetcode-cli/new_lib/plugins/solution.discuss.ts b/src/childProcessCall/plugins/solution.discuss.ts
similarity index 78%
rename from src/vsc-leetcode-cli/new_lib/plugins/solution.discuss.ts
rename to src/childProcessCall/plugins/solution.discuss.ts
index 8d5cadc..ac24a4f 100644
--- a/src/vsc-leetcode-cli/new_lib/plugins/solution.discuss.ts
+++ b/src/childProcessCall/plugins/solution.discuss.ts
@@ -1,25 +1,28 @@
-var request = require('request');
+/*
+ * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/plugins/solution.discuss.ts
+ * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
+ * Created Date: Thursday, October 27th 2022, 7:43:29 pm
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
+
+
+let request = require('request');
 
 
 import { log } from "../log";
 import { session } from "../session";
 import { MyPluginBase } from "../my_plugin_base";
 
-//
-// [Usage]
-//
-// https://github.com/skygragon/leetcode-cli-plugins/blob/master/docs/solution.discuss.md
-//
-// var plugin = new Plugin(200, 'solution.discuss', '',
-//   'Plugin to fetch most voted solution in discussions.');
 
 
 class SolutionDiscuss extends MyPluginBase {
-  id = 200
-  name = "solution.discuss"
+  id = 200;
+  name = "solution.discuss";
   builtin = true;
   constructor() {
-    super()
+    super();
   }
 
 
@@ -28,13 +31,13 @@ class SolutionDiscuss extends MyPluginBase {
     this.next.getProblem(problem, needTranslation, function (e, problem) {
       if (e || !session.argv.solution) return cb(e, problem);
 
-      var lang = session.argv.lang;
+      let lang = session.argv.lang;
       getSolution(problem, lang, function (e, solution) {
         if (e) return cb(e);
         if (!solution) return log.error('Solution not found for ' + lang);
 
-        var link = URL_DISCUSS.replace('$slug', problem.slug).replace('$id', solution.id);
-        var content = solution.post.content.replace(/\\n/g, '\n').replace(/\\t/g, '\t');
+        let link = URL_DISCUSS.replace('$slug', problem.slug).replace('$id', solution.id);
+        let content = solution.post.content.replace(/\\n/g, '\n').replace(/\\t/g, '\t');
 
         log.info();
         log.info(problem.name);
@@ -54,15 +57,15 @@ class SolutionDiscuss extends MyPluginBase {
 
 }
 
-var URL_DISCUSSES = 'https://leetcode.com/graphql';
-var URL_DISCUSS = 'https://leetcode.com/problems/$slug/discuss/$id';
+let URL_DISCUSSES = 'https://leetcode.com/graphql';
+let URL_DISCUSS = 'https://leetcode.com/problems/$slug/discuss/$id';
 
 function getSolution(problem, lang, cb) {
   if (!problem) return cb();
 
   if (lang === 'python3') lang = 'python';
 
-  var opts = {
+  let opts = {
     url: URL_DISCUSSES,
     json: true,
     body: {
diff --git a/src/vsc-leetcode-cli/new_lib/queue.ts b/src/childProcessCall/queue.ts
similarity index 72%
rename from src/vsc-leetcode-cli/new_lib/queue.ts
rename to src/childProcessCall/queue.ts
index 1e2f781..1db7165 100644
--- a/src/vsc-leetcode-cli/new_lib/queue.ts
+++ b/src/childProcessCall/queue.ts
@@ -1,15 +1,25 @@
+/*
+ * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/queue.ts
+ * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
+ * Created Date: Thursday, October 27th 2022, 7:43:29 pm
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
 
-var underscore = require('underscore');
+
+
+let underscore = require('underscore');
 
 import { config } from "./config";
 
 export class Queue {
-  tasks
-  ctx
-  onTask
-  error
-  concurrency
-  onDone
+  tasks;
+  ctx;
+  onTask;
+  error;
+  concurrency;
+  onDone;
   constructor(tasks, ctx, onTask) {
     this.tasks = underscore.clone(tasks) || [];
     this.ctx = ctx || {};
diff --git a/src/vsc-leetcode-cli/new_lib/session.ts b/src/childProcessCall/session.ts
similarity index 78%
rename from src/vsc-leetcode-cli/new_lib/session.ts
rename to src/childProcessCall/session.ts
index 164a220..315ad7b 100644
--- a/src/vsc-leetcode-cli/new_lib/session.ts
+++ b/src/childProcessCall/session.ts
@@ -1,6 +1,15 @@
+/*
+ * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/session.ts
+ * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
+ * Created Date: Thursday, October 27th 2022, 7:43:29 pm
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
 
-var moment_out = require('moment');
-var underscore = require('underscore');
+
+let moment_out = require('moment');
+let underscore = require('underscore');
 
 
 import { cache } from "./cache";
@@ -16,7 +25,7 @@ class Session {
   };
   argv: any = {
 
-  }
+  };
   constructor() {
 
   }
diff --git a/src/codelens/CodeLensController.ts b/src/codelens/CodeLensController.ts
deleted file mode 100644
index b41f28f..0000000
--- a/src/codelens/CodeLensController.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) jdneo. All rights reserved.
-// Licensed under the MIT license.
-
-import { ConfigurationChangeEvent, Disposable, languages, workspace } from "vscode";
-import { customCodeLensProvider, CustomCodeLensProvider } from "./CustomCodeLensProvider";
-
-class CodeLensController implements Disposable {
-    private internalProvider: CustomCodeLensProvider;
-    private registeredProvider: Disposable | undefined;
-    private configurationChangeListener: Disposable;
-
-    constructor() {
-        this.internalProvider = customCodeLensProvider;
-
-        this.configurationChangeListener = workspace.onDidChangeConfiguration((event: ConfigurationChangeEvent) => {
-            if (event.affectsConfiguration("leetcode.editor.shortcuts")) {
-                this.internalProvider.refresh();
-            }
-        }, this);
-
-        this.registeredProvider = languages.registerCodeLensProvider({ scheme: "file" }, this.internalProvider);
-    }
-
-    public dispose(): void {
-        if (this.registeredProvider) {
-            this.registeredProvider.dispose();
-        }
-        this.configurationChangeListener.dispose();
-    }
-}
-
-export const codeLensController: CodeLensController = new CodeLensController();
diff --git a/src/commands/cache.ts b/src/commands/cache.ts
deleted file mode 100644
index 1f6b656..0000000
--- a/src/commands/cache.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) jdneo. All rights reserved.
-// Licensed under the MIT license.
-
-import { leetCodeExecutor } from "../leetCodeExecutor";
-import { DialogType, promptForOpenOutputChannel } from "../utils/uiUtils";
-
-export async function deleteCache(): Promise {
-    try {
-        await leetCodeExecutor.deleteCache();
-    } catch (error) {
-        await promptForOpenOutputChannel("Failed to delete cache. Please open the output channel for details.", DialogType.error);
-    }
-}
diff --git a/src/commands/language.ts b/src/commands/language.ts
deleted file mode 100644
index aec9b38..0000000
--- a/src/commands/language.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) jdneo. All rights reserved.
-// Licensed under the MIT license.
-
-import { QuickPickItem, window, workspace, WorkspaceConfiguration } from "vscode";
-import { languages } from "../shared";
-
-export async function switchDefaultLanguage(): Promise {
-    const leetCodeConfig: WorkspaceConfiguration = workspace.getConfiguration("leetcode-problem-rating");
-    const defaultLanguage: string | undefined = leetCodeConfig.get("defaultLanguage");
-    const languageItems: QuickPickItem[] = [];
-    for (const language of languages) {
-        languageItems.push({
-            label: language,
-            description: defaultLanguage === language ? "Currently used" : undefined,
-        });
-    }
-    // Put the default language at the top of the list
-    languageItems.sort((a: QuickPickItem, b: QuickPickItem) => {
-        if (a.description) {
-            return Number.MIN_SAFE_INTEGER;
-        } else if (b.description) {
-            return Number.MAX_SAFE_INTEGER;
-        }
-        return a.label.localeCompare(b.label);
-    });
-
-    const selectedItem: QuickPickItem | undefined = await window.showQuickPick(languageItems, {
-        placeHolder: "Please the default language",
-        ignoreFocusOut: true,
-    });
-
-    if (!selectedItem) {
-        return;
-    }
-
-    leetCodeConfig.update("defaultLanguage", selectedItem.label, true /* Global */);
-    window.showInformationMessage(`Successfully set the default language to ${selectedItem.label}`);
-}
diff --git a/src/commands/list.ts b/src/commands/list.ts
deleted file mode 100644
index 2ba5c36..0000000
--- a/src/commands/list.ts
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright (c) jdneo. All rights reserved.
-// Licensed under the MIT license.
-
-import * as vscode from "vscode";
-import { leetCodeExecutor } from "../leetCodeExecutor";
-import { leetCodeManager } from "../leetCodeManager";
-import { IProblem, ProblemState, RootNodeSort, UserStatus } from "../shared";
-import * as settingUtils from "../utils/settingUtils";
-import { DialogType, promptForOpenOutputChannel } from "../utils/uiUtils";
-import { leetCodeTreeDataProvider } from "../explorer/LeetCodeTreeDataProvider";
-import { resourcesData } from "../ResourcesData";
-
-export async function listProblems(): Promise {
-    try {
-        if (leetCodeManager.getStatus() === UserStatus.SignedOut) {
-            return [];
-        }
-        const leetCodeConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("leetcode-problem-rating");
-        const showLocked: boolean = !!leetCodeConfig.get("showLocked");
-        const useEndpointTranslation: boolean = settingUtils.shouldUseEndpointTranslation();
-        const result: string = await leetCodeExecutor.listProblems(showLocked, useEndpointTranslation);
-        const all_problem_info = JSON.parse(result);
-        const problems: IProblem[] = [];
-        // const lines: string[] = result.split("\n");
-        // const reg: RegExp = /^(.)\s(.{1,2})\s(.)\s\[\s*(\d*)\s*\]\s*(.*)\s*(Easy|Medium|Hard)\s*\((\s*\d+\.\d+ %)\)/;
-        // const { companies, tags } = await leetCodeExecutor.getCompaniesAndTags();
-        const AllScoreData = leetCodeTreeDataProvider.getScoreData();
-        for (const p of all_problem_info) {
-            // console.log(p)
-            problems.push({
-                id: p.fid,
-                qid: p.id,
-                isFavorite: p.starred,
-                locked: p.locked,
-                state: parseProblemState(p.state),
-                name: p.name,
-                difficulty: p.level,
-                passRate: p.percent,
-                companies: p.companies || [],
-                tags: resourcesData.getTagsData(p.fid) || ["Unknown"],
-                scoreData: AllScoreData.get(p.fid),
-                isSearchResult: false,
-                input: "",
-                rootNodeSortId: RootNodeSort.ZERO,
-                todayData: undefined,
-            });
-        }
-        return problems.reverse();
-    } catch (error) {
-        await promptForOpenOutputChannel("Failed to list problems. Please open the output channel for details.", DialogType.error);
-        return [];
-    }
-}
-
-function parseProblemState(stateOutput: string): ProblemState {
-    if (!stateOutput) {
-        return ProblemState.Unknown;
-    }
-    switch (stateOutput.trim()) {
-        case "v":
-        case "✔":
-        case "√":
-        case "ac":
-            return ProblemState.AC;
-        case "X":
-        case "✘":
-        case "×":
-        case "notac":
-            return ProblemState.NotAC;
-        default:
-            return ProblemState.Unknown;
-    }
-}
diff --git a/src/commands/plugin.ts b/src/commands/plugin.ts
deleted file mode 100644
index b39efc1..0000000
--- a/src/commands/plugin.ts
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright (c) jdneo. All rights reserved.
-// Licensed under the MIT license.
-
-import * as vscode from "vscode";
-import { leetCodeTreeDataProvider } from "../explorer/LeetCodeTreeDataProvider";
-import { leetCodeExecutor } from "../leetCodeExecutor";
-import { IQuickItemEx } from "../shared";
-import { Endpoint, SortingStrategy } from "../shared";
-import { DialogType, promptForOpenOutputChannel, promptForSignIn } from "../utils/uiUtils";
-import { deleteCache } from "./cache";
-
-export async function switchEndpoint(): Promise {
-    const isCnEnabled: boolean = getLeetCodeEndpoint() === Endpoint.LeetCodeCN;
-    const picks: Array> = [];
-    picks.push(
-        {
-            label: `${isCnEnabled ? "" : "$(check) "}LeetCode`,
-            description: "leetcode.com",
-            detail: `Enable LeetCode US`,
-            value: Endpoint.LeetCode,
-        },
-        {
-            label: `${isCnEnabled ? "$(check) " : ""}力扣`,
-            description: "leetcode.cn",
-            detail: `启用中国版 LeetCode`,
-            value: Endpoint.LeetCodeCN,
-        },
-    );
-    const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(picks);
-    if (!choice || choice.value === getLeetCodeEndpoint()) {
-        return;
-    }
-    const leetCodeConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("leetcode-problem-rating");
-    try {
-        const endpoint: string = choice.value;
-        await leetCodeExecutor.switchEndpoint(endpoint);
-        await leetCodeConfig.update("endpoint", endpoint, true /* UserSetting */);
-        vscode.window.showInformationMessage(`Switched the endpoint to ${endpoint}`);
-    } catch (error) {
-        await promptForOpenOutputChannel("Failed to switch endpoint. Please open the output channel for details.", DialogType.error);
-    }
-
-    try {
-        await vscode.commands.executeCommand("leetcode.signout");
-        await deleteCache();
-        await promptForSignIn();
-    } catch (error) {
-        await promptForOpenOutputChannel("Failed to sign in. Please open the output channel for details.", DialogType.error);
-    }
-}
-
-export function getLeetCodeEndpoint(): string {
-    const leetCodeConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("leetcode-problem-rating");
-    return leetCodeConfig.get("endpoint", Endpoint.LeetCodeCN);
-}
-
-const SORT_ORDER: SortingStrategy[] = [
-    SortingStrategy.None,
-    SortingStrategy.AcceptanceRateAsc,
-    SortingStrategy.AcceptanceRateDesc,
-    SortingStrategy.ScoreAsc,
-    SortingStrategy.ScoreDesc,
-    SortingStrategy.IDDesc,
-];
-
-export async function switchSortingStrategy(): Promise {
-    const currentStrategy: SortingStrategy = getSortingStrategy();
-    const picks: Array> = [];
-    picks.push(
-        ...SORT_ORDER.map((s: SortingStrategy) => {
-            return {
-                label: `${currentStrategy === s ? "$(check)" : "    "} ${s}`,
-                value: s,
-            };
-        }),
-    );
-
-    const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(picks);
-    if (!choice || choice.value === currentStrategy) {
-        return;
-    }
-
-    const leetCodeConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("leetcode-problem-rating");
-    await leetCodeConfig.update("problems.sortStrategy", choice.value, true);
-    await leetCodeTreeDataProvider.refresh();
-}
-
-export function getSortingStrategy(): SortingStrategy {
-    const leetCodeConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("leetcode-problem-rating");
-    return leetCodeConfig.get("problems.sortStrategy", SortingStrategy.None);
-}
diff --git a/src/commands/session.ts b/src/commands/session.ts
deleted file mode 100644
index 2b26f26..0000000
--- a/src/commands/session.ts
+++ /dev/null
@@ -1,156 +0,0 @@
-// Copyright (c) jdneo. All rights reserved.
-// Licensed under the MIT license.
-
-// import * as vscode from "vscode";
-import { leetCodeExecutor } from "../leetCodeExecutor";
-import { leetCodeManager } from "../leetCodeManager";
-// import { IQuickItemEx } from "../shared";
-// import { DialogOptions, DialogType, promptForOpenOutputChannel, promptForSignIn } from "../utils/uiUtils";
-import { promptForSignIn } from "../utils/uiUtils";
-
-export async function getSessionList(): Promise {
-    const signInStatus: string | undefined = leetCodeManager.getUser();
-    if (!signInStatus) {
-        promptForSignIn();
-        return [];
-    }
-    const result: string = await leetCodeExecutor.listSessions();
-    const lines: string[] = result.split("\n");
-    const sessions: ISession[] = [];
-    const reg: RegExp = /(.?)\s*(\d+)\s+(.*)\s+(\d+ \(\s*\d+\.\d+ %\))\s+(\d+ \(\s*\d+\.\d+ %\))/;
-    for (const line of lines) {
-        const match: RegExpMatchArray | null = line.match(reg);
-        if (match && match.length === 6) {
-            sessions.push({
-                active: !!(match[1].trim()),
-                id: match[2].trim(),
-                name: match[3].trim(),
-                acQuestions: match[4].trim(),
-                acSubmits: match[5].trim(),
-            });
-        }
-    }
-    return sessions;
-}
-
-export async function manageSessions(): Promise {
-    // const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(parseSessionsToPicks(true /* includeOperation */));
-    // if (!choice || choice.description === "Active") {
-    //     return;
-    // }
-    // if (choice.value === ":createSession") {
-    //     await createSession();
-    //     return;
-    // }
-    // if (choice.value === ":deleteSession") {
-    //     await deleteSession();
-    //     return;
-    // }
-    // try {
-    //     await leetCodeExecutor.enableSession((choice.value as ISession).id);
-    //     vscode.window.showInformationMessage(`Successfully switched to session '${choice.label}'.`);
-    //     await vscode.commands.executeCommand("leetcode.refreshExplorer");
-    // } catch (error) {
-    //     await promptForOpenOutputChannel("Failed to switch session. Please open the output channel for details.", DialogType.error);
-    // }
-}
-
-// async function parseSessionsToPicks(includeOperations: boolean = false): Promise>> {
-//     return new Promise(async (resolve: (res: Array>) => void): Promise => {
-//         try {
-//             const sessions: ISession[] = await getSessionList();
-//             const picks: Array> = sessions.map((s: ISession) => Object.assign({}, {
-//                 label: `${s.active ? "$(check) " : ""}${s.name}`,
-//                 description: s.active ? "Active" : "",
-//                 detail: `AC Questions: ${s.acQuestions}, AC Submits: ${s.acSubmits}`,
-//                 value: s,
-//             }));
-
-//             if (includeOperations) {
-//                 picks.push(...parseSessionManagementOperations());
-//             }
-//             resolve(picks);
-//         } catch (error) {
-//             return await promptForOpenOutputChannel("Failed to list sessions. Please open the output channel for details.", DialogType.error);
-//         }
-//     });
-// }
-
-// function parseSessionManagementOperations(): Array> {
-//     return [{
-//         label: "$(plus) Create a session",
-//         description: "",
-//         detail: "Click this item to create a session",
-//         value: ":createSession",
-//     }, {
-//         label: "$(trashcan) Delete a session",
-//         description: "",
-//         detail: "Click this item to DELETE a session",
-//         value: ":deleteSession",
-//     }];
-// }
-
-// async function createSession(): Promise {
-//     const session: string | undefined = await vscode.window.showInputBox({
-//         prompt: "Enter the new session name.",
-//         validateInput: (s: string): string | undefined => s && s.trim() ? undefined : "Session name must not be empty",
-//     });
-//     if (!session) {
-//         return;
-//     }
-//     try {
-//         await leetCodeExecutor.createSession(session);
-//         vscode.window.showInformationMessage("New session created, you can switch to it by clicking the status bar.");
-//     } catch (error) {
-//         await promptForOpenOutputChannel("Failed to create session. Please open the output channel for details.", DialogType.error);
-//     }
-// }
-
-// async function deleteSession(): Promise {
-//     const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(
-//         parseSessionsToPicks(false /* includeOperation */),
-//         { placeHolder: "Please select the session you want to delete" },
-//     );
-//     if (!choice) {
-//         return;
-//     }
-
-//     const selectedSession: ISession = choice.value as ISession;
-//     if (selectedSession.active) {
-//         vscode.window.showInformationMessage("Cannot delete an active session.");
-//         return;
-//     }
-
-//     const action: vscode.MessageItem | undefined = await vscode.window.showWarningMessage(
-//         `This operation cannot be reverted. Are you sure to delete the session: ${selectedSession.name}?`,
-//         DialogOptions.yes,
-//         DialogOptions.no,
-//     );
-//     if (action !== DialogOptions.yes) {
-//         return;
-//     }
-
-//     const confirm: string | undefined = await vscode.window.showInputBox({
-//         prompt: "Enter 'yes' to confirm deleting the session",
-//         validateInput: (value: string): string => {
-//             if (value === "yes") {
-//                 return "";
-//             } else {
-//                 return "Enter 'yes' to confirm";
-//             }
-//         },
-//     });
-
-//     if (confirm === "yes") {
-//         await leetCodeExecutor.deleteSession(selectedSession.id);
-//         vscode.window.showInformationMessage("The session has been successfully deleted.");
-//     }
-// }
-
-export interface ISession {
-    active: boolean;
-    id: string;
-    name: string;
-    acQuestions: string;
-    acSubmits: string;
-}
diff --git a/src/commands/show.ts b/src/commands/show.ts
deleted file mode 100644
index 5e127d8..0000000
--- a/src/commands/show.ts
+++ /dev/null
@@ -1,497 +0,0 @@
-// Copyright (c) jdneo. All rights reserved.
-// Licensed under the MIT license.
-
-import * as _ from "lodash";
-import * as path from "path";
-import * as unescapeJS from "unescape-js";
-import * as vscode from "vscode";
-import { explorerNodeManager } from "../explorer/explorerNodeManager";
-import { LeetCodeNode } from "../explorer/LeetCodeNode";
-import { leetCodeChannel } from "../leetCodeChannel";
-import { leetCodeExecutor } from "../leetCodeExecutor";
-import { leetCodeManager } from "../leetCodeManager";
-import { IProblem, IQuickItemEx, languages, ProblemState, SearchNode, SearchSetType, userContestRankingObj, userContestRanKingBase } from "../shared";
-import { leetCodeTreeDataProvider } from "../explorer/LeetCodeTreeDataProvider";
-import { genFileExt, genFileName, getNodeIdFromFile } from "../utils/problemUtils";
-import * as settingUtils from "../utils/settingUtils";
-import { IDescriptionConfiguration } from "../utils/settingUtils";
-import { DialogOptions, DialogType, openSettingsEditor, promptForOpenOutputChannel, promptForSignIn, promptHintMessage } from "../utils/uiUtils";
-import { getActiveFilePath, selectWorkspaceFolder } from "../utils/workspaceUtils";
-import * as wsl from "../utils/wslUtils";
-import { leetCodePreviewProvider } from "../webview/leetCodePreviewProvider";
-import { leetCodeSolutionProvider } from "../webview/leetCodeSolutionProvider";
-import { getPickOneByRankRangeMin, getPickOneByRankRangeMax } from "../utils/settingUtils";
-import * as list from "./list";
-import { getLeetCodeEndpoint } from "./plugin";
-
-export async function previewProblem(input: IProblem | vscode.Uri, isSideMode: boolean = false): Promise {
-    let node: IProblem;
-    if (input instanceof vscode.Uri) {
-        const activeFilePath: string = input.fsPath;
-        const id: string = await getNodeIdFromFile(activeFilePath);
-        if (!id) {
-            vscode.window.showErrorMessage(`Failed to resolve the problem id from file: ${activeFilePath}.`);
-            return;
-        }
-        const cachedNode: IProblem | undefined = explorerNodeManager.getNodeById(id);
-        if (!cachedNode) {
-            vscode.window.showErrorMessage(`Failed to resolve the problem with id: ${id}.`);
-            return;
-        }
-        node = cachedNode;
-        // Move the preview page aside if it's triggered from Code Lens
-        isSideMode = true;
-    } else {
-        node = input;
-    }
-    const needTranslation: boolean = settingUtils.shouldUseEndpointTranslation();
-    const descString: string = await leetCodeExecutor.getDescription(node.qid, needTranslation);
-    leetCodePreviewProvider.show(descString, node, isSideMode);
-}
-
-export async function deleteAllCache(): Promise {
-    await leetCodeManager.signOut();
-    await leetCodeExecutor.removeOldCache();
-    await leetCodeExecutor.switchEndpoint(getLeetCodeEndpoint());
-    await leetCodeTreeDataProvider.refresh()
-}
-
-
-export async function pickOne(): Promise {
-    const problems: IProblem[] = await list.listProblems();
-    var randomProblem: IProblem;
-
-    const user_score = leetCodeManager.getUserContestScore()
-    if (user_score > 0) {
-
-        let min_score: number = getPickOneByRankRangeMin();
-        let max_score: number = getPickOneByRankRangeMax();
-        let temp_problems: IProblem[] = new Array();
-        const need_min = user_score + min_score;
-        const need_max = user_score + max_score;
-        problems.forEach(element => {
-            if (element.scoreData?.Rating) {
-                if (element.scoreData.Rating >= need_min && element.scoreData.Rating <= need_max) {
-                    temp_problems.push(element);
-                }
-            }
-        });
-        randomProblem = temp_problems[Math.floor(Math.random() * temp_problems.length)];
-
-    } else {
-        randomProblem = problems[Math.floor(Math.random() * problems.length)];
-    }
-    if (randomProblem) {
-        await showProblemInternal(randomProblem);
-    }
-}
-export async function searchScoreRange(): Promise {
-    const twoFactor: string | undefined = await vscode.window.showInputBox({
-        prompt: "输入分数范围 低分-高分 例如: 1500-1600",
-        ignoreFocusOut: true,
-        validateInput: (s: string): string | undefined => s && s.trim() ? undefined : "The input must not be empty",
-    });
-
-    // vscode.window.showErrorMessage(twoFactor || "输入错误");
-    const tt = Object.assign({}, SearchNode, {
-        value: twoFactor,
-        type: SearchSetType.ScoreRange,
-        time: Math.floor(Date.now() / 1000)
-    })
-    explorerNodeManager.insertSearchSet(tt);
-    await leetCodeTreeDataProvider.refresh()
-}
-
-export async function searchContest(): Promise {
-    const twoFactor: string | undefined = await vscode.window.showInputBox({
-        prompt: "单期数 例如: 300 或者 输入期数范围 低期数-高期数 例如: 303-306",
-        ignoreFocusOut: true,
-        validateInput: (s: string): string | undefined => s && s.trim() ? undefined : "The input must not be empty",
-    });
-
-    // vscode.window.showErrorMessage(twoFactor || "输入错误");
-    const tt = Object.assign({}, SearchNode, {
-        value: twoFactor,
-        type: SearchSetType.Context,
-        time: Math.floor(Date.now() / 1000)
-    })
-    explorerNodeManager.insertSearchSet(tt);
-    await leetCodeTreeDataProvider.refresh()
-}
-
-export async function showProblem(node?: LeetCodeNode): Promise {
-    if (!node) {
-        return;
-    }
-    await showProblemInternal(node);
-}
-
-
-export async function searchProblemByID(): Promise {
-    if (!leetCodeManager.getUser()) {
-        promptForSignIn();
-        return;
-    }
-    const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(
-        parseProblemsToPicks(list.listProblems()),
-        {
-            matchOnDetail: true,
-            matchOnDescription: true,
-            placeHolder: "Select one problem",
-        },
-    );
-    if (!choice) {
-        return;
-    }
-    await showProblemInternal(choice.value);
-}
-
-
-export async function searchProblem(): Promise {
-    if (!leetCodeManager.getUser()) {
-        promptForSignIn();
-        return;
-    }
-
-    const picks: Array> = [];
-    picks.push(
-        {
-            label: `题目id查询`,
-            detail: `通过题目id查询`,
-            value: `byid`,
-        },
-        {
-            label: `分数范围查询`,
-            detail: `例如 1500-1600`,
-            value: `range`,
-        },
-        {
-            label: `周赛期数查询`,
-            detail: `周赛期数查询`,
-            value: `contest`,
-        },
-        // {
-        //     label: `测试api`,
-        //     detail: `测试api`,
-        //     value: `testapi`,
-        // }
-        // ,
-        // {
-        //     label: `每日一题`,
-        //     detail: `每日一题`,
-        //     value: `today`,
-        // },
-        // {
-        //     label: `查询自己竞赛信息`,
-        //     detail: `查询自己竞赛信息`,
-        //     value: `userContest`,
-        // }
-    );
-    const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(
-        picks,
-        { title: "选择查询选项" },
-    );
-    if (!choice) {
-        return
-    }
-    if (choice.value == "byid") {
-        await searchProblemByID();
-    } else if (choice.value == "range") {
-        await searchScoreRange();
-    } else if (choice.value == "contest") {
-        await searchContest();
-    } else if (choice.value == "today") {
-        await searchToday();
-    } else if (choice.value == "userContest") {
-        await searchUserContest();
-    } else if (choice.value == "testapi") {
-        await testapi();
-    }
-
-}
-
-export async function testapi(): Promise {
-    if (!leetCodeManager.getUser()) {
-        promptForSignIn();
-        return;
-    }
-    try {
-        const twoFactor: string | undefined = await vscode.window.showInputBox({
-            prompt: "测试数据",
-            ignoreFocusOut: true,
-            validateInput: (s: string): string | undefined => s && s.trim() ? undefined : "The input must not be empty",
-        });
-
-        // vscode.window.showErrorMessage(twoFactor || "输入错误");
-        const solution: string = await leetCodeExecutor.getTestApi(twoFactor || "")
-        const query_result = JSON.parse(solution);
-        console.log(query_result);
-    } catch (error) {
-        leetCodeChannel.appendLine(error.toString());
-        await promptForOpenOutputChannel("Failed to fetch today question. Please open the output channel for details.", DialogType.error);
-    }
-}
-
-export async function searchUserContest(): Promise {
-    if (!leetCodeManager.getUser()) {
-        promptForSignIn();
-        return;
-    }
-    try {
-        const needTranslation: boolean = settingUtils.shouldUseEndpointTranslation();
-        const solution: string = await leetCodeExecutor.getUserContest(needTranslation, leetCodeManager.getUser() || "");
-        const query_result = JSON.parse(solution);
-        const tt: userContestRanKingBase = Object.assign({}, userContestRankingObj, query_result.userContestRanking)
-        await leetCodeManager.insertCurrentUserContestInfo(tt);
-        leetCodeManager.emit("searchUserContest")
-    } catch (error) {
-        leetCodeChannel.appendLine(error.toString());
-        await promptForOpenOutputChannel("Failed to fetch today question. Please open the output channel for details.", DialogType.error);
-    }
-}
-export async function searchToday(): Promise {
-    if (!leetCodeManager.getUser()) {
-        promptForSignIn();
-        return;
-    }
-    try {
-        const needTranslation: boolean = settingUtils.shouldUseEndpointTranslation();
-        const solution: string = await leetCodeExecutor.getTodayQuestion(needTranslation);
-        const query_result = JSON.parse(solution);
-        // const titleSlug: string = query_result.titleSlug
-        // const questionId: string = query_result.questionId
-        const fid: string = query_result.fid
-        if (fid) {
-            const tt = Object.assign({}, SearchNode, {
-                value: fid,
-                type: SearchSetType.Day,
-                time: Math.floor(Date.now() / 1000),
-                todayData: query_result,
-            })
-            explorerNodeManager.insertSearchSet(tt);
-            await leetCodeTreeDataProvider.refresh()
-        }
-
-    } catch (error) {
-        leetCodeChannel.appendLine(error.toString());
-        await promptForOpenOutputChannel("Failed to fetch today question. Please open the output channel for details.", DialogType.error);
-    }
-}
-
-
-export async function showSolution(input: LeetCodeNode | vscode.Uri): Promise {
-    let problemInput: string | undefined;
-    if (input instanceof LeetCodeNode) { // Triggerred from explorer
-        problemInput = input.qid;
-    } else if (input instanceof vscode.Uri) { // Triggerred from Code Lens/context menu
-        if (wsl.useVscodeNode()) {
-            problemInput = `${input.fsPath}`;
-        } else {
-            problemInput = `"${input.fsPath}"`;
-            if (wsl.useWsl()) {
-                problemInput = await wsl.toWslPath(input.fsPath);
-            }
-        }
-    } else if (!input) { // Triggerred from command
-        problemInput = await getActiveFilePath();
-    }
-
-    if (!problemInput) {
-        vscode.window.showErrorMessage("Invalid input to fetch the solution data.");
-        return;
-    }
-
-    const language: string | undefined = await fetchProblemLanguage();
-    if (!language) {
-        return;
-    }
-    try {
-        const needTranslation: boolean = settingUtils.shouldUseEndpointTranslation();
-        const solution: string = await leetCodeExecutor.showSolution(problemInput, language, needTranslation);
-        leetCodeSolutionProvider.show(unescapeJS(solution));
-    } catch (error) {
-        leetCodeChannel.appendLine(error.toString());
-        await promptForOpenOutputChannel("Failed to fetch the top voted solution. Please open the output channel for details.", DialogType.error);
-    }
-}
-
-async function fetchProblemLanguage(): Promise {
-    const leetCodeConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("leetcode-problem-rating");
-    let defaultLanguage: string | undefined = leetCodeConfig.get("defaultLanguage");
-    if (defaultLanguage && languages.indexOf(defaultLanguage) < 0) {
-        defaultLanguage = undefined;
-    }
-    const language: string | undefined = defaultLanguage || await vscode.window.showQuickPick(languages, { placeHolder: "Select the language you want to use", ignoreFocusOut: true });
-    // fire-and-forget default language query
-    (async (): Promise => {
-        if (language && !defaultLanguage && leetCodeConfig.get("hint.setDefaultLanguage")) {
-            const choice: vscode.MessageItem | undefined = await vscode.window.showInformationMessage(
-                `Would you like to set '${language}' as your default language?`,
-                DialogOptions.yes,
-                DialogOptions.no,
-                DialogOptions.never,
-            );
-            if (choice === DialogOptions.yes) {
-                leetCodeConfig.update("defaultLanguage", language, true /* UserSetting */);
-            } else if (choice === DialogOptions.never) {
-                leetCodeConfig.update("hint.setDefaultLanguage", false, true /* UserSetting */);
-            }
-        }
-    })();
-    return language;
-}
-
-async function showProblemInternal(node: IProblem): Promise {
-    try {
-        const language: string | undefined = await fetchProblemLanguage();
-        if (!language) {
-            return;
-        }
-
-        const leetCodeConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("leetcode-problem-rating");
-        const workspaceFolder: string = await selectWorkspaceFolder();
-        if (!workspaceFolder) {
-            return;
-        }
-
-        const fileFolder: string = leetCodeConfig
-            .get(`filePath.${language}.folder`, leetCodeConfig.get(`filePath.default.folder`, ""))
-            .trim();
-        const fileName: string = leetCodeConfig
-            .get(
-                `filePath.${language}.filename`,
-                leetCodeConfig.get(`filePath.default.filename`) || genFileName(node, language),
-            )
-            .trim();
-
-        let finalPath: string = path.join(workspaceFolder, fileFolder, fileName);
-
-        if (finalPath) {
-            finalPath = await resolveRelativePath(finalPath, node, language);
-            if (!finalPath) {
-                leetCodeChannel.appendLine("Showing problem canceled by user.");
-                return;
-            }
-        }
-
-        finalPath = wsl.useWsl() ? await wsl.toWinPath(finalPath) : finalPath;
-
-        const descriptionConfig: IDescriptionConfiguration = settingUtils.getDescriptionConfiguration();
-        const needTranslation: boolean = settingUtils.shouldUseEndpointTranslation();
-
-        await leetCodeExecutor.showProblem(node, language, finalPath, descriptionConfig.showInComment, needTranslation);
-        const promises: any[] = [
-            vscode.window.showTextDocument(vscode.Uri.file(finalPath), { preview: false, viewColumn: vscode.ViewColumn.One }),
-            promptHintMessage(
-                "hint.commentDescription",
-                'You can config how to show the problem description through "leetcode.showDescription".',
-                "Open settings",
-                (): Promise => openSettingsEditor("leetcode.showDescription"),
-            ),
-        ];
-        if (descriptionConfig.showInWebview) {
-            promises.push(showDescriptionView(node));
-        }
-
-        await Promise.all(promises);
-    } catch (error) {
-        await promptForOpenOutputChannel(`${error} Please open the output channel for details.`, DialogType.error);
-    }
-}
-
-async function showDescriptionView(node: IProblem): Promise {
-    return previewProblem(node, vscode.workspace.getConfiguration("leetcode-problem-rating").get("enableSideMode", true));
-}
-async function parseProblemsToPicks(p: Promise): Promise>> {
-    return new Promise(async (resolve: (res: Array>) => void): Promise => {
-        const picks: Array> = (await p).map((problem: IProblem) => Object.assign({}, {
-            label: `${parseProblemDecorator(problem.state, problem.locked)}${problem.id}.${problem.name}`,
-            description: `QID:${problem.qid}`,
-            detail: ((problem.scoreData?.score || "0") > "0" ? ("score: " + problem.scoreData?.score + " , ") : "") + `AC rate: ${problem.passRate}, Difficulty: ${problem.difficulty}`,
-            value: problem,
-        }));
-        resolve(picks);
-    });
-}
-
-function parseProblemDecorator(state: ProblemState, locked: boolean): string {
-    switch (state) {
-        case ProblemState.AC:
-            return "$(check) ";
-        case ProblemState.NotAC:
-            return "$(x) ";
-        default:
-            return locked ? "$(lock) " : "";
-    }
-}
-
-async function resolveRelativePath(relativePath: string, node: IProblem, selectedLanguage: string): Promise {
-    let tag: string = "";
-    if (/\$\{tag\}/i.test(relativePath)) {
-        tag = (await resolveTagForProblem(node)) || "";
-    }
-
-    let company: string = "";
-    if (/\$\{company\}/i.test(relativePath)) {
-        company = (await resolveCompanyForProblem(node)) || "";
-    }
-
-    return relativePath.replace(/\$\{(.*?)\}/g, (_substring: string, ...args: string[]) => {
-        const placeholder: string = args[0].toLowerCase().trim();
-        switch (placeholder) {
-            case "id":
-                return node.id;
-            case "name":
-                return node.name;
-            case "camelcasename":
-                return _.camelCase(node.name);
-            case "pascalcasename":
-                return _.upperFirst(_.camelCase(node.name));
-            case "kebabcasename":
-            case "kebab-case-name":
-                return _.kebabCase(node.name);
-            case "snakecasename":
-            case "snake_case_name":
-                return _.snakeCase(node.name);
-            case "ext":
-                return genFileExt(selectedLanguage);
-            case "language":
-                return selectedLanguage;
-            case "difficulty":
-                return node.difficulty.toLocaleLowerCase();
-            case "tag":
-                return tag;
-            case "company":
-                return company;
-            default:
-                const errorMsg: string = `The config '${placeholder}' is not supported.`;
-                leetCodeChannel.appendLine(errorMsg);
-                throw new Error(errorMsg);
-        }
-    });
-}
-
-async function resolveTagForProblem(problem: IProblem): Promise {
-    if (problem.tags.length === 1) {
-        return problem.tags[0];
-    }
-    return await vscode.window.showQuickPick(
-        problem.tags,
-        {
-            matchOnDetail: true,
-            placeHolder: "Multiple tags available, please select one",
-            ignoreFocusOut: true,
-        },
-    );
-}
-
-async function resolveCompanyForProblem(problem: IProblem): Promise {
-    if (problem.companies.length === 1) {
-        return problem.companies[0];
-    }
-    return await vscode.window.showQuickPick(problem.companies, {
-        matchOnDetail: true,
-        placeHolder: "Multiple tags available, please select one",
-        ignoreFocusOut: true,
-    });
-}
diff --git a/src/commands/star.ts b/src/commands/star.ts
deleted file mode 100644
index 3661149..0000000
--- a/src/commands/star.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-
-// Copyright (c) jdneo. All rights reserved.
-// Licensed under the MIT license.
-
-import { customCodeLensProvider } from "../codelens/CustomCodeLensProvider";
-import { LeetCodeNode } from "../explorer/LeetCodeNode";
-import { leetCodeTreeDataProvider } from "../explorer/LeetCodeTreeDataProvider";
-import { leetCodeExecutor } from "../leetCodeExecutor";
-import { hasStarShortcut } from "../utils/settingUtils";
-import { DialogType, promptForOpenOutputChannel } from "../utils/uiUtils";
-
-export async function addFavorite(node: LeetCodeNode): Promise {
-    try {
-        await leetCodeExecutor.toggleFavorite(node, true);
-        await leetCodeTreeDataProvider.refresh();
-        if (hasStarShortcut()) {
-            customCodeLensProvider.refresh();
-        }
-    } catch (error) {
-        await promptForOpenOutputChannel("Failed to add the problem to favorite. Please open the output channel for details.", DialogType.error);
-    }
-}
-
-export async function removeFavorite(node: LeetCodeNode): Promise {
-    try {
-        await leetCodeExecutor.toggleFavorite(node, false);
-        await leetCodeTreeDataProvider.refresh();
-        if (hasStarShortcut()) {
-            customCodeLensProvider.refresh();
-        }
-    } catch (error) {
-        await promptForOpenOutputChannel("Failed to remove the problem from favorite. Please open the output channel for details.", DialogType.error);
-    }
-}
diff --git a/src/commands/submit.ts b/src/commands/submit.ts
deleted file mode 100644
index 34710b6..0000000
--- a/src/commands/submit.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) jdneo. All rights reserved.
-// Licensed under the MIT license.
-
-import * as vscode from "vscode";
-import { leetCodeTreeDataProvider } from "../explorer/LeetCodeTreeDataProvider";
-import { leetCodeExecutor } from "../leetCodeExecutor";
-import { leetCodeManager } from "../leetCodeManager";
-import { DialogType, promptForOpenOutputChannel, promptForSignIn } from "../utils/uiUtils";
-import { getActiveFilePath } from "../utils/workspaceUtils";
-import { leetCodeSubmissionProvider } from "../webview/leetCodeSubmissionProvider";
-
-export async function submitSolution(uri?: vscode.Uri): Promise {
-    if (!leetCodeManager.getUser()) {
-        promptForSignIn();
-        return;
-    }
-
-    const filePath: string | undefined = await getActiveFilePath(uri);
-    if (!filePath) {
-        return;
-    }
-
-    try {
-        const result: string = await leetCodeExecutor.submitSolution(filePath);
-        leetCodeSubmissionProvider.show(result);
-        leetCodeManager.emit("submit", leetCodeSubmissionProvider.getSubmitEvent());
-    } catch (error) {
-        await promptForOpenOutputChannel("Failed to submit the solution. Please open the output channel for details.", DialogType.error);
-        return;
-    }
-
-    leetCodeTreeDataProvider.refresh();
-}
diff --git a/src/commands/test.ts b/src/commands/test.ts
deleted file mode 100644
index 7b0c18e..0000000
--- a/src/commands/test.ts
+++ /dev/null
@@ -1,144 +0,0 @@
-// Copyright (c) jdneo. All rights reserved.
-// Licensed under the MIT license.
-
-import * as fse from "fs-extra";
-import * as vscode from "vscode";
-import { leetCodeExecutor } from "../leetCodeExecutor";
-import { leetCodeManager } from "../leetCodeManager";
-import { IQuickItemEx, UserStatus } from "../shared";
-import { isWindows, usingCmd } from "../utils/osUtils";
-import { DialogType, promptForOpenOutputChannel, showFileSelectDialog } from "../utils/uiUtils";
-import { getActiveFilePath } from "../utils/workspaceUtils";
-import * as wsl from "../utils/wslUtils";
-import { leetCodeSubmissionProvider } from "../webview/leetCodeSubmissionProvider";
-
-export async function testSolution(uri?: vscode.Uri): Promise {
-    try {
-        if (leetCodeManager.getStatus() === UserStatus.SignedOut) {
-            return;
-        }
-
-        const filePath: string | undefined = await getActiveFilePath(uri);
-        if (!filePath) {
-            return;
-        }
-        const picks: Array> = [];
-        picks.push(
-            {
-                label: "$(three-bars) Default test cases",
-                description: "",
-                detail: "Test with the default cases",
-                value: ":default",
-            },
-            {
-                label: "$(pencil) Write directly...",
-                description: "",
-                detail: "Write test cases in input box",
-                value: ":direct",
-            },
-            {
-                label: "$(file-text) Browse...",
-                description: "",
-                detail: "Test with the written cases in file",
-                value: ":file",
-            },
-            {
-                label: "All Default test cases...",
-                description: "",
-                detail: "Test with the all default cases",
-                value: ":alldefault",
-            },
-        );
-        const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(picks);
-        if (!choice) {
-            return;
-        }
-
-        let result: string | undefined;
-        switch (choice.value) {
-            case ":default":
-                result = await leetCodeExecutor.testSolution(filePath);
-                break;
-            case ":direct":
-                const testString: string | undefined = await vscode.window.showInputBox({
-                    prompt: "Enter the test cases.",
-                    validateInput: (s: string): string | undefined => s && s.trim() ? undefined : "Test case must not be empty.",
-                    placeHolder: "Example: [1,2,3]\\n4",
-                    ignoreFocusOut: true,
-                });
-                if (testString) {
-                    result = await leetCodeExecutor.testSolution(filePath, parseTestString(testString));
-                }
-                break;
-            case ":file":
-                const testFile: vscode.Uri[] | undefined = await showFileSelectDialog(filePath);
-                if (testFile && testFile.length) {
-                    const input: string = (await fse.readFile(testFile[0].fsPath, "utf-8")).trim();
-                    if (input) {
-                        result = await leetCodeExecutor.testSolution(filePath, parseTestString(input.replace(/\r?\n/g, "\\n")));
-                    } else {
-                        vscode.window.showErrorMessage("The selected test file must not be empty.");
-                    }
-                }
-                break;
-            case ":alldefault":
-                result = await leetCodeExecutor.testSolution(filePath, undefined, true);
-                break;
-            default:
-                break;
-        }
-        if (!result) {
-            return;
-        }
-        leetCodeSubmissionProvider.show(result);
-        leetCodeManager.emit("submit", leetCodeSubmissionProvider.getSubmitEvent());
-    } catch (error) {
-        await promptForOpenOutputChannel("Failed to test the solution. Please open the output channel for details.", DialogType.error);
-    }
-}
-
-export async function testSolutionDefault(uri?: vscode.Uri, allCase?: boolean): Promise {
-    try {
-        if (leetCodeManager.getStatus() === UserStatus.SignedOut) {
-            return;
-        }
-
-        const filePath: string | undefined = await getActiveFilePath(uri);
-        if (!filePath) {
-            return;
-        }
-
-        let result: string | undefined = await leetCodeExecutor.testSolution(filePath, undefined, allCase || false);
-        if (!result) {
-            return;
-        }
-        leetCodeSubmissionProvider.show(result);
-        leetCodeManager.emit("submit", leetCodeSubmissionProvider.getSubmitEvent());
-    } catch (error) {
-        await promptForOpenOutputChannel("Failed to test the solution. Please open the output channel for details.", DialogType.error);
-    }
-}
-
-
-function parseTestString(test: string): string {
-    if (wsl.useWsl() || !isWindows()) {
-        if (wsl.useVscodeNode()) {
-            return `${test}`;
-        }
-        return `'${test}'`;
-    }
-
-    // In windows and not using WSL
-    if (usingCmd()) {
-        // 一般需要走进这里, 除非改了 环境变量ComSpec的值
-        if (wsl.useVscodeNode()) {
-            return `${test.replace(/"/g, '\"')}`;
-        }
-        return `"${test.replace(/"/g, '\\"')}"`;
-    } else {
-        if (wsl.useVscodeNode()) {
-            return `${test.replace(/"/g, '\"')}`;
-        }
-        return `'${test.replace(/"/g, '\\"')}'`;
-    }
-}
diff --git a/src/controller/EventController.ts b/src/controller/EventController.ts
new file mode 100644
index 0000000..4f55adf
--- /dev/null
+++ b/src/controller/EventController.ts
@@ -0,0 +1,21 @@
+/*
+ * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/controller/EventController.ts
+ * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
+ * Created Date: Monday, October 31st 2022, 10:16:47 am
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
+
+import { eventService } from "../service/EventService";
+// 事件的控制器
+class EventContorller {
+    /**
+     * 监听事件
+     */
+    public add_event() {
+        eventService.add_event();
+    }
+}
+
+export const eventController: EventContorller = new EventContorller();
diff --git a/src/controller/FileButtonController.ts b/src/controller/FileButtonController.ts
new file mode 100644
index 0000000..c3f5cf0
--- /dev/null
+++ b/src/controller/FileButtonController.ts
@@ -0,0 +1,37 @@
+/*
+ * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/controller/FileButtonController.ts
+ * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
+ * Created Date: Thursday, October 27th 2022, 7:43:29 pm
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
+
+
+import { ConfigurationChangeEvent, Disposable, languages, workspace } from "vscode";
+import { fileButtonService } from "../service/FileButtonService";
+// 文件按钮的控制器
+class FileButtonController implements Disposable {
+
+    private registeredProvider: Disposable | undefined;
+    private configurationChangeListener: Disposable;
+
+    constructor() {
+        this.configurationChangeListener = workspace.onDidChangeConfiguration((event: ConfigurationChangeEvent) => {
+            if (event.affectsConfiguration("leetcode-problem-rating.editor.shortcuts")) {
+                fileButtonService.refresh();
+            }
+        }, this);
+
+        this.registeredProvider = languages.registerCodeLensProvider({ scheme: "file" }, fileButtonService);
+    }
+
+    public dispose(): void {
+        if (this.registeredProvider) {
+            this.registeredProvider.dispose();
+        }
+        this.configurationChangeListener.dispose();
+    }
+}
+
+export const fileButtonController: FileButtonController = new FileButtonController();
diff --git a/src/controller/LoginController.ts b/src/controller/LoginController.ts
new file mode 100644
index 0000000..cfd5a43
--- /dev/null
+++ b/src/controller/LoginController.ts
@@ -0,0 +1,181 @@
+/*
+ * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/controller/LoginController.ts
+ * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
+ * Created Date: Thursday, November 10th 2022, 3:06:12 pm
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
+
+import * as cp from "child_process";
+import * as systemUtils from "../utils/SystemUtils";
+import { executeService } from "../service/ExecuteService";
+
+import { DialogType, IQuickItemEx, loginArgsMapping, UserStatus } from "../model/Model";
+import { createEnvOption } from "../utils/CliUtils";
+import { logOutput, promptForOpenOutputChannel } from "../utils/OutputUtils";
+import { eventService } from "../service/EventService";
+import { window } from "vscode";
+import { statusBarService } from "../service/StatusBarService";
+import { treeDataService } from "../service/TreeDataService";
+import { getLeetCodeEndpoint } from "../utils/ConfigUtils";
+
+
+// 登录控制器
+class LoginContorller {
+    constructor() { }
+
+    // 登录操作
+    public async signIn(): Promise {
+        const picks: Array> = [];
+        picks.push(
+            {
+                label: "LeetCode Account",
+                detail: "只能登录leetcode.cn",
+                value: "LeetCode",
+            },
+            {
+                label: "Third-Party: GitHub",
+                detail: "Use GitHub account to login",
+                value: "GitHub",
+            },
+            {
+                label: "Third-Party: LinkedIn",
+                detail: "Use LinkedIn account to login",
+                value: "LinkedIn",
+            },
+            {
+                label: "LeetCode Cookie",
+                detail: "Use LeetCode cookie copied from browser to login",
+                value: "Cookie",
+            },
+        );
+        const choice: IQuickItemEx | undefined = await window.showQuickPick(picks);
+        if (!choice) {
+            return;
+        }
+        const loginMethod: string = choice.value;
+        const commandArg: string | undefined = loginArgsMapping.get(loginMethod);
+        if (!commandArg) {
+            throw new Error(`不支持 "${loginMethod}" 方式登录`);
+        }
+        const isByCookie: boolean = loginMethod === "Cookie";
+        const inMessage: string = isByCookie ? " 通过cookie登录" : "登录";
+        try {
+            const userName: string | undefined = await new Promise(async (resolve: (res: string | undefined) => void, reject: (e: Error) => void): Promise => {
+
+                const leetCodeBinaryPath: string = await executeService.getLeetCodeBinaryPath();
+
+                let childProc: cp.ChildProcess;
+
+                if (systemUtils.useVscodeNode()) {
+                    childProc = cp.fork(await executeService.getLeetCodeBinaryPath(), ["user", commandArg], {
+                        silent: true,
+                        env: createEnvOption(),
+                    });
+                } else {
+                    if (systemUtils.useWsl()) {
+                        childProc = cp.spawn("wsl", [executeService.node, leetCodeBinaryPath, "user", commandArg], { shell: true });
+                    } else {
+                        childProc = cp.spawn(executeService.node, [leetCodeBinaryPath, "user", commandArg], {
+                            shell: true,
+                            env: createEnvOption(),
+                        });
+                    }
+
+                }
+
+                childProc.stdout?.on("data", async (data: string | Buffer) => {
+                    data = data.toString();
+                    // vscode.window.showInformationMessage(`cc login msg ${data}.`);
+                    logOutput.append(data);
+                    if (data.includes("twoFactorCode")) {
+                        const twoFactor: string | undefined = await window.showInputBox({
+                            prompt: "Enter two-factor code.",
+                            ignoreFocusOut: true,
+                            validateInput: (s: string): string | undefined => s && s.trim() ? undefined : "The input must not be empty",
+                        });
+                        if (!twoFactor) {
+                            childProc.kill();
+                            return resolve(undefined);
+                        }
+                        childProc.stdin?.write(`${twoFactor}\n`);
+                    }
+
+                    let successMatch;
+                    try {
+                        successMatch = JSON.parse(data);
+                    } catch (e) {
+                        successMatch = {};
+                    }
+                    if (successMatch.code == 100) {
+                        childProc.stdin?.end();
+                        return resolve(successMatch.user_name);
+                    } else if (successMatch.code < 0) {
+                        childProc.stdin?.end();
+                        return reject(new Error(successMatch.msg));
+                    }
+                });
+
+                childProc.stderr?.on("data", (data: string | Buffer) => logOutput.append(data.toString()));
+
+                childProc.on("error", reject);
+                const name: string | undefined = await window.showInputBox({
+                    prompt: "Enter username or E-mail.",
+                    ignoreFocusOut: true,
+                    validateInput: (s: string): string | undefined => s && s.trim() ? undefined : "The input must not be empty",
+                });
+                if (!name) {
+                    childProc.kill();
+                    return resolve(undefined);
+                }
+                childProc.stdin?.write(`${name}\n`);
+                const pwd: string | undefined = await window.showInputBox({
+                    prompt: isByCookie ? "Enter cookie" : "Enter password.",
+                    password: true,
+                    ignoreFocusOut: true,
+                    validateInput: (s: string): string | undefined => s ? undefined : isByCookie ? "Cookie must not be empty" : "Password must not be empty",
+                });
+                if (!pwd) {
+                    childProc.kill();
+                    return resolve(undefined);
+                }
+                childProc.stdin?.write(`${pwd}\n`);
+            });
+            if (userName) {
+                window.showInformationMessage(`${inMessage} 成功`);
+                eventService.emit("statusChanged", UserStatus.SignedIn, userName);
+            }
+        } catch (error) {
+            promptForOpenOutputChannel(`${inMessage}失败. 请看看控制台输出信息`, DialogType.error);
+        }
+
+    }
+
+    // 登出
+    public async signOut(): Promise {
+        try {
+            await executeService.signOut();
+            window.showInformationMessage("成功登出");
+            eventService.emit("statusChanged", UserStatus.SignedOut, undefined);
+        } catch (error) {
+            // promptForOpenOutputChannel(`Failed to signOut. Please open the output channel for details`, DialogType.error);
+        }
+    }
+
+    // 获取登录状态
+    public async getLoginStatus() {
+        return await statusBarService.getLoginStatus();
+    }
+
+    // 删除所有缓存
+    public async deleteAllCache(): Promise {
+        await this.signOut();
+        await executeService.removeOldCache();
+        await executeService.switchEndpoint(getLeetCodeEndpoint());
+        await treeDataService.refresh();
+    }
+
+}
+
+export const loginContorller: LoginContorller = new LoginContorller();
diff --git a/src/controller/MainController.ts b/src/controller/MainController.ts
new file mode 100644
index 0000000..f5abdaa
--- /dev/null
+++ b/src/controller/MainController.ts
@@ -0,0 +1,42 @@
+/*
+ * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/controller/MainController.ts
+ * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
+ * Created Date: Thursday, November 10th 2022, 2:18:21 pm
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
+
+import * as systemUtils from "../utils/SystemUtils";
+import { executeService } from "../service/ExecuteService";
+import { ExtensionContext } from "vscode";
+import { treeDataService } from "../service/TreeDataService";
+
+// 做杂活
+class MainContorller {
+    constructor() { }
+
+    /**
+     * 检查运行环境
+     */
+    public async checkNodeEnv(context: ExtensionContext) {
+        if (!systemUtils.useVscodeNode()) {
+            if (!await executeService.checkNodeEnv(context)) {
+                throw new Error("The environment doesn't meet requirements.");
+            }
+        }
+    }
+
+    // 初始化上下文
+    public initialize(context: ExtensionContext) {
+        treeDataService.initialize(context);
+    }
+
+
+    // 删除缓存
+    public async deleteCache() {
+        await executeService.deleteCache();
+    }
+}
+
+export const mainContorller: MainContorller = new MainContorller();
diff --git a/src/controller/TreeViewController.ts b/src/controller/TreeViewController.ts
new file mode 100644
index 0000000..c152a06
--- /dev/null
+++ b/src/controller/TreeViewController.ts
@@ -0,0 +1,1453 @@
+/*
+ * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/controller/TreeViewController.ts
+ * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
+ * Created Date: Thursday, October 27th 2022, 7:43:29 pm
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
+
+
+import * as lodash from "lodash";
+import * as path from "path";
+import * as unescapeJS from "unescape-js";
+import * as vscode from "vscode";
+import { toNumber } from "lodash";
+import { Disposable, Uri, window, QuickPickItem, workspace, WorkspaceConfiguration } from "vscode";
+import { SearchNode, userContestRankingObj, userContestRanKingBase, UserStatus, IProblem, IQuickItemEx, languages, Category, defaultProblem, ProblemState, SortingStrategy, SearchSetTypeName, RootNodeSort, SearchSetType, ISubmitEvent, SORT_ORDER, Endpoint, OpenOption, DialogType, DialogOptions } from "../model/Model";
+import { isHideSolvedProblem, isHideScoreProblem, getDescriptionConfiguration, isUseEndpointTranslation, enableSideMode, getPickOneByRankRangeMin, getPickOneByRankRangeMax, isShowLocked, updateSortingStrategy, getSortingStrategy, getLeetCodeEndpoint, openSettingsEditor } from "../utils/ConfigUtils";
+import { NodeModel } from "../model/NodeModel";
+import { ISearchSet } from "../model/Model";
+import { statusBarService } from "../service/StatusBarService";
+import { previewService } from "../service/PreviewService";
+import { executeService } from "../service/ExecuteService";
+import { getNodeIdFromFile } from "../utils/SystemUtils";
+import { logOutput, promptForOpenOutputChannel, promptForSignIn, promptHintMessage } from "../utils/OutputUtils";
+import { treeDataService } from "../service/TreeDataService";
+import { genFileExt, genFileName } from "../utils/SystemUtils";
+import { IDescriptionConfiguration, isStarShortcut } from "../utils/ConfigUtils";
+import * as systemUtils from "../utils/SystemUtils";
+import { solutionService } from "../service/SolutionService";
+import { eventService } from "../service/EventService";
+import { fileButtonService } from "../service/FileButtonService";
+
+import * as fse from "fs-extra";
+import { submissionService } from "../service/SubmissionService";
+
+
+import * as os from "os";
+import { getVsCodeConfig, getWorkspaceFolder } from "../utils/ConfigUtils";
+
+
+// 视图控制器
+class TreeViewController implements Disposable {
+    private explorerNodeMap: Map = new Map();
+    private companySet: Set = new Set();
+    private tagSet: Set = new Set();
+    private searchSet: Map = new Map();
+    private waitTodayQuestion: boolean;
+    private waitUserContest: boolean;
+
+    // 获取当前文件的路径
+    public async getActiveFilePath(uri?: vscode.Uri): Promise {
+        let textEditor: vscode.TextEditor | undefined;
+        if (uri) {
+            textEditor = await vscode.window.showTextDocument(uri, { preview: false });
+        } else {
+            textEditor = vscode.window.activeTextEditor;
+        }
+
+        if (!textEditor) {
+            return undefined;
+        }
+        if (textEditor.document.isDirty && !await textEditor.document.save()) {
+            vscode.window.showWarningMessage("请先保存当前文件");
+            return undefined;
+        }
+        return systemUtils.useWsl() ? systemUtils.toWslPath(textEditor.document.uri.fsPath) : textEditor.document.uri.fsPath;
+    }
+
+    // 提交问题
+    public async submitSolution(uri?: vscode.Uri): Promise {
+        if (!statusBarService.getUser()) {
+            promptForSignIn();
+            return;
+        }
+
+        const filePath: string | undefined = await this.getActiveFilePath(uri);
+        if (!filePath) {
+            return;
+        }
+
+        try {
+            const result: string = await executeService.submitSolution(filePath);
+            submissionService.show(result);
+            eventService.emit("submit", submissionService.getSubmitEvent());
+        } catch (error) {
+            await promptForOpenOutputChannel("提交出错了. 请查看控制台信息~", DialogType.error);
+            return;
+        }
+
+        treeDataService.refresh();
+    }
+
+
+    // 提交测试用例
+    public async testSolution(uri?: vscode.Uri): Promise {
+        try {
+            if (statusBarService.getStatus() === UserStatus.SignedOut) {
+                return;
+            }
+
+            const filePath: string | undefined = await this.getActiveFilePath(uri);
+            if (!filePath) {
+                return;
+            }
+            const picks: Array> = [];
+            picks.push(
+                {
+                    label: "$(three-bars) Default test cases",
+                    description: "",
+                    detail: "默认用例",
+                    value: ":default",
+                },
+                {
+                    label: "$(pencil) Write directly...",
+                    description: "",
+                    detail: "输入框的测试用例",
+                    value: ":direct",
+                },
+                {
+                    label: "$(file-text) Browse...",
+                    description: "",
+                    detail: "文件中的测试用例",
+                    value: ":file",
+                },
+                {
+                    label: "All Default test cases...",
+                    description: "",
+                    detail: "所有的测试用例",
+                    value: ":alldefault",
+                },
+            );
+            const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(picks);
+            if (!choice) {
+                return;
+            }
+
+            let result: string | undefined;
+            let testString: string | undefined;
+            let testFile: vscode.Uri[] | undefined;
+            switch (choice.value) {
+                case ":default":
+                    result = await executeService.testSolution(filePath);
+                    break;
+                case ":direct":
+                    testString = await vscode.window.showInputBox({
+                        prompt: "Enter the test cases.",
+                        validateInput: (s: string): string | undefined => s && s.trim() ? undefined : "Test case must not be empty.",
+                        placeHolder: "Example: [1,2,3]\\n4",
+                        ignoreFocusOut: true,
+                    });
+                    if (testString) {
+                        result = await executeService.testSolution(filePath, this.parseTestString(testString));
+                    }
+                    break;
+                case ":file":
+                    testFile = await this.showFileSelectDialog(filePath);
+                    if (testFile && testFile.length) {
+                        const input: string = (await fse.readFile(testFile[0].fsPath, "utf-8")).trim();
+                        if (input) {
+                            result = await executeService.testSolution(filePath, this.parseTestString(input.replace(/\r?\n/g, "\\n")));
+                        } else {
+                            vscode.window.showErrorMessage("The selected test file must not be empty.");
+                        }
+                    }
+                    break;
+                case ":alldefault":
+                    result = await executeService.testSolution(filePath, undefined, true);
+                    break;
+                default:
+                    break;
+            }
+            if (!result) {
+                return;
+            }
+            submissionService.show(result);
+            eventService.emit("submit", submissionService.getSubmitEvent());
+        } catch (error) {
+            await promptForOpenOutputChannel("提交测试出错了. 请查看控制台信息~", DialogType.error);
+        }
+    }
+    public async showFileSelectDialog(fsPath?: string): Promise {
+        const defaultUri: vscode.Uri | undefined = this.getBelongingWorkspaceFolderUri(fsPath);
+        const options: vscode.OpenDialogOptions = {
+            defaultUri,
+            canSelectFiles: true,
+            canSelectFolders: false,
+            canSelectMany: false,
+            openLabel: "Select",
+        };
+        return await vscode.window.showOpenDialog(options);
+    }
+
+
+    public async testSolutionDefault(uri?: vscode.Uri, allCase?: boolean): Promise {
+        try {
+            if (statusBarService.getStatus() === UserStatus.SignedOut) {
+                return;
+            }
+
+            const filePath: string | undefined = await this.getActiveFilePath(uri);
+            if (!filePath) {
+                return;
+            }
+
+            let result: string | undefined = await executeService.testSolution(filePath, undefined, allCase || false);
+            if (!result) {
+                return;
+            }
+            submissionService.show(result);
+            eventService.emit("submit", submissionService.getSubmitEvent());
+        } catch (error) {
+            await promptForOpenOutputChannel("提交测试出错了. 请查看控制台信息~", DialogType.error);
+        }
+    }
+
+    public usingCmd(): boolean {
+        const comSpec: string | undefined = process.env.ComSpec;
+        // 'cmd.exe' is used as a fallback if process.env.ComSpec is unavailable.
+        if (!comSpec) {
+            return true;
+        }
+
+        if (comSpec.indexOf("cmd.exe") > -1) {
+            return true;
+        }
+        return false;
+    }
+
+    public parseTestString(test: string): string {
+        if (systemUtils.useWsl() || !systemUtils.isWindows()) {
+            if (systemUtils.useVscodeNode()) {
+                return `${test}`;
+            }
+            return `'${test}'`;
+        }
+
+        if (this.usingCmd()) {
+            // 一般需要走进这里, 除非改了 环境变量ComSpec的值
+            if (systemUtils.useVscodeNode()) {
+                //eslint-disable-next-line
+                return `${test.replace(/"/g, '\"')}`;
+            }
+            return `"${test.replace(/"/g, '\\"')}"`;
+        } else {
+            if (systemUtils.useVscodeNode()) {
+                //eslint-disable-next-line
+                return `${test.replace(/"/g, '\"')}`;
+            }
+            return `'${test.replace(/"/g, '\\"')}'`;
+        }
+    }
+
+
+    public async switchEndpoint(): Promise {
+        const isCnEnabled: boolean = getLeetCodeEndpoint() === Endpoint.LeetCodeCN;
+        const picks: Array> = [];
+        picks.push(
+            {
+                label: `${isCnEnabled ? "" : "$(check) "}LeetCode`,
+                description: "leetcode.com",
+                detail: `Enable LeetCode.com US`,
+                value: Endpoint.LeetCode,
+            },
+            {
+                label: `${isCnEnabled ? "$(check) " : ""}力扣`,
+                description: "leetcode.cn",
+                detail: `启用中国版 LeetCode.cn`,
+                value: Endpoint.LeetCodeCN,
+            },
+        );
+        const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(picks);
+        if (!choice || choice.value === getLeetCodeEndpoint()) {
+            return;
+        }
+        const leetCodeConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("leetcode-problem-rating");
+        try {
+            const endpoint: string = choice.value;
+            await executeService.switchEndpoint(endpoint);
+            await leetCodeConfig.update("endpoint", endpoint, true /* UserSetting */);
+            vscode.window.showInformationMessage(`Switched the endpoint to ${endpoint}`);
+        } catch (error) {
+            await promptForOpenOutputChannel("切换站点出错. 请查看控制台信息~", DialogType.error);
+        }
+
+        try {
+            await vscode.commands.executeCommand("leetcode.signout");
+            await executeService.deleteCache();
+            await promptForSignIn();
+        } catch (error) {
+            await promptForOpenOutputChannel("登录失败. 请查看控制台信息~", DialogType.error);
+        }
+    }
+
+
+    public async switchSortingStrategy(): Promise {
+        const currentStrategy: SortingStrategy = getSortingStrategy();
+        const picks: Array> = [];
+        picks.push(
+            ...SORT_ORDER.map((s: SortingStrategy) => {
+                return {
+                    label: `${currentStrategy === s ? "$(check)" : "    "} ${s}`,
+                    value: s,
+                };
+            }),
+        );
+
+        const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(picks);
+        if (!choice || choice.value === currentStrategy) {
+            return;
+        }
+
+        await updateSortingStrategy(choice.value, true);
+        await treeDataService.refresh();
+    }
+
+
+    public async addFavorite(node: NodeModel): Promise {
+        try {
+            await executeService.toggleFavorite(node, true);
+            await treeDataService.refresh();
+            if (isStarShortcut()) {
+                fileButtonService.refresh();
+            }
+        } catch (error) {
+            await promptForOpenOutputChannel("添加喜欢题目失败. 请查看控制台信息~", DialogType.error);
+        }
+    }
+
+    public async removeFavorite(node: NodeModel): Promise {
+        try {
+            await executeService.toggleFavorite(node, false);
+            await treeDataService.refresh();
+            if (isStarShortcut()) {
+                fileButtonService.refresh();
+            }
+        } catch (error) {
+            await promptForOpenOutputChannel("移除喜欢题目失败. 请查看控制台信息~", DialogType.error);
+        }
+    }
+
+    public async listProblems(): Promise {
+        try {
+            if (statusBarService.getStatus() === UserStatus.SignedOut) {
+                return [];
+            }
+
+            const showLockedFlag: boolean = isShowLocked();
+            const useEndpointTranslation: boolean = isUseEndpointTranslation();
+            const result: string = await executeService.listProblems(showLockedFlag, useEndpointTranslation);
+            const all_problem_info = JSON.parse(result);
+            const problems: IProblem[] = [];
+            const AllScoreData = treeDataService.getScoreData();
+            for (const p of all_problem_info) {
+                problems.push({
+                    id: p.fid,
+                    qid: p.id,
+                    isFavorite: p.starred,
+                    locked: p.locked,
+                    state: this.parseProblemState(p.state),
+                    name: p.name,
+                    difficulty: p.level,
+                    passRate: p.percent,
+                    companies: p.companies || [],
+                    tags: treeDataService.getTagsData(p.fid),
+                    scoreData: AllScoreData.get(p.fid),
+                    isSearchResult: false,
+                    input: "",
+                    rootNodeSortId: RootNodeSort.ZERO,
+                    todayData: undefined,
+                });
+            }
+            return problems.reverse();
+        } catch (error) {
+            await promptForOpenOutputChannel("获取题目失败. 请查看控制台信息~", DialogType.error);
+            return [];
+        }
+    }
+
+    public parseProblemState(stateOutput: string): ProblemState {
+        if (!stateOutput) {
+            return ProblemState.Unknown;
+        }
+        switch (stateOutput.trim()) {
+            case "v":
+            case "✔":
+            case "√":
+            case "ac":
+                return ProblemState.AC;
+            case "X":
+            case "✘":
+            case "×":
+            case "notac":
+                return ProblemState.NotAC;
+            default:
+                return ProblemState.Unknown;
+        }
+    }
+
+
+    public async switchDefaultLanguage(): Promise {
+        const leetCodeConfig: WorkspaceConfiguration = workspace.getConfiguration("leetcode-problem-rating");
+        const defaultLanguage: string | undefined = leetCodeConfig.get("defaultLanguage");
+        const languageItems: QuickPickItem[] = [];
+        for (const language of languages) {
+            languageItems.push({
+                label: language,
+                description: defaultLanguage === language ? "Currently used" : undefined,
+            });
+        }
+        // Put the default language at the top of the list
+        languageItems.sort((a: QuickPickItem, b: QuickPickItem) => {
+            if (a.description) {
+                return Number.MIN_SAFE_INTEGER;
+            } else if (b.description) {
+                return Number.MAX_SAFE_INTEGER;
+            }
+            return a.label.localeCompare(b.label);
+        });
+
+        const selectedItem: QuickPickItem | undefined = await window.showQuickPick(languageItems, {
+            placeHolder: "请设置默认语言",
+            ignoreFocusOut: true,
+        });
+
+        if (!selectedItem) {
+            return;
+        }
+
+        leetCodeConfig.update("defaultLanguage", selectedItem.label, true /* Global */);
+        window.showInformationMessage(`设置默认语言 ${selectedItem.label} 成功`);
+    }
+
+
+    public isSubFolder(from: string, to: string): boolean {
+        const relative: string = path.relative(from, to);
+        if (relative === "") {
+            return true;
+        }
+        return !relative.startsWith("..") && !path.isAbsolute(relative);
+    }
+
+    public async determineLeetCodeFolder(): Promise {
+        let result: string;
+        const picks: Array> = [];
+        picks.push(
+            {
+                label: `Default location`,
+                detail: `${path.join(os.homedir(), ".leetcode")}`,
+                value: `${path.join(os.homedir(), ".leetcode")}`,
+            },
+            {
+                label: "$(file-directory) Browse...",
+                value: ":browse",
+            },
+        );
+        const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(
+            picks,
+            { placeHolder: "Select where you would like to save your LeetCode files" },
+        );
+        if (!choice) {
+            result = "";
+        } else if (choice.value === ":browse") {
+            const directory: vscode.Uri[] | undefined = await this.showDirectorySelectDialog();
+            if (!directory || directory.length < 1) {
+                result = "";
+            } else {
+                result = directory[0].fsPath;
+            }
+        } else {
+            result = choice.value;
+        }
+
+        getVsCodeConfig().update("workspaceFolder", result, vscode.ConfigurationTarget.Global);
+
+        return result;
+    }
+
+    public async showDirectorySelectDialog(fsPath?: string): Promise {
+        const defaultUri: vscode.Uri | undefined = this.getBelongingWorkspaceFolderUri(fsPath);
+        const options: vscode.OpenDialogOptions = {
+            defaultUri,
+            canSelectFiles: false,
+            canSelectFolders: true,
+            canSelectMany: false,
+            openLabel: "Select",
+        };
+        return await vscode.window.showOpenDialog(options);
+    }
+
+    public getBelongingWorkspaceFolderUri(fsPath: string | undefined): vscode.Uri | undefined {
+        let defaultUri: vscode.Uri | undefined;
+        if (fsPath) {
+            const workspaceFolder: vscode.WorkspaceFolder | undefined = vscode.workspace.getWorkspaceFolder(vscode.Uri.file(fsPath));
+            if (workspaceFolder) {
+                defaultUri = workspaceFolder.uri;
+            }
+        }
+        return defaultUri;
+    }
+
+
+    public async searchProblem(): Promise {
+        if (!statusBarService.getUser()) {
+            promptForSignIn();
+            return;
+        }
+
+        const picks: Array> = [];
+        picks.push(
+            {
+                label: `题目id查询`,
+                detail: `通过题目id查询`,
+                value: `byid`,
+            },
+            {
+                label: `分数范围查询`,
+                detail: `例如 1500-1600`,
+                value: `range`,
+            },
+            {
+                label: `周赛期数查询`,
+                detail: `周赛期数查询`,
+                value: `contest`,
+            },
+            // {
+            //     label: `测试api`,
+            //     detail: `测试api`,
+            //     value: `testapi`,
+            // }
+            // ,
+            // {
+            //     label: `每日一题`,
+            //     detail: `每日一题`,
+            //     value: `today`,
+            // },
+            // {
+            //     label: `查询自己竞赛信息`,
+            //     detail: `查询自己竞赛信息`,
+            //     value: `userContest`,
+            // }
+        );
+        const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(
+            picks,
+            { title: "选择查询选项" },
+        );
+        if (!choice) {
+            return;
+        }
+        if (choice.value == "byid") {
+            await this.searchProblemByID();
+        } else if (choice.value == "range") {
+            await this.searchScoreRange();
+        } else if (choice.value == "contest") {
+            await this.searchContest();
+        } else if (choice.value == "today") {
+            await this.searchToday();
+        } else if (choice.value == "userContest") {
+            await this.searchUserContest();
+        } else if (choice.value == "testapi") {
+            await this.testapi();
+        }
+
+    }
+
+    public async showSolution(input: NodeModel | vscode.Uri): Promise {
+        let problemInput: string | undefined;
+        if (input instanceof NodeModel) { // Triggerred from explorer
+            problemInput = input.qid;
+        } else if (input instanceof vscode.Uri) { // Triggerred from Code Lens/context menu
+            if (systemUtils.useVscodeNode()) {
+                problemInput = `${input.fsPath}`;
+            } else {
+                problemInput = `"${input.fsPath}"`;
+                if (systemUtils.useWsl()) {
+                    problemInput = await systemUtils.toWslPath(input.fsPath);
+                }
+            }
+        } else if (!input) { // Triggerred from command
+            problemInput = await this.getActiveFilePath();
+        }
+
+        if (!problemInput) {
+            vscode.window.showErrorMessage("Invalid input to fetch the solution data.");
+            return;
+        }
+
+        const language: string | undefined = await this.fetchProblemLanguage();
+        if (!language) {
+            return;
+        }
+        try {
+            const needTranslation: boolean = isUseEndpointTranslation();
+            const solution: string = await executeService.showSolution(problemInput, language, needTranslation);
+            solutionService.show(unescapeJS(solution));
+        } catch (error) {
+            logOutput.appendLine(error.toString());
+            await promptForOpenOutputChannel("Failed to fetch the top voted solution. 请查看控制台信息~", DialogType.error);
+        }
+    }
+
+
+
+    public async testapi(): Promise {
+        if (!statusBarService.getUser()) {
+            promptForSignIn();
+            return;
+        }
+        try {
+            const twoFactor: string | undefined = await vscode.window.showInputBox({
+                prompt: "测试数据",
+                ignoreFocusOut: true,
+                validateInput: (s: string): string | undefined => s && s.trim() ? undefined : "The input must not be empty",
+            });
+
+            // vscode.window.showErrorMessage(twoFactor || "输入错误");
+            const solution: string = await executeService.getTestApi(twoFactor || "");
+            const query_result = JSON.parse(solution);
+            console.log(query_result);
+        } catch (error) {
+            logOutput.appendLine(error.toString());
+            await promptForOpenOutputChannel("Failed to fetch today question. 请查看控制台信息~", DialogType.error);
+        }
+    }
+
+
+    public async searchProblemByID(): Promise {
+        if (!statusBarService.getUser()) {
+            promptForSignIn();
+            return;
+        }
+        const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(
+            this.parseProblemsToPicks(this.listProblems()),
+            {
+                matchOnDetail: true,
+                matchOnDescription: true,
+                placeHolder: "Select one problem",
+            },
+        );
+        if (!choice) {
+            return;
+        }
+        await this.showProblemInternal(choice.value);
+    }
+
+    public async showProblem(node?: NodeModel): Promise {
+        if (!node) {
+            return;
+        }
+        await this.showProblemInternal(node);
+    }
+
+
+    public async pickOne(): Promise {
+        const problems: IProblem[] = await this.listProblems();
+        let randomProblem: IProblem;
+
+        const user_score = statusBarService.getUserContestScore();
+        if (user_score > 0) {
+
+            let min_score: number = getPickOneByRankRangeMin();
+            let max_score: number = getPickOneByRankRangeMax();
+            let temp_problems: IProblem[] = [];
+            const need_min = user_score + min_score;
+            const need_max = user_score + max_score;
+            problems.forEach(element => {
+                if (element.scoreData?.Rating) {
+                    if (element.scoreData.Rating >= need_min && element.scoreData.Rating <= need_max) {
+                        temp_problems.push(element);
+                    }
+                }
+            });
+            randomProblem = temp_problems[Math.floor(Math.random() * temp_problems.length)];
+
+        } else {
+            randomProblem = problems[Math.floor(Math.random() * problems.length)];
+        }
+        if (randomProblem) {
+            await this.showProblemInternal(randomProblem);
+        }
+    }
+
+    public async fetchProblemLanguage(): Promise {
+        const leetCodeConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("leetcode-problem-rating");
+        let defaultLanguage: string | undefined = leetCodeConfig.get("defaultLanguage");
+        if (defaultLanguage && languages.indexOf(defaultLanguage) < 0) {
+            defaultLanguage = undefined;
+        }
+        const language: string | undefined = defaultLanguage || await vscode.window.showQuickPick(languages, { placeHolder: "Select the language you want to use", ignoreFocusOut: true });
+        // fire-and-forget default language query
+        (async (): Promise => {
+            if (language && !defaultLanguage && leetCodeConfig.get("hint.setDefaultLanguage")) {
+                const choice: vscode.MessageItem | undefined = await vscode.window.showInformationMessage(
+                    `Would you like to set '${language}' as your default language?`,
+                    DialogOptions.yes,
+                    DialogOptions.no,
+                    DialogOptions.never,
+                );
+                if (choice === DialogOptions.yes) {
+                    leetCodeConfig.update("defaultLanguage", language, true /* UserSetting */);
+                } else if (choice === DialogOptions.never) {
+                    leetCodeConfig.update("hint.setDefaultLanguage", false, true /* UserSetting */);
+                }
+            }
+        })();
+        return language;
+    }
+
+    public async selectWorkspaceFolder(): Promise {
+        let workspaceFolderSetting: string = getWorkspaceFolder();
+        if (workspaceFolderSetting.trim() === "") {
+            workspaceFolderSetting = await this.determineLeetCodeFolder();
+            if (workspaceFolderSetting === "") {
+                // User cancelled
+                return workspaceFolderSetting;
+            }
+        }
+        let needAsk: boolean = true;
+        await fse.ensureDir(workspaceFolderSetting);
+        for (const folder of vscode.workspace.workspaceFolders || []) {
+            if (this.isSubFolder(folder.uri.fsPath, workspaceFolderSetting)) {
+                needAsk = false;
+            }
+        }
+
+        if (needAsk) {
+            const choice: string | undefined = await vscode.window.showQuickPick(
+                [
+                    OpenOption.justOpenFile,
+                    OpenOption.openInCurrentWindow,
+                    OpenOption.openInNewWindow,
+                    OpenOption.addToWorkspace,
+                ],
+                { placeHolder: "The LeetCode workspace folder is not opened in VS Code, would you like to open it?" },
+            );
+
+            // Todo: generate file first
+            switch (choice) {
+                case OpenOption.justOpenFile:
+                    return workspaceFolderSetting;
+                case OpenOption.openInCurrentWindow:
+                    await vscode.commands.executeCommand("vscode.openFolder", vscode.Uri.file(workspaceFolderSetting), false);
+                    return "";
+                case OpenOption.openInNewWindow:
+                    await vscode.commands.executeCommand("vscode.openFolder", vscode.Uri.file(workspaceFolderSetting), true);
+                    return "";
+                case OpenOption.addToWorkspace:
+                    vscode.workspace.updateWorkspaceFolders(vscode.workspace.workspaceFolders?.length ?? 0, 0, { uri: vscode.Uri.file(workspaceFolderSetting) });
+                    break;
+                default:
+                    return "";
+            }
+        }
+
+        return systemUtils.useWsl() ? systemUtils.toWslPath(workspaceFolderSetting) : workspaceFolderSetting;
+    }
+
+    public async showProblemInternal(node: IProblem): Promise {
+        try {
+            const language: string | undefined = await this.fetchProblemLanguage();
+            if (!language) {
+                return;
+            }
+
+            const leetCodeConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("leetcode-problem-rating");
+            const workspaceFolder: string = await this.selectWorkspaceFolder();
+            if (!workspaceFolder) {
+                return;
+            }
+
+            const fileFolder: string = leetCodeConfig
+                .get(`filePath.${language}.folder`, leetCodeConfig.get(`filePath.default.folder`, ""))
+                .trim();
+            const fileName: string = leetCodeConfig
+                .get(
+                    `filePath.${language}.filename`,
+                    leetCodeConfig.get(`filePath.default.filename`) || genFileName(node, language),
+                )
+                .trim();
+
+            let finalPath: string = path.join(workspaceFolder, fileFolder, fileName);
+
+            if (finalPath) {
+                finalPath = await this.resolveRelativePath(finalPath, node, language);
+                if (!finalPath) {
+                    logOutput.appendLine("Showing problem canceled by user.");
+                    return;
+                }
+            }
+
+            finalPath = systemUtils.useWsl() ? await systemUtils.toWinPath(finalPath) : finalPath;
+
+            const descriptionConfig: IDescriptionConfiguration = getDescriptionConfiguration();
+            const needTranslation: boolean = isUseEndpointTranslation();
+
+            await executeService.showProblem(node, language, finalPath, descriptionConfig.showInComment, needTranslation);
+            const promises: any[] = [
+                vscode.window.showTextDocument(vscode.Uri.file(finalPath), { preview: false, viewColumn: vscode.ViewColumn.One }),
+                promptHintMessage(
+                    "hint.commentDescription",
+                    'You can config how to show the problem description through "leetcode-problem-rating.showDescription".',
+                    "Open settings",
+                    (): Promise => openSettingsEditor("leetcode-problem-rating.showDescription"),
+                ),
+            ];
+            if (descriptionConfig.showInWebview) {
+                promises.push(this.showDescriptionView(node));
+            }
+
+            await Promise.all(promises);
+        } catch (error) {
+            await promptForOpenOutputChannel(`${error} 请查看控制台信息~`, DialogType.error);
+        }
+    }
+
+    public async showDescriptionView(node: IProblem): Promise {
+        return this.previewProblem(node, enableSideMode());
+    }
+
+    public async previewProblem(input: IProblem | Uri, isSideMode: boolean = false): Promise {
+        let node: IProblem;
+        if (input instanceof Uri) {
+            const activeFilePath: string = input.fsPath;
+            const id: string = await getNodeIdFromFile(activeFilePath);
+            if (!id) {
+                window.showErrorMessage(`Failed to resolve the problem id from file: ${activeFilePath}.`);
+                return;
+            }
+            const cachedNode: IProblem | undefined = treeViewController.getNodeById(id);
+            if (!cachedNode) {
+                window.showErrorMessage(`Failed to resolve the problem with id: ${id}.`);
+                return;
+            }
+            node = cachedNode;
+            // Move the preview page aside if it's triggered from Code Lens
+            isSideMode = true;
+        } else {
+            node = input;
+        }
+        const needTranslation: boolean = isUseEndpointTranslation();
+        const descString: string = await executeService.getDescription(node.qid, needTranslation);
+        previewService.show(descString, node, isSideMode);
+    }
+
+
+    public async searchScoreRange(): Promise {
+        const twoFactor: string | undefined = await vscode.window.showInputBox({
+            prompt: "输入分数范围 低分-高分 例如: 1500-1600",
+            ignoreFocusOut: true,
+            validateInput: (s: string): string | undefined => s && s.trim() ? undefined : "The input must not be empty",
+        });
+
+        // vscode.window.showErrorMessage(twoFactor || "输入错误");
+        const tt = Object.assign({}, SearchNode, {
+            value: twoFactor,
+            type: SearchSetType.ScoreRange,
+            time: Math.floor(Date.now() / 1000)
+        });
+        treeViewController.insertSearchSet(tt);
+        await treeDataService.refresh();
+    }
+
+    public async searchContest(): Promise {
+        const twoFactor: string | undefined = await vscode.window.showInputBox({
+            prompt: "单期数 例如: 300 或者 输入期数范围 低期数-高期数 例如: 303-306",
+            ignoreFocusOut: true,
+            validateInput: (s: string): string | undefined => s && s.trim() ? undefined : "The input must not be empty",
+        });
+
+        // vscode.window.showErrorMessage(twoFactor || "输入错误");
+        const tt = Object.assign({}, SearchNode, {
+            value: twoFactor,
+            type: SearchSetType.Context,
+            time: Math.floor(Date.now() / 1000)
+        });
+        treeViewController.insertSearchSet(tt);
+        await treeDataService.refresh();
+    }
+
+
+
+    public async searchUserContest(): Promise {
+        if (!statusBarService.getUser()) {
+            promptForSignIn();
+            return;
+        }
+        try {
+            const needTranslation: boolean = isUseEndpointTranslation();
+            const solution: string = await executeService.getUserContest(needTranslation, statusBarService.getUser() || "");
+            const query_result = JSON.parse(solution);
+            const tt: userContestRanKingBase = Object.assign({}, userContestRankingObj, query_result.userContestRanking);
+            eventService.emit("searchUserContest", tt);
+        } catch (error) {
+            logOutput.appendLine(error.toString());
+            await promptForOpenOutputChannel("Failed to fetch today question. 请查看控制台信息~", DialogType.error);
+        }
+    }
+    public async searchToday(): Promise {
+        if (!statusBarService.getUser()) {
+            promptForSignIn();
+            return;
+        }
+        try {
+            const needTranslation: boolean = isUseEndpointTranslation();
+            const solution: string = await executeService.getTodayQuestion(needTranslation);
+            const query_result = JSON.parse(solution);
+            // const titleSlug: string = query_result.titleSlug
+            // const questionId: string = query_result.questionId
+            const fid: string = query_result.fid;
+            if (fid) {
+                const tt = Object.assign({}, SearchNode, {
+                    value: fid,
+                    type: SearchSetType.Day,
+                    time: Math.floor(Date.now() / 1000),
+                    todayData: query_result,
+                });
+                treeViewController.insertSearchSet(tt);
+                await treeDataService.refresh();
+            }
+
+        } catch (error) {
+            logOutput.appendLine(error.toString());
+            await promptForOpenOutputChannel("Failed to fetch today question. 请查看控制台信息~", DialogType.error);
+        }
+    }
+
+
+
+
+    public async parseProblemsToPicks(p: Promise): Promise>> {
+        return new Promise(async (resolve: (res: Array>) => void): Promise => {
+            const picks: Array> = (await p).map((problem: IProblem) => Object.assign({}, {
+                label: `${this.parseProblemDecorator(problem.state, problem.locked)}${problem.id}.${problem.name}`,
+                description: `QID:${problem.qid}`,
+                detail: ((problem.scoreData?.score || "0") > "0" ? ("score: " + problem.scoreData?.score + " , ") : "") + `AC rate: ${problem.passRate}, Difficulty: ${problem.difficulty}`,
+                value: problem,
+            }));
+            resolve(picks);
+        });
+    }
+
+    public parseProblemDecorator(state: ProblemState, locked: boolean): string {
+        switch (state) {
+            case ProblemState.AC:
+                return "$(check) ";
+            case ProblemState.NotAC:
+                return "$(x) ";
+            default:
+                return locked ? "$(lock) " : "";
+        }
+    }
+
+    public async resolveRelativePath(relativePath: string, node: IProblem, selectedLanguage: string): Promise {
+        let tag: string = "";
+        if (/\$\{ tag \} /i.test(relativePath)) {
+            tag = (await this.resolveTagForProblem(node)) || "";
+        }
+
+        let company: string = "";
+        if (/\$\{company\}/i.test(relativePath)) {
+            company = (await this.resolveCompanyForProblem(node)) || "";
+        }
+
+        let errorMsg: string;
+        return relativePath.replace(/\$\{(.*?)\}/g, (_substring: string, ...args: string[]) => {
+            const placeholder: string = args[0].toLowerCase().trim();
+            switch (placeholder) {
+                case "id":
+                    return node.id;
+                case "name":
+                    return node.name;
+                case "camelcasename":
+                    return lodash.camelCase(node.name);
+                case "pascalcasename":
+                    return lodash.upperFirst(lodash.camelCase(node.name));
+                case "kebabcasename":
+                case "kebab-case-name":
+                    return lodash.kebabCase(node.name);
+                case "snakecasename":
+                case "snake_case_name":
+                    return lodash.snakeCase(node.name);
+                case "ext":
+                    return genFileExt(selectedLanguage);
+                case "language":
+                    return selectedLanguage;
+                case "difficulty":
+                    return node.difficulty.toLocaleLowerCase();
+                case "tag":
+                    return tag;
+                case "company":
+                    return company;
+                default:
+                    errorMsg = `The config '${placeholder}' is not supported.`;
+                    logOutput.appendLine(errorMsg);
+                    throw new Error(errorMsg);
+            }
+        });
+    }
+
+    public async resolveTagForProblem(problem: IProblem): Promise {
+        if (problem.tags.length === 1) {
+            return problem.tags[0];
+        }
+        return await vscode.window.showQuickPick(
+            problem.tags,
+            {
+                matchOnDetail: true,
+                placeHolder: "Multiple tags available, please select one",
+                ignoreFocusOut: true,
+            },
+        );
+    }
+
+    public async resolveCompanyForProblem(problem: IProblem): Promise {
+        if (problem.companies.length === 1) {
+            return problem.companies[0];
+        }
+        return await vscode.window.showQuickPick(problem.companies, {
+            matchOnDetail: true,
+            placeHolder: "Multiple tags available, please select one",
+            ignoreFocusOut: true,
+        });
+    }
+
+
+    public insertSearchSet(tt: ISearchSet) {
+        this.searchSet.set(tt.value, tt);
+    }
+    public clearUserScore() {
+        this.waitUserContest = false;
+        this.waitTodayQuestion = false;
+        this.searchSet = new Map();
+    }
+
+    public checkSubmit(e: ISubmitEvent) {
+        if (e.sub_type == "submit" && e.accepted) {
+            const day_start = new Date(new Date().setHours(0, 0, 0, 0)).getTime() / 1000; //获取当天零点的时间
+            const day_end = new Date(new Date().setHours(0, 0, 0, 0) + 24 * 60 * 60 * 1000 - 1).getTime() / 1000; //获取当天23:59:59的时间
+            let need_get_today: boolean = false;
+            this.searchSet.forEach(element => {
+                if (element.type == SearchSetType.Day) {
+                    if (day_start <= element.time && element.time <= day_end) {
+                        if (e.fid == element.value) {
+                            need_get_today = true;
+                        }
+                    }
+                }
+            });
+            if (need_get_today) {
+                this.searchToday();
+            }
+        }
+    }
+
+    public async refreshCheck(): Promise {
+        if (!statusBarService.getUser()) {
+            return;
+        }
+        const day_start = new Date(new Date().setHours(0, 0, 0, 0)).getTime() / 1000; //获取当天零点的时间
+        const day_end = new Date(new Date().setHours(0, 0, 0, 0) + 24 * 60 * 60 * 1000 - 1).getTime() / 1000; //获取当天23:59:59的时间
+        let need_get_today: boolean = true;
+        this.searchSet.forEach(element => {
+            if (element.type == SearchSetType.Day) {
+                if (day_start <= element.time && element.time <= day_end) {
+                    need_get_today = false;
+                } else {
+                    this.waitTodayQuestion = false;
+                }
+            }
+        });
+        if (need_get_today && !this.waitTodayQuestion) {
+            this.waitTodayQuestion = true;
+            await this.searchToday();
+        }
+        let user_score = statusBarService.getUserContestScore();
+        if (!user_score && !this.waitUserContest) {
+            this.waitUserContest = true;
+            await this.searchUserContest();
+        }
+    }
+
+    public async refreshCache(): Promise {
+        const temp_searchSet: Map = this.searchSet;
+        const temp_waitTodayQuestion: boolean = this.waitTodayQuestion;
+        const temp_waitUserContest: boolean = this.waitUserContest;
+        this.dispose();
+        let user_score = statusBarService.getUserContestScore();
+        for (const problem of await this.listProblems()) {
+            this.explorerNodeMap.set(problem.id, new NodeModel(problem, true, user_score));
+            for (const company of problem.companies) {
+                this.companySet.add(company);
+            }
+            for (const tag of problem.tags) {
+                this.tagSet.add(tag);
+            }
+        }
+        this.searchSet = temp_searchSet;
+        this.waitTodayQuestion = temp_waitTodayQuestion;
+        this.waitUserContest = temp_waitUserContest;
+    }
+
+    public getRootNodes(): NodeModel[] {
+        let user_score = statusBarService.getUserContestScore();
+        const baseNode: NodeModel[] = [
+            new NodeModel(Object.assign({}, defaultProblem, {
+                id: Category.All,
+                name: Category.All,
+                rootNodeSortId: RootNodeSort.All,
+            }), false),
+            new NodeModel(Object.assign({}, defaultProblem, {
+                id: Category.Difficulty,
+                name: Category.Difficulty,
+                rootNodeSortId: RootNodeSort.Difficulty,
+            }), false),
+            new NodeModel(Object.assign({}, defaultProblem, {
+                id: Category.Tag,
+                name: Category.Tag,
+                rootNodeSortId: RootNodeSort.Tag,
+            }), false),
+            // new NodeModel(Object.assign({}, defaultProblem, {
+            //     id: Category.Company,
+            //     name: Category.Company,
+            //     rootNodeSortId: RootNodeSort.Company,
+            // }), false),
+            new NodeModel(Object.assign({}, defaultProblem, {
+                id: Category.Favorite,
+                name: Category.Favorite,
+                rootNodeSortId: RootNodeSort.Favorite,
+            }), false),
+            new NodeModel(Object.assign({}, defaultProblem, {
+                id: Category.Score,
+                name: Category.Score,
+                rootNodeSortId: RootNodeSort.Score,
+            }), false, user_score),
+            new NodeModel(Object.assign({}, defaultProblem, {
+                id: Category.Choice,
+                name: Category.Choice,
+                rootNodeSortId: RootNodeSort.Choice,
+            }), false),
+        ];
+        this.searchSet.forEach(element => {
+            if (element.type == SearchSetType.Day) {
+                const curDate = new Date(element.time * 1000);
+                baseNode.push(new NodeModel(Object.assign({}, defaultProblem, {
+                    id: element.type,
+                    name: "[" + (curDate.getFullYear()) + "-" + (curDate.getMonth() + 1) + "-" + (curDate.getDate()) + "]" + SearchSetTypeName[SearchSetType.Day],
+                    input: element.value,
+                    isSearchResult: true,
+                    rootNodeSortId: RootNodeSort[element.type],
+                    todayData: element.todayData
+                }), false));
+            } else {
+                baseNode.push(new NodeModel(Object.assign({}, defaultProblem, {
+                    id: element.type,
+                    name: SearchSetTypeName[element.type] + element.value,
+                    input: element.value,
+                    isSearchResult: true,
+                    rootNodeSortId: RootNodeSort[element.type],
+                }), false));
+            }
+        });
+        baseNode.sort(function (a: NodeModel, b: NodeModel): number {
+            if (a.rootNodeSortId < b.rootNodeSortId) {
+                return -1;
+            } else if (a.rootNodeSortId > b.rootNodeSortId) {
+                return 1;
+            }
+            return 0;
+        });
+        return baseNode;
+    }
+
+    public getScoreRangeNodes(rank_range: string): NodeModel[] {
+        const sorceNode: NodeModel[] = [];
+        const rank_r: Array = rank_range.split("-");
+        let rank_a = Number(rank_r[0]);
+        let rank_b = Number(rank_r[1]);
+        if (rank_a > 0 && rank_b > 0) {
+            if (rank_a > rank_b) {
+                const rank_c: number = rank_a;
+                rank_a = rank_b;
+                rank_b = rank_c;
+            }
+
+            this.explorerNodeMap.forEach(element => {
+                if (!this.canShow(element)) {
+                    return;
+                }
+                if (rank_a <= Number(element.score) && Number(element.score) <= rank_b) {
+                    sorceNode.push(element);
+                }
+            });
+        }
+        return this.applySortingStrategy(sorceNode);
+    }
+
+    public canShow(element: NodeModel) {
+        if (isHideSolvedProblem() && element.state === ProblemState.AC) {
+            return false;
+        }
+        if (isHideScoreProblem(element, element.user_score)) {
+            return false;
+        }
+        return true;
+    }
+
+    public getContextNodes(rank_range: string): NodeModel[] {
+        const sorceNode: NodeModel[] = [];
+        const rank_r: Array = rank_range.split("-");
+        let rank_a = Number(rank_r[0]);
+        let rank_b = Number(rank_r[1]);
+        if (rank_a > 0) {
+            this.explorerNodeMap.forEach(element => {
+                if (!this.canShow(element)) {
+                    return;
+                }
+                const slu = element.ContestSlug;
+                const slu_arr: Array = slu.split("-");
+                const slu_id = Number(slu_arr[slu_arr.length - 1]);
+                if (rank_b > 0 && rank_a <= slu_id && slu_id <= rank_b) {
+                    sorceNode.push(element);
+                } else if (rank_a == slu_id) {
+                    sorceNode.push(element);
+                }
+            });
+        }
+        return this.applySortingStrategy(sorceNode);
+    }
+    public getDayNodes(element: NodeModel | undefined): NodeModel[] {
+        const rank_range: string = element?.input || "";
+        const sorceNode: NodeModel[] = [];
+        if (rank_range) {
+            this.explorerNodeMap.forEach(new_node => {
+                if (new_node.id == rank_range) {
+                    new_node.todayData = element?.todayData;
+                    sorceNode.push(new_node);
+                }
+            });
+        }
+        return this.applySortingStrategy(sorceNode);
+    }
+
+    public getAllNodes(): NodeModel[] {
+        return this.applySortingStrategy(
+            Array.from(this.explorerNodeMap.values()).filter(p => this.canShow(p)),
+        );
+    }
+
+    public getAllDifficultyNodes(): NodeModel[] {
+        const res: NodeModel[] = [];
+        res.push(
+            new NodeModel(Object.assign({}, defaultProblem, {
+                id: `${Category.Difficulty}.Easy`,
+                name: "Easy",
+            }), false),
+            new NodeModel(Object.assign({}, defaultProblem, {
+                id: `${Category.Difficulty}.Medium`,
+                name: "Medium",
+            }), false),
+            new NodeModel(Object.assign({}, defaultProblem, {
+                id: `${Category.Difficulty}.Hard`,
+                name: "Hard",
+            }), false),
+        );
+        this.sortSubCategoryNodes(res, Category.Difficulty);
+        return res;
+    }
+
+    public getAllScoreNodes(user_score: number): NodeModel[] {
+        const res: NodeModel[] = [];
+        const score_array: Array = ["3300", "3200", "3100", "3000", "2900", "2800", "2700", "2600", "2500", "2400", "2300", "2200", "2100", "2000", "1900", "1800", "1700", "1600", "1500", "1400", "1300", "1200", "1100"];
+        score_array.forEach(element => {
+            const temp_num = Number(element);
+            const diff = Math.abs(temp_num - user_score);
+            if (diff <= 200) {
+                res.push(new NodeModel(Object.assign({}, defaultProblem, {
+                    id: `${Category.Score}.${element}`,
+                    name: `${element}`,
+                }), false, user_score));
+            }
+        });
+
+        this.sortSubCategoryNodes(res, Category.Score);
+        return res;
+    }
+
+    public getAllChoiceNodes(): NodeModel[] {
+        const res: NodeModel[] = [];
+
+        const all_choice = treeDataService.getChoiceData();
+        all_choice.forEach(element => {
+            res.push(new NodeModel(Object.assign({}, defaultProblem, {
+                id: `${Category.Choice}.${element.id}`,
+                name: `${element.name}`,
+            }), false));
+        });
+        this.sortSubCategoryNodes(res, Category.Choice);
+        return res;
+    }
+
+    public getAllCompanyNodes(): NodeModel[] {
+        const res: NodeModel[] = [];
+        for (const company of this.companySet.values()) {
+            res.push(new NodeModel(Object.assign({}, defaultProblem, {
+                id: `${Category.Company}.${company}`,
+                name: lodash.startCase(company),
+            }), false));
+        }
+        this.sortSubCategoryNodes(res, Category.Company);
+        return res;
+    }
+
+    public getAllTagNodes(): NodeModel[] {
+        const res: NodeModel[] = [];
+        for (const tag of this.tagSet.values()) {
+            res.push(new NodeModel(Object.assign({}, defaultProblem, {
+                id: `${Category.Tag}.${tag}`,
+                name: lodash.startCase(tag),
+            }), false));
+        }
+        this.sortSubCategoryNodes(res, Category.Tag);
+        return res;
+    }
+
+    public getNodeById(id: string): NodeModel | undefined {
+        return this.explorerNodeMap.get(id);
+    }
+
+    public getFavoriteNodes(): NodeModel[] {
+        const res: NodeModel[] = [];
+        for (const node of this.explorerNodeMap.values()) {
+            if (!this.canShow(node)) {
+                continue;
+            }
+            if (node.isFavorite) {
+                res.push(node);
+            }
+        }
+        return this.applySortingStrategy(res);
+    }
+
+    public getChildrenNodesById(id: string): NodeModel[] {
+        // The sub-category node's id is named as {Category.SubName}
+        const metaInfo: string[] = id.split(".");
+        const res: NodeModel[] = [];
+
+        const choiceQuestionId: Map = new Map();
+        if (metaInfo[0] == Category.Choice) {
+            const all_choice = treeDataService.getChoiceData();
+            all_choice.forEach(element => {
+                if (element.id == metaInfo[1]) {
+                    element.questions.forEach(kk => {
+                        choiceQuestionId[kk] = true;
+                    });
+                    return;
+                }
+            });
+        }
+
+        for (const node of this.explorerNodeMap.values()) {
+            if (!this.canShow(node)) {
+                continue;
+            }
+            switch (metaInfo[0]) {
+                case Category.Company:
+                    if (node.companies.indexOf(metaInfo[1]) >= 0) {
+                        res.push(node);
+                    }
+                    break;
+                case Category.Difficulty:
+                    if (node.difficulty === metaInfo[1]) {
+                        res.push(node);
+                    }
+                    break;
+                case Category.Tag:
+                    if (node.tags.indexOf(metaInfo[1]) >= 0) {
+                        res.push(node);
+                    }
+                    break;
+                case Category.Score:
+                    if (node.score > "0") {
+                        const check_rank = toNumber(metaInfo[1]);
+                        const node_rank = toNumber(node.score);
+                        if (check_rank <= node_rank && node_rank < check_rank + 100) {
+                            res.push(node);
+                        }
+                    }
+                    break;
+                case Category.Choice:
+                    if (choiceQuestionId[Number(node.qid)]) {
+                        res.push(node);
+                    }
+            }
+        }
+        return this.applySortingStrategy(res);
+    }
+
+    public dispose(): void {
+        this.explorerNodeMap.clear();
+        this.companySet.clear();
+        this.tagSet.clear();
+    }
+
+    private sortSubCategoryNodes(subCategoryNodes: NodeModel[], category: Category): void {
+        switch (category) {
+            case Category.Difficulty:
+                subCategoryNodes.sort((a: NodeModel, b: NodeModel): number => {
+                    function getValue(input: NodeModel): number {
+                        switch (input.name.toLowerCase()) {
+                            case "easy":
+                                return 1;
+                            case "medium":
+                                return 2;
+                            case "hard":
+                                return 3;
+                            default:
+                                return Number.MAX_SAFE_INTEGER;
+                        }
+                    }
+                    return getValue(a) - getValue(b);
+                });
+                break;
+            case Category.Tag:
+            case Category.Company:
+                subCategoryNodes.sort((a: NodeModel, b: NodeModel): number => {
+                    if (a.name === "Unknown") {
+                        return 1;
+                    } else if (b.name === "Unknown") {
+                        return -1;
+                    } else {
+                        return Number(a.name > b.name) - Number(a.name < b.name);
+                    }
+                });
+                break;
+            default:
+                break;
+        }
+    }
+
+    private applySortingStrategy(nodes: NodeModel[]): NodeModel[] {
+        const strategy: SortingStrategy = getSortingStrategy();
+        switch (strategy) {
+            case SortingStrategy.AcceptanceRateAsc: return nodes.sort((x: NodeModel, y: NodeModel) => Number(x.acceptanceRate) - Number(y.acceptanceRate));
+            case SortingStrategy.AcceptanceRateDesc: return nodes.sort((x: NodeModel, y: NodeModel) => Number(y.acceptanceRate) - Number(x.acceptanceRate));
+            case SortingStrategy.ScoreAsc: return nodes.sort((x: NodeModel, y: NodeModel) => Number(x.score) - Number(y.score));
+            case SortingStrategy.ScoreDesc: return nodes.sort((x: NodeModel, y: NodeModel) => Number(y.score) - Number(x.score));
+            case SortingStrategy.IDDesc: return nodes.sort((x: NodeModel, y: NodeModel) => Number(y.id) - Number(x.id));
+            default: return nodes;
+        }
+    }
+}
+
+export const treeViewController: TreeViewController = new TreeViewController();
diff --git a/src/dao/choiceDao.ts b/src/dao/choiceDao.ts
new file mode 100644
index 0000000..ec3bba4
--- /dev/null
+++ b/src/dao/choiceDao.ts
@@ -0,0 +1,2095 @@
+/*
+ * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/dao/choiceDao.ts
+ * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
+ * Created Date: Thursday, November 10th 2022, 11:34:10 pm
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
+
+class ChoiceDao {
+
+    public getChoiceData() {
+        return this.choiceData;
+    }
+
+    private choiceData = [
+        {
+            "id": "shopee",
+            "name": "Shopee精选",
+            "questions": [
+                341,
+                1000447,
+                1000446,
+                1000445,
+                1000444,
+                1000443,
+                232,
+                871,
+                102,
+                101,
+                15,
+                460,
+                456,
+                448,
+                179,
+                432,
+                48,
+                37,
+                20,
+                146
+            ],
+
+        },
+        {
+            "id": "binary-search",
+            "name": "二分查找",
+            "questions": [
+                4,
+                1550,
+                540,
+                1056,
+                33,
+                34,
+                35,
+                1059,
+                1060,
+                1083,
+                2047,
+                69,
+                1605,
+                74,
+                1612,
+                1102,
+                1615,
+                81,
+                1621,
+                1122,
+                611,
+                1645,
+                1134,
+                1646,
+                1143,
+                633,
+                1149,
+                644,
+                1672,
+                1675,
+                1679,
+                658,
+                1684,
+                153,
+                154,
+                668,
+                1185,
+                162,
+                167,
+                1192,
+                1730,
+                718,
+                719,
+                1232,
+                209,
+                1753,
+                222,
+                1249,
+                1766,
+                745,
+                1771,
+                1262,
+                240,
+                1290,
+                270,
+                786,
+                275,
+                788,
+                278,
+                792,
+                794,
+                1307,
+                287,
+                802,
+                1831,
+                1832,
+                809,
+                300,
+                302,
+                1326,
+                1851,
+                1352,
+                853,
+                350,
+                1374,
+                352,
+                1886,
+                1891,
+                1384,
+                363,
+                367,
+                882,
+                374,
+                378,
+                894,
+                1918,
+                1408,
+                1413,
+                1929,
+                907,
+                912,
+                1946,
+                923,
+                1957,
+                1966,
+                947,
+                436,
+                1463,
+                441,
+                1468,
+                1984,
+                1476,
+                1486,
+                2000,
+                2006,
+                2018,
+                2027,
+                2036,
+                2045,
+                1023
+            ],
+
+        },
+        {
+            "id": "lcof",
+            "name": "剑指 Offer",
+            "questions": [
+                1000228,
+                1000229,
+                1000230,
+                1000231,
+                1000232,
+                1000233,
+                1000234,
+                1000235,
+                1000236,
+                1000237,
+                1000238,
+                1000239,
+                1000240,
+                1000241,
+                1000242,
+                1000243,
+                1000244,
+                1000245,
+                1000246,
+                1000247,
+                1000248,
+                1000249,
+                1000250,
+                1000251,
+                1000252,
+                1000253,
+                1000254,
+                1000255,
+                1000256,
+                1000257,
+                1000258,
+                1000259,
+                1000260,
+                1000261,
+                1000262,
+                1000263,
+                1000264,
+                1000265,
+                1000266,
+                1000267,
+                1000268,
+                1000269,
+                1000270,
+                1000271,
+                1000272,
+                1000273,
+                1000274,
+                1000275,
+                1000276,
+                1000277,
+                1000278,
+                1000279,
+                1000280,
+                1000281,
+                1000282,
+                1000283,
+                1000284,
+                1000285,
+                1000286,
+                1000287,
+                1000288,
+                1000289,
+                1000290,
+                1000291,
+                1000292,
+                1000293,
+                1000294,
+                1000295,
+                1000296,
+                1000297,
+                1000298,
+                1000299,
+                1000300,
+                1000301,
+                1000302,
+                1000303,
+                1000304,
+                1000305,
+                1000306,
+                1000307,
+                1000308,
+                1000309,
+                1000310,
+                1000311,
+                1000312,
+                1000313,
+                1000314,
+                1000315,
+                1000316,
+                1000317,
+                1000318,
+                1000319,
+                1000320,
+                1000321,
+                1000322,
+                1000323,
+                1000324,
+                1000325,
+                1000326,
+                1000327,
+                1000328,
+                1000329,
+                1000330,
+                1000331,
+                1000332,
+                1000333,
+                1000334,
+                1000335,
+                1000336,
+                1000337,
+                1000338,
+                1000339,
+                1000340,
+                1000341,
+                1000342,
+                1000343,
+                1000344,
+                1000345,
+                1000346,
+                100273,
+                100274,
+                100275,
+                100276,
+                100277,
+                100278,
+                100279,
+                100280,
+                100281,
+                100282,
+                100283,
+                100284,
+                100285,
+                100286,
+                100287,
+                100288,
+                100289,
+                100290,
+                100291,
+                100292,
+                100293,
+                100294,
+                100295,
+                100296,
+                100297,
+                100298,
+                100299,
+                100300,
+                100301,
+                100302,
+                100303,
+                100304,
+                100305,
+                100306,
+                100307,
+                100308,
+                100309,
+                100310,
+                100311,
+                100312,
+                100313,
+                100314,
+                100315,
+                100316,
+                100317,
+                100318,
+                100319,
+                100320,
+                100321,
+                100322,
+                100323,
+                100324,
+                100325,
+                100326,
+                100327,
+                100328,
+                100329,
+                100330,
+                100331,
+                100332,
+                100333,
+                100334,
+                100335,
+                100336,
+                100337,
+                100338,
+                100339,
+                100340,
+                100341,
+                100342,
+                100343,
+                100344,
+                100345,
+                100346,
+                100347
+            ],
+
+        },
+        {
+            "id": "e8X3pBZi",
+            "name": "剑指 Offer(专项突击版)",
+            "questions": [
+                1000228,
+                1000229,
+                1000230,
+                1000231,
+                1000232,
+                1000233,
+                1000234,
+                1000235,
+                1000236,
+                1000237,
+                1000238,
+                1000239,
+                1000240,
+                1000241,
+                1000242,
+                1000243,
+                1000244,
+                1000245,
+                1000246,
+                1000247,
+                1000248,
+                1000249,
+                1000250,
+                1000251,
+                1000252,
+                1000253,
+                1000254,
+                1000255,
+                1000256,
+                1000257,
+                1000258,
+                1000259,
+                1000260,
+                1000261,
+                1000262,
+                1000263,
+                1000264,
+                1000265,
+                1000266,
+                1000267,
+                1000268,
+                1000269,
+                1000270,
+                1000271,
+                1000272,
+                1000273,
+                1000274,
+                1000275,
+                1000276,
+                1000277,
+                1000278,
+                1000279,
+                1000280,
+                1000281,
+                1000282,
+                1000283,
+                1000284,
+                1000285,
+                1000286,
+                1000287,
+                1000288,
+                1000289,
+                1000290,
+                1000291,
+                1000292,
+                1000293,
+                1000294,
+                1000295,
+                1000296,
+                1000297,
+                1000298,
+                1000299,
+                1000300,
+                1000301,
+                1000302,
+                1000303,
+                1000304,
+                1000305,
+                1000306,
+                1000307,
+                1000308,
+                1000309,
+                1000310,
+                1000311,
+                1000312,
+                1000313,
+                1000314,
+                1000315,
+                1000316,
+                1000317,
+                1000318,
+                1000319,
+                1000320,
+                1000321,
+                1000322,
+                1000323,
+                1000324,
+                1000325,
+                1000326,
+                1000327,
+                1000328,
+                1000329,
+                1000330,
+                1000331,
+                1000332,
+                1000333,
+                1000334,
+                1000335,
+                1000336,
+                1000337,
+                1000338,
+                1000339,
+                1000340,
+                1000341,
+                1000342,
+                1000343,
+                1000344,
+                1000345,
+                1000346
+            ],
+
+        },
+        {
+            "id": "xb9nqhhg",
+            "name": "剑指 Offer(第 2 版)",
+            "questions": [
+                100319,
+                100328,
+                100327,
+                100326,
+                100325,
+                100324,
+                100323,
+                100322,
+                100321,
+                100320,
+                100329,
+                100318,
+                100317,
+                100316,
+                100315,
+                100314,
+                100313,
+                100312,
+                100311,
+                100338,
+                100347,
+                100346,
+                100345,
+                100344,
+                100343,
+                100342,
+                100341,
+                100340,
+                100339,
+                100310,
+                100337,
+                100336,
+                100335,
+                100334,
+                100333,
+                100332,
+                100331,
+                100330,
+                100282,
+                100291,
+                100290,
+                100289,
+                100288,
+                100287,
+                100286,
+                100285,
+                100284,
+                100283,
+                100292,
+                100281,
+                100280,
+                100279,
+                100278,
+                100277,
+                100276,
+                100275,
+                100274,
+                100301,
+                100309,
+                100308,
+                100307,
+                100306,
+                100305,
+                100304,
+                100303,
+                100302,
+                100273,
+                100300,
+                100299,
+                100298,
+                100297,
+                100296,
+                100295,
+                100294,
+                100293
+            ],
+
+        },
+        {
+            "id": "lccup",
+            "name": "力扣杯竞赛真题集",
+            "questions": [
+                1000134,
+                1000222,
+                1000362,
+                1000367,
+                1000368,
+                1000369,
+                1000370,
+                1000371,
+                1000373,
+                1000374,
+                1000375,
+                1000130,
+                1000131,
+                1000132,
+                1000133,
+                100094,
+                1000138,
+                1000139,
+                1000140,
+                1000146,
+                1000147,
+                1000056,
+                1000057,
+                1000058,
+                1000059,
+                100092,
+                100093,
+                1000062,
+                1000063,
+                1000218,
+                100107,
+                1000085,
+                1000086,
+                1000087,
+                1000088,
+                1000089,
+                1000090,
+                1000091,
+                1052,
+                1053,
+                1000093,
+                1000215,
+                1000216,
+                100096,
+                1058,
+                1059,
+                1060,
+                1061,
+                1000219,
+                1000220,
+                1000223,
+                1000224,
+                1000221,
+                1000359,
+                1000361,
+                813,
+                1069
+            ],
+
+        },
+        {
+            "id": "dynamic-programming",
+            "name": "动态规划",
+            "questions": [
+                1025,
+                514,
+                516,
+                5,
+                518,
+                10,
+                526,
+                1042,
+                1559,
+                1051,
+                32,
+                1057,
+                546,
+                1571,
+                1060,
+                549,
+                39,
+                40,
+                1063,
+                42,
+                1067,
+                1068,
+                45,
+                1583,
+                562,
+                53,
+                55,
+                568,
+                62,
+                63,
+                64,
+                576,
+                70,
+                72,
+                1105,
+                1617,
+                600,
+                91,
+                96,
+                1129,
+                1130,
+                1134,
+                115,
+                118,
+                119,
+                120,
+                121,
+                122,
+                123,
+                124,
+                634,
+                1669,
+                646,
+                647,
+                650,
+                139,
+                140,
+                651,
+                1166,
+                1680,
+                1170,
+                152,
+                664,
+                1178,
+                1690,
+                673,
+                1196,
+                174,
+                688,
+                1201,
+                1202,
+                691,
+                698,
+                188,
+                1213,
+                1220,
+                198,
+                712,
+                714,
+                1228,
+                1744,
+                1236,
+                213,
+                727,
+                1240,
+                1242,
+                221,
+                1758,
+                1250,
+                740,
+                741,
+                747,
+                238,
+                751,
+                1263,
+                1789,
+                254,
+                256,
+                1286,
+                264,
+                265,
+                1296,
+                279,
+                1822,
+                1828,
+                294,
+                298,
+                300,
+                304,
+                309,
+                312,
+                1851,
+                322,
+                1352,
+                329,
+                333,
+                337,
+                1361,
+                343,
+                351,
+                867,
+                1893,
+                361,
+                877,
+                368,
+                1906,
+                1398,
+                376,
+                377,
+                1402,
+                1403,
+                896,
+                1924,
+                392,
+                911,
+                923,
+                413,
+                1437,
+                416,
+                418,
+                930,
+                938,
+                435,
+                954,
+                446,
+                1471,
+                1474,
+                452,
+                1989,
+                967,
+                1996,
+                464,
+                977,
+                471,
+                486,
+                487,
+                494,
+                2031,
+                1008,
+                1522,
+                1013,
+                1017,
+                1531,
+                1022,
+                1535
+            ],
+
+        },
+        {
+            "id": "tusmiple",
+            "name": "图森未来",
+            "questions": [
+                718,
+                127,
+                1005,
+                1000428,
+                1000427,
+                1000426,
+                1000425,
+                1000424,
+                1000423,
+                726,
+                522,
+                973,
+                1217,
+                193,
+                1972,
+                171,
+                1957,
+                36,
+                27,
+                1294
+            ],
+
+        },
+        {
+            "id": "graph",
+            "name": "图论",
+            "questions": [
+                317,
+                1912,
+                1389,
+                877,
+                365,
+                871,
+                869,
+                1380,
+                352,
+                863,
+                323,
+                895,
+                310,
+                820,
+                305,
+                1325,
+                813,
+                803,
+                801,
+                1309,
+                1308,
+                794,
+                1986,
+                505,
+                2040,
+                2038,
+                2035,
+                499,
+                490,
+                1492,
+                1485,
+                971,
+                964,
+                1815,
+                960,
+                949,
+                433,
+                1456,
+                1447,
+                1442,
+                417,
+                922,
+                1428,
+                1100,
+                1191,
+                1701,
+                1696,
+                1171,
+                127,
+                1661,
+                1144,
+                1117,
+                1613,
+                1101,
+                1706,
+                1085,
+                1587,
+                1073,
+                1576,
+                547,
+                1058,
+                542,
+                1558,
+                1039,
+                721,
+                1300,
+                269,
+                261,
+                753,
+                744,
+                737,
+                1757,
+                733,
+                1753,
+                210,
+                1032,
+                207,
+                1229,
+                1738,
+                200,
+                1223,
+                695,
+                694,
+                685,
+                684
+            ],
+
+        },
+        {
+            "id": "bytedancecampus",
+            "name": "字节校园",
+            "questions": [
+                69,
+                88,
+                215,
+                206,
+                76,
+                200,
+                72,
+                199,
+                198,
+                92,
+                322,
+                64,
+                56,
+                54,
+                53,
+                948,
+                46,
+                300,
+                94,
+                102,
+                103,
+                232,
+                105,
+                236,
+                239,
+                1000185,
+                1000182,
+                1000183,
+                1000184,
+                121,
+                1000186,
+                1000187,
+                124,
+                135,
+                146,
+                143,
+                142,
+                15,
+                14,
+                141,
+                394,
+                1000188,
+                20,
+                7,
+                129,
+                5,
+                4,
+                3,
+                2,
+                1,
+                128,
+                21,
+                22,
+                23,
+                151,
+                25,
+                152,
+                792,
+                923,
+                31,
+                160,
+                33,
+                415,
+                41,
+                42,
+                43
+            ],
+
+        },
+        {
+            "id": "ponyai",
+            "name": "小马智行 Pony.ai",
+            "questions": [
+                15,
+                1000351,
+                1000350,
+                1000349,
+                92,
+                1000347,
+                148,
+                146,
+                1105,
+                1000352,
+                909,
+                173,
+                1000348,
+                105,
+                39,
+                1860,
+                98,
+                1441
+            ],
+
+        },
+        {
+            "id": "cmbchina-cc",
+            "name": "招商银行信用卡",
+            "questions": [
+                33,
+                124,
+                103,
+                88,
+                199,
+                198,
+                322,
+                64,
+                53,
+                41,
+                1,
+                415,
+                923,
+                22,
+                21,
+                20,
+                15,
+                7,
+                5,
+                3
+            ],
+        },
+        {
+            "id": "data-structures",
+            "name": "数据结构",
+            "questions": [
+                1,
+                2,
+                5,
+                1032,
+                15,
+                1039,
+                20,
+                21,
+                23,
+                24,
+                25,
+                547,
+                36,
+                42,
+                43,
+                44,
+                48,
+                49,
+                560,
+                53,
+                566,
+                56,
+                59,
+                1085,
+                73,
+                1609,
+                75,
+                82,
+                83,
+                84,
+                1107,
+                88,
+                94,
+                98,
+                101,
+                102,
+                103,
+                104,
+                105,
+                108,
+                112,
+                113,
+                118,
+                119,
+                121,
+                124,
+                1661,
+                128,
+                1665,
+                642,
+                136,
+                138,
+                141,
+                142,
+                143,
+                144,
+                145,
+                653,
+                148,
+                155,
+                1693,
+                160,
+                1701,
+                169,
+                173,
+                1710,
+                187,
+                199,
+                203,
+                206,
+                208,
+                1745,
+                211,
+                212,
+                214,
+                215,
+                217,
+                218,
+                729,
+                226,
+                739,
+                230,
+                232,
+                235,
+                236,
+                238,
+                1774,
+                240,
+                242,
+                761,
+                253,
+                766,
+                768,
+                261,
+                783,
+                784,
+                281,
+                290,
+                803,
+                295,
+                297,
+                305,
+                817,
+                1345,
+                323,
+                325,
+                838,
+                334,
+                336,
+                337,
+                347,
+                1371,
+                350,
+                358,
+                871,
+                366,
+                1903,
+                369,
+                378,
+                892,
+                383,
+                387,
+                394,
+                402,
+                409,
+                922,
+                415,
+                1951,
+                1442,
+                1450,
+                435,
+                448,
+                450,
+                451,
+                452,
+                454,
+                456,
+                2009,
+                1008,
+                1014
+            ],
+
+        },
+        {
+            "id": "xb9lfcwi",
+            "name": "程序员面试金典(第 6 版)",
+            "questions": [
+                100352,
+                100353,
+                100354,
+                100355,
+                100356,
+                1000003,
+                1000004,
+                1000005,
+                1000006,
+                1000007,
+                1000008,
+                1000009,
+                1000010,
+                1000011,
+                1000012,
+                1000013,
+                1000015,
+                1000016,
+                1000017,
+                1000018,
+                1000019,
+                1000020,
+                1000021,
+                1000022,
+                1000023,
+                1000024,
+                1000025,
+                1000026,
+                1000027,
+                1000028,
+                1000029,
+                1000030,
+                1000031,
+                1000032,
+                1000033,
+                1000034,
+                1000035,
+                1000036,
+                1000037,
+                1000038,
+                1000039,
+                1000040,
+                1000041,
+                1000042,
+                1000043,
+                1000044,
+                1000045,
+                1000046,
+                1000047,
+                1000048,
+                1000049,
+                1000050,
+                1000051,
+                100158,
+                100159,
+                100160,
+                100161,
+                100162,
+                100163,
+                100164,
+                100167,
+                100168,
+                100169,
+                100170,
+                100171,
+                100172,
+                100173,
+                100174,
+                100175,
+                100176,
+                100177,
+                100178,
+                100179,
+                100180,
+                100181,
+                100182,
+                100183,
+                100184,
+                100185,
+                100186,
+                100187,
+                100188,
+                100195,
+                100196,
+                100197,
+                100198,
+                100199,
+                100200,
+                100201,
+                100202,
+                100203,
+                100228,
+                100229,
+                100230,
+                100231,
+                100232,
+                100233,
+                100240,
+                100241,
+                100242,
+                100258,
+                100259,
+                100260,
+                100261,
+                100262,
+                100348,
+                100349,
+                100350,
+                100351
+            ],
+
+        },
+        {
+            "id": "algorithms",
+            "name": "算法",
+            "questions": [
+                1025,
+                3,
+                4,
+                5,
+                1028,
+                10,
+                11,
+                1036,
+                1037,
+                15,
+                17,
+                19,
+                21,
+                22,
+                1046,
+                542,
+                33,
+                34,
+                35,
+                547,
+                37,
+                1059,
+                39,
+                40,
+                42,
+                45,
+                46,
+                47,
+                557,
+                51,
+                53,
+                55,
+                567,
+                2047,
+                572,
+                62,
+                70,
+                582,
+                72,
+                583,
+                74,
+                1609,
+                76,
+                77,
+                78,
+                79,
+                1101,
+                82,
+                85,
+                90,
+                91,
+                617,
+                1134,
+                116,
+                117,
+                120,
+                123,
+                130,
+                131,
+                132,
+                136,
+                139,
+                1165,
+                146,
+                1171,
+                149,
+                153,
+                159,
+                673,
+                162,
+                167,
+                1192,
+                174,
+                695,
+                189,
+                190,
+                191,
+                198,
+                200,
+                201,
+                202,
+                713,
+                714,
+                715,
+                206,
+                207,
+                209,
+                210,
+                213,
+                221,
+                733,
+                1250,
+                231,
+                239,
+                241,
+                753,
+                254,
+                260,
+                269,
+                1300,
+                278,
+                792,
+                283,
+                286,
+                287,
+                800,
+                300,
+                301,
+                813,
+                309,
+                310,
+                315,
+                322,
+                329,
+                337,
+                340,
+                343,
+                344,
+                865,
+                874,
+                893,
+                895,
+                384,
+                394,
+                908,
+                410,
+                413,
+                416,
+                417,
+                1442,
+                438,
+                460,
+                1485,
+                2019,
+                486,
+                1512,
+                1019,
+                1023
+            ],
+
+        },
+        {
+            "id": "programming-skills",
+            "name": "编程能力",
+            "questions": [
+                2,
+                1031,
+                8,
+                525,
+                23,
+                535,
+                28,
+                43,
+                556,
+                48,
+                49,
+                1584,
+                54,
+                566,
+                58,
+                61,
+                65,
+                66,
+                67,
+                1626,
+                1630,
+                1125,
+                104,
+                110,
+                631,
+                635,
+                642,
+                138,
+                1677,
+                143,
+                146,
+                148,
+                150,
+                1176,
+                155,
+                1693,
+                1708,
+                173,
+                1713,
+                191,
+                1728,
+                1729,
+                1736,
+                713,
+                202,
+                715,
+                208,
+                209,
+                211,
+                214,
+                1752,
+                217,
+                729,
+                224,
+                227,
+                739,
+                742,
+                232,
+                1768,
+                1774,
+                241,
+                242,
+                244,
+                758,
+                251,
+                764,
+                255,
+                1791,
+                771,
+                1797,
+                775,
+                785,
+                2322,
+                281,
+                282,
+                283,
+                295,
+                297,
+                303,
+                304,
+                307,
+                325,
+                838,
+                1349,
+                850,
+                341,
+                859,
+                348,
+                860,
+                1888,
+                353,
+                1894,
+                369,
+                1905,
+                885,
+                890,
+                1915,
+                380,
+                381,
+                1406,
+                1411,
+                389,
+                1930,
+                908,
+                404,
+                1434,
+                1949,
+                1950,
+                931,
+                932,
+                1955,
+                937,
+                946,
+                1458,
+                438,
+                445,
+                1982,
+                449,
+                1477,
+                459,
+                460,
+                1484,
+                1492,
+                990,
+                2015,
+                1512,
+                496,
+                1014,
+                503,
+                1018
+            ],
+
+        },
+        {
+            "id": "meituan",
+            "name": "美团真题",
+            "questions": [
+                1000192,
+                1000193,
+                1000194,
+                1000195,
+                1000196,
+                1000197,
+                1000198,
+                1000199,
+                1000200,
+                1000201,
+                1000202,
+                1000203,
+                1000189,
+                1000190,
+                1000191,
+                257,
+                100158,
+                13,
+                455,
+                45,
+                200,
+                143,
+                139,
+                19,
+                100344,
+                162,
+                177,
+                75,
+                1036,
+                71,
+                475,
+                42,
+                51,
+                440,
+                25
+            ],
+
+        },
+        {
+            "id": "ke",
+            "name": "贝壳找房",
+            "questions": [
+                30,
+                120,
+                113,
+                85,
+                82,
+                209,
+                200,
+                315,
+                56,
+                53,
+                43,
+                2,
+                152,
+                20,
+                19,
+                17,
+                15,
+                14,
+                264,
+                135,
+                4
+            ],
+
+        },
+        {
+            "id": "efficient-winning",
+            "name": "高效制胜",
+            "questions": [
+                230,
+                329,
+                79,
+                720,
+                218,
+                1120,
+                97,
+                483,
+                1508,
+                456,
+                112,
+                496,
+                1008,
+                1013,
+                119,
+                121,
+                122,
+                416,
+                3,
+                11,
+                524,
+                15,
+                18,
+                20,
+                279,
+                28,
+                1,
+                803,
+                167,
+                42,
+                53,
+                825,
+                322,
+                70
+            ],
+
+        },
+        {
+            "id": "2cktkvj",
+            "name": "LeetCode 热题 HOT 100",
+            "questions": [
+                160,
+                236,
+                234,
+                739,
+                226,
+                221,
+                215,
+                208,
+                207,
+                206,
+                200,
+                198,
+                169,
+                238,
+                155,
+                152,
+                148,
+                146,
+                142,
+                141,
+                139,
+                136,
+                647,
+                128,
+                124,
+                322,
+                494,
+                461,
+                448,
+                438,
+                437,
+                416,
+                406,
+                399,
+                394,
+                347,
+                338,
+                337,
+                121,
+                312,
+                309,
+                301,
+                300,
+                297,
+                287,
+                283,
+                279,
+                253,
+                240,
+                239,
+                22,
+                49,
+                48,
+                46,
+                42,
+                39,
+                543,
+                34,
+                33,
+                32,
+                31,
+                538,
+                23,
+                560,
+                21,
+                20,
+                19,
+                17,
+                15,
+                11,
+                10,
+                5,
+                4,
+                3,
+                2,
+                79,
+                114,
+                621,
+                617,
+                105,
+                104,
+                102,
+                101,
+                98,
+                96,
+                94,
+                85,
+                84,
+                1,
+                78,
+                76,
+                75,
+                72,
+                70,
+                581,
+                64,
+                62,
+                56,
+                55,
+                53
+            ],
+
+        },
+        {
+            "id": "7cyqwuv",
+            "name": "力扣杯 - 竞赛合集",
+            "questions": [
+                1000134,
+                1000222,
+                1000362,
+                1000367,
+                1000368,
+                1000369,
+                1000370,
+                1000371,
+                1000373,
+                1000374,
+                1000375,
+                1000130,
+                1000131,
+                1000132,
+                1000133,
+                100094,
+                1000138,
+                1000139,
+                1000140,
+                1000146,
+                1000147,
+                1000056,
+                1000057,
+                1000058,
+                1000059,
+                100092,
+                100093,
+                1000062,
+                1000063,
+                1000216,
+                100107,
+                511,
+                1000085,
+                1000086,
+                1000087,
+                1000088,
+                1000089,
+                1000090,
+                1000091,
+                1052,
+                1053,
+                1000093,
+                1000215,
+                100096,
+                1000218,
+                1058,
+                1059,
+                1060,
+                1061,
+                1000219,
+                1000220,
+                1000223,
+                1000224,
+                1000221,
+                1000359,
+                1000361,
+                1069
+            ],
+
+        },
+        {
+            "id": "ex0k24j",
+            "name": "腾讯精选练习 50 题",
+            "questions": [
+                217,
+                46,
+                53,
+                54,
+                59,
+                61,
+                62,
+                70,
+                78,
+                206,
+                215,
+                88,
+                89,
+                557,
+                344,
+                230,
+                231,
+                104,
+                235,
+                236,
+                237,
+                238,
+                121,
+                122,
+                124,
+                146,
+                4,
+                5,
+                7,
+                8,
+                9,
+                136,
+                11,
+                141,
+                14,
+                15,
+                16,
+                142,
+                2,
+                20,
+                21,
+                148,
+                23,
+                26,
+                155,
+                160,
+                33,
+                292,
+                169,
+                43
+            ],
+
+        },
+        {
+            "id": "2ckc81c",
+            "name": "LeetCode 精选 TOP 面试题",
+            "questions": [
+                1,
+                2,
+                3,
+                4,
+                5,
+                7,
+                8,
+                10,
+                11,
+                13,
+                14,
+                15,
+                17,
+                19,
+                20,
+                21,
+                22,
+                23,
+                26,
+                28,
+                29,
+                33,
+                34,
+                36,
+                38,
+                41,
+                42,
+                44,
+                46,
+                48,
+                49,
+                50,
+                53,
+                54,
+                55,
+                56,
+                62,
+                66,
+                69,
+                70,
+                73,
+                75,
+                76,
+                78,
+                79,
+                84,
+                88,
+                91,
+                94,
+                98,
+                101,
+                102,
+                103,
+                104,
+                105,
+                108,
+                116,
+                118,
+                121,
+                122,
+                124,
+                125,
+                127,
+                128,
+                130,
+                131,
+                134,
+                136,
+                138,
+                139,
+                140,
+                141,
+                146,
+                148,
+                149,
+                150,
+                152,
+                155,
+                160,
+                162,
+                163,
+                166,
+                169,
+                171,
+                172,
+                179,
+                189,
+                190,
+                191,
+                198,
+                200,
+                202,
+                204,
+                206,
+                207,
+                208,
+                210,
+                212,
+                215,
+                217,
+                218,
+                227,
+                230,
+                234,
+                236,
+                237,
+                238,
+                239,
+                240,
+                242,
+                251,
+                253,
+                268,
+                269,
+                277,
+                279,
+                283,
+                285,
+                287,
+                289,
+                295,
+                297,
+                300,
+                308,
+                315,
+                322,
+                324,
+                326,
+                328,
+                329,
+                334,
+                340,
+                341,
+                344,
+                347,
+                348,
+                350,
+                371,
+                378,
+                380,
+                384,
+                387,
+                395,
+                412,
+                454
+            ],
+
+        }
+    ];
+}
+
+
+export const choiceDao: ChoiceDao = new ChoiceDao();
+
+
+
+
+
+
diff --git a/src/dao/scoreDao.ts b/src/dao/scoreDao.ts
new file mode 100644
index 0000000..9aab549
--- /dev/null
+++ b/src/dao/scoreDao.ts
@@ -0,0 +1,40 @@
+/*
+ * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/dao/scoreDao.ts
+ * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
+ * Created Date: Thursday, November 10th 2022, 11:40:22 pm
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
+
+import { IScoreData } from "../model/Model";
+
+
+
+
+class ScoreDao {
+    private scoreBase = require("../../../resources/data.json");
+
+    public getScoreData(): Map {
+
+        let nameSiteMapping = new Map();
+        const temp = this.scoreBase as IScoreData[];
+        temp.forEach(element => {
+            // Rating
+            // ID
+            // ContestSlug
+            element.score = "" + Math.floor(element.Rating || 0);
+            nameSiteMapping.set("" + element.ID, element);
+        });
+        return nameSiteMapping;
+    }
+}
+
+
+export const scoreDao: ScoreDao = new ScoreDao();
+
+
+
+
+
+
diff --git a/src/ResourcesData.ts b/src/dao/tagsDao.ts
similarity index 82%
rename from src/ResourcesData.ts
rename to src/dao/tagsDao.ts
index 1c568db..42ee915 100644
--- a/src/ResourcesData.ts
+++ b/src/dao/tagsDao.ts
@@ -1,2080 +1,17 @@
-import { IScoreData } from "./shared";
+/*
+ * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/dao/tagsDao.ts
+ * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
+ * Created Date: Thursday, November 10th 2022, 11:38:10 pm
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
 
-class ResourcesData {
 
-    private scoreBase = require("../../resources/data.json")
 
-    private choiceData = [
-        {
-            "id": "shopee",
-            "name": "Shopee精选",
-            "questions": [
-                341,
-                1000447,
-                1000446,
-                1000445,
-                1000444,
-                1000443,
-                232,
-                871,
-                102,
-                101,
-                15,
-                460,
-                456,
-                448,
-                179,
-                432,
-                48,
-                37,
-                20,
-                146
-            ],
+class TagsDao {
 
-        },
-        {
-            "id": "binary-search",
-            "name": "二分查找",
-            "questions": [
-                4,
-                1550,
-                540,
-                1056,
-                33,
-                34,
-                35,
-                1059,
-                1060,
-                1083,
-                2047,
-                69,
-                1605,
-                74,
-                1612,
-                1102,
-                1615,
-                81,
-                1621,
-                1122,
-                611,
-                1645,
-                1134,
-                1646,
-                1143,
-                633,
-                1149,
-                644,
-                1672,
-                1675,
-                1679,
-                658,
-                1684,
-                153,
-                154,
-                668,
-                1185,
-                162,
-                167,
-                1192,
-                1730,
-                718,
-                719,
-                1232,
-                209,
-                1753,
-                222,
-                1249,
-                1766,
-                745,
-                1771,
-                1262,
-                240,
-                1290,
-                270,
-                786,
-                275,
-                788,
-                278,
-                792,
-                794,
-                1307,
-                287,
-                802,
-                1831,
-                1832,
-                809,
-                300,
-                302,
-                1326,
-                1851,
-                1352,
-                853,
-                350,
-                1374,
-                352,
-                1886,
-                1891,
-                1384,
-                363,
-                367,
-                882,
-                374,
-                378,
-                894,
-                1918,
-                1408,
-                1413,
-                1929,
-                907,
-                912,
-                1946,
-                923,
-                1957,
-                1966,
-                947,
-                436,
-                1463,
-                441,
-                1468,
-                1984,
-                1476,
-                1486,
-                2000,
-                2006,
-                2018,
-                2027,
-                2036,
-                2045,
-                1023
-            ],
-
-        },
-        {
-            "id": "lcof",
-            "name": "剑指 Offer",
-            "questions": [
-                1000228,
-                1000229,
-                1000230,
-                1000231,
-                1000232,
-                1000233,
-                1000234,
-                1000235,
-                1000236,
-                1000237,
-                1000238,
-                1000239,
-                1000240,
-                1000241,
-                1000242,
-                1000243,
-                1000244,
-                1000245,
-                1000246,
-                1000247,
-                1000248,
-                1000249,
-                1000250,
-                1000251,
-                1000252,
-                1000253,
-                1000254,
-                1000255,
-                1000256,
-                1000257,
-                1000258,
-                1000259,
-                1000260,
-                1000261,
-                1000262,
-                1000263,
-                1000264,
-                1000265,
-                1000266,
-                1000267,
-                1000268,
-                1000269,
-                1000270,
-                1000271,
-                1000272,
-                1000273,
-                1000274,
-                1000275,
-                1000276,
-                1000277,
-                1000278,
-                1000279,
-                1000280,
-                1000281,
-                1000282,
-                1000283,
-                1000284,
-                1000285,
-                1000286,
-                1000287,
-                1000288,
-                1000289,
-                1000290,
-                1000291,
-                1000292,
-                1000293,
-                1000294,
-                1000295,
-                1000296,
-                1000297,
-                1000298,
-                1000299,
-                1000300,
-                1000301,
-                1000302,
-                1000303,
-                1000304,
-                1000305,
-                1000306,
-                1000307,
-                1000308,
-                1000309,
-                1000310,
-                1000311,
-                1000312,
-                1000313,
-                1000314,
-                1000315,
-                1000316,
-                1000317,
-                1000318,
-                1000319,
-                1000320,
-                1000321,
-                1000322,
-                1000323,
-                1000324,
-                1000325,
-                1000326,
-                1000327,
-                1000328,
-                1000329,
-                1000330,
-                1000331,
-                1000332,
-                1000333,
-                1000334,
-                1000335,
-                1000336,
-                1000337,
-                1000338,
-                1000339,
-                1000340,
-                1000341,
-                1000342,
-                1000343,
-                1000344,
-                1000345,
-                1000346,
-                100273,
-                100274,
-                100275,
-                100276,
-                100277,
-                100278,
-                100279,
-                100280,
-                100281,
-                100282,
-                100283,
-                100284,
-                100285,
-                100286,
-                100287,
-                100288,
-                100289,
-                100290,
-                100291,
-                100292,
-                100293,
-                100294,
-                100295,
-                100296,
-                100297,
-                100298,
-                100299,
-                100300,
-                100301,
-                100302,
-                100303,
-                100304,
-                100305,
-                100306,
-                100307,
-                100308,
-                100309,
-                100310,
-                100311,
-                100312,
-                100313,
-                100314,
-                100315,
-                100316,
-                100317,
-                100318,
-                100319,
-                100320,
-                100321,
-                100322,
-                100323,
-                100324,
-                100325,
-                100326,
-                100327,
-                100328,
-                100329,
-                100330,
-                100331,
-                100332,
-                100333,
-                100334,
-                100335,
-                100336,
-                100337,
-                100338,
-                100339,
-                100340,
-                100341,
-                100342,
-                100343,
-                100344,
-                100345,
-                100346,
-                100347
-            ],
-
-        },
-        {
-            "id": "e8X3pBZi",
-            "name": "剑指 Offer(专项突击版)",
-            "questions": [
-                1000228,
-                1000229,
-                1000230,
-                1000231,
-                1000232,
-                1000233,
-                1000234,
-                1000235,
-                1000236,
-                1000237,
-                1000238,
-                1000239,
-                1000240,
-                1000241,
-                1000242,
-                1000243,
-                1000244,
-                1000245,
-                1000246,
-                1000247,
-                1000248,
-                1000249,
-                1000250,
-                1000251,
-                1000252,
-                1000253,
-                1000254,
-                1000255,
-                1000256,
-                1000257,
-                1000258,
-                1000259,
-                1000260,
-                1000261,
-                1000262,
-                1000263,
-                1000264,
-                1000265,
-                1000266,
-                1000267,
-                1000268,
-                1000269,
-                1000270,
-                1000271,
-                1000272,
-                1000273,
-                1000274,
-                1000275,
-                1000276,
-                1000277,
-                1000278,
-                1000279,
-                1000280,
-                1000281,
-                1000282,
-                1000283,
-                1000284,
-                1000285,
-                1000286,
-                1000287,
-                1000288,
-                1000289,
-                1000290,
-                1000291,
-                1000292,
-                1000293,
-                1000294,
-                1000295,
-                1000296,
-                1000297,
-                1000298,
-                1000299,
-                1000300,
-                1000301,
-                1000302,
-                1000303,
-                1000304,
-                1000305,
-                1000306,
-                1000307,
-                1000308,
-                1000309,
-                1000310,
-                1000311,
-                1000312,
-                1000313,
-                1000314,
-                1000315,
-                1000316,
-                1000317,
-                1000318,
-                1000319,
-                1000320,
-                1000321,
-                1000322,
-                1000323,
-                1000324,
-                1000325,
-                1000326,
-                1000327,
-                1000328,
-                1000329,
-                1000330,
-                1000331,
-                1000332,
-                1000333,
-                1000334,
-                1000335,
-                1000336,
-                1000337,
-                1000338,
-                1000339,
-                1000340,
-                1000341,
-                1000342,
-                1000343,
-                1000344,
-                1000345,
-                1000346
-            ],
-
-        },
-        {
-            "id": "xb9nqhhg",
-            "name": "剑指 Offer(第 2 版)",
-            "questions": [
-                100319,
-                100328,
-                100327,
-                100326,
-                100325,
-                100324,
-                100323,
-                100322,
-                100321,
-                100320,
-                100329,
-                100318,
-                100317,
-                100316,
-                100315,
-                100314,
-                100313,
-                100312,
-                100311,
-                100338,
-                100347,
-                100346,
-                100345,
-                100344,
-                100343,
-                100342,
-                100341,
-                100340,
-                100339,
-                100310,
-                100337,
-                100336,
-                100335,
-                100334,
-                100333,
-                100332,
-                100331,
-                100330,
-                100282,
-                100291,
-                100290,
-                100289,
-                100288,
-                100287,
-                100286,
-                100285,
-                100284,
-                100283,
-                100292,
-                100281,
-                100280,
-                100279,
-                100278,
-                100277,
-                100276,
-                100275,
-                100274,
-                100301,
-                100309,
-                100308,
-                100307,
-                100306,
-                100305,
-                100304,
-                100303,
-                100302,
-                100273,
-                100300,
-                100299,
-                100298,
-                100297,
-                100296,
-                100295,
-                100294,
-                100293
-            ],
-
-        },
-        {
-            "id": "lccup",
-            "name": "力扣杯竞赛真题集",
-            "questions": [
-                1000134,
-                1000222,
-                1000362,
-                1000367,
-                1000368,
-                1000369,
-                1000370,
-                1000371,
-                1000373,
-                1000374,
-                1000375,
-                1000130,
-                1000131,
-                1000132,
-                1000133,
-                100094,
-                1000138,
-                1000139,
-                1000140,
-                1000146,
-                1000147,
-                1000056,
-                1000057,
-                1000058,
-                1000059,
-                100092,
-                100093,
-                1000062,
-                1000063,
-                1000218,
-                100107,
-                1000085,
-                1000086,
-                1000087,
-                1000088,
-                1000089,
-                1000090,
-                1000091,
-                1052,
-                1053,
-                1000093,
-                1000215,
-                1000216,
-                100096,
-                1058,
-                1059,
-                1060,
-                1061,
-                1000219,
-                1000220,
-                1000223,
-                1000224,
-                1000221,
-                1000359,
-                1000361,
-                813,
-                1069
-            ],
-
-        },
-        {
-            "id": "dynamic-programming",
-            "name": "动态规划",
-            "questions": [
-                1025,
-                514,
-                516,
-                5,
-                518,
-                10,
-                526,
-                1042,
-                1559,
-                1051,
-                32,
-                1057,
-                546,
-                1571,
-                1060,
-                549,
-                39,
-                40,
-                1063,
-                42,
-                1067,
-                1068,
-                45,
-                1583,
-                562,
-                53,
-                55,
-                568,
-                62,
-                63,
-                64,
-                576,
-                70,
-                72,
-                1105,
-                1617,
-                600,
-                91,
-                96,
-                1129,
-                1130,
-                1134,
-                115,
-                118,
-                119,
-                120,
-                121,
-                122,
-                123,
-                124,
-                634,
-                1669,
-                646,
-                647,
-                650,
-                139,
-                140,
-                651,
-                1166,
-                1680,
-                1170,
-                152,
-                664,
-                1178,
-                1690,
-                673,
-                1196,
-                174,
-                688,
-                1201,
-                1202,
-                691,
-                698,
-                188,
-                1213,
-                1220,
-                198,
-                712,
-                714,
-                1228,
-                1744,
-                1236,
-                213,
-                727,
-                1240,
-                1242,
-                221,
-                1758,
-                1250,
-                740,
-                741,
-                747,
-                238,
-                751,
-                1263,
-                1789,
-                254,
-                256,
-                1286,
-                264,
-                265,
-                1296,
-                279,
-                1822,
-                1828,
-                294,
-                298,
-                300,
-                304,
-                309,
-                312,
-                1851,
-                322,
-                1352,
-                329,
-                333,
-                337,
-                1361,
-                343,
-                351,
-                867,
-                1893,
-                361,
-                877,
-                368,
-                1906,
-                1398,
-                376,
-                377,
-                1402,
-                1403,
-                896,
-                1924,
-                392,
-                911,
-                923,
-                413,
-                1437,
-                416,
-                418,
-                930,
-                938,
-                435,
-                954,
-                446,
-                1471,
-                1474,
-                452,
-                1989,
-                967,
-                1996,
-                464,
-                977,
-                471,
-                486,
-                487,
-                494,
-                2031,
-                1008,
-                1522,
-                1013,
-                1017,
-                1531,
-                1022,
-                1535
-            ],
-
-        },
-        {
-            "id": "tusmiple",
-            "name": "图森未来",
-            "questions": [
-                718,
-                127,
-                1005,
-                1000428,
-                1000427,
-                1000426,
-                1000425,
-                1000424,
-                1000423,
-                726,
-                522,
-                973,
-                1217,
-                193,
-                1972,
-                171,
-                1957,
-                36,
-                27,
-                1294
-            ],
-
-        },
-        {
-            "id": "graph",
-            "name": "图论",
-            "questions": [
-                317,
-                1912,
-                1389,
-                877,
-                365,
-                871,
-                869,
-                1380,
-                352,
-                863,
-                323,
-                895,
-                310,
-                820,
-                305,
-                1325,
-                813,
-                803,
-                801,
-                1309,
-                1308,
-                794,
-                1986,
-                505,
-                2040,
-                2038,
-                2035,
-                499,
-                490,
-                1492,
-                1485,
-                971,
-                964,
-                1815,
-                960,
-                949,
-                433,
-                1456,
-                1447,
-                1442,
-                417,
-                922,
-                1428,
-                1100,
-                1191,
-                1701,
-                1696,
-                1171,
-                127,
-                1661,
-                1144,
-                1117,
-                1613,
-                1101,
-                1706,
-                1085,
-                1587,
-                1073,
-                1576,
-                547,
-                1058,
-                542,
-                1558,
-                1039,
-                721,
-                1300,
-                269,
-                261,
-                753,
-                744,
-                737,
-                1757,
-                733,
-                1753,
-                210,
-                1032,
-                207,
-                1229,
-                1738,
-                200,
-                1223,
-                695,
-                694,
-                685,
-                684
-            ],
-
-        },
-        {
-            "id": "bytedancecampus",
-            "name": "字节校园",
-            "questions": [
-                69,
-                88,
-                215,
-                206,
-                76,
-                200,
-                72,
-                199,
-                198,
-                92,
-                322,
-                64,
-                56,
-                54,
-                53,
-                948,
-                46,
-                300,
-                94,
-                102,
-                103,
-                232,
-                105,
-                236,
-                239,
-                1000185,
-                1000182,
-                1000183,
-                1000184,
-                121,
-                1000186,
-                1000187,
-                124,
-                135,
-                146,
-                143,
-                142,
-                15,
-                14,
-                141,
-                394,
-                1000188,
-                20,
-                7,
-                129,
-                5,
-                4,
-                3,
-                2,
-                1,
-                128,
-                21,
-                22,
-                23,
-                151,
-                25,
-                152,
-                792,
-                923,
-                31,
-                160,
-                33,
-                415,
-                41,
-                42,
-                43
-            ],
-
-        },
-        {
-            "id": "ponyai",
-            "name": "小马智行 Pony.ai",
-            "questions": [
-                15,
-                1000351,
-                1000350,
-                1000349,
-                92,
-                1000347,
-                148,
-                146,
-                1105,
-                1000352,
-                909,
-                173,
-                1000348,
-                105,
-                39,
-                1860,
-                98,
-                1441
-            ],
-
-        },
-        {
-            "id": "cmbchina-cc",
-            "name": "招商银行信用卡",
-            "questions": [
-                33,
-                124,
-                103,
-                88,
-                199,
-                198,
-                322,
-                64,
-                53,
-                41,
-                1,
-                415,
-                923,
-                22,
-                21,
-                20,
-                15,
-                7,
-                5,
-                3
-            ],
-        },
-        {
-            "id": "data-structures",
-            "name": "数据结构",
-            "questions": [
-                1,
-                2,
-                5,
-                1032,
-                15,
-                1039,
-                20,
-                21,
-                23,
-                24,
-                25,
-                547,
-                36,
-                42,
-                43,
-                44,
-                48,
-                49,
-                560,
-                53,
-                566,
-                56,
-                59,
-                1085,
-                73,
-                1609,
-                75,
-                82,
-                83,
-                84,
-                1107,
-                88,
-                94,
-                98,
-                101,
-                102,
-                103,
-                104,
-                105,
-                108,
-                112,
-                113,
-                118,
-                119,
-                121,
-                124,
-                1661,
-                128,
-                1665,
-                642,
-                136,
-                138,
-                141,
-                142,
-                143,
-                144,
-                145,
-                653,
-                148,
-                155,
-                1693,
-                160,
-                1701,
-                169,
-                173,
-                1710,
-                187,
-                199,
-                203,
-                206,
-                208,
-                1745,
-                211,
-                212,
-                214,
-                215,
-                217,
-                218,
-                729,
-                226,
-                739,
-                230,
-                232,
-                235,
-                236,
-                238,
-                1774,
-                240,
-                242,
-                761,
-                253,
-                766,
-                768,
-                261,
-                783,
-                784,
-                281,
-                290,
-                803,
-                295,
-                297,
-                305,
-                817,
-                1345,
-                323,
-                325,
-                838,
-                334,
-                336,
-                337,
-                347,
-                1371,
-                350,
-                358,
-                871,
-                366,
-                1903,
-                369,
-                378,
-                892,
-                383,
-                387,
-                394,
-                402,
-                409,
-                922,
-                415,
-                1951,
-                1442,
-                1450,
-                435,
-                448,
-                450,
-                451,
-                452,
-                454,
-                456,
-                2009,
-                1008,
-                1014
-            ],
-
-        },
-        {
-            "id": "xb9lfcwi",
-            "name": "程序员面试金典(第 6 版)",
-            "questions": [
-                100352,
-                100353,
-                100354,
-                100355,
-                100356,
-                1000003,
-                1000004,
-                1000005,
-                1000006,
-                1000007,
-                1000008,
-                1000009,
-                1000010,
-                1000011,
-                1000012,
-                1000013,
-                1000015,
-                1000016,
-                1000017,
-                1000018,
-                1000019,
-                1000020,
-                1000021,
-                1000022,
-                1000023,
-                1000024,
-                1000025,
-                1000026,
-                1000027,
-                1000028,
-                1000029,
-                1000030,
-                1000031,
-                1000032,
-                1000033,
-                1000034,
-                1000035,
-                1000036,
-                1000037,
-                1000038,
-                1000039,
-                1000040,
-                1000041,
-                1000042,
-                1000043,
-                1000044,
-                1000045,
-                1000046,
-                1000047,
-                1000048,
-                1000049,
-                1000050,
-                1000051,
-                100158,
-                100159,
-                100160,
-                100161,
-                100162,
-                100163,
-                100164,
-                100167,
-                100168,
-                100169,
-                100170,
-                100171,
-                100172,
-                100173,
-                100174,
-                100175,
-                100176,
-                100177,
-                100178,
-                100179,
-                100180,
-                100181,
-                100182,
-                100183,
-                100184,
-                100185,
-                100186,
-                100187,
-                100188,
-                100195,
-                100196,
-                100197,
-                100198,
-                100199,
-                100200,
-                100201,
-                100202,
-                100203,
-                100228,
-                100229,
-                100230,
-                100231,
-                100232,
-                100233,
-                100240,
-                100241,
-                100242,
-                100258,
-                100259,
-                100260,
-                100261,
-                100262,
-                100348,
-                100349,
-                100350,
-                100351
-            ],
-
-        },
-        {
-            "id": "algorithms",
-            "name": "算法",
-            "questions": [
-                1025,
-                3,
-                4,
-                5,
-                1028,
-                10,
-                11,
-                1036,
-                1037,
-                15,
-                17,
-                19,
-                21,
-                22,
-                1046,
-                542,
-                33,
-                34,
-                35,
-                547,
-                37,
-                1059,
-                39,
-                40,
-                42,
-                45,
-                46,
-                47,
-                557,
-                51,
-                53,
-                55,
-                567,
-                2047,
-                572,
-                62,
-                70,
-                582,
-                72,
-                583,
-                74,
-                1609,
-                76,
-                77,
-                78,
-                79,
-                1101,
-                82,
-                85,
-                90,
-                91,
-                617,
-                1134,
-                116,
-                117,
-                120,
-                123,
-                130,
-                131,
-                132,
-                136,
-                139,
-                1165,
-                146,
-                1171,
-                149,
-                153,
-                159,
-                673,
-                162,
-                167,
-                1192,
-                174,
-                695,
-                189,
-                190,
-                191,
-                198,
-                200,
-                201,
-                202,
-                713,
-                714,
-                715,
-                206,
-                207,
-                209,
-                210,
-                213,
-                221,
-                733,
-                1250,
-                231,
-                239,
-                241,
-                753,
-                254,
-                260,
-                269,
-                1300,
-                278,
-                792,
-                283,
-                286,
-                287,
-                800,
-                300,
-                301,
-                813,
-                309,
-                310,
-                315,
-                322,
-                329,
-                337,
-                340,
-                343,
-                344,
-                865,
-                874,
-                893,
-                895,
-                384,
-                394,
-                908,
-                410,
-                413,
-                416,
-                417,
-                1442,
-                438,
-                460,
-                1485,
-                2019,
-                486,
-                1512,
-                1019,
-                1023
-            ],
-
-        },
-        {
-            "id": "programming-skills",
-            "name": "编程能力",
-            "questions": [
-                2,
-                1031,
-                8,
-                525,
-                23,
-                535,
-                28,
-                43,
-                556,
-                48,
-                49,
-                1584,
-                54,
-                566,
-                58,
-                61,
-                65,
-                66,
-                67,
-                1626,
-                1630,
-                1125,
-                104,
-                110,
-                631,
-                635,
-                642,
-                138,
-                1677,
-                143,
-                146,
-                148,
-                150,
-                1176,
-                155,
-                1693,
-                1708,
-                173,
-                1713,
-                191,
-                1728,
-                1729,
-                1736,
-                713,
-                202,
-                715,
-                208,
-                209,
-                211,
-                214,
-                1752,
-                217,
-                729,
-                224,
-                227,
-                739,
-                742,
-                232,
-                1768,
-                1774,
-                241,
-                242,
-                244,
-                758,
-                251,
-                764,
-                255,
-                1791,
-                771,
-                1797,
-                775,
-                785,
-                2322,
-                281,
-                282,
-                283,
-                295,
-                297,
-                303,
-                304,
-                307,
-                325,
-                838,
-                1349,
-                850,
-                341,
-                859,
-                348,
-                860,
-                1888,
-                353,
-                1894,
-                369,
-                1905,
-                885,
-                890,
-                1915,
-                380,
-                381,
-                1406,
-                1411,
-                389,
-                1930,
-                908,
-                404,
-                1434,
-                1949,
-                1950,
-                931,
-                932,
-                1955,
-                937,
-                946,
-                1458,
-                438,
-                445,
-                1982,
-                449,
-                1477,
-                459,
-                460,
-                1484,
-                1492,
-                990,
-                2015,
-                1512,
-                496,
-                1014,
-                503,
-                1018
-            ],
-
-        },
-        {
-            "id": "meituan",
-            "name": "美团真题",
-            "questions": [
-                1000192,
-                1000193,
-                1000194,
-                1000195,
-                1000196,
-                1000197,
-                1000198,
-                1000199,
-                1000200,
-                1000201,
-                1000202,
-                1000203,
-                1000189,
-                1000190,
-                1000191,
-                257,
-                100158,
-                13,
-                455,
-                45,
-                200,
-                143,
-                139,
-                19,
-                100344,
-                162,
-                177,
-                75,
-                1036,
-                71,
-                475,
-                42,
-                51,
-                440,
-                25
-            ],
-
-        },
-        {
-            "id": "ke",
-            "name": "贝壳找房",
-            "questions": [
-                30,
-                120,
-                113,
-                85,
-                82,
-                209,
-                200,
-                315,
-                56,
-                53,
-                43,
-                2,
-                152,
-                20,
-                19,
-                17,
-                15,
-                14,
-                264,
-                135,
-                4
-            ],
-
-        },
-        {
-            "id": "efficient-winning",
-            "name": "高效制胜",
-            "questions": [
-                230,
-                329,
-                79,
-                720,
-                218,
-                1120,
-                97,
-                483,
-                1508,
-                456,
-                112,
-                496,
-                1008,
-                1013,
-                119,
-                121,
-                122,
-                416,
-                3,
-                11,
-                524,
-                15,
-                18,
-                20,
-                279,
-                28,
-                1,
-                803,
-                167,
-                42,
-                53,
-                825,
-                322,
-                70
-            ],
-
-        },
-        {
-            "id": "2cktkvj",
-            "name": "LeetCode 热题 HOT 100",
-            "questions": [
-                160,
-                236,
-                234,
-                739,
-                226,
-                221,
-                215,
-                208,
-                207,
-                206,
-                200,
-                198,
-                169,
-                238,
-                155,
-                152,
-                148,
-                146,
-                142,
-                141,
-                139,
-                136,
-                647,
-                128,
-                124,
-                322,
-                494,
-                461,
-                448,
-                438,
-                437,
-                416,
-                406,
-                399,
-                394,
-                347,
-                338,
-                337,
-                121,
-                312,
-                309,
-                301,
-                300,
-                297,
-                287,
-                283,
-                279,
-                253,
-                240,
-                239,
-                22,
-                49,
-                48,
-                46,
-                42,
-                39,
-                543,
-                34,
-                33,
-                32,
-                31,
-                538,
-                23,
-                560,
-                21,
-                20,
-                19,
-                17,
-                15,
-                11,
-                10,
-                5,
-                4,
-                3,
-                2,
-                79,
-                114,
-                621,
-                617,
-                105,
-                104,
-                102,
-                101,
-                98,
-                96,
-                94,
-                85,
-                84,
-                1,
-                78,
-                76,
-                75,
-                72,
-                70,
-                581,
-                64,
-                62,
-                56,
-                55,
-                53
-            ],
-
-        },
-        {
-            "id": "7cyqwuv",
-            "name": "力扣杯 - 竞赛合集",
-            "questions": [
-                1000134,
-                1000222,
-                1000362,
-                1000367,
-                1000368,
-                1000369,
-                1000370,
-                1000371,
-                1000373,
-                1000374,
-                1000375,
-                1000130,
-                1000131,
-                1000132,
-                1000133,
-                100094,
-                1000138,
-                1000139,
-                1000140,
-                1000146,
-                1000147,
-                1000056,
-                1000057,
-                1000058,
-                1000059,
-                100092,
-                100093,
-                1000062,
-                1000063,
-                1000216,
-                100107,
-                511,
-                1000085,
-                1000086,
-                1000087,
-                1000088,
-                1000089,
-                1000090,
-                1000091,
-                1052,
-                1053,
-                1000093,
-                1000215,
-                100096,
-                1000218,
-                1058,
-                1059,
-                1060,
-                1061,
-                1000219,
-                1000220,
-                1000223,
-                1000224,
-                1000221,
-                1000359,
-                1000361,
-                1069
-            ],
-
-        },
-        {
-            "id": "ex0k24j",
-            "name": "腾讯精选练习 50 题",
-            "questions": [
-                217,
-                46,
-                53,
-                54,
-                59,
-                61,
-                62,
-                70,
-                78,
-                206,
-                215,
-                88,
-                89,
-                557,
-                344,
-                230,
-                231,
-                104,
-                235,
-                236,
-                237,
-                238,
-                121,
-                122,
-                124,
-                146,
-                4,
-                5,
-                7,
-                8,
-                9,
-                136,
-                11,
-                141,
-                14,
-                15,
-                16,
-                142,
-                2,
-                20,
-                21,
-                148,
-                23,
-                26,
-                155,
-                160,
-                33,
-                292,
-                169,
-                43
-            ],
-
-        },
-        {
-            "id": "2ckc81c",
-            "name": "LeetCode 精选 TOP 面试题",
-            "questions": [
-                1,
-                2,
-                3,
-                4,
-                5,
-                7,
-                8,
-                10,
-                11,
-                13,
-                14,
-                15,
-                17,
-                19,
-                20,
-                21,
-                22,
-                23,
-                26,
-                28,
-                29,
-                33,
-                34,
-                36,
-                38,
-                41,
-                42,
-                44,
-                46,
-                48,
-                49,
-                50,
-                53,
-                54,
-                55,
-                56,
-                62,
-                66,
-                69,
-                70,
-                73,
-                75,
-                76,
-                78,
-                79,
-                84,
-                88,
-                91,
-                94,
-                98,
-                101,
-                102,
-                103,
-                104,
-                105,
-                108,
-                116,
-                118,
-                121,
-                122,
-                124,
-                125,
-                127,
-                128,
-                130,
-                131,
-                134,
-                136,
-                138,
-                139,
-                140,
-                141,
-                146,
-                148,
-                149,
-                150,
-                152,
-                155,
-                160,
-                162,
-                163,
-                166,
-                169,
-                171,
-                172,
-                179,
-                189,
-                190,
-                191,
-                198,
-                200,
-                202,
-                204,
-                206,
-                207,
-                208,
-                210,
-                212,
-                215,
-                217,
-                218,
-                227,
-                230,
-                234,
-                236,
-                237,
-                238,
-                239,
-                240,
-                242,
-                251,
-                253,
-                268,
-                269,
-                277,
-                279,
-                283,
-                285,
-                287,
-                289,
-                295,
-                297,
-                300,
-                308,
-                315,
-                322,
-                324,
-                326,
-                328,
-                329,
-                334,
-                340,
-                341,
-                344,
-                347,
-                348,
-                350,
-                371,
-                378,
-                380,
-                384,
-                387,
-                395,
-                412,
-                454
-            ],
-
-        }
-    ]
-    private tags_data = {
+    private tagsData = {
         "1": { "topicTags": ["array", "hash-table"] },
         "2": { "topicTags": ["recursion", "linked-list", "math"] },
         "3": { "topicTags": ["hash-table", "string", "sliding-window"] },
@@ -4867,7 +2804,7 @@ class ResourcesData {
         "面试题 17.26": { "topicTags": ["array", "hash-table", "sorting"] },
         "面试题13": { "topicTags": ["depth-first-search", "breadth-first-search", "dynamic-programming"] },
         "面试题59 - II": { "topicTags": ["design", "queue", "monotonic-queue"] }
-    }
+    };
 
     private tags_name = {
         'array': '数组',
@@ -4942,29 +2879,20 @@ class ResourcesData {
         'biconnected-component': '双连接组件',
         'strongly-connected-component': '强连接组件'
 
-    }
-    public getChoiceData() {
-        return this.choiceData
-    }
-
-    public getScoreData(): Map {
-
-        let nameSiteMapping = new Map();
-        const temp = this.scoreBase as IScoreData[]
-        temp.forEach(element => {
-            // Rating
-            // ID
-            // ContestSlug
-            element.score = "" + Math.floor(element.Rating || 0);
-            nameSiteMapping.set("" + element.ID, element)
-        });
-        return nameSiteMapping
-    }
+    };
     public getTagsData(fid: string): Array {
-        return (this.tags_data[fid]?.topicTags || []).map(p => {
-            return this.tags_name[p]
-        })
+        return (this.tagsData[fid]?.topicTags || []).map(p => {
+            return this.tags_name[p];
+        });
     }
+
 }
 
-export const resourcesData: ResourcesData = new ResourcesData();
+
+export const tagsDao: TagsDao = new TagsDao();
+
+
+
+
+
+
diff --git a/src/explorer/explorerNodeManager.ts b/src/explorer/explorerNodeManager.ts
deleted file mode 100644
index 0b5e0e1..0000000
--- a/src/explorer/explorerNodeManager.ts
+++ /dev/null
@@ -1,460 +0,0 @@
-// Copyright (c) jdneo. All rights reserved.
-// Licensed under the MIT license.
-
-import * as _ from "lodash";
-import { toNumber } from "lodash";
-import { Disposable } from "vscode";
-import * as list from "../commands/list";
-import { getSortingStrategy } from "../commands/plugin";
-import { Category, defaultProblem, ProblemState, SortingStrategy, SearchSetTypeName, RootNodeSort, SearchSetType, ISubmitEvent } from "../shared";
-import { shouldHideSolvedProblem, shouldHideScoreProblem } from "../utils/settingUtils";
-import { LeetCodeNode } from "./LeetCodeNode";
-import { ISearchSet } from "../shared";
-import { searchToday, searchUserContest } from "../commands/show";
-import { leetCodeTreeDataProvider } from "./LeetCodeTreeDataProvider";
-import { resourcesData } from "../ResourcesData";
-import { leetCodeManager } from "../leetCodeManager";
-
-class ExplorerNodeManager implements Disposable {
-    private explorerNodeMap: Map = new Map();
-    private companySet: Set = new Set();
-    private tagSet: Set = new Set();
-    private searchSet: Map = new Map();
-    private waitTodayQuestion: boolean;
-    private waitUserContest: boolean;
-    private user_score: number;
-
-
-    public async update_user_score(user_score: number) {
-        this.user_score = user_score;
-        await leetCodeTreeDataProvider.refresh()
-    }
-
-    public insertSearchSet(tt: ISearchSet) {
-        this.searchSet.set(tt.value, tt);
-    }
-    public clearUserScore() {
-        this.user_score = 0;
-        this.waitUserContest = false;
-        this.waitTodayQuestion = false;
-        this.searchSet = new Map();
-    }
-
-    public checkSubmit(e: ISubmitEvent) {
-        if (e.sub_type == "submit" && e.accepted) {
-            const day_start = new Date(new Date().setHours(0, 0, 0, 0)).getTime() / 1000; //获取当天零点的时间
-            const day_end = new Date(new Date().setHours(0, 0, 0, 0) + 24 * 60 * 60 * 1000 - 1).getTime() / 1000; //获取当天23:59:59的时间
-            var need_get_today: boolean = false;
-            this.searchSet.forEach(element => {
-                if (element.type == SearchSetType.Day) {
-                    if (day_start <= element.time && element.time <= day_end) {
-                        if (e.fid == element.value) {
-                            need_get_today = true;
-                        }
-                    }
-                }
-            });
-            if (need_get_today) {
-                searchToday();
-            }
-        }
-    }
-
-    public async refreshCheck(): Promise {
-        if (!leetCodeManager.getUser()) {
-            return;
-        }
-        const day_start = new Date(new Date().setHours(0, 0, 0, 0)).getTime() / 1000; //获取当天零点的时间
-        const day_end = new Date(new Date().setHours(0, 0, 0, 0) + 24 * 60 * 60 * 1000 - 1).getTime() / 1000; //获取当天23:59:59的时间
-        var need_get_today: boolean = true;
-        this.searchSet.forEach(element => {
-            if (element.type == SearchSetType.Day) {
-                if (day_start <= element.time && element.time <= day_end) {
-                    need_get_today = false;
-                } else {
-                    this.waitTodayQuestion = false
-                }
-            }
-        });
-        if (need_get_today && !this.waitTodayQuestion) {
-            this.waitTodayQuestion = true
-            await searchToday();
-        }
-        if (!this.user_score && !this.waitUserContest) {
-            this.waitUserContest = true;
-            await searchUserContest();
-        }
-    }
-
-    public async refreshCache(): Promise {
-        const temp_searchSet: Map = this.searchSet
-        const temp_waitTodayQuestion: boolean = this.waitTodayQuestion
-        const temp_waitUserContest: boolean = this.waitUserContest
-        this.dispose();
-        for (const problem of await list.listProblems()) {
-            this.explorerNodeMap.set(problem.id, new LeetCodeNode(problem, true, this.user_score));
-            for (const company of problem.companies) {
-                this.companySet.add(company);
-            }
-            for (const tag of problem.tags) {
-                this.tagSet.add(tag);
-            }
-        }
-        this.searchSet = temp_searchSet;
-        this.waitTodayQuestion = temp_waitTodayQuestion
-        this.waitUserContest = temp_waitUserContest
-    }
-
-    public getRootNodes(): LeetCodeNode[] {
-        const baseNode: LeetCodeNode[] = [
-            new LeetCodeNode(Object.assign({}, defaultProblem, {
-                id: Category.All,
-                name: Category.All,
-                rootNodeSortId: RootNodeSort.All,
-            }), false),
-            new LeetCodeNode(Object.assign({}, defaultProblem, {
-                id: Category.Difficulty,
-                name: Category.Difficulty,
-                rootNodeSortId: RootNodeSort.Difficulty,
-            }), false),
-            new LeetCodeNode(Object.assign({}, defaultProblem, {
-                id: Category.Tag,
-                name: Category.Tag,
-                rootNodeSortId: RootNodeSort.Tag,
-            }), false),
-            // new LeetCodeNode(Object.assign({}, defaultProblem, {
-            //     id: Category.Company,
-            //     name: Category.Company,
-            //     rootNodeSortId: RootNodeSort.Company,
-            // }), false),
-            new LeetCodeNode(Object.assign({}, defaultProblem, {
-                id: Category.Favorite,
-                name: Category.Favorite,
-                rootNodeSortId: RootNodeSort.Favorite,
-            }), false),
-            new LeetCodeNode(Object.assign({}, defaultProblem, {
-                id: Category.Score,
-                name: Category.Score,
-                rootNodeSortId: RootNodeSort.Score,
-            }), false, this.user_score),
-            new LeetCodeNode(Object.assign({}, defaultProblem, {
-                id: Category.Choice,
-                name: Category.Choice,
-                rootNodeSortId: RootNodeSort.Choice,
-            }), false),
-        ];
-        this.searchSet.forEach(element => {
-            if (element.type == SearchSetType.Day) {
-                const curDate = new Date(element.time * 1000)
-                baseNode.push(new LeetCodeNode(Object.assign({}, defaultProblem, {
-                    id: element.type,
-                    name: "[" + (curDate.getFullYear()) + "-" + (curDate.getMonth() + 1) + "-" + (curDate.getDate()) + "]" + SearchSetTypeName[SearchSetType.Day],
-                    input: element.value,
-                    isSearchResult: true,
-                    rootNodeSortId: RootNodeSort[element.type],
-                    todayData: element.todayData
-                }), false));
-            } else {
-                baseNode.push(new LeetCodeNode(Object.assign({}, defaultProblem, {
-                    id: element.type,
-                    name: SearchSetTypeName[element.type] + element.value,
-                    input: element.value,
-                    isSearchResult: true,
-                    rootNodeSortId: RootNodeSort[element.type],
-                }), false));
-            }
-        });
-        baseNode.sort(function (a: LeetCodeNode, b: LeetCodeNode): number {
-            if (a.rootNodeSortId < b.rootNodeSortId) {
-                return -1;
-            } else if (a.rootNodeSortId > b.rootNodeSortId) {
-                return 1
-            }
-            return 0;
-        })
-        return baseNode;
-    }
-
-    public getScoreRangeNodes(rank_range: string): LeetCodeNode[] {
-        const sorceNode: LeetCodeNode[] = []
-        const rank_r: Array = rank_range.split("-")
-        var rank_a = Number(rank_r[0])
-        var rank_b = Number(rank_r[1])
-        if (rank_a > 0 && rank_b > 0) {
-            if (rank_a > rank_b) {
-                const rank_c: number = rank_a
-                rank_a = rank_b
-                rank_b = rank_c
-            }
-
-            this.explorerNodeMap.forEach(element => {
-                if (!this.canShow(element)) {
-                    return;
-                }
-                if (rank_a <= Number(element.score) && Number(element.score) <= rank_b) {
-                    sorceNode.push(element)
-                }
-            });
-        }
-        return this.applySortingStrategy(sorceNode);
-    }
-
-    public canShow(element: LeetCodeNode) {
-        if (shouldHideSolvedProblem() && element.state === ProblemState.AC) {
-            return false;
-        }
-        if (shouldHideScoreProblem(element, element.user_score)) {
-            return false;
-        }
-        return true;
-    }
-
-    public getContextNodes(rank_range: string): LeetCodeNode[] {
-        const sorceNode: LeetCodeNode[] = []
-        const rank_r: Array = rank_range.split("-")
-        var rank_a = Number(rank_r[0])
-        var rank_b = Number(rank_r[1])
-        if (rank_a > 0) {
-            this.explorerNodeMap.forEach(element => {
-                if (!this.canShow(element)) {
-                    return;
-                }
-                const slu = element.ContestSlug;
-                const slu_arr: Array = slu.split("-")
-                const slu_id = Number(slu_arr[slu_arr.length - 1]);
-                if (rank_b > 0 && rank_a <= slu_id && slu_id <= rank_b) {
-                    sorceNode.push(element)
-                } else if (rank_a == slu_id) {
-                    sorceNode.push(element)
-                }
-            });
-        }
-        return this.applySortingStrategy(sorceNode);
-    }
-    public getDayNodes(element: LeetCodeNode | undefined): LeetCodeNode[] {
-        const rank_range: string = element?.input || ""
-        const sorceNode: LeetCodeNode[] = []
-        if (rank_range) {
-            this.explorerNodeMap.forEach(new_node => {
-                if (new_node.id == rank_range) {
-                    new_node.todayData = element?.todayData
-                    sorceNode.push(new_node);
-                }
-            });
-        }
-        return this.applySortingStrategy(sorceNode);
-    }
-
-    public getAllNodes(): LeetCodeNode[] {
-        return this.applySortingStrategy(
-            Array.from(this.explorerNodeMap.values()).filter(p => this.canShow(p)),
-        );
-    }
-
-    public getAllDifficultyNodes(): LeetCodeNode[] {
-        const res: LeetCodeNode[] = [];
-        res.push(
-            new LeetCodeNode(Object.assign({}, defaultProblem, {
-                id: `${Category.Difficulty}.Easy`,
-                name: "Easy",
-            }), false),
-            new LeetCodeNode(Object.assign({}, defaultProblem, {
-                id: `${Category.Difficulty}.Medium`,
-                name: "Medium",
-            }), false),
-            new LeetCodeNode(Object.assign({}, defaultProblem, {
-                id: `${Category.Difficulty}.Hard`,
-                name: "Hard",
-            }), false),
-        );
-        this.sortSubCategoryNodes(res, Category.Difficulty);
-        return res;
-    }
-
-    public getAllScoreNodes(user_score: number): LeetCodeNode[] {
-        const res: LeetCodeNode[] = [];
-        const score_array: Array = ["3300", "3200", "3100", "3000", "2900", "2800", "2700", "2600", "2500", "2400", "2300", "2200", "2100", "2000", "1900", "1800", "1700", "1600", "1500", "1400", "1300", "1200", "1100"];
-        score_array.forEach(element => {
-            const temp_num = Number(element);
-            const diff = Math.abs(temp_num - user_score)
-            if (diff <= 200) {
-                res.push(new LeetCodeNode(Object.assign({}, defaultProblem, {
-                    id: `${Category.Score}.${element}`,
-                    name: `${element}`,
-                }), false, user_score))
-            }
-        })
-
-        this.sortSubCategoryNodes(res, Category.Score);
-        return res;
-    }
-
-    public getAllChoiceNodes(): LeetCodeNode[] {
-        const res: LeetCodeNode[] = [];
-
-        const all_choice = resourcesData.getChoiceData();
-        all_choice.forEach(element => {
-            res.push(new LeetCodeNode(Object.assign({}, defaultProblem, {
-                id: `${Category.Choice}.${element.id}`,
-                name: `${element.name}`,
-            }), false))
-        })
-        this.sortSubCategoryNodes(res, Category.Choice);
-        return res;
-    }
-
-    public getAllCompanyNodes(): LeetCodeNode[] {
-        const res: LeetCodeNode[] = [];
-        for (const company of this.companySet.values()) {
-            res.push(new LeetCodeNode(Object.assign({}, defaultProblem, {
-                id: `${Category.Company}.${company}`,
-                name: _.startCase(company),
-            }), false));
-        }
-        this.sortSubCategoryNodes(res, Category.Company);
-        return res;
-    }
-
-    public getAllTagNodes(): LeetCodeNode[] {
-        const res: LeetCodeNode[] = [];
-        for (const tag of this.tagSet.values()) {
-            res.push(new LeetCodeNode(Object.assign({}, defaultProblem, {
-                id: `${Category.Tag}.${tag}`,
-                name: _.startCase(tag),
-            }), false));
-        }
-        this.sortSubCategoryNodes(res, Category.Tag);
-        return res;
-    }
-
-    public getNodeById(id: string): LeetCodeNode | undefined {
-        return this.explorerNodeMap.get(id);
-    }
-
-    public getFavoriteNodes(): LeetCodeNode[] {
-        const res: LeetCodeNode[] = [];
-        for (const node of this.explorerNodeMap.values()) {
-            if (!this.canShow(node)) {
-                continue;
-            }
-            if (node.isFavorite) {
-                res.push(node);
-            }
-        }
-        return this.applySortingStrategy(res);
-    }
-
-    public getChildrenNodesById(id: string): LeetCodeNode[] {
-        // The sub-category node's id is named as {Category.SubName}
-        const metaInfo: string[] = id.split(".");
-        const res: LeetCodeNode[] = [];
-
-        const choiceQuestionId: Map = new Map()
-        if (metaInfo[0] == Category.Choice) {
-            const all_choice = resourcesData.getChoiceData();
-            all_choice.forEach(element => {
-                if (element.id == metaInfo[1]) {
-                    element.questions.forEach(kk => {
-                        choiceQuestionId[kk] = true
-                    })
-                    return
-                }
-            })
-        }
-
-        for (const node of this.explorerNodeMap.values()) {
-            if (!this.canShow(node)) {
-                continue;
-            }
-            switch (metaInfo[0]) {
-                case Category.Company:
-                    if (node.companies.indexOf(metaInfo[1]) >= 0) {
-                        res.push(node);
-                    }
-                    break;
-                case Category.Difficulty:
-                    if (node.difficulty === metaInfo[1]) {
-                        res.push(node);
-                    }
-                    break;
-                case Category.Tag:
-                    if (node.tags.indexOf(metaInfo[1]) >= 0) {
-                        res.push(node);
-                    }
-                    break;
-                case Category.Score:
-                    if (node.score > "0") {
-                        const check_rank = toNumber(metaInfo[1]);
-                        const node_rank = toNumber(node.score);
-                        if (check_rank <= node_rank && node_rank < check_rank + 100) {
-                            res.push(node);
-                        }
-                    }
-                    break;
-                case Category.Choice:
-                    if (choiceQuestionId[Number(node.qid)]) {
-                        res.push(node);
-                    }
-                default:
-                    break;
-            }
-        }
-        return this.applySortingStrategy(res);
-    }
-
-    public dispose(): void {
-        this.explorerNodeMap.clear();
-        this.companySet.clear();
-        this.tagSet.clear();
-    }
-
-    private sortSubCategoryNodes(subCategoryNodes: LeetCodeNode[], category: Category): void {
-        switch (category) {
-            case Category.Difficulty:
-                subCategoryNodes.sort((a: LeetCodeNode, b: LeetCodeNode): number => {
-                    function getValue(input: LeetCodeNode): number {
-                        switch (input.name.toLowerCase()) {
-                            case "easy":
-                                return 1;
-                            case "medium":
-                                return 2;
-                            case "hard":
-                                return 3;
-                            default:
-                                return Number.MAX_SAFE_INTEGER;
-                        }
-                    }
-                    return getValue(a) - getValue(b);
-                });
-                break;
-            case Category.Tag:
-            case Category.Company:
-                subCategoryNodes.sort((a: LeetCodeNode, b: LeetCodeNode): number => {
-                    if (a.name === "Unknown") {
-                        return 1;
-                    } else if (b.name === "Unknown") {
-                        return -1;
-                    } else {
-                        return Number(a.name > b.name) - Number(a.name < b.name);
-                    }
-                });
-                break;
-            default:
-                break;
-        }
-    }
-
-    private applySortingStrategy(nodes: LeetCodeNode[]): LeetCodeNode[] {
-        const strategy: SortingStrategy = getSortingStrategy();
-        switch (strategy) {
-            case SortingStrategy.AcceptanceRateAsc: return nodes.sort((x: LeetCodeNode, y: LeetCodeNode) => Number(x.acceptanceRate) - Number(y.acceptanceRate));
-            case SortingStrategy.AcceptanceRateDesc: return nodes.sort((x: LeetCodeNode, y: LeetCodeNode) => Number(y.acceptanceRate) - Number(x.acceptanceRate));
-            case SortingStrategy.ScoreAsc: return nodes.sort((x: LeetCodeNode, y: LeetCodeNode) => Number(x.score) - Number(y.score));
-            case SortingStrategy.ScoreDesc: return nodes.sort((x: LeetCodeNode, y: LeetCodeNode) => Number(y.score) - Number(x.score));
-            case SortingStrategy.IDDesc: return nodes.sort((x: LeetCodeNode, y: LeetCodeNode) => Number(y.id) - Number(x.id));
-            default: return nodes;
-        }
-    }
-}
-
-export const explorerNodeManager: ExplorerNodeManager = new ExplorerNodeManager();
diff --git a/src/extension.ts b/src/extension.ts
index 829a168..5ddec09 100644
--- a/src/extension.ts
+++ b/src/extension.ts
@@ -1,96 +1,83 @@
-// Copyright (c) jdneo. All rights reserved.
-// Licensed under the MIT license.
+/*
+ * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/extension.ts
+ * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
+ * Created Date: Monday, October 31st 2022, 10:16:47 am
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
 
-import * as vscode from "vscode";
-import { codeLensController } from "./codelens/CodeLensController";
-import * as cache from "./commands/cache";
-import { switchDefaultLanguage } from "./commands/language";
-import * as plugin from "./commands/plugin";
-import * as session from "./commands/session";
-import * as show from "./commands/show";
-import * as star from "./commands/star";
-import * as submit from "./commands/submit";
-import * as test from "./commands/test";
-import { explorerNodeManager } from "./explorer/explorerNodeManager";
-import { LeetCodeNode } from "./explorer/LeetCodeNode";
-import { leetCodeTreeDataProvider } from "./explorer/LeetCodeTreeDataProvider";
-import { leetCodeTreeItemDecorationProvider } from "./explorer/LeetCodeTreeItemDecorationProvider";
-import { leetCodeChannel } from "./leetCodeChannel";
-import { leetCodeExecutor } from "./leetCodeExecutor";
-import { leetCodeManager } from "./leetCodeManager";
-import { leetCodeStatusBarController } from "./statusbar/leetCodeStatusBarController";
-import { DialogType, promptForOpenOutputChannel } from "./utils/uiUtils";
-import { leetCodePreviewProvider } from "./webview/leetCodePreviewProvider";
-import { leetCodeSolutionProvider } from "./webview/leetCodeSolutionProvider";
-import { leetCodeSubmissionProvider } from "./webview/leetCodeSubmissionProvider";
-import { markdownEngine } from "./webview/markdownEngine";
-import { ISubmitEvent } from "./shared";
-import * as wsl from "./utils/wslUtils";
 
+import { ExtensionContext, window, commands, Uri } from "vscode";
+import { fileButtonController } from "./controller/FileButtonController";
+import { treeViewController } from "./controller/TreeViewController";
+import { NodeModel } from "./model/NodeModel";
+import { treeDataService } from "./service/TreeDataService";
+import { treeItemDecorationService } from "./service/TreeItemDecorationService";
+import { logOutput, promptForOpenOutputChannel } from "./utils/OutputUtils";
+import { executeService } from "./service/ExecuteService";
+import { eventController } from "./controller/EventController";
+import { statusBarService } from "./service/StatusBarService";
+import { previewService } from "./service/PreviewService";
+import { solutionService } from "./service/SolutionService";
+import { submissionService } from "./service/SubmissionService";
+import { markdownService } from "./service/MarkdownService";
+import { mainContorller } from "./controller/MainController";
+import { loginContorller } from "./controller/LoginController";
+import { getLeetCodeEndpoint } from "./utils/ConfigUtils";
+import { DialogType } from "./model/Model";
 
-export async function activate(context: vscode.ExtensionContext): Promise {
+// 激活插件
+export async function activate(context: ExtensionContext): Promise {
     try {
 
-        if (!wsl.useVscodeNode()) {
-            if (!await leetCodeExecutor.meetRequirements(context)) {
-                throw new Error("The environment doesn't meet requirements.");
-            }
-        }
-
-
-        leetCodeManager.on("statusChanged", () => {
-            leetCodeStatusBarController.updateStatusBar(leetCodeManager.getStatus(), leetCodeManager.getUser());
-            leetCodeTreeDataProvider.cleanUserScore();
-            leetCodeTreeDataProvider.refresh();
-        });
-        leetCodeManager.on("submit", (e: ISubmitEvent) => {
-            leetCodeTreeDataProvider.checkSubmit(e);
-        });
-
-        leetCodeManager.on("searchUserContest", () => {
-            leetCodeStatusBarController.updateStatusBar(leetCodeManager.getStatus(), leetCodeManager.getUser(), leetCodeManager.getUserContestInfo());
-        });
-
-        leetCodeTreeDataProvider.initialize(context);
+        // 初始化控制器
+        mainContorller.initialize(context);
+        // 检查node环境
+        await mainContorller.checkNodeEnv(context);
+        // 事件监听
+        eventController.add_event();
 
+        // 资源管理
         context.subscriptions.push(
-            leetCodeStatusBarController,
-            leetCodeChannel,
-            leetCodePreviewProvider,
-            leetCodeSubmissionProvider,
-            leetCodeSolutionProvider,
-            leetCodeExecutor,
-            markdownEngine,
-            codeLensController,
-            explorerNodeManager,
-            vscode.window.registerFileDecorationProvider(leetCodeTreeItemDecorationProvider),
-            vscode.window.createTreeView("leetCodeExplorer", { treeDataProvider: leetCodeTreeDataProvider, showCollapseAll: true }),
-            vscode.commands.registerCommand("leetcode.deleteCache", () => cache.deleteCache()),
-            vscode.commands.registerCommand("leetcode.toggleLeetCodeCn", () => plugin.switchEndpoint()),
-            vscode.commands.registerCommand("leetcode.signin", () => leetCodeManager.signIn()),
-            vscode.commands.registerCommand("leetcode.signout", () => leetCodeManager.signOut()),
-            vscode.commands.registerCommand("leetcode.manageSessions", () => session.manageSessions()),
-            vscode.commands.registerCommand("leetcode.previewProblem", (node: LeetCodeNode) => show.previewProblem(node)),
-            vscode.commands.registerCommand("leetcode.showProblem", (node: LeetCodeNode) => show.showProblem(node)),
-            vscode.commands.registerCommand("leetcode.pickOne", () => show.pickOne()),
-            vscode.commands.registerCommand("leetcode.deleteAllCache", () => show.deleteAllCache()),
-            vscode.commands.registerCommand("leetcode.searchScoreRange", () => show.searchScoreRange()),
-            vscode.commands.registerCommand("leetcode.searchProblem", () => show.searchProblem()),
-            vscode.commands.registerCommand("leetcode.showSolution", (input: LeetCodeNode | vscode.Uri) => show.showSolution(input)),
-            vscode.commands.registerCommand("leetcode.refreshExplorer", () => leetCodeTreeDataProvider.refresh()),
-            vscode.commands.registerCommand("leetcode.testSolution", (uri?: vscode.Uri) => test.testSolution(uri)),
-            vscode.commands.registerCommand("leetcode.testSolutionDefault", (uri?: vscode.Uri, allCase?: boolean) => test.testSolutionDefault(uri, allCase)),
-            vscode.commands.registerCommand("leetcode.submitSolution", (uri?: vscode.Uri) => submit.submitSolution(uri)),
-            vscode.commands.registerCommand("leetcode.switchDefaultLanguage", () => switchDefaultLanguage()),
-            vscode.commands.registerCommand("leetcode.addFavorite", (node: LeetCodeNode) => star.addFavorite(node)),
-            vscode.commands.registerCommand("leetcode.removeFavorite", (node: LeetCodeNode) => star.removeFavorite(node)),
-            vscode.commands.registerCommand("leetcode.problems.sort", () => plugin.switchSortingStrategy()),
+            statusBarService,
+            logOutput,
+            previewService,
+            submissionService,
+            solutionService,
+            executeService,
+            markdownService,
+            fileButtonController,
+            treeViewController,
+            window.registerFileDecorationProvider(treeItemDecorationService),
+            window.createTreeView("leetCodeExplorer", { treeDataProvider: treeDataService, showCollapseAll: true }),
+            commands.registerCommand("leetcode.deleteCache", () => mainContorller.deleteCache()),
+            commands.registerCommand("leetcode.toggleLeetCodeCn", () => treeViewController.switchEndpoint()),
+            commands.registerCommand("leetcode.signin", () => loginContorller.signIn()),
+            commands.registerCommand("leetcode.signout", () => loginContorller.signOut()),
+            commands.registerCommand("leetcode.previewProblem", (node: NodeModel) => treeViewController.previewProblem(node)),
+            commands.registerCommand("leetcode.showProblem", (node: NodeModel) => treeViewController.showProblem(node)),
+            commands.registerCommand("leetcode.pickOne", () => treeViewController.pickOne()),
+            commands.registerCommand("leetcode.deleteAllCache", () => loginContorller.deleteAllCache()),
+            commands.registerCommand("leetcode.searchScoreRange", () => treeViewController.searchScoreRange()),
+            commands.registerCommand("leetcode.searchProblem", () => treeViewController.searchProblem()),
+            commands.registerCommand("leetcode.showSolution", (input: NodeModel | Uri) => treeViewController.showSolution(input)),
+            commands.registerCommand("leetcode.refreshExplorer", () => treeDataService.refresh()),
+            commands.registerCommand("leetcode.testSolution", (uri?: Uri) => treeViewController.testSolution(uri)),
+            commands.registerCommand("leetcode.testSolutionDefault", (uri?: Uri, allCase?: boolean) => treeViewController.testSolutionDefault(uri, allCase)),
+            commands.registerCommand("leetcode.submitSolution", (uri?: Uri) => treeViewController.submitSolution(uri)),
+            commands.registerCommand("leetcode.switchDefaultLanguage", () => treeViewController.switchDefaultLanguage()),
+            commands.registerCommand("leetcode.addFavorite", (node: NodeModel) => treeViewController.addFavorite(node)),
+            commands.registerCommand("leetcode.removeFavorite", (node: NodeModel) => treeViewController.removeFavorite(node)),
+            commands.registerCommand("leetcode.problems.sort", () => treeViewController.switchSortingStrategy()),
         );
 
-        await leetCodeExecutor.switchEndpoint(plugin.getLeetCodeEndpoint());
-        await leetCodeManager.getLoginStatus();
+        // 设置站点
+        await executeService.switchEndpoint(getLeetCodeEndpoint());
+        // 获取登录状态
+        await loginContorller.getLoginStatus();
     } catch (error) {
-        leetCodeChannel.appendLine(error.toString());
+        logOutput.appendLine(error.toString());
         promptForOpenOutputChannel("Extension initialization failed. Please open output channel for details.", DialogType.error);
     }
 }
@@ -98,7 +85,7 @@ export async function activate(context: vscode.ExtensionContext): Promise
 export function deactivate(): void {
     // Do nothing.
     if (0) {
-        var a = 0;
+        let a = 0;
         console.log(a);
     }
 }
diff --git a/src/leetCodeChannel.ts b/src/leetCodeChannel.ts
deleted file mode 100644
index fa32ac2..0000000
--- a/src/leetCodeChannel.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) jdneo. All rights reserved.
-// Licensed under the MIT license.
-
-import * as vscode from "vscode";
-
-class LeetCodeChannel implements vscode.Disposable {
-    private readonly channel: vscode.OutputChannel = vscode.window.createOutputChannel("LeetCode");
-
-    public appendLine(message: string): void {
-        this.channel.appendLine(message);
-    }
-
-    public append(message: string): void {
-        this.channel.append(message);
-    }
-
-    public show(): void {
-        this.channel.show();
-    }
-
-    public dispose(): void {
-        this.channel.dispose();
-    }
-}
-
-export const leetCodeChannel: LeetCodeChannel = new LeetCodeChannel();
diff --git a/src/leetCodeManager.ts b/src/leetCodeManager.ts
deleted file mode 100644
index 2dc42bd..0000000
--- a/src/leetCodeManager.ts
+++ /dev/null
@@ -1,223 +0,0 @@
-// Copyright (c) jdneo. All rights reserved.
-// Licensed under the MIT license.
-
-import * as cp from "child_process";
-import { EventEmitter } from "events";
-import * as vscode from "vscode";
-import { leetCodeChannel } from "./leetCodeChannel";
-import { leetCodeExecutor } from "./leetCodeExecutor";
-import { IQuickItemEx, loginArgsMapping, UserStatus, userContestRanKingBase, userContestRankingObj } from "./shared";
-import { createEnvOption } from "./utils/cpUtils";
-import { DialogType, promptForOpenOutputChannel } from "./utils/uiUtils";
-import * as wsl from "./utils/wslUtils";
-import { explorerNodeManager } from "./explorer/explorerNodeManager";
-
-class LeetCodeManager extends EventEmitter {
-    private currentUser: string | undefined;
-    private userStatus: UserStatus;
-    // private readonly successRegex: RegExp = /(?:.*)Successfully .*login as (.*)/i;
-    // private readonly failRegex: RegExp = /.*\[ERROR\].*/i;
-    private currentUserContestInfo: userContestRanKingBase;
-
-    constructor() {
-        super();
-        this.currentUser = undefined;
-        this.userStatus = UserStatus.SignedOut;
-    }
-
-    public async insertCurrentUserContestInfo(tt: userContestRanKingBase) {
-        this.currentUserContestInfo = tt;
-        await explorerNodeManager.update_user_score(tt.rating);
-    }
-    public async getLoginStatus(): Promise {
-        try {
-            const result: string = await leetCodeExecutor.getUserInfo();
-            this.currentUser = this.tryParseUserName(result);
-            this.userStatus = UserStatus.SignedIn;
-            if (this.currentUser == undefined) {
-                this.userStatus = UserStatus.SignedOut;
-            }
-        } catch (error) {
-            this.currentUser = undefined;
-            this.userStatus = UserStatus.SignedOut;
-        } finally {
-            this.emit("statusChanged");
-        }
-    }
-
-    public async signIn(): Promise {
-        const picks: Array> = [];
-        picks.push(
-            {
-                label: "LeetCode Account",
-                detail: "Use LeetCode account to login (US endpoint is not supported)",
-                value: "LeetCode",
-            },
-            {
-                label: "Third-Party: GitHub",
-                detail: "Use GitHub account to login",
-                value: "GitHub",
-            },
-            {
-                label: "Third-Party: LinkedIn",
-                detail: "Use LinkedIn account to login",
-                value: "LinkedIn",
-            },
-            {
-                label: "LeetCode Cookie",
-                detail: "Use LeetCode cookie copied from browser to login",
-                value: "Cookie",
-            },
-        );
-        const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(picks);
-        if (!choice) {
-            return;
-        }
-        const loginMethod: string = choice.value;
-        const commandArg: string | undefined = loginArgsMapping.get(loginMethod);
-        if (!commandArg) {
-            throw new Error(`The login method "${loginMethod}" is not supported.`);
-        }
-        const isByCookie: boolean = loginMethod === "Cookie";
-        const inMessage: string = isByCookie ? "sign in by cookie" : "sign in";
-        try {
-            const userName: string | undefined = await new Promise(async (resolve: (res: string | undefined) => void, reject: (e: Error) => void): Promise => {
-
-                const leetCodeBinaryPath: string = await leetCodeExecutor.getLeetCodeBinaryPath();
-
-                var childProc: cp.ChildProcess;
-
-                if (wsl.useVscodeNode()) {
-                    childProc = cp.fork(await leetCodeExecutor.getLeetCodeBinaryPath(), ["user", commandArg], {
-                        silent: true,
-                        env: createEnvOption(),
-                    });
-                } else {
-                    if (wsl.useWsl()) {
-                        childProc = cp.spawn("wsl", [leetCodeExecutor.node, leetCodeBinaryPath, "user", commandArg], { shell: true })
-                    } else {
-                        childProc = cp.spawn(leetCodeExecutor.node, [leetCodeBinaryPath, "user", commandArg], {
-                            shell: true,
-                            env: createEnvOption(),
-                        });
-                    }
-
-                }
-
-                childProc.stdout?.on("data", async (data: string | Buffer) => {
-                    data = data.toString();
-                    // vscode.window.showInformationMessage(`cc login msg ${data}.`);
-                    leetCodeChannel.append(data);
-                    if (data.includes("twoFactorCode")) {
-                        const twoFactor: string | undefined = await vscode.window.showInputBox({
-                            prompt: "Enter two-factor code.",
-                            ignoreFocusOut: true,
-                            validateInput: (s: string): string | undefined => s && s.trim() ? undefined : "The input must not be empty",
-                        });
-                        if (!twoFactor) {
-                            childProc.kill();
-                            return resolve(undefined);
-                        }
-                        childProc.stdin?.write(`${twoFactor}\n`);
-                    }
-
-                    var successMatch;
-                    try {
-                        successMatch = JSON.parse(data);
-                    } catch (e) {
-                        successMatch = {};
-                    }
-                    if (successMatch.code == 100) {
-                        childProc.stdin?.end();
-                        return resolve(successMatch.user_name);
-                    } else if (successMatch.code < 0) {
-                        childProc.stdin?.end();
-                        return reject(new Error(successMatch.msg));
-                    }
-                });
-
-                childProc.stderr?.on("data", (data: string | Buffer) => leetCodeChannel.append(data.toString()));
-
-                childProc.on("error", reject);
-                const name: string | undefined = await vscode.window.showInputBox({
-                    prompt: "Enter username or E-mail.",
-                    ignoreFocusOut: true,
-                    validateInput: (s: string): string | undefined => s && s.trim() ? undefined : "The input must not be empty",
-                });
-                if (!name) {
-                    childProc.kill();
-                    return resolve(undefined);
-                }
-                childProc.stdin?.write(`${name}\n`);
-                const pwd: string | undefined = await vscode.window.showInputBox({
-                    prompt: isByCookie ? "Enter cookie" : "Enter password.",
-                    password: true,
-                    ignoreFocusOut: true,
-                    validateInput: (s: string): string | undefined => s ? undefined : isByCookie ? "Cookie must not be empty" : "Password must not be empty",
-                });
-                if (!pwd) {
-                    childProc.kill();
-                    return resolve(undefined);
-                }
-                childProc.stdin?.write(`${pwd}\n`);
-            });
-            if (userName) {
-                vscode.window.showInformationMessage(`Successfully ${inMessage}.`);
-                this.currentUser = userName;
-                this.userStatus = UserStatus.SignedIn;
-                this.emit("statusChanged");
-            }
-        } catch (error) {
-            promptForOpenOutputChannel(`Failed to ${inMessage}. Please open the output channel for details`, DialogType.error);
-        }
-
-    }
-
-    public async signOut(): Promise {
-        try {
-            await leetCodeExecutor.signOut();
-            vscode.window.showInformationMessage("Successfully signed out.");
-            this.currentUser = undefined;
-            this.userStatus = UserStatus.SignedOut;
-            this.currentUserContestInfo = Object.assign({}, userContestRankingObj, {})
-            this.emit("statusChanged");
-        } catch (error) {
-            // swallow the error when sign out.
-        }
-    }
-
-    public getStatus(): UserStatus {
-        return this.userStatus;
-    }
-
-    // 获取竞赛分
-    public getUserContestScore(): number {
-        if (this.currentUserContestInfo.rating > 0) {
-            return this.currentUserContestInfo.rating
-        }
-        return 0;
-    }
-
-    public getUserContestInfo(): userContestRanKingBase | undefined {
-        return this.currentUserContestInfo;
-    }
-
-    public getUser(): string | undefined {
-        return this.currentUser;
-    }
-
-    private tryParseUserName(output: string): string | undefined {
-        var successMatch;
-        try {
-            successMatch = JSON.parse(output);
-        } catch (e) {
-            successMatch = {};
-        }
-        if (successMatch.code == 100) {
-            return successMatch.user_name;
-        }
-        return undefined;
-    }
-}
-
-export const leetCodeManager: LeetCodeManager = new LeetCodeManager();
diff --git a/src/shared.ts b/src/model/Model.ts
similarity index 74%
rename from src/shared.ts
rename to src/model/Model.ts
index 37ce32e..170dea0 100644
--- a/src/shared.ts
+++ b/src/model/Model.ts
@@ -1,9 +1,16 @@
-// Copyright (c) jdneo. All rights reserved.
-// Licensed under the MIT license.
+/*
+ * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/model/Model.ts
+ * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
+ * Created Date: Thursday, October 27th 2022, 7:43:29 pm
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
 
-import * as vscode from "vscode";
 
-export interface IQuickItemEx extends vscode.QuickPickItem {
+import { ViewColumn, QuickPickItem, MessageItem } from "vscode";
+
+export interface IQuickItemEx extends QuickPickItem {
     value: T;
 }
 
@@ -173,6 +180,17 @@ export enum SortingStrategy {
     IDDesc = "ID (Descending)"
 }
 
+
+export const SORT_ORDER: SortingStrategy[] = [
+    SortingStrategy.None,
+    SortingStrategy.AcceptanceRateAsc,
+    SortingStrategy.AcceptanceRateDesc,
+    SortingStrategy.ScoreAsc,
+    SortingStrategy.ScoreDesc,
+    SortingStrategy.IDDesc,
+];
+
+
 export enum SearchSetType {
     ScoreRange = "ScoreRange",
     Context = "Context",
@@ -197,7 +215,7 @@ export const SearchNode: ISearchSet = {
     type: SearchSetType.ScoreRange,
     time: 0,
     todayData: undefined
-}
+};
 
 export interface userContestRanKingBase {
     attendedContestsCount: number, // 参与次数
@@ -227,3 +245,39 @@ export interface ISubmitEvent {
     sub_type: string; // test  submit
     accepted: boolean
 }
+
+
+export interface IWebViewOption {
+    title: string;
+    viewColumn: ViewColumn;
+    preserveFocus?: boolean;
+}
+
+
+export enum OpenOption {
+    justOpenFile = "仅打开问题文件",
+    openInCurrentWindow = "在当前VsCode窗口打开",
+    openInNewWindow = "在新的VsCode窗口打开",
+    addToWorkspace = "添加到工作空间",
+}
+
+export enum DialogType {
+    info = "info",
+    warning = "warning",
+    error = "error",
+}
+
+
+export const MessageItemObj: MessageItem = {
+    title: "",
+    isCloseAffordance: false,
+};
+
+
+export const DialogOptions = {
+    open: Object.assign({}, MessageItemObj, { title: "Open" }),
+    yes: Object.assign({}, MessageItemObj, { title: "Yes" }),
+    no: Object.assign({}, MessageItemObj, { title: "No", isCloseAffordance: true }),
+    never: Object.assign({}, MessageItemObj, { title: "Never" }),
+    singUp: Object.assign({}, MessageItemObj, { title: "Sign up" }),
+};
diff --git a/src/explorer/LeetCodeNode.ts b/src/model/NodeModel.ts
similarity index 79%
rename from src/explorer/LeetCodeNode.ts
rename to src/model/NodeModel.ts
index 821517e..39c0e52 100644
--- a/src/explorer/LeetCodeNode.ts
+++ b/src/model/NodeModel.ts
@@ -1,10 +1,17 @@
-// Copyright (c) jdneo. All rights reserved.
-// Licensed under the MIT license.
+/*
+ * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/model/NodeMOdel.ts
+ * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
+ * Created Date: Thursday, October 27th 2022, 7:43:29 pm
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
+
 
 import { Command, Uri } from "vscode";
-import { IProblem, IScoreData, ITodayData, ProblemState, RootNodeSort } from "../shared";
+import { IProblem, IScoreData, ITodayData, ProblemState, RootNodeSort } from "./Model";
 
-export class LeetCodeNode {
+export class NodeModel {
     private _u_score;
     constructor(private data: IProblem, private isProblemNode: boolean = true, userscore: number = 0) {
         this._u_score = userscore;
@@ -21,11 +28,11 @@ export class LeetCodeNode {
 
         // 每日一题的修正
         if (this.todayData) {
-            const us = this.todayDataUserStatus
+            const us = this.todayDataUserStatus;
             if (us == "FINISH") {
-                return ProblemState.AC
+                return ProblemState.AC;
             } else {
-                return ProblemState.Unknown
+                return ProblemState.Unknown;
             }
         }
 
@@ -109,28 +116,28 @@ export class LeetCodeNode {
         return this.data.scoreData?.ContestSlug || "";
     }
     public get scoreData(): IScoreData | undefined {
-        return this.data.scoreData
+        return this.data.scoreData;
     }
     public get isSearchResult(): boolean {
-        return this.data.isSearchResult
+        return this.data.isSearchResult;
     }
     public get input(): string {
         return this.data.input || "";
     }
     // 每日一题的一些信息
     public get todayData(): ITodayData | undefined {
-        return this.data.todayData
+        return this.data.todayData;
     }
     public set todayData(s: ITodayData | undefined) {
-        this.data.todayData = s
+        this.data.todayData = s;
     }
     public get todayDataDate(): string {
-        return this.data.todayData?.date || ""
+        return this.data.todayData?.date || "";
     }
     public get todayDataUserStatus(): string {
-        return this.data.todayData?.userStatus || ""
+        return this.data.todayData?.userStatus || "";
     }
     public get qid(): string {
-        return this.data.qid || ""
+        return this.data.qid || "";
     }
 }
diff --git a/src/webview/LeetCodeWebview.ts b/src/service/BaseWebviewService.ts
similarity index 78%
rename from src/webview/LeetCodeWebview.ts
rename to src/service/BaseWebviewService.ts
index 8532c8d..3646604 100644
--- a/src/webview/LeetCodeWebview.ts
+++ b/src/service/BaseWebviewService.ts
@@ -1,11 +1,20 @@
-// Copyright (c) jdneo. All rights reserved.
-// Licensed under the MIT license.
+/*
+ * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/webview/BaseWebViewService.ts
+ * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
+ * Created Date: Thursday, October 27th 2022, 7:43:29 pm
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
+
 
 import { commands, ConfigurationChangeEvent, Disposable, ViewColumn, WebviewPanel, window, workspace } from "vscode";
-import { openSettingsEditor, promptHintMessage } from "../utils/uiUtils";
-import { markdownEngine } from "./markdownEngine";
+import { markdownService } from "./MarkdownService";
+import { IWebViewOption } from "../model/Model";
+import { openSettingsEditor } from "../utils/ConfigUtils";
+import { promptHintMessage } from "../utils/OutputUtils";
 
-export abstract class LeetCodeWebview implements Disposable {
+export abstract class BaseWebViewService implements Disposable {
 
     protected readonly viewType: string = "leetcode.webview";
     protected panel: WebviewPanel | undefined;
@@ -25,7 +34,7 @@ export abstract class LeetCodeWebview implements Disposable {
                 enableCommandUris: true,
                 enableFindWidget: true,
                 retainContextWhenHidden: true,
-                localResourceRoots: markdownEngine.localResourceRoots,
+                localResourceRoots: markdownService.localResourceRoots,
             });
             this.panel.onDidDispose(this.onDidDisposeWebview, this, this.listeners);
             this.panel.webview.onDidReceiveMessage(this.onDidReceiveMessage, this, this.listeners);
@@ -61,7 +70,7 @@ export abstract class LeetCodeWebview implements Disposable {
 
     protected async onDidReceiveMessage(_message: any): Promise { /* no special rule */ }
 
-    protected abstract getWebviewOption(): ILeetCodeWebviewOption;
+    protected abstract getWebviewOption(): IWebViewOption;
 
     protected abstract getWebviewContent(): string;
 
@@ -75,8 +84,3 @@ export abstract class LeetCodeWebview implements Disposable {
     }
 }
 
-export interface ILeetCodeWebviewOption {
-    title: string;
-    viewColumn: ViewColumn;
-    preserveFocus?: boolean;
-}
diff --git a/src/service/EventService.ts b/src/service/EventService.ts
new file mode 100644
index 0000000..a89d488
--- /dev/null
+++ b/src/service/EventService.ts
@@ -0,0 +1,49 @@
+/*
+ * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/service/EventService.ts
+ * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
+ * Created Date: Thursday, November 10th 2022, 3:14:29 pm
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
+
+
+
+import { EventEmitter } from "events";
+
+
+import { UserStatus } from "../model/Model";
+import { ISubmitEvent } from "../model/Model";
+import { statusBarService } from "../service/StatusBarService";
+import { treeDataService } from "../service/TreeDataService";
+
+class EventService extends EventEmitter {
+
+    constructor() {
+        super();
+    }
+
+    /**
+     * 监听事件
+     */
+    public add_event() {
+        this.on("statusChanged", (userStatus: UserStatus, userName?: string) => {
+            statusBarService.update_status(userStatus, userName);
+            statusBarService.update();
+            treeDataService.cleanUserScore();
+            treeDataService.refresh();
+        });
+        this.on("submit", (e: ISubmitEvent) => {
+            treeDataService.checkSubmit(e);
+        });
+
+        this.on("searchUserContest", (tt) => {
+            statusBarService.update_UserContestInfo(tt);
+            statusBarService.update();
+            treeDataService.refresh();
+        });
+    }
+}
+
+export const eventService: EventService = new EventService();
+
diff --git a/src/leetCodeExecutor.ts b/src/service/ExecuteService.ts
similarity index 71%
rename from src/leetCodeExecutor.ts
rename to src/service/ExecuteService.ts
index f16b200..7e3078e 100644
--- a/src/leetCodeExecutor.ts
+++ b/src/service/ExecuteService.ts
@@ -1,51 +1,58 @@
-// Copyright (c) jdneo. All rights reserved.
-// Licensed under the MIT license.
+/*
+ * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/service/executeService.ts
+ * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
+ * Created Date: Monday, October 31st 2022, 10:16:47 am
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
+
 
 import * as cp from "child_process";
 import * as fse from "fs-extra";
 import * as os from "os";
 import * as path from "path";
-import * as requireFromString from "require-from-string";
 import { ExtensionContext } from "vscode";
-import { ConfigurationChangeEvent, Disposable, MessageItem, window, workspace, WorkspaceConfiguration } from "vscode";
-import { Endpoint, IProblem, leetcodeHasInited } from "./shared";
-import { executeCommand, executeCommandWithProgress } from "./utils/cpUtils";
-import { DialogOptions, openUrl } from "./utils/uiUtils";
-import * as wsl from "./utils/wslUtils";
-import { toWslPath, useWsl } from "./utils/wslUtils";
-
-class LeetCodeExecutor implements Disposable {
+import { ConfigurationChangeEvent, Disposable, MessageItem, window, workspace } from "vscode";
+import { DialogOptions, DialogType, Endpoint, IProblem, leetcodeHasInited } from "../model/Model";
+import { executeCommand, executeCommandWithProgress } from "../utils/CliUtils";
+import { getNodePath } from "../utils/ConfigUtils";
+import { openUrl, promptForOpenOutputChannel } from "../utils/OutputUtils";
+import * as systemUtils from "../utils/SystemUtils";
+import { toWslPath, useWsl } from "../utils/SystemUtils";
+
+class ExecuteService implements Disposable {
     private leetCodeCliResourcesRootPath: string;
     private leetCodeCliRootPath: string;
     private nodeExecutable: string;
     private configurationChangeListener: Disposable;
 
     constructor() {
-        // this.leetCodeCliResourcesRootPath = path.join(__dirname, "..", "..", "node_modules", "vsc-leetcode-cli");
-        if (!wsl.useVscodeNode()) {
-            this.leetCodeCliResourcesRootPath = path.join(__dirname, "..", "..", "resources");
+        // this.leetCodeCliResourcesRootPath = path.join(__dirname, "..", "..", "node_modules", "childProcessCall");
+        if (!systemUtils.useVscodeNode()) {
+            this.leetCodeCliResourcesRootPath = path.join(__dirname, "..", "..", "..", "resources");
         }
-        this.leetCodeCliRootPath = path.join(__dirname, "..", "..", "out", "src", "vsc-leetcode-cli");
-        this.nodeExecutable = this.getNodePath();
+        this.leetCodeCliRootPath = path.join(__dirname, "..", "..", "..", "out", "src", "childProcessCall");
+        this.nodeExecutable = this.initNodePath();
         this.configurationChangeListener = workspace.onDidChangeConfiguration((event: ConfigurationChangeEvent) => {
-            if (event.affectsConfiguration("leetcode.nodePath")) {
-                this.nodeExecutable = this.getNodePath();
+            if (event.affectsConfiguration("leetcode-problem-rating.nodePath")) {
+                this.nodeExecutable = this.initNodePath();
             }
         }, this);
     }
 
     public async getLeetCodeBinaryPath(): Promise {
-        if (wsl.useVscodeNode()) {
-            return `${path.join(this.leetCodeCliRootPath, "new_lib", "cli.js")}`;
+        if (systemUtils.useVscodeNode()) {
+            return `${path.join(this.leetCodeCliRootPath, "cli.js")}`;
         } else {
-            if (wsl.useWsl()) {
-                return `${await wsl.toWslPath(`"${path.join(this.leetCodeCliResourcesRootPath, "bin", "leetcode")}"`)}`;
+            if (systemUtils.useWsl()) {
+                return `${await systemUtils.toWslPath(`"${path.join(this.leetCodeCliResourcesRootPath, "bin", "leetcode")}"`)}`;
             }
             return `"${path.join(this.leetCodeCliResourcesRootPath, "bin", "leetcode")}"`;
         }
     }
 
-    public async meetRequirements(context: ExtensionContext): Promise {
+    public async checkNodeEnv(context: ExtensionContext): Promise {
         const hasInited: boolean | undefined = context.globalState.get(leetcodeHasInited);
         if (!hasInited) {
             await this.removeOldCache();
@@ -85,8 +92,12 @@ class LeetCodeExecutor implements Disposable {
         return true;
     }
 
-    public async deleteCache(): Promise {
-        return await this.executeCommandEx(this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "cache", "-d"]);
+    public async deleteCache() {
+        try {
+            await this.executeCommandEx(this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "cache", "-d"]);
+        } catch (error) {
+            await promptForOpenOutputChannel("Failed to delete cache. 请查看控制台信息~", DialogType.error);
+        }
     }
 
     public async getUserInfo(): Promise {
@@ -124,19 +135,7 @@ class LeetCodeExecutor implements Disposable {
         }
     }
 
-    /**
-     * This function returns solution of a problem identified by input
-     *
-     * @remarks
-     * Even though this function takes the needTranslation flag, it is important to note
-     * that as of vsc-leetcode-cli 2.8.0, leetcode-cli doesn't support querying solution
-     * on CN endpoint yet. So this flag doesn't have any effect right now.
-     *
-     * @param input - parameter to pass to cli that can identify a problem
-     * @param language - the source code language of the solution desired
-     * @param needTranslation - whether or not to use endPoint translation on solution query
-     * @returns promise of the solution string
-     */
+
     public async showSolution(input: string, language: string, needTranslation: boolean): Promise {
         // solution don't support translation
         const cmd: string[] = [await this.getLeetCodeBinaryPath(), "show", input, "--solution", "-l", language];
@@ -183,25 +182,10 @@ class LeetCodeExecutor implements Disposable {
         return await this.executeCommandWithProgressEx("Fetching problem description...", this.nodeExecutable, cmd);
     }
 
-    public async listSessions(): Promise {
-        return await this.executeCommandEx(this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "session"]);
-    }
-
-    public async enableSession(name: string): Promise {
-        return await this.executeCommandEx(this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "session", "-e", name]);
-    }
-
-    public async createSession(id: string): Promise {
-        return await this.executeCommandEx(this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "session", "-c", id]);
-    }
-
-    public async deleteSession(id: string): Promise {
-        return await this.executeCommandEx(this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "session", "-d", id]);
-    }
 
     public async submitSolution(filePath: string): Promise {
         try {
-            if (wsl.useVscodeNode()) {
+            if (systemUtils.useVscodeNode()) {
                 return await this.executeCommandWithProgressEx("Submitting to LeetCode...", this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "submit", `${filePath}`]);
             }
             return await this.executeCommandWithProgressEx("Submitting to LeetCode...", this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "submit", `"${filePath}"`]);
@@ -215,18 +199,18 @@ class LeetCodeExecutor implements Disposable {
 
     public async testSolution(filePath: string, testString?: string, allCase?: boolean): Promise {
         if (testString) {
-            if (wsl.useVscodeNode()) {
+            if (systemUtils.useVscodeNode()) {
                 return await this.executeCommandWithProgressEx("Submitting to LeetCode...", this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "test", `${filePath}`, "-t", `${testString}`]);
             }
             return await this.executeCommandWithProgressEx("Submitting to LeetCode...", this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "test", `"${filePath}"`, "-t", `${testString}`]);
         }
         if (allCase) {
-            if (wsl.useVscodeNode()) {
+            if (systemUtils.useVscodeNode()) {
                 return await this.executeCommandWithProgressEx("Submitting to LeetCode...", this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "test", `${filePath}`, "-a"]);
             }
             return await this.executeCommandWithProgressEx("Submitting to LeetCode...", this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "test", `"${filePath}"`, "-a"]);
         }
-        if (wsl.useVscodeNode()) {
+        if (systemUtils.useVscodeNode()) {
             return await this.executeCommandWithProgressEx("Submitting to LeetCode...", this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "test", `${filePath}`]);
         }
         return await this.executeCommandWithProgressEx("Submitting to LeetCode...", this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "test", `"${filePath}"`]);
@@ -249,17 +233,7 @@ class LeetCodeExecutor implements Disposable {
         }
         await this.executeCommandWithProgressEx("Updating the favorite list...", "node", commandParams);
     }
-    // 读取tag 编号看着只有钱1148才有
-    public async getCompaniesAndTags(): Promise<{ companies: { [key: string]: string[] }, tags: { [key: string]: string[] } }> {
-        // preprocess the plugin source
-        const companiesTagsPath: string = path.join(this.leetCodeCliRootPath, "lib", "plugins", "company.js");
-        const companiesTagsSrc: string = (await fse.readFile(companiesTagsPath, "utf8")).replace(
-            "module.exports = plugin",
-            "module.exports = { COMPONIES, TAGS }",
-        );
-        const { COMPONIES, TAGS } = requireFromString(companiesTagsSrc, companiesTagsPath);
-        return { companies: COMPONIES, tags: TAGS };
-    }
+
 
     public get node(): string {
         return this.nodeExecutable;
@@ -269,23 +243,22 @@ class LeetCodeExecutor implements Disposable {
         this.configurationChangeListener.dispose();
     }
 
-    private getNodePath(): string {
-        if (wsl.useVscodeNode()) {
-            return "node"
+    private initNodePath(): string {
+        if (systemUtils.useVscodeNode()) {
+            return "node";
         }
-        const extensionConfig: WorkspaceConfiguration = workspace.getConfiguration("leetcode-problem-rating", null);
-        return extensionConfig.get("nodePath", "node" /* default value */);
+        return getNodePath();
     }
 
     private async executeCommandEx(command: string, args: string[], options: cp.SpawnOptions = { shell: true }): Promise {
-        if (wsl.useWsl()) {
+        if (systemUtils.useWsl()) {
             return await executeCommand("wsl", [command].concat(args), options);
         }
         return await executeCommand(command, args, options);
     }
 
     private async executeCommandWithProgressEx(message: string, command: string, args: string[], options: cp.SpawnOptions = { shell: true }): Promise {
-        if (wsl.useWsl()) {
+        if (systemUtils.useWsl()) {
             return await executeCommandWithProgress(message, "wsl", [command].concat(args), options);
         }
         return await executeCommandWithProgress(message, command, args, options);
@@ -300,4 +273,4 @@ class LeetCodeExecutor implements Disposable {
 
 }
 
-export const leetCodeExecutor: LeetCodeExecutor = new LeetCodeExecutor();
+export const executeService: ExecuteService = new ExecuteService();
diff --git a/src/codelens/CustomCodeLensProvider.ts b/src/service/FileButtonService.ts
similarity index 81%
rename from src/codelens/CustomCodeLensProvider.ts
rename to src/service/FileButtonService.ts
index 3322ed2..d922fae 100644
--- a/src/codelens/CustomCodeLensProvider.ts
+++ b/src/service/FileButtonService.ts
@@ -1,12 +1,18 @@
-// Copyright (c) jdneo. All rights reserved.
-// Licensed under the MIT license.
+/*
+ * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/service/FileButtonService.ts
+ * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
+ * Created Date: Thursday, October 27th 2022, 7:43:29 pm
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
 
 import * as vscode from "vscode";
-import { explorerNodeManager } from "../explorer/explorerNodeManager";
-import { LeetCodeNode } from "../explorer/LeetCodeNode";
-import { getEditorShortcuts } from "../utils/settingUtils";
+import { treeViewController } from "../controller/TreeViewController";
+import { NodeModel } from "../model/NodeModel";
+import { getEditorShortcuts } from "../utils/ConfigUtils";
 
-export class CustomCodeLensProvider implements vscode.CodeLensProvider {
+export class FileButtonService implements vscode.CodeLensProvider {
 
     private onDidChangeCodeLensesEmitter: vscode.EventEmitter = new vscode.EventEmitter();
 
@@ -30,9 +36,9 @@ export class CustomCodeLensProvider implements vscode.CodeLensProvider {
             return undefined;
         }
         const nodeId: string | undefined = matchResult[1];
-        let node: LeetCodeNode | undefined;
+        let node: NodeModel | undefined;
         if (nodeId) {
-            node = explorerNodeManager.getNodeById(nodeId);
+            node = treeViewController.getNodeById(nodeId);
         }
 
         let codeLensLine: number = document.lineCount - 1;
@@ -106,4 +112,4 @@ export class CustomCodeLensProvider implements vscode.CodeLensProvider {
     }
 }
 
-export const customCodeLensProvider: CustomCodeLensProvider = new CustomCodeLensProvider();
+export const fileButtonService: FileButtonService = new FileButtonService();
diff --git a/src/webview/markdownEngine.ts b/src/service/MarkdownService.ts
similarity index 90%
rename from src/webview/markdownEngine.ts
rename to src/service/MarkdownService.ts
index 4c1db65..a2e8405 100644
--- a/src/webview/markdownEngine.ts
+++ b/src/service/MarkdownService.ts
@@ -1,15 +1,22 @@
-// Copyright (c) jdneo. All rights reserved.
-// Licensed under the MIT license.
+/*
+ * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/service/markdownService.ts
+ * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
+ * Created Date: Thursday, October 27th 2022, 7:43:29 pm
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
+
 
 import * as hljs from "highlight.js";
 import * as MarkdownIt from "markdown-it";
 import * as os from "os";
 import * as path from "path";
 import * as vscode from "vscode";
-import { leetCodeChannel } from "../leetCodeChannel";
-import { isWindows } from "../utils/osUtils";
+import { logOutput } from "../utils/OutputUtils";
+import { isWindows } from "../utils/SystemUtils";
 
-class MarkdownEngine implements vscode.Disposable {
+class MarkdownService implements vscode.Disposable {
 
     private engine: MarkdownIt;
     private config: MarkdownConfiguration;
@@ -54,7 +61,7 @@ class MarkdownEngine implements vscode.Disposable {
             const stylePaths: string[] = require(path.join(this.config.extRoot, "package.json"))["contributes"]["markdown.previewStyles"];
             styles = stylePaths.map((p: string) => vscode.Uri.file(path.join(this.config.extRoot, p)).with({ scheme: "vscode-resource" }));
         } catch (error) {
-            leetCodeChannel.appendLine("[Error] Fail to load built-in markdown style file.");
+            logOutput.appendLine("[Error] Fail to load built-in markdown style file.");
         }
         return styles.map((style: vscode.Uri) => ``).join(os.EOL);
     }
@@ -163,4 +170,4 @@ class MarkdownConfiguration {
     }
 }
 
-export const markdownEngine: MarkdownEngine = new MarkdownEngine();
+export const markdownService: MarkdownService = new MarkdownService();
diff --git a/src/webview/leetCodePreviewProvider.ts b/src/service/PreviewService.ts
similarity index 85%
rename from src/webview/leetCodePreviewProvider.ts
rename to src/service/PreviewService.ts
index 78b4099..ff94145 100644
--- a/src/webview/leetCodePreviewProvider.ts
+++ b/src/service/PreviewService.ts
@@ -1,13 +1,20 @@
-// Copyright (c) jdneo. All rights reserved.
-// Licensed under the MIT license.
+/*
+ * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/service/previewService.ts
+ * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
+ * Created Date: Thursday, October 27th 2022, 7:43:29 pm
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
+
 
 import { commands, ViewColumn } from "vscode";
-import { getLeetCodeEndpoint } from "../commands/plugin";
-import { Endpoint, IProblem } from "../shared";
-import { ILeetCodeWebviewOption, LeetCodeWebview } from "./LeetCodeWebview";
-import { markdownEngine } from "./markdownEngine";
+import { Endpoint, IProblem, IWebViewOption } from "../model/Model";
+import { getLeetCodeEndpoint } from "../utils/ConfigUtils";
+import { BaseWebViewService } from "./BaseWebviewService";
+import { markdownService } from "./MarkdownService";
 
-class LeetCodePreviewProvider extends LeetCodeWebview {
+class PreviewService extends BaseWebViewService {
 
     protected readonly viewType: string = "leetcode.preview";
     private node: IProblem;
@@ -30,7 +37,7 @@ class LeetCodePreviewProvider extends LeetCodeWebview {
         // }
     }
 
-    protected getWebviewOption(): ILeetCodeWebviewOption {
+    protected getWebviewOption(): IWebViewOption {
         if (!this.sideMode) {
             return {
                 title: `${this.node.name}: Preview`,
@@ -72,8 +79,8 @@ class LeetCodePreviewProvider extends LeetCodeWebview {
                 `,
         };
         const { title, url, category, difficulty, likes, dislikes, body } = this.description;
-        const head: string = markdownEngine.render(`# [${title}](${url})`);
-        const info: string = markdownEngine.render([
+        const head: string = markdownService.render(`# [${title}](${url})`);
+        const info: string = markdownService.render([
             `| Category | Difficulty | Likes | Dislikes |`,
             `| :------: | :--------: | :---: | :------: |`,
             `| ${category} | ${difficulty} | ${likes} | ${dislikes} |`,
@@ -81,7 +88,7 @@ class LeetCodePreviewProvider extends LeetCodeWebview {
         const tags: string = [
             `
`, `Tags`, - markdownEngine.render( + markdownService.render( this.description.tags .map((t: string) => `[\`${t}\`](https://leetcode.com/tag/${t})`) .join(" | "), @@ -91,20 +98,20 @@ class LeetCodePreviewProvider extends LeetCodeWebview { const companies: string = [ `
`, `Companies`, - markdownEngine.render( + markdownService.render( this.description.companies .map((c: string) => `\`${c}\``) .join(" | "), ), `
`, ].join("\n"); - const links: string = markdownEngine.render(`[Discussion](${this.getDiscussionLink(url)}) | [Solution](${this.getSolutionLink(url)})`); + const links: string = markdownService.render(`[Discussion](${this.getDiscussionLink(url)}) | [Solution](${this.getSolutionLink(url)})`); return ` - ${markdownEngine.getStyles()} + ${markdownService.getStyles()} ${!this.sideMode ? button.style : ""}