diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..d07c4e4e --- /dev/null +++ b/.prettierrc @@ -0,0 +1,7 @@ +{ + "printWidth": 100, + "tabWidth": 2, + "semi": true, + "singleQuote": true, + "trailingComma": "none" +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json index f3fda475..1f6fc4b7 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,5 +1,5 @@ { // See http://go.microsoft.com/fwlink/?LinkId=827846 // for the documentation about the extensions.json format - "recommendations": ["eliostruyf.vscode-typescript-exportallmodules"] + "recommendations": ["eliostruyf.vscode-typescript-exportallmodules", "esbenp.prettier-vscode"] } diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7d5ebb4b..1e6fdd80 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -25,9 +25,9 @@ Eager to start contributing? Great 🤩, you can contribute to the following pro - Start by forking this project; - Clone your fork to your local machine; -- Run `npm i`; +- Run `pnpm i`; - Open the project in VS Code; -- To start developing, run `npm run dev:ext` and press `f5` to start the debugging session. +- To start developing, run `pnpm dev:ext` and press `f5` to start the debugging session. ### Tips diff --git a/README.md b/README.md index b02a9877..b95d21e3 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Number of installs - + Ratings @@ -115,7 +115,7 @@ You can get the extension via: If you have the courage to test out the beta features, we made available a beta version as well. You can install this via: - Uninstall the main Front Matter version -- Install the beta version +- Install the beta version - VS Code marketplace: [VS Code Marketplace - Front Matter BETA](https://marketplace.visualstudio.com/items?itemName=eliostruyf.vscode-front-matter-beta). - The extension CLI: `ext install eliostruyf.vscode-front-matter-beta` - Or by clicking on the following link: open extension in VS Code @@ -200,4 +200,4 @@ You can open showcase issues for the following things: Front Matter visitors -

\ No newline at end of file +

diff --git a/e2e/src/runTests.ts b/e2e/src/runTests.ts index bb1e755d..99a69824 100644 --- a/e2e/src/runTests.ts +++ b/e2e/src/runTests.ts @@ -1,33 +1,33 @@ -import * as path from 'path'; -import * as semver from "semver"; -import { ExTester, ReleaseQuality } from "vscode-extension-tester"; - +import * as path from 'path' +import * as semver from 'semver' +import { ExTester, ReleaseQuality } from 'vscode-extension-tester' async function main(): Promise { - const vsCodeVersion: semver.SemVer = new semver.SemVer(`1.66.0`); - const version = vsCodeVersion.version; + const vsCodeVersion: semver.SemVer = new semver.SemVer(`1.66.0`) + const version = vsCodeVersion.version - const storageFolder = path.join(__dirname, "..", "storage"); - const extFolder = path.join(__dirname, "..", "extensions"); + const storageFolder = path.join(__dirname, '..', 'storage') + const extFolder = path.join(__dirname, '..', 'extensions') try { - const testPath = path.join(__dirname, "command.test.js"); + const testPath = path.join(__dirname, 'command.test.js') - const exTester = new ExTester(storageFolder, ReleaseQuality.Stable, extFolder); - await exTester.downloadCode(version); - await exTester.installVsix({ useYarn: false }); + const exTester = new ExTester(storageFolder, ReleaseQuality.Stable, extFolder) + await exTester.downloadCode(version) + await exTester.installVsix({ useYarn: false }) // await exTester.installFromMarketplace("eliostruyf.vscode-front-matter"); - await exTester.downloadChromeDriver(version); + await exTester.downloadChromeDriver(version) // await exTester.setupRequirements({vscodeVersion: version}); const result = await exTester.runTests(testPath, { - vscodeVersion: version - }); + vscodeVersion: version, + resources: [storageFolder], + }) - process.exit(result); + process.exit(result) } catch (err) { - console.log(err); - process.exit(1); + console.log(err) + process.exit(1) } } -main(); +main() diff --git a/package.json b/package.json index 724c6fe4..75360f06 100644 --- a/package.json +++ b/package.json @@ -2177,8 +2177,9 @@ "clean": "rimraf dist", "start:site": "cd ./docs && npm run dev", "clean:test": "rm ./e2e/sample/frontmatter.json || exit 0 && rm -rf ./e2e/sample/.frontmatter || exit 0", - "test": "tsc -p tsconfig.e2e.json && npm run clean:test && pnpm i -g @vscode/vsce && node ./e2e/out/runTests.js", - "lint": "eslint --max-warnings=0 ./src/{commands,components}" + "test": "pnpm lint; tsc -p tsconfig.e2e.json && npm run clean:test && pnpm i -g @vscode/vsce && node ./e2e/out/runTests.js", + "lint": "eslint --max-warnings=0 ./src/{commands,components}", + "prettier": "prettier --write ./src" }, "devDependencies": { "@actions/core": "^1.8.2", @@ -2247,6 +2248,8 @@ "postcss": "^8.3.6", "postcss-loader": "4.3.0", "postcss-nested": "^5.0.6", + "prettier": "^2.8.3", + "prettier-plugin-tailwindcss": "^0.2.2", "react": "17.0.1", "react-datepicker": "4.2.1", "react-dom": "17.0.1", @@ -2263,14 +2266,14 @@ "style-loader": "2.0.0", "tailwindcss": "^2.2.7", "tailwindcss-nested-groups": "^1.2.4", - "ts-loader": "8.0.3", - "typescript": "4.5.5", + "ts-loader": "^9.4.2", + "typescript": "^4.6.2", "uniforms": "^3.7.0", "uniforms-antd": "^3.7.0", "uniforms-bridge-json-schema": "^3.7.0", "uniforms-unstyled": "^3.7.0", "url-join-ts": "^1.0.5", - "vscode-extension-tester": "4.2.5", + "vscode-extension-tester": "^5.3.0", "wc-react": "github:estruyf/wc-react", "webpack": "^5.65.0", "webpack-bundle-analyzer": "^4.5.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e135ddcf..afcfaade 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -67,6 +67,8 @@ specifiers: postcss: ^8.3.6 postcss-loader: 4.3.0 postcss-nested: ^5.0.6 + prettier: ^2.8.3 + prettier-plugin-tailwindcss: ^0.2.2 react: 17.0.1 react-datepicker: 4.2.1 react-dom: 17.0.1 @@ -83,14 +85,14 @@ specifiers: style-loader: 2.0.0 tailwindcss: ^2.2.7 tailwindcss-nested-groups: ^1.2.4 - ts-loader: 8.0.3 - typescript: 4.5.5 + ts-loader: ^9.4.2 + typescript: ^4.6.2 uniforms: ^3.7.0 uniforms-antd: ^3.7.0 uniforms-bridge-json-schema: ^3.7.0 uniforms-unstyled: ^3.7.0 url-join-ts: ^1.0.5 - vscode-extension-tester: 4.2.5 + vscode-extension-tester: ^5.3.0 wc-react: github:estruyf/wc-react webpack: ^5.65.0 webpack-bundle-analyzer: ^4.5.0 @@ -128,8 +130,8 @@ devDependencies: '@types/react-datepicker': 4.8.0_w7o5yyljkiidx2s2nzb26ottzu '@types/react-dom': 17.0.0 '@types/vscode': 1.74.0 - '@typescript-eslint/eslint-plugin': 5.50.0_463slnisjmie3ga6nht6iq5g4u - '@typescript-eslint/parser': 5.50.0_gpshh2li6qp2z6l6wwjxu2emgi + '@typescript-eslint/eslint-plugin': 5.50.0_go4drrxstycfikanvu45pi4vgq + '@typescript-eslint/parser': 5.50.0_4vsywjlpuriuw3tl5oq6zy5a64 '@vscode/codicons': 0.0.20 '@vscode/extension-telemetry': 0.4.10 '@vscode/webview-ui-toolkit': 0.9.3_react@17.0.1 @@ -166,6 +168,8 @@ devDependencies: postcss: 8.4.21 postcss-loader: 4.3.0_6jdsrmfenkuhhw3gx4zvjlznce postcss-nested: 5.0.6_postcss@8.4.21 + prettier: 2.8.3 + prettier-plugin-tailwindcss: 0.2.2_prettier@2.8.3 react: 17.0.1 react-datepicker: 4.2.1_w7o5yyljkiidx2s2nzb26ottzu react-dom: 17.0.1_react@17.0.1 @@ -182,14 +186,14 @@ devDependencies: style-loader: 2.0.0_webpack@5.75.0 tailwindcss: 2.2.19_4xaawq3hrlasat64u2hch2fhdy tailwindcss-nested-groups: 1.2.4_tailwindcss@2.2.19 - ts-loader: 8.0.3_typescript@4.5.5 - typescript: 4.5.5 + ts-loader: 9.4.2_hhrrucqyg4eysmfpujvov2ym5u + typescript: 4.9.5 uniforms: 3.10.2_react@17.0.1 uniforms-antd: 3.10.2_pmcwetab3euy6ubdu5x4dhisee uniforms-bridge-json-schema: 3.10.2_react@17.0.1 uniforms-unstyled: 3.10.2_react@17.0.1 url-join-ts: 1.0.5 - vscode-extension-tester: 4.2.5_rgw4eiitjdvgxwfnqqw3bex6ee + vscode-extension-tester: 5.3.0_4r5rv57huad4ctfiz6vn747ruu wc-react: github.com/estruyf/wc-react/0989e37af55d3ee97392bf2747a818e4873243fa webpack: 5.75.0_webpack-cli@4.10.0 webpack-bundle-analyzer: 4.7.0 @@ -937,8 +941,10 @@ packages: resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} dev: true - /@types/selenium-webdriver/3.0.20: - resolution: {integrity: sha512-6d8Q5fqS9DWOXEhMDiF6/2FjyHdmP/jSTAUyeQR7QwrFeNmYyzmvGxD5aLIHL445HjWgibs0eAig+KPnbaesXA==} + /@types/selenium-webdriver/4.1.10: + resolution: {integrity: sha512-o6ARpkBI8J0b+jhLjXF46rYc8Vsb5CLrRetyA3V3qUPVDwNjPDyHZsZOCFSXH0KPZ6lIn2BfP1xVEPnO+AQy5w==} + dependencies: + '@types/ws': 8.5.4 dev: true /@types/semver/7.3.13: @@ -1015,7 +1021,7 @@ packages: '@types/node': 10.17.48 dev: true - /@typescript-eslint/eslint-plugin/5.50.0_463slnisjmie3ga6nht6iq5g4u: + /@typescript-eslint/eslint-plugin/5.50.0_go4drrxstycfikanvu45pi4vgq: resolution: {integrity: sha512-vwksQWSFZiUhgq3Kv7o1Jcj0DUNylwnIlGvKvLLYsq8pAWha6/WCnXUeaSoNNha/K7QSf2+jvmkxggC1u3pIwQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -1026,10 +1032,10 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/parser': 5.50.0_gpshh2li6qp2z6l6wwjxu2emgi + '@typescript-eslint/parser': 5.50.0_4vsywjlpuriuw3tl5oq6zy5a64 '@typescript-eslint/scope-manager': 5.50.0 - '@typescript-eslint/type-utils': 5.50.0_gpshh2li6qp2z6l6wwjxu2emgi - '@typescript-eslint/utils': 5.50.0_gpshh2li6qp2z6l6wwjxu2emgi + '@typescript-eslint/type-utils': 5.50.0_4vsywjlpuriuw3tl5oq6zy5a64 + '@typescript-eslint/utils': 5.50.0_4vsywjlpuriuw3tl5oq6zy5a64 debug: 4.3.4 eslint: 8.33.0 grapheme-splitter: 1.0.4 @@ -1037,13 +1043,13 @@ packages: natural-compare-lite: 1.4.0 regexpp: 3.2.0 semver: 7.3.8 - tsutils: 3.21.0_typescript@4.5.5 - typescript: 4.5.5 + tsutils: 3.21.0_typescript@4.9.5 + typescript: 4.9.5 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/parser/5.50.0_gpshh2li6qp2z6l6wwjxu2emgi: + /@typescript-eslint/parser/5.50.0_4vsywjlpuriuw3tl5oq6zy5a64: resolution: {integrity: sha512-KCcSyNaogUDftK2G9RXfQyOCt51uB5yqC6pkUYqhYh8Kgt+DwR5M0EwEAxGPy/+DH6hnmKeGsNhiZRQxjH71uQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -1055,10 +1061,10 @@ packages: dependencies: '@typescript-eslint/scope-manager': 5.50.0 '@typescript-eslint/types': 5.50.0 - '@typescript-eslint/typescript-estree': 5.50.0_typescript@4.5.5 + '@typescript-eslint/typescript-estree': 5.50.0_typescript@4.9.5 debug: 4.3.4 eslint: 8.33.0 - typescript: 4.5.5 + typescript: 4.9.5 transitivePeerDependencies: - supports-color dev: true @@ -1071,7 +1077,7 @@ packages: '@typescript-eslint/visitor-keys': 5.50.0 dev: true - /@typescript-eslint/type-utils/5.50.0_gpshh2li6qp2z6l6wwjxu2emgi: + /@typescript-eslint/type-utils/5.50.0_4vsywjlpuriuw3tl5oq6zy5a64: resolution: {integrity: sha512-dcnXfZ6OGrNCO7E5UY/i0ktHb7Yx1fV6fnQGGrlnfDhilcs6n19eIRcvLBqx6OQkrPaFlDPk3OJ0WlzQfrV0bQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -1081,12 +1087,12 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 5.50.0_typescript@4.5.5 - '@typescript-eslint/utils': 5.50.0_gpshh2li6qp2z6l6wwjxu2emgi + '@typescript-eslint/typescript-estree': 5.50.0_typescript@4.9.5 + '@typescript-eslint/utils': 5.50.0_4vsywjlpuriuw3tl5oq6zy5a64 debug: 4.3.4 eslint: 8.33.0 - tsutils: 3.21.0_typescript@4.5.5 - typescript: 4.5.5 + tsutils: 3.21.0_typescript@4.9.5 + typescript: 4.9.5 transitivePeerDependencies: - supports-color dev: true @@ -1096,7 +1102,7 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /@typescript-eslint/typescript-estree/5.50.0_typescript@4.5.5: + /@typescript-eslint/typescript-estree/5.50.0_typescript@4.9.5: resolution: {integrity: sha512-Gq4zapso+OtIZlv8YNAStFtT6d05zyVCK7Fx3h5inlLBx2hWuc/0465C2mg/EQDDU2LKe52+/jN4f0g9bd+kow==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -1111,13 +1117,13 @@ packages: globby: 11.1.0 is-glob: 4.0.3 semver: 7.3.8 - tsutils: 3.21.0_typescript@4.5.5 - typescript: 4.5.5 + tsutils: 3.21.0_typescript@4.9.5 + typescript: 4.9.5 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/utils/5.50.0_gpshh2li6qp2z6l6wwjxu2emgi: + /@typescript-eslint/utils/5.50.0_4vsywjlpuriuw3tl5oq6zy5a64: resolution: {integrity: sha512-v/AnUFImmh8G4PH0NDkf6wA8hujNNcrwtecqW4vtQ1UOSNBaZl49zP1SHoZ/06e+UiwzHpgb5zP5+hwlYYWYAw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -1127,7 +1133,7 @@ packages: '@types/semver': 7.3.13 '@typescript-eslint/scope-manager': 5.50.0 '@typescript-eslint/types': 5.50.0 - '@typescript-eslint/typescript-estree': 5.50.0_typescript@4.5.5 + '@typescript-eslint/typescript-estree': 5.50.0_typescript@4.9.5 eslint: 8.33.0 eslint-scope: 5.1.1 eslint-utils: 3.0.0_eslint@8.33.0 @@ -1154,6 +1160,34 @@ packages: engines: {vscode: ^1.60.0} dev: true + /@vscode/vsce/2.17.0: + resolution: {integrity: sha512-W4HN5MtTVj/mroQU1d82bUEeWM3dUykMFnMYZPtZ6jrMiHN1PUoN3RGcS896N0r2rIq8KpWDtufcQHgK8VfgpA==} + engines: {node: '>= 14'} + hasBin: true + dependencies: + azure-devops-node-api: 11.2.0 + chalk: 2.4.2 + cheerio: 1.0.0-rc.12 + commander: 6.2.1 + glob: 7.2.0 + hosted-git-info: 4.1.0 + leven: 3.1.0 + markdown-it: 12.3.2 + mime: 1.6.0 + minimatch: 3.1.2 + parse-semver: 1.1.1 + read: 1.0.7 + semver: 5.7.1 + tmp: 0.2.1 + typed-rest-client: 1.8.9 + url-join: 4.0.1 + xml2js: 0.4.23 + yauzl: 2.10.0 + yazl: 2.5.1 + optionalDependencies: + keytar: 7.9.0 + dev: true + /@vscode/webview-ui-toolkit/0.9.3_react@17.0.1: resolution: {integrity: sha512-uEEpTVA21zkHtWMR8TPT7vbIZ1+tvfhQPThEdmmDjh0PulKPvaAVNqnGbQitU3F9GVqpq2AdIKAq6N1jFeBoXg==} peerDependencies: @@ -1610,6 +1644,7 @@ packages: /base64-js/1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} dev: true + optional: true /batch/0.6.1: resolution: {integrity: sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==} @@ -1649,6 +1684,7 @@ packages: inherits: 2.0.4 readable-stream: 3.6.0 dev: true + optional: true /body-parser/1.20.1: resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==} @@ -1747,6 +1783,7 @@ packages: base64-js: 1.5.1 ieee754: 1.2.1 dev: true + optional: true /buffers/0.1.1: resolution: {integrity: sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==} @@ -2018,6 +2055,11 @@ packages: delayed-stream: 1.0.0 dev: true + /commander/10.0.0: + resolution: {integrity: sha512-zS5PnTI22FIRM6ylNW8G4Ap0IEOyk62fhLSD0+uHRT9McRCLGpkVNvao4bjimpK/GShynyQkFFxHhwMcETmduA==} + engines: {node: '>=14'} + dev: true + /commander/2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} dev: true @@ -2042,8 +2084,8 @@ packages: engines: {node: '>= 12'} dev: true - /compare-versions/3.6.0: - resolution: {integrity: sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==} + /compare-versions/5.0.3: + resolution: {integrity: sha512-4UZlZP8Z99MGEY+Ovg/uJxJuvoXuN4M6B3hKaiackiHrgzQFEe3diJi1mf1PNHbFujM7FvLrK2bpgIaImbtZ1A==} dev: true /compressible/2.0.18: @@ -2290,6 +2332,7 @@ packages: resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} engines: {node: '>=4.0.0'} dev: true + optional: true /deep-is/0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} @@ -2357,6 +2400,7 @@ packages: resolution: {integrity: sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==} engines: {node: '>=8'} dev: true + optional: true /detect-node/2.1.0: resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} @@ -2533,15 +2577,6 @@ packages: once: 1.4.0 dev: true - /enhanced-resolve/4.5.0: - resolution: {integrity: sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==} - engines: {node: '>=6.9.0'} - dependencies: - graceful-fs: 4.2.10 - memory-fs: 0.5.0 - tapable: 1.1.3 - dev: true - /enhanced-resolve/5.12.0: resolution: {integrity: sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==} engines: {node: '>=10.13.0'} @@ -2569,13 +2604,6 @@ packages: hasBin: true dev: true - /errno/0.1.8: - resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==} - hasBin: true - dependencies: - prr: 1.0.1 - dev: true - /error-ex/1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} dependencies: @@ -2848,6 +2876,7 @@ packages: resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} engines: {node: '>=6'} dev: true + optional: true /express/4.18.2: resolution: {integrity: sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==} @@ -3071,6 +3100,15 @@ packages: universalify: 2.0.0 dev: true + /fs-extra/11.1.0: + resolution: {integrity: sha512-0rcTq621PD5jM/e0a3EJoGC/1TC5ZBCERW82LQuwfGnCa1V8w7dpYH1yNu+SLb6E5dkeCBzKEyLGlFrnr+dUyw==} + engines: {node: '>=14.14'} + dependencies: + graceful-fs: 4.2.10 + jsonfile: 6.1.0 + universalify: 2.0.0 + dev: true + /fs-monkey/1.0.3: resolution: {integrity: sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==} dev: true @@ -3157,6 +3195,7 @@ packages: /github-from-package/0.0.0: resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} dev: true + optional: true /glob-parent/5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} @@ -3198,6 +3237,17 @@ packages: path-is-absolute: 1.0.1 dev: true + /glob/8.1.0: + resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} + engines: {node: '>=12'} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 5.0.1 + once: 1.4.0 + dev: true + /globals/13.20.0: resolution: {integrity: sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==} engines: {node: '>=8'} @@ -3359,8 +3409,9 @@ packages: wbuf: 1.7.3 dev: true - /hpagent/0.1.2: - resolution: {integrity: sha512-ePqFXHtSQWAFXYmj+JtOTHr84iNrII4/QRlAAPPE+zqnKy4xJo7Ie1Y4kC7AdB+LxLxSTTzBMASsEcy0q8YyvQ==} + /hpagent/1.2.0: + resolution: {integrity: sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA==} + engines: {node: '>=14'} dev: true /hsl-regex/1.0.0: @@ -3547,6 +3598,7 @@ packages: /ieee754/1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} dev: true + optional: true /ignore/5.2.4: resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} @@ -3605,6 +3657,7 @@ packages: /ini/1.3.8: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} dev: true + optional: true /internal-slot/1.0.4: resolution: {integrity: sha512-tA8URYccNzMo94s5MQZgH8NB/XTa6HsOo0MLfXTKKEnHVVdegzaQoFZ7Jp44bdvLvY2waT5dc+j5ICEswhi7UQ==} @@ -3984,6 +4037,7 @@ packages: node-addon-api: 4.3.0 prebuild-install: 7.1.1 dev: true + optional: true /keyv/4.5.2: resolution: {integrity: sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==} @@ -4214,14 +4268,6 @@ packages: fs-monkey: 1.0.3 dev: true - /memory-fs/0.5.0: - resolution: {integrity: sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==} - engines: {node: '>=4.3.0 <5.0.0 || >=5.10'} - dependencies: - errno: 0.1.8 - readable-stream: 2.3.7 - dev: true - /memorystream/0.3.1: resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==} engines: {node: '>= 0.10.0'} @@ -4482,6 +4528,7 @@ packages: /mkdirp-classic/0.5.3: resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} dev: true + optional: true /mkdirp/0.5.6: resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} @@ -4533,19 +4580,19 @@ packages: resolution: {integrity: sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==} dev: true - /monaco-page-objects/1.9.2_nd7aufnafpcvjaepgzlwugj3oe: - resolution: {integrity: sha512-1/JHv0ZwGnoWfq23IyP5PVLRq8NC0YXIoP6jG02R5Ev73hDznwJ3xTEVMzzpRPRGfMyVK4JNaA1aqax82jzaQA==} + /monaco-page-objects/3.3.0_mcttbz3hm275ldw6tl6gcvo6pq: + resolution: {integrity: sha512-BnyE3MYuKhcqqhkAdVWNDSS8wWaPSKPz9PDb2KovBqeTnzbiZ4R5SpupsupJe23Fg9QwKCXe06EcYU2ofwKyAA==} peerDependencies: - selenium-webdriver: ^3.0.0 + selenium-webdriver: ^4.6.1 + typescript: '>=4.6.2' dependencies: clipboardy: 2.3.0 clone-deep: 4.0.1 - compare-versions: 3.6.0 - fs-extra: 10.1.0 - selenium-webdriver: 3.6.0 - ts-essentials: 8.1.0_typescript@4.5.5 - transitivePeerDependencies: - - typescript + compare-versions: 5.0.3 + fs-extra: 11.1.0 + selenium-webdriver: 4.8.0 + ts-essentials: 9.3.0_typescript@4.9.5 + typescript: 4.9.5 dev: true /mri/1.2.0: @@ -4602,6 +4649,7 @@ packages: /napi-build-utils/1.0.2: resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} dev: true + optional: true /natural-compare-lite/1.4.0: resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} @@ -4637,10 +4685,12 @@ packages: dependencies: semver: 7.3.8 dev: true + optional: true /node-addon-api/4.3.0: resolution: {integrity: sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==} dev: true + optional: true /node-emoji/1.11.0: resolution: {integrity: sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==} @@ -4837,11 +4887,6 @@ packages: word-wrap: 1.2.3 dev: true - /os-tmpdir/1.0.2: - resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} - engines: {node: '>=0.10.0'} - dev: true - /p-cancelable/2.1.1: resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==} engines: {node: '>=8'} @@ -5190,12 +5235,71 @@ packages: tar-fs: 2.1.1 tunnel-agent: 0.6.0 dev: true + optional: true /prelude-ls/1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} dev: true + /prettier-plugin-tailwindcss/0.2.2_prettier@2.8.3: + resolution: {integrity: sha512-5RjUbWRe305pUpc48MosoIp6uxZvZxrM6GyOgsbGLTce+ehePKNm7ziW2dLG2air9aXbGuXlHVSQQw4Lbosq3w==} + engines: {node: '>=12.17.0'} + peerDependencies: + '@prettier/plugin-php': '*' + '@prettier/plugin-pug': '*' + '@shopify/prettier-plugin-liquid': '*' + '@shufo/prettier-plugin-blade': '*' + '@trivago/prettier-plugin-sort-imports': '*' + prettier: '>=2.2.0' + prettier-plugin-astro: '*' + prettier-plugin-css-order: '*' + prettier-plugin-import-sort: '*' + prettier-plugin-jsdoc: '*' + prettier-plugin-organize-attributes: '*' + prettier-plugin-organize-imports: '*' + prettier-plugin-style-order: '*' + prettier-plugin-svelte: '*' + prettier-plugin-twig-melody: '*' + peerDependenciesMeta: + '@prettier/plugin-php': + optional: true + '@prettier/plugin-pug': + optional: true + '@shopify/prettier-plugin-liquid': + optional: true + '@shufo/prettier-plugin-blade': + optional: true + '@trivago/prettier-plugin-sort-imports': + optional: true + prettier-plugin-astro: + optional: true + prettier-plugin-css-order: + optional: true + prettier-plugin-import-sort: + optional: true + prettier-plugin-jsdoc: + optional: true + prettier-plugin-organize-attributes: + optional: true + prettier-plugin-organize-imports: + optional: true + prettier-plugin-style-order: + optional: true + prettier-plugin-svelte: + optional: true + prettier-plugin-twig-melody: + optional: true + dependencies: + prettier: 2.8.3 + dev: true + + /prettier/2.8.3: + resolution: {integrity: sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw==} + engines: {node: '>=10.13.0'} + hasBin: true + dev: true + /pretty-error/2.1.2: resolution: {integrity: sha512-EY5oDzmsX5wvuynAByrmY0P0hcp+QpnAKbJng2A2MPjVKXCxrDSUkzghVJ4ZGPIv+JC4gX8fPUWscC0RtjsWGw==} dependencies: @@ -5228,10 +5332,6 @@ packages: ipaddr.js: 1.9.1 dev: true - /prr/1.0.1: - resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==} - dev: true - /pump/1.0.3: resolution: {integrity: sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==} dependencies: @@ -5860,6 +5960,7 @@ packages: minimist: 1.2.7 strip-json-comments: 2.0.1 dev: true + optional: true /react-datepicker/4.2.1_w7o5yyljkiidx2s2nzb26ottzu: resolution: {integrity: sha512-0gcvHMnX8rS1fV90PjjsB7MQdsWNU77JeVHf6bbwK9HnFxgwjVflTx40ebKmHV+leqe+f+FgUP9Nvqbe5RGyfA==} @@ -6181,13 +6282,6 @@ packages: resolution: {integrity: sha512-zgn5OjNQXLUTdq8m17KdaicF6w89TZs8ZU8y0AYENIU6wG8GG6LLm0yLSiPY8DmaYmHdgRW8rnApjoT0fQRfMg==} dev: true - /rimraf/2.7.1: - resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} - hasBin: true - dependencies: - glob: 7.2.0 - dev: true - /rimraf/3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} hasBin: true @@ -6282,14 +6376,16 @@ packages: resolution: {integrity: sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==} dev: true - /selenium-webdriver/3.6.0: - resolution: {integrity: sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q==} - engines: {node: '>= 6.9.0'} + /selenium-webdriver/4.8.0: + resolution: {integrity: sha512-s/HL8WNwy1ggHR244+tAhjhyKMJnZLt1HKJ6Gn7nQgVjB/ybDF+46Uui0qI2J7AjPNJzlUmTncdC/jg/kKkn0A==} + engines: {node: '>= 14.20.0'} dependencies: jszip: 3.10.1 - rimraf: 2.7.1 - tmp: 0.0.30 - xml2js: 0.4.23 + tmp: 0.2.1 + ws: 8.12.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate dev: true /selfsigned/2.1.1: @@ -6304,11 +6400,6 @@ packages: hasBin: true dev: true - /semver/6.3.0: - resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} - hasBin: true - dev: true - /semver/7.3.8: resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==} engines: {node: '>=10'} @@ -6443,6 +6534,7 @@ packages: /simple-concat/1.0.1: resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} dev: true + optional: true /simple-get/4.0.1: resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} @@ -6451,6 +6543,7 @@ packages: once: 1.4.0 simple-concat: 1.0.1 dev: true + optional: true /simple-git/3.16.0: resolution: {integrity: sha512-zuWYsOLEhbJRWVxpjdiXl6eyAyGo/KzVW+KFhhw9MqEEJttcq+32jTWSGyxTdf9e/YCohxRE+9xpWFj9FdiJNw==} @@ -6662,6 +6755,7 @@ packages: resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} engines: {node: '>=0.10.0'} dev: true + optional: true /strip-json-comments/3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} @@ -6792,6 +6886,7 @@ packages: pump: 3.0.0 tar-stream: 2.2.0 dev: true + optional: true /tar-stream/1.6.2: resolution: {integrity: sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==} @@ -6816,6 +6911,7 @@ packages: inherits: 2.0.4 readable-stream: 3.6.0 dev: true + optional: true /targz/1.0.1: resolution: {integrity: sha512-6q4tP9U55mZnRuMTBqnqc3nwYQY3kv+QthCFZuMk+Tn1qYUnMPmL/JZ/mzgXINzFpSqfU+242IFmFU9VPvqaQw==} @@ -6877,13 +6973,6 @@ packages: resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==} dev: true - /tmp/0.0.30: - resolution: {integrity: sha512-HXdTB7lvMwcb55XFfrTM8CPr/IYREk4hVBFaQ4b/6nInrluSL86hfHm7vu0luYKCfyBZp2trCjpc8caC3vVM3w==} - engines: {node: '>=0.4.0'} - dependencies: - os-tmpdir: 1.0.2 - dev: true - /tmp/0.2.1: resolution: {integrity: sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==} engines: {node: '>=8.17.0'} @@ -6930,26 +7019,27 @@ packages: utf8-byte-length: 1.0.4 dev: true - /ts-essentials/8.1.0_typescript@4.5.5: - resolution: {integrity: sha512-34xALeQADWRYq9kbtprP4KdpTQ3v3BBIs/U4SpaP+C4++B8ijXY5NnILRJLchQVMzw7YBzKuGMUMrI9uT+ALVw==} + /ts-essentials/9.3.0_typescript@4.9.5: + resolution: {integrity: sha512-XeiCboEyBG8UqXZtXl59bWEi4ZgOqRsogFDI6WDGIF1LmzbYiAkIwjkXN6zZWWl4re/lsOqMlYfe8KA0XiiEPw==} peerDependencies: - typescript: '>=4.0.0' + typescript: '>=4.1.0' dependencies: - typescript: 4.5.5 + typescript: 4.9.5 dev: true - /ts-loader/8.0.3_typescript@4.5.5: - resolution: {integrity: sha512-wsqfnVdB7xQiqhqbz2ZPLGHLPZbHVV5Qn/MNFZkCFxRU1miDyxKORucDGxKtsQJ63Rfza0udiUxWF5nHY6bpdQ==} - engines: {node: '>=10.0.0'} + /ts-loader/9.4.2_hhrrucqyg4eysmfpujvov2ym5u: + resolution: {integrity: sha512-OmlC4WVmFv5I0PpaxYb+qGeGOdm5giHU7HwDDUjw59emP2UYMHy9fFSDcYgSNoH8sXcj4hGCSEhlDZ9ULeDraA==} + engines: {node: '>=12.0.0'} peerDependencies: typescript: '*' + webpack: ^5.0.0 dependencies: - chalk: 2.4.2 - enhanced-resolve: 4.5.0 - loader-utils: 1.4.2 + chalk: 4.1.2 + enhanced-resolve: 5.12.0 micromatch: 4.0.5 - semver: 6.3.0 - typescript: 4.5.5 + semver: 7.3.8 + typescript: 4.9.5 + webpack: 5.75.0_webpack-cli@4.10.0 dev: true /tslib/1.14.1: @@ -6960,14 +7050,14 @@ packages: resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==} dev: true - /tsutils/3.21.0_typescript@4.5.5: + /tsutils/3.21.0_typescript@4.9.5: resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} 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' dependencies: tslib: 1.14.1 - typescript: 4.5.5 + typescript: 4.9.5 dev: true /tunnel-agent/0.6.0: @@ -6975,6 +7065,7 @@ packages: dependencies: safe-buffer: 5.2.1 dev: true + optional: true /tunnel/0.0.6: resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==} @@ -7022,8 +7113,8 @@ packages: underscore: 1.13.6 dev: true - /typescript/4.5.5: - resolution: {integrity: sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==} + /typescript/4.9.5: + resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==} engines: {node: '>=4.2.0'} hasBin: true dev: true @@ -7200,68 +7291,43 @@ packages: engines: {node: '>= 0.8'} dev: true - /vsce/2.15.0: - resolution: {integrity: sha512-P8E9LAZvBCQnoGoizw65JfGvyMqNGlHdlUXD1VAuxtvYAaHBKLBdKPnpy60XKVDAkQCfmMu53g+gq9FM+ydepw==} - engines: {node: '>= 14'} - deprecated: vsce has been renamed to @vscode/vsce. Install using @vscode/vsce instead. - hasBin: true - dependencies: - azure-devops-node-api: 11.2.0 - chalk: 2.4.2 - cheerio: 1.0.0-rc.12 - commander: 6.2.1 - glob: 7.2.0 - hosted-git-info: 4.1.0 - keytar: 7.9.0 - leven: 3.1.0 - markdown-it: 12.3.2 - mime: 1.6.0 - minimatch: 3.1.2 - parse-semver: 1.1.1 - read: 1.0.7 - semver: 5.7.1 - tmp: 0.2.1 - typed-rest-client: 1.8.9 - url-join: 4.0.1 - xml2js: 0.4.23 - yauzl: 2.10.0 - yazl: 2.5.1 - dev: true - - /vscode-extension-tester-locators/1.62.2_gbv7m2qd3dlril5shkdv2le4qm: - resolution: {integrity: sha512-XzN0Tus5ct2aQKY/KpQbRz/M4+0isKC5/5SvS+6djLphBj3pZqvwduOdp6Gb6ATHt3AkwGn+Yau3X6mwgNJGlg==} + /vscode-extension-tester-locators/3.3.0_uesc2kg7tcvmuropzf2xkvkrym: + resolution: {integrity: sha512-rpeuCVNTxy5fGy2lQKPNUBCt6/7nSJBZY91J2MtwVYv1Nj6VbVZl38JNq7KAM9J+7pNSPYLsFAmHB2NzLWkD5g==} peerDependencies: - monaco-page-objects: ^1.0.0 - selenium-webdriver: ^3.0.0 + monaco-page-objects: ^3.3.0 + selenium-webdriver: ^4.6.1 dependencies: - monaco-page-objects: 1.9.2_nd7aufnafpcvjaepgzlwugj3oe - selenium-webdriver: 3.6.0 + monaco-page-objects: 3.3.0_mcttbz3hm275ldw6tl6gcvo6pq + selenium-webdriver: 4.8.0 dev: true - /vscode-extension-tester/4.2.5_rgw4eiitjdvgxwfnqqw3bex6ee: - resolution: {integrity: sha512-Igl3hnnLOtcC7vBJyMui5G+Vt6OiWtoomtqdD1oD+7bZFsF9OqBqDE9tD2K1mTYI4tlRFEBgC7jRi2h29bRNfg==} + /vscode-extension-tester/5.3.0_4r5rv57huad4ctfiz6vn747ruu: + resolution: {integrity: sha512-AWUJkeEsKCxQniD2p1N6gtnLHilgAtz0FszRfqL898z4ZJuySmkKD2+GOuqeacU/PjmSEsVd3h8BcxyvDswcVw==} hasBin: true peerDependencies: mocha: '>=5.2.0' + typescript: '>=4.6.2' dependencies: - '@types/selenium-webdriver': 3.0.20 - commander: 8.3.0 - compare-versions: 3.6.0 - fs-extra: 10.1.0 - glob: 7.2.0 + '@types/selenium-webdriver': 4.1.10 + '@vscode/vsce': 2.17.0 + commander: 10.0.0 + compare-versions: 5.0.3 + fs-extra: 11.1.0 + glob: 8.1.0 got: 11.8.6 - hpagent: 0.1.2 + hpagent: 1.2.0 js-yaml: 4.1.0 mocha: 10.2.0 - monaco-page-objects: 1.9.2_nd7aufnafpcvjaepgzlwugj3oe + monaco-page-objects: 3.3.0_mcttbz3hm275ldw6tl6gcvo6pq sanitize-filename: 1.6.3 - selenium-webdriver: 3.6.0 + selenium-webdriver: 4.8.0 targz: 1.0.1 + typescript: 4.9.5 unzip-stream: 0.3.1 - vsce: 2.15.0 - vscode-extension-tester-locators: 1.62.2_gbv7m2qd3dlril5shkdv2le4qm + vscode-extension-tester-locators: 3.3.0_uesc2kg7tcvmuropzf2xkvkrym transitivePeerDependencies: - - typescript + - bufferutil + - utf-8-validate dev: true /warning/4.0.3: diff --git a/src/commands/Article.ts b/src/commands/Article.ts index 8baec070..2dbc670f 100644 --- a/src/commands/Article.ts +++ b/src/commands/Article.ts @@ -1,10 +1,20 @@ import { Folders } from './Folders'; import { DEFAULT_CONTENT_TYPE } from './../constants/ContentType'; import { isValidFile } from './../helpers/isValidFile'; -import { SETTING_AUTO_UPDATE_DATE, SETTING_SLUG_UPDATE_FILE_NAME, SETTING_TEMPLATES_PREFIX, CONFIG_KEY, SETTING_DATE_FORMAT, SETTING_SLUG_PREFIX, SETTING_SLUG_SUFFIX, SETTING_CONTENT_PLACEHOLDERS, TelemetryEvent } from './../constants'; +import { + SETTING_AUTO_UPDATE_DATE, + SETTING_SLUG_UPDATE_FILE_NAME, + SETTING_TEMPLATES_PREFIX, + CONFIG_KEY, + SETTING_DATE_FORMAT, + SETTING_SLUG_PREFIX, + SETTING_SLUG_SUFFIX, + SETTING_CONTENT_PLACEHOLDERS, + TelemetryEvent +} from './../constants'; import * as vscode from 'vscode'; -import { CustomPlaceholder, Field, TaxonomyType } from "../models"; -import { format } from "date-fns"; +import { CustomPlaceholder, Field, TaxonomyType } from '../models'; +import { format } from 'date-fns'; import { ArticleHelper, Settings, SlugHelper } from '../helpers'; import { Notifications } from '../helpers/Notifications'; import { extname, basename, parse, dirname } from 'path'; @@ -18,13 +28,12 @@ import { MediaListener } from '../listeners/panel'; import { NavigationType } from '../dashboardWebView/models'; import { processKnownPlaceholders } from '../helpers/PlaceholderHelper'; - export class Article { /** - * Insert taxonomy - * - * @param type - */ + * Insert taxonomy + * + * @param type + */ public static async insert(type: TaxonomyType) { const editor = vscode.window.activeTextEditor; if (!editor) { @@ -38,16 +47,21 @@ export class Article { } let options: vscode.QuickPickItem[] = []; - const matterProp: string = type === TaxonomyType.Tag ? "tags" : "categories"; + const matterProp: string = type === TaxonomyType.Tag ? 'tags' : 'categories'; // Add the selected options to the options array if (article.data[matterProp]) { const propData = article.data[matterProp]; if (propData && propData.length > 0) { - options = [...propData].filter(p => p).map(p => ({ - label: p, - picked: true - } as vscode.QuickPickItem)); + options = [...propData] + .filter((p) => p) + .map( + (p) => + ({ + label: p, + picked: true + } as vscode.QuickPickItem) + ); } } @@ -55,7 +69,7 @@ export class Article { const crntOptions = Settings.getTaxonomy(type); if (crntOptions && crntOptions.length > 0) { for (const crntOpt of crntOptions) { - if (!options.find(o => o.label === crntOpt)) { + if (!options.find((o) => o.label === crntOpt)) { options.push({ label: crntOpt }); @@ -64,18 +78,18 @@ export class Article { } if (options.length === 0) { - Notifications.info(`No ${type === TaxonomyType.Tag ? "tags" : "categories"} configured.`); + Notifications.info(`No ${type === TaxonomyType.Tag ? 'tags' : 'categories'} configured.`); return; } const selectedOptions = await vscode.window.showQuickPick(options, { - placeHolder: `Select your ${type === TaxonomyType.Tag ? "tags" : "categories"} to insert`, + placeHolder: `Select your ${type === TaxonomyType.Tag ? 'tags' : 'categories'} to insert`, canPickMany: true, ignoreFocusOut: true }); if (selectedOptions) { - article.data[matterProp] = selectedOptions.map(o => o.label); + article.data[matterProp] = selectedOptions.map((o) => o.label); } ArticleHelper.update(editor, article); @@ -100,7 +114,9 @@ export class Article { try { ArticleHelper.update(editor, article); } catch (e) { - Notifications.error(`Something failed while parsing the date format. Check your "${CONFIG_KEY}${SETTING_DATE_FORMAT}" setting.`); + Notifications.error( + `Something failed while parsing the date format. Check your "${CONFIG_KEY}${SETTING_DATE_FORMAT}" setting.` + ); } } @@ -124,14 +140,11 @@ export class Article { const updatedArticle = this.setLastModifiedDateInner(editor.document); - if (typeof updatedArticle === "undefined") { + if (typeof updatedArticle === 'undefined') { return; } - ArticleHelper.update( - editor, - updatedArticle as ParsedFrontMatter - ); + ArticleHelper.update(editor, updatedArticle as ParsedFrontMatter); } public static async setLastModifiedDateOnSave( @@ -139,7 +152,7 @@ export class Article { ): Promise { const updatedArticle = this.setLastModifiedDateInner(document); - if (typeof updatedArticle === "undefined") { + if (typeof updatedArticle === 'undefined') { return []; } @@ -164,7 +177,9 @@ export class Article { cloneArticle.data[dateField] = Article.formatDate(new Date()); return cloneArticle; } catch (e: unknown) { - Notifications.error(`Something failed while parsing the date format. Check your "${CONFIG_KEY}${SETTING_DATE_FORMAT}" setting.`); + Notifications.error( + `Something failed while parsing the date format. Check your "${CONFIG_KEY}${SETTING_DATE_FORMAT}" setting.` + ); } } @@ -194,8 +209,8 @@ export class Article { /** * Generate the slug based on the article title */ - public static async updateSlug() { - Telemetry.send(TelemetryEvent.generateSlug); + public static async updateSlug() { + Telemetry.send(TelemetryEvent.generateSlug); const updateFileName = Settings.get(SETTING_SLUG_UPDATE_FILE_NAME) as string; const editor = vscode.window.activeTextEditor; @@ -212,30 +227,38 @@ export class Article { let filePrefix = Settings.get(SETTING_TEMPLATES_PREFIX); const contentType = ArticleHelper.getContentType(article.data); filePrefix = ArticleHelper.getFilePrefix(editor.document.uri.fsPath, contentType); - - const titleField = "title"; + + const titleField = 'title'; const articleTitle: string = article.data[titleField]; const slugInfo = Article.generateSlug(articleTitle); if (slugInfo && slugInfo.slug && slugInfo.slugWithPrefixAndSuffix) { - article.data["slug"] = slugInfo.slugWithPrefixAndSuffix; + article.data['slug'] = slugInfo.slugWithPrefixAndSuffix; if (contentType) { // Update the fields containing the slug placeholder - const fieldsToUpdate: Field[] = contentType.fields.filter(f => f.default === "{{slug}}"); + const fieldsToUpdate: Field[] = contentType.fields.filter((f) => f.default === '{{slug}}'); for (const field of fieldsToUpdate) { article.data[field.name] = slugInfo.slug; } // Update the fields containing a custom placeholder that depends on slug const placeholders = Settings.get(SETTING_CONTENT_PLACEHOLDERS); - const customPlaceholders = placeholders?.filter(p => p.value && p.value.includes("{{slug}}")); + const customPlaceholders = placeholders?.filter( + (p) => p.value && p.value.includes('{{slug}}') + ); const dateFormat = Settings.get(SETTING_DATE_FORMAT) as string; - for (const customPlaceholder of (customPlaceholders || [])) { - const customPlaceholderFields = contentType.fields.filter(f => f.default === `{{${customPlaceholder.id}}}`); + for (const customPlaceholder of customPlaceholders || []) { + const customPlaceholderFields = contentType.fields.filter( + (f) => f.default === `{{${customPlaceholder.id}}}` + ); for (const pField of customPlaceholderFields) { article.data[pField.name] = customPlaceholder.value; - article.data[pField.name] = processKnownPlaceholders(article.data[pField.name], articleTitle, dateFormat); + article.data[pField.name] = processKnownPlaceholders( + article.data[pField.name], + articleTitle, + dateFormat + ); } } } @@ -250,11 +273,11 @@ export class Article { const ext = extname(editor.document.fileName); const fileName = basename(editor.document.fileName); - let slugName = slugInfo.slug.startsWith("/") ? slugInfo.slug.substring(1) : slugInfo.slug; - slugName = slugName.endsWith("/") ? slugName.substring(0, slugName.length - 1) : slugName; + let slugName = slugInfo.slug.startsWith('/') ? slugInfo.slug.substring(1) : slugInfo.slug; + slugName = slugName.endsWith('/') ? slugName.substring(0, slugName.length - 1) : slugName; let newFileName = `${slugName}${ext}`; - if (filePrefix && typeof filePrefix === "string") { + if (filePrefix && typeof filePrefix === 'string') { newFileName = `${filePrefix}-${newFileName}`; } @@ -272,7 +295,7 @@ export class Article { } } } - } + } /** * Retrieve the slug from the front matter @@ -291,7 +314,7 @@ export class Article { const parsedFile = parse(file); - if (parsedFile.name.toLowerCase() !== "index") { + if (parsedFile.name.toLowerCase() !== 'index') { return parsedFile.name; } @@ -312,8 +335,8 @@ export class Article { return; } - const newDraftStatus = !article.data["draft"]; - article.data["draft"] = newDraftStatus; + const newDraftStatus = !article.data['draft']; + article.data['draft'] = newDraftStatus; ArticleHelper.update(editor, article); } @@ -329,7 +352,7 @@ export class Article { // Is article located in one of the content folders const folders = Folders.get(); const documentPath = parseWinPath(document.fileName); - const folder = folders.find(f => documentPath.startsWith(f.path)); + const folder = folders.find((f) => documentPath.startsWith(f.path)); if (!folder) { return; } @@ -346,10 +369,12 @@ export class Article { public static formatDate(dateValue: Date): string { const dateFormat = Settings.get(SETTING_DATE_FORMAT) as string; - if (dateFormat && typeof dateFormat === "string") { + if (dateFormat && typeof dateFormat === 'string') { return format(dateValue, DateHelper.formatUpdate(dateFormat) as string); } else { - return typeof dateValue.toISOString === 'function' ? dateValue.toISOString() : dateValue?.toString(); + return typeof dateValue.toISOString === 'function' + ? dateValue.toISOString() + : dateValue?.toString(); } } @@ -357,19 +382,20 @@ export class Article { * Insert an image from the media dashboard into the article */ public static async insertMedia() { - const editor = vscode.window.activeTextEditor; + const editor = vscode.window.activeTextEditor; if (!editor) { return; } const article = ArticleHelper.getFrontMatter(editor); - const contentType = article && article.data ? ArticleHelper.getContentType(article.data) : DEFAULT_CONTENT_TYPE; + const contentType = + article && article.data ? ArticleHelper.getContentType(article.data) : DEFAULT_CONTENT_TYPE; const position = editor.selection.active; const selectionText = editor.document.getText(editor.selection); await vscode.commands.executeCommand(COMMAND_NAME.dashboard, { - type: "media", + type: 'media', data: { pageBundle: !!contentType.pageBundle, filePath: editor.document.uri.fsPath, @@ -381,13 +407,13 @@ export class Article { // Let the editor panel know you are selecting an image MediaListener.getMediaSelection(); - } + } /** * Insert a snippet into the article */ public static async insertSnippet() { - const editor = vscode.window.activeTextEditor; + const editor = vscode.window.activeTextEditor; if (!editor) { return; } @@ -400,14 +426,14 @@ export class Article { await vscode.commands.executeCommand(COMMAND_NAME.dashboard, { type: NavigationType.Snippets, data: { - fileTitle: article?.data.title || "", + fileTitle: article?.data.title || '', filePath: editor.document.uri.fsPath, fieldName: basename(editor.document.uri.fsPath), position, selection: selectionText } } as DashboardData); - } + } /** * Update the article date and return it @@ -417,7 +443,7 @@ export class Article { * @param forceCreate */ private static articleDate(article: ParsedFrontMatter, field: string, forceCreate: boolean) { - if (typeof article.data[field] !== "undefined" || forceCreate) { + if (typeof article.data[field] !== 'undefined' || forceCreate) { article.data[field] = Article.formatDate(new Date()); } return article; diff --git a/src/commands/Backers.ts b/src/commands/Backers.ts index 73bb80a4..31b7d59e 100644 --- a/src/commands/Backers.ts +++ b/src/commands/Backers.ts @@ -1,8 +1,8 @@ import { commands, ExtensionContext } from 'vscode'; import { COMMAND_NAME, CONTEXT } from '../constants'; import { Extension } from '../helpers'; -import { Credentials } from "../services/Credentials"; -import fetch from "node-fetch"; +import { Credentials } from '../services/Credentials'; +import fetch from 'node-fetch'; import { ExplorerView } from '../explorerView/ExplorerView'; import { Dashboard } from './Dashboard'; import { SettingsListener } from '../listeners/panel'; @@ -26,16 +26,16 @@ export class Backers { public static async tryUsernameCheck() { try { const username = await Backers.getUsername(); - Backers.validate(username || ""); + Backers.validate(username || ''); } catch (e) { - Backers.validate(""); + Backers.validate(''); } } public static async getUsername() { const octokit = await Backers.creds?.getOctokit(); const user = await octokit?.users.getAuthenticated(); - + if (user?.data?.login) { return user?.data?.login; } @@ -52,7 +52,9 @@ export class Backers { const isBeta = ext.isBetaVersion(); - const response = await fetch(`https://${isBeta ? `beta.` : ``}frontmatter.codes/api/backers?backer=${username}`); + const response = await fetch( + `https://${isBeta ? `beta.` : ``}frontmatter.codes/api/backers?backer=${username}` + ); if (response.ok) { const prevData = await ext.getState(CONTEXT.backer, 'global'); @@ -63,7 +65,7 @@ export class Backers { if (explorerView.visible) { SettingsListener.getSettings(); } - + if (Dashboard.isOpen) { Dashboard.reload(); } @@ -72,4 +74,4 @@ export class Backers { ext.setState(CONTEXT.backer, false, 'global'); } } -} \ No newline at end of file +} diff --git a/src/commands/Cache.ts b/src/commands/Cache.ts index 67b6b387..9924dcfb 100644 --- a/src/commands/Cache.ts +++ b/src/commands/Cache.ts @@ -1,35 +1,32 @@ -import { commands } from "vscode"; -import { COMMAND_NAME, ExtensionState } from "../constants"; -import { Extension, Notifications } from "../helpers"; +import { commands } from 'vscode'; +import { COMMAND_NAME, ExtensionState } from '../constants'; +import { Extension, Notifications } from '../helpers'; export class Cache { - public static async registerCommands() { const ext = Extension.getInstance(); const subscriptions = ext.subscriptions; - subscriptions.push( - commands.registerCommand(COMMAND_NAME.clearCache, Cache.clear) - ); + subscriptions.push(commands.registerCommand(COMMAND_NAME.clearCache, Cache.clear)); } - public static async get(key: string, type: "workspace" | "global"): Promise { + public static async get(key: string, type: 'workspace' | 'global'): Promise { const ext = Extension.getInstance(); const cache = await ext.getState(key, type); return cache || undefined; } - public static async set(key: string, data: any, type: "workspace" | "global") { - await Extension.getInstance().setState(key, data, "workspace"); + public static async set(key: string, data: unknown, type: 'workspace' | 'global' = 'workspace') { + await Extension.getInstance().setState(key, data, type); } private static async clear() { const ext = Extension.getInstance(); - await ext.setState(ExtensionState.Dashboard.Pages.Cache, undefined, "workspace"); - await ext.setState(ExtensionState.Dashboard.Pages.Index, undefined, "workspace"); - await ext.setState(ExtensionState.Settings.Extends, undefined, "workspace"); + await ext.setState(ExtensionState.Dashboard.Pages.Cache, undefined, 'workspace'); + await ext.setState(ExtensionState.Dashboard.Pages.Index, undefined, 'workspace'); + await ext.setState(ExtensionState.Settings.Extends, undefined, 'workspace'); - Notifications.info("Cache cleared"); + Notifications.info('Cache cleared'); } -} \ No newline at end of file +} diff --git a/src/commands/Content.ts b/src/commands/Content.ts index 1c048e93..6c4ef060 100644 --- a/src/commands/Content.ts +++ b/src/commands/Content.ts @@ -1,9 +1,8 @@ -import { commands, QuickPickItem, window } from 'vscode'; +import { commands, QuickPickItem, window } from 'vscode'; import { COMMAND_NAME, SETTING_TEMPLATES_ENABLED } from '../constants'; import { Settings } from '../helpers'; export class Content { - public static async create() { const templatesEnabled = await Settings.get(SETTING_TEMPLATES_ENABLED); if (!templatesEnabled) { @@ -11,16 +10,19 @@ export class Content { return; } - const options: QuickPickItem[] = [{ - label: "Create content by content type", - description: "Select if you want to create new content by the available content type(s)" - }, { - label: "Create content by template", - description: "Select if you want to create new content by the available template(s)" - } as QuickPickItem]; + const options: QuickPickItem[] = [ + { + label: 'Create content by content type', + description: 'Select if you want to create new content by the available content type(s)' + }, + { + label: 'Create content by template', + description: 'Select if you want to create new content by the available template(s)' + } as QuickPickItem + ]; const selectedOption = await window.showQuickPick(options, { - title: "Create content", + title: 'Create content', placeHolder: `Select how you want to create your new content`, canPickMany: false, ignoreFocusOut: true @@ -36,4 +38,4 @@ export class Content { return; } -} \ No newline at end of file +} diff --git a/src/commands/Dashboard.ts b/src/commands/Dashboard.ts index c6057b1f..158eca26 100644 --- a/src/commands/Dashboard.ts +++ b/src/commands/Dashboard.ts @@ -1,14 +1,25 @@ import { SETTING_DASHBOARD_OPENONSTART, CONTEXT, ExtensionState } from '../constants'; -import { join } from "path"; -import { commands, Uri, ViewColumn, Webview, WebviewPanel, window } from "vscode"; +import { join } from 'path'; +import { commands, Uri, ViewColumn, Webview, WebviewPanel, window } from 'vscode'; import { Logger, Settings as SettingsHelper } from '../helpers'; import { DashboardCommand } from '../dashboardWebView/DashboardCommand'; import { Extension } from '../helpers/Extension'; import { WebviewHelper } from '@estruyf/vscode'; import { DashboardData } from '../models/DashboardData'; import { MediaLibrary } from '../helpers/MediaLibrary'; -import { DashboardListener, MediaListener, SettingsListener, TelemetryListener, DataListener, PagesListener, ExtensionListener, SnippetListener, TaxonomyListener, LogListener } from '../listeners/dashboard'; -import { MediaListener as PanelMediaListener } from '../listeners/panel' +import { + DashboardListener, + MediaListener, + SettingsListener, + TelemetryListener, + DataListener, + PagesListener, + ExtensionListener, + SnippetListener, + TaxonomyListener, + LogListener +} from '../listeners/dashboard'; +import { MediaListener as PanelMediaListener } from '../listeners/panel'; import { GitListener, ModeListener } from '../listeners/general'; export class Dashboard { @@ -39,10 +50,10 @@ export class Dashboard { Dashboard._viewData = data; if (Dashboard.isOpen) { - Dashboard.reveal(!!data); - } else { - Dashboard.create(); - } + Dashboard.reveal(!!data); + } else { + Dashboard.create(); + } await commands.executeCommand('setContext', CONTEXT.isDashboardOpen, true); } @@ -62,7 +73,10 @@ export class Dashboard { Dashboard.webview.reveal(); if (hasData) { - Dashboard.postWebviewMessage({ command: DashboardCommand.viewData, data: Dashboard.viewData }); + Dashboard.postWebviewMessage({ + command: DashboardCommand.viewData, + data: Dashboard.viewData + }); } } } @@ -74,7 +88,11 @@ export class Dashboard { public static reload() { if (Dashboard.isOpen) { Dashboard.webview?.dispose(); - Extension.getInstance().setState(ExtensionState.Dashboard.Pages.Cache, undefined, "workspace") + Extension.getInstance().setState( + ExtensionState.Dashboard.Pages.Cache, + undefined, + 'workspace' + ); setTimeout(() => { Dashboard.open(); @@ -110,14 +128,20 @@ export class Dashboard { light: Uri.file(join(extensionUri.fsPath, 'assets/icons/frontmatter-short-light.svg')) }; - Dashboard.webview.webview.html = Dashboard.getWebviewContent(Dashboard.webview.webview, extensionUri); + Dashboard.webview.webview.html = Dashboard.getWebviewContent( + Dashboard.webview.webview, + extensionUri + ); Dashboard.webview.onDidChangeViewState(async () => { if (!this.webview?.visible) { Dashboard._viewData = undefined; PanelMediaListener.getMediaSelection(); - Dashboard.postWebviewMessage({ command: DashboardCommand.viewData, data: null }); + Dashboard.postWebviewMessage({ + command: DashboardCommand.viewData, + data: null + }); } await commands.executeCommand('setContext', CONTEXT.isDashboardOpen, this.webview?.visible); @@ -164,7 +188,7 @@ export class Dashboard { * Post data to the dashboard * @param msg */ - public static postWebviewMessage(msg: { command: DashboardCommand, data?: unknown }) { + public static postWebviewMessage(msg: { command: DashboardCommand; data?: unknown }) { if (Dashboard.isDisposed) { return; } @@ -179,14 +203,16 @@ export class Dashboard { * @param webView */ private static getWebviewContent(webView: Webview, extensionPath: Uri): string { - const dashboardFile = "dashboardWebView.js"; + const dashboardFile = 'dashboardWebView.js'; const localPort = `9000`; const localServerUrl = `localhost:${localPort}`; - let scriptUri = ""; + let scriptUri = ''; const isProd = Extension.getInstance().isProductionMode; if (isProd) { - scriptUri = webView.asWebviewUri(Uri.joinPath(extensionPath, 'dist', dashboardFile)).toString(); + scriptUri = webView + .asWebviewUri(Uri.joinPath(extensionPath, 'dist', dashboardFile)) + .toString(); } else { scriptUri = `http://${localServerUrl}/${dashboardFile}`; } @@ -199,12 +225,22 @@ export class Dashboard { const csp = [ `default-src 'none';`, - `img-src ${`vscode-file://vscode-app`} ${webView.cspSource} https://api.visitorbadge.io 'self' 'unsafe-inline' https://*`, - `media-src ${`vscode-file://vscode-app`} ${webView.cspSource} 'self' 'unsafe-inline' https://*`, - `script-src ${isProd ? `'nonce-${nonce}'` : `http://${localServerUrl} http://0.0.0.0:${localPort}`} 'unsafe-eval'`, + `img-src ${`vscode-file://vscode-app`} ${ + webView.cspSource + } https://api.visitorbadge.io 'self' 'unsafe-inline' https://*`, + `media-src ${`vscode-file://vscode-app`} ${ + webView.cspSource + } 'self' 'unsafe-inline' https://*`, + `script-src ${ + isProd ? `'nonce-${nonce}'` : `http://${localServerUrl} http://0.0.0.0:${localPort}` + } 'unsafe-eval'`, `style-src ${webView.cspSource} 'self' 'unsafe-inline'`, `font-src ${webView.cspSource}`, - `connect-src https://o1022172.ingest.sentry.io ${isProd ? `` : `ws://${localServerUrl} ws://0.0.0.0:${localPort} http://${localServerUrl} http://0.0.0.0:${localPort}`}` + `connect-src https://o1022172.ingest.sentry.io ${ + isProd + ? `` + : `ws://${localServerUrl} ws://0.0.0.0:${localPort} http://${localServerUrl} http://0.0.0.0:${localPort}` + }` ]; return ` @@ -218,11 +254,15 @@ export class Dashboard { Front Matter Dashboard -
+
Daily usage - + `; diff --git a/src/commands/Diagnostics.ts b/src/commands/Diagnostics.ts index fc24be1d..622a8fce 100644 --- a/src/commands/Diagnostics.ts +++ b/src/commands/Diagnostics.ts @@ -1,13 +1,11 @@ -import { Folders } from "./Folders"; -import { ViewColumn, workspace } from "vscode"; -import ContentProvider from "../providers/ContentProvider"; -import { join } from "path"; -import { ContentFolder } from "../models"; -import { Settings } from "../helpers/SettingsHelper"; - +import { Folders } from './Folders'; +import { ViewColumn, workspace } from 'vscode'; +import ContentProvider from '../providers/ContentProvider'; +import { join } from 'path'; +import { ContentFolder } from '../models'; +import { Settings } from '../helpers/SettingsHelper'; export class Diagnostics { - public static async show() { const folders = Folders.get(); const projectName = Folders.getProjectFolderName(); @@ -26,11 +24,11 @@ ${projectName} # Folders -${folders.map(f => `- ${f.title}: "${f.path}"`).join("\n")} +${folders.map((f) => `- ${f.title}: "${f.path}"`).join('\n')} # Workspace folder -${wsFolder ? wsFolder.fsPath : "No workspace folder"} +${wsFolder ? wsFolder.fsPath : 'No workspace folder'} # Total files @@ -38,7 +36,7 @@ ${all} # Folders to search files -${folderData.join("\n")} +${folderData.join('\n')} # Complete frontmatter.json config @@ -47,7 +45,7 @@ ${JSON.stringify(Settings.globalConfig, null, 2)} \`\`\` `; - ContentProvider.show(logging, `${projectName} diagnostics`, "markdown", ViewColumn.One); + ContentProvider.show(logging, `${projectName} diagnostics`, 'markdown', ViewColumn.One); } private static async allProjectFiles() { @@ -57,14 +55,26 @@ ${JSON.stringify(Settings.globalConfig, null, 2)} private static async processFolder(folder: ContentFolder, projectName: string) { let projectStart = folder.path.split(projectName).pop(); - projectStart = projectStart || ""; + projectStart = projectStart || ''; projectStart = projectStart?.replace(/\\/g, '/'); projectStart = projectStart?.startsWith('/') ? projectStart.substring(1) : projectStart; - const mdFiles = await workspace.findFiles(join(projectStart, folder.excludeSubdir ? '/' : '**/', '*.md')); - const mdxFiles = await workspace.findFiles(join(projectStart, folder.excludeSubdir ? '/' : '**/', '*.mdx')); - const markdownFiles = await workspace.findFiles(join(projectStart, folder.excludeSubdir ? '/' : '**/', '*.markdown')); + const mdFiles = await workspace.findFiles( + join(projectStart, folder.excludeSubdir ? '/' : '**/', '*.md') + ); + const mdxFiles = await workspace.findFiles( + join(projectStart, folder.excludeSubdir ? '/' : '**/', '*.mdx') + ); + const markdownFiles = await workspace.findFiles( + join(projectStart, folder.excludeSubdir ? '/' : '**/', '*.markdown') + ); - return `- Project start length: ${projectStart.length} | Search in: "${join(projectStart, folder.excludeSubdir ? '/' : '**/', '*.*')}" | mdFiles: ${mdFiles.length} | mdxFiles: ${mdxFiles.length} | markdownFiles: ${markdownFiles.length}`; + return `- Project start length: ${projectStart.length} | Search in: "${join( + projectStart, + folder.excludeSubdir ? '/' : '**/', + '*.*' + )}" | mdFiles: ${mdFiles.length} | mdxFiles: ${mdxFiles.length} | markdownFiles: ${ + markdownFiles.length + }`; } -} \ No newline at end of file +} diff --git a/src/commands/Folders.ts b/src/commands/Folders.ts index d1ee95f9..ad22fafc 100644 --- a/src/commands/Folders.ts +++ b/src/commands/Folders.ts @@ -1,13 +1,18 @@ import { STATIC_FOLDER_PLACEHOLDER } from './../constants/StaticFolderPlaceholder'; import { Questions } from './../helpers/Questions'; -import { SETTING_CONTENT_PAGE_FOLDERS, SETTING_CONTENT_STATIC_FOLDER, SETTING_CONTENT_SUPPORTED_FILETYPES, TelemetryEvent } from './../constants'; -import { commands, Uri, workspace, window } from "vscode"; -import { basename, dirname, join, relative, sep } from "path"; -import { ContentFolder, FileInfo, FolderInfo } from "../models"; -import uniqBy = require("lodash.uniqby"); -import { Template } from "./Template"; -import { Notifications } from "../helpers/Notifications"; -import { Logger, Settings } from "../helpers"; +import { + SETTING_CONTENT_PAGE_FOLDERS, + SETTING_CONTENT_STATIC_FOLDER, + SETTING_CONTENT_SUPPORTED_FILETYPES, + TelemetryEvent +} from './../constants'; +import { commands, Uri, workspace, window } from 'vscode'; +import { basename, dirname, join, relative, sep } from 'path'; +import { ContentFolder, FileInfo, FolderInfo } from '../models'; +import uniqBy = require('lodash.uniqby'); +import { Template } from './Template'; +import { Notifications } from '../helpers/Notifications'; +import { Logger, Settings } from '../helpers'; import { existsSync } from 'fs'; import { format } from 'date-fns'; import { Dashboard } from './Dashboard'; @@ -23,29 +28,31 @@ import { existsAsync } from '../utils'; export const WORKSPACE_PLACEHOLDER = `[[workspace]]`; export class Folders { - /** * Add a media folder * @returns */ - public static async addMediaFolder(data?: {selectedFolder?: string}) { + public static async addMediaFolder(data?: { selectedFolder?: string }) { const wsFolder = Folders.getWorkspaceFolder(); const staticFolder = Folders.getStaticFolderRelativePath(); - let startPath = ""; + let startPath = ''; if (data?.selectedFolder) { - startPath = data.selectedFolder.replace(parseWinPath(wsFolder?.fsPath || ""), ""); + startPath = data.selectedFolder.replace(parseWinPath(wsFolder?.fsPath || ''), ''); } else if (staticFolder) { startPath = `/${staticFolder}`; } - if (startPath && !startPath.endsWith("/")) { - startPath += "/"; + if (startPath && !startPath.endsWith('/')) { + startPath += '/'; } if (startPath.includes(STATIC_FOLDER_PLACEHOLDER.hexo.placeholder)) { - startPath = startPath.replace(STATIC_FOLDER_PLACEHOLDER.hexo.placeholder, STATIC_FOLDER_PLACEHOLDER.hexo.postsFolder); + startPath = startPath.replace( + STATIC_FOLDER_PLACEHOLDER.hexo.placeholder, + STATIC_FOLDER_PLACEHOLDER.hexo.postsFolder + ); } const folderName = await window.showInputBox({ @@ -61,7 +68,7 @@ export class Folders { return; } - await Folders.createFolder(join(parseWinPath(wsFolder?.fsPath || ""), folderName)); + await Folders.createFolder(join(parseWinPath(wsFolder?.fsPath || ''), folderName)); } public static async createFolder(folderPath: string) { @@ -81,14 +88,14 @@ export class Folders { * Create content in a registered folder * @returns */ - public static async create() { + public static async create() { const selectedFolder = await Questions.SelectContentFolder(); if (!selectedFolder) { return; } const folders = Folders.get(); - const location = folders.find(f => f.title === selectedFolder); + const location = folders.find((f) => f.title === selectedFolder); if (location) { const folderPath = Folders.getFolderPath(Uri.file(location.path)); if (folderPath) { @@ -101,7 +108,7 @@ export class Folders { * Register the new folder path * @param folderInfo */ - public static async register(folderInfo: { title: string, path: Uri } | Uri) { + public static async register(folderInfo: { title: string; path: Uri } | Uri) { let folderName = folderInfo instanceof Uri ? undefined : folderInfo.title; const folder = folderInfo instanceof Uri ? folderInfo : folderInfo.path; @@ -110,7 +117,9 @@ export class Folders { let folders = Folders.get(); - const exists = folders.find(f => f.path.includes(folder.fsPath) || f.path.includes(wslPath)); + const exists = folders.find( + (f) => f.path.includes(folder.fsPath) || f.path.includes(wslPath) + ); if (exists) { Notifications.warning(`Folder is already registered`); @@ -132,7 +141,7 @@ export class Folders { path: folder.fsPath } as ContentFolder); - folders = uniqBy(folders, f => f.path); + folders = uniqBy(folders, (f) => f.path); await Folders.update(folders); Notifications.info(`Folder registered`); @@ -150,7 +159,7 @@ export class Folders { public static async unregister(folder: Uri) { if (folder && folder.path) { let folders = Folders.get(); - folders = folders.filter(f => f.path !== folder.fsPath); + folders = folders.filter((f) => f.path !== folder.fsPath); await Folders.update(folders); Telemetry.send(TelemetryEvent.unregisterFolder); @@ -182,13 +191,13 @@ export class Folders { * @returns */ public static getFolderPath(folder: Uri) { - let folderPath = ""; + let folderPath = ''; const wsFolder = Folders.getWorkspaceFolder(); - if (folder && folder.fsPath) { - folderPath = folder.fsPath; - } else if (wsFolder) { - folderPath = wsFolder.fsPath; - } + if (folder && folder.fsPath) { + folderPath = folder.fsPath; + } else if (wsFolder) { + folderPath = wsFolder.fsPath; + } return folderPath; } @@ -210,15 +219,17 @@ export class Folders { } if (!projectFolder) { - window.showWorkspaceFolderPick({ - placeHolder: `Please select the main workspace folder for Front Matter to use.` - }).then(async (selectedFolder) => { - if (selectedFolder) { - await Settings.createGlobalFile(selectedFolder.uri); - // Full reload to make sure the whole extension is reloaded correctly - commands.executeCommand(`workbench.action.reloadWindow`); - } - }); + window + .showWorkspaceFolderPick({ + placeHolder: `Please select the main workspace folder for Front Matter to use.` + }) + .then(async (selectedFolder) => { + if (selectedFolder) { + await Settings.createGlobalFile(selectedFolder.uri); + // Full reload to make sure the whole extension is reloaded correctly + commands.executeCommand(`workbench.action.reloadWindow`); + } + }); } return projectFolder; @@ -235,7 +246,7 @@ export class Folders { if (wsFolder) { return basename(wsFolder.fsPath); } - return ""; + return ''; } /** @@ -244,14 +255,14 @@ export class Folders { public static async getInfo(limit?: number): Promise { const supportedFiles = Settings.get(SETTING_CONTENT_SUPPORTED_FILETYPES); const folders = Folders.get(); - const wsFolder = parseWinPath(Folders.getWorkspaceFolder()?.fsPath || ""); + const wsFolder = parseWinPath(Folders.getWorkspaceFolder()?.fsPath || ''); if (folders && folders.length > 0) { const folderInfo: FolderInfo[] = []; for (const folder of folders) { try { - let projectStart = parseWinPath(folder.path).replace(wsFolder, ""); + let projectStart = parseWinPath(folder.path).replace(wsFolder, ''); if (typeof projectStart === 'string') { projectStart = projectStart.replace(/\\/g, '/'); @@ -259,8 +270,12 @@ export class Folders { let files: Uri[] = []; - for (const fileType of (supportedFiles || DEFAULT_FILE_TYPES)) { - let filePath = join(projectStart, folder.excludeSubdir ? '/' : '**', `*${fileType.startsWith('.') ? '' : '.'}${fileType}`); + for (const fileType of supportedFiles || DEFAULT_FILE_TYPES) { + let filePath = join( + projectStart, + folder.excludeSubdir ? '/' : '**', + `*${fileType.startsWith('.') ? '' : '.'}${fileType}` + ); if (projectStart === '' && folder.excludeSubdir) { filePath = `*${fileType.startsWith('.') ? '' : '.'}${fileType}`; @@ -323,17 +338,20 @@ export class Folders { const wsFolder = Folders.getWorkspaceFolder(); const folders: ContentFolder[] = Settings.get(SETTING_CONTENT_PAGE_FOLDERS) as ContentFolder[]; - const contentFolders = folders.map(folder => { + const contentFolders = folders.map((folder) => { if (!folder.title) { folder.title = basename(folder.path); } const folderPath = Folders.absWsFolder(folder, wsFolder); if (!existsSync(folderPath)) { - Notifications.errorShowOnce(`Folder "${folder.title} (${folder.path})" does not exist. Please remove it from the settings.`, "Remove folder").then(answer => { - if (answer === "Remove folder") { + Notifications.errorShowOnce( + `Folder "${folder.title} (${folder.path})" does not exist. Please remove it from the settings.`, + 'Remove folder' + ).then((answer) => { + if (answer === 'Remove folder') { const folders = Folders.get(); - Folders.update(folders.filter(f => f.path !== folder.path)); + Folders.update(folders.filter((f) => f.path !== folder.path)); } }); return null; @@ -342,10 +360,10 @@ export class Folders { return { ...folder, path: folderPath - } - }) + }; + }); - return contentFolders.filter(folder => folder !== null) as ContentFolder[]; + return contentFolders.filter((folder) => folder !== null) as ContentFolder[]; } /** @@ -355,7 +373,7 @@ export class Folders { public static async update(folders: ContentFolder[]) { const wsFolder = Folders.getWorkspaceFolder(); - const folderDetails = folders.map(folder => ({ + const folderDetails = folders.map((folder) => ({ ...folder, path: Folders.relWsFolder(folder, wsFolder) })); @@ -374,7 +392,7 @@ export class Folders { public static getAbsFilePath(filePath: string): string { const wsFolder = Folders.getWorkspaceFolder(); const isWindows = process.platform === 'win32'; - let absPath = filePath.replace(WORKSPACE_PLACEHOLDER, parseWinPath(wsFolder?.fsPath || "")); + let absPath = filePath.replace(WORKSPACE_PLACEHOLDER, parseWinPath(wsFolder?.fsPath || '')); absPath = isWindows ? absPath.split('/').join('\\') : absPath; return parseWinPath(absPath); } @@ -387,7 +405,7 @@ export class Folders { */ private static absWsFolder(folder: ContentFolder, wsFolder?: Uri) { const isWindows = process.platform === 'win32'; - let absPath = folder.path.replace(WORKSPACE_PLACEHOLDER, parseWinPath(wsFolder?.fsPath || "")); + let absPath = folder.path.replace(WORKSPACE_PLACEHOLDER, parseWinPath(wsFolder?.fsPath || '')); absPath = isWindows ? absPath.split('/').join('\\') : absPath; return parseWinPath(absPath); } @@ -400,7 +418,10 @@ export class Folders { */ public static relWsFolder(folder: ContentFolder, wsFolder?: Uri) { const isWindows = process.platform === 'win32'; - let absPath = parseWinPath(folder.path).replace(parseWinPath(wsFolder?.fsPath || ""), WORKSPACE_PLACEHOLDER); + let absPath = parseWinPath(folder.path).replace( + parseWinPath(wsFolder?.fsPath || ''), + WORKSPACE_PLACEHOLDER + ); absPath = isWindows ? absPath.split('\\').join('/') : absPath; return absPath; } @@ -411,25 +432,37 @@ export class Folders { public static async getContentFolders() { // Find folders that contain files const wsFolder = Folders.getWorkspaceFolder(); - const supportedFiles = Settings.get(SETTING_CONTENT_SUPPORTED_FILETYPES) || DEFAULT_FILE_TYPES; - const patterns = supportedFiles.map(fileType => `${join(parseWinPath(wsFolder?.fsPath || ""), "**", `*${fileType.startsWith('.') ? '' : '.'}${fileType}`)}`); + const supportedFiles = + Settings.get(SETTING_CONTENT_SUPPORTED_FILETYPES) || DEFAULT_FILE_TYPES; + const patterns = supportedFiles.map( + (fileType) => + `${join( + parseWinPath(wsFolder?.fsPath || ''), + '**', + `*${fileType.startsWith('.') ? '' : '.'}${fileType}` + )}` + ); let folders: string[] = []; for (const pattern of patterns) { try { folders = [...folders, ...(await this.findFolders(pattern))]; } catch (e) { - Logger.error(`Something went wrong while searching for folders with pattern "${pattern}": ${(e as Error).message}`); + Logger.error( + `Something went wrong while searching for folders with pattern "${pattern}": ${ + (e as Error).message + }` + ); } } // Filter out the workspace folder if (wsFolder) { - folders = folders.filter(folder => folder !== wsFolder.fsPath); + folders = folders.filter((folder) => folder !== wsFolder.fsPath); } const uniqueFolders = [...new Set(folders)]; - return uniqueFolders.map(folder => relative(wsFolder?.path || "", folder)); + return uniqueFolders.map((folder) => relative(wsFolder?.path || '', folder)); } /** @@ -439,16 +472,15 @@ export class Folders { */ public static getFilePrefixByFolderPath(folderPath: string) { const folders = Folders.get(); - const pageFolder = folders.find(f => parseWinPath(f.path) === parseWinPath(folderPath)); + const pageFolder = folders.find((f) => parseWinPath(f.path) === parseWinPath(folderPath)); - if (pageFolder && typeof pageFolder.filePrefix !== "undefined") { + if (pageFolder && typeof pageFolder.filePrefix !== 'undefined') { return pageFolder.filePrefix; } return; } - /** * Returns the file prefix for the given file path * @param filePath @@ -469,7 +501,7 @@ export class Folders { } } - if (selectedFolder && typeof selectedFolder.filePrefix !== "undefined") { + if (selectedFolder && typeof selectedFolder.filePrefix !== 'undefined') { return selectedFolder.filePrefix; } } @@ -483,9 +515,9 @@ export class Folders { * @returns */ private static findFolders(pattern: string): Promise { - return new Promise(resolve => { - glob(pattern, { ignore: "**/node_modules/**" }, (err, files) => { - const allFolders = files.map(file => dirname(file)); + return new Promise((resolve) => { + glob(pattern, { ignore: '**/node_modules/**' }, (err, files) => { + const allFolders = files.map((file) => dirname(file)); const uniqueFolders = [...new Set(allFolders)]; resolve(uniqueFolders); }); diff --git a/src/commands/Preview.ts b/src/commands/Preview.ts index eb3b4d84..583fbfd0 100644 --- a/src/commands/Preview.ts +++ b/src/commands/Preview.ts @@ -1,8 +1,14 @@ import { Telemetry } from './../helpers/Telemetry'; -import { SETTING_PREVIEW_HOST, SETTING_PREVIEW_PATHNAME, CONTEXT, TelemetryEvent, PreviewCommands } from './../constants'; +import { + SETTING_PREVIEW_HOST, + SETTING_PREVIEW_PATHNAME, + CONTEXT, + TelemetryEvent, + PreviewCommands +} from './../constants'; import { ArticleHelper } from './../helpers/ArticleHelper'; -import { join } from "path"; -import { commands, env, Uri, ViewColumn, window } from "vscode"; +import { join } from 'path'; +import { commands, env, Uri, ViewColumn, window } from 'vscode'; import { Extension, parseWinPath, Settings } from '../helpers'; import { ContentFolder, PreviewSettings } from '../models'; import { format } from 'date-fns'; @@ -12,9 +18,7 @@ import { urlJoin } from 'url-join-ts'; import { WebviewHelper } from '@estruyf/vscode'; import { Folders } from './Folders'; - export class Preview { - /** * Init the preview */ @@ -22,7 +26,7 @@ export class Preview { const settings = Preview.getSettings(); await commands.executeCommand('setContext', CONTEXT.canOpenPreview, !!settings.host); } - + /** * Open the markdown preview in the editor */ @@ -32,17 +36,17 @@ export class Preview { if (!settings.host) { return; } - + const editor = window.activeTextEditor; const article = editor ? ArticleHelper.getFrontMatter(editor) : null; - let slug = article?.data ? article.data.slug : ""; + let slug = article?.data ? article.data.slug : ''; let pathname = settings.pathname; // Check if there is a pathname defined on content folder level const folders = Folders.get(); if (folders.length > 0) { - const foldersWithPath = folders.filter(folder => folder.previewPath); + const foldersWithPath = folders.filter((folder) => folder.previewPath); const filePath = parseWinPath(editor?.document.uri.fsPath); let selectedFolder: ContentFolder | null = null; @@ -76,7 +80,10 @@ export class Preview { const articleDate = ArticleHelper.getDate(article); try { - slug = join(format(articleDate || new Date(), DateHelper.formatUpdate(pathname) as string), slug); + slug = join( + format(articleDate || new Date(), DateHelper.formatUpdate(pathname) as string), + slug + ); } catch (error) { slug = join(pathname, slug); } @@ -106,15 +113,13 @@ export class Preview { webView.iconPath = { dark: Uri.file(join(extensionPath, 'assets/icons/frontmatter-short-dark.svg')), light: Uri.file(join(extensionPath, 'assets/icons/frontmatter-short-light.svg')) - } + }; - const localhostUrl = await env.asExternalUri( - Uri.parse(settings.host) - ); + const localhostUrl = await env.asExternalUri(Uri.parse(settings.host)); const cspSource = webView.webview.cspSource; - webView.webview.onDidReceiveMessage(message => { + webView.webview.onDidReceiveMessage((message) => { switch (message.command) { case PreviewCommands.toVSCode.open: if (message.data) { @@ -124,8 +129,7 @@ export class Preview { } }); - - const dashboardFile = "dashboardWebView.js"; + const dashboardFile = 'dashboardWebView.js'; const localPort = `9000`; const localServerUrl = `localhost:${localPort}`; @@ -136,21 +140,29 @@ export class Preview { const version = ext.getVersion(); const isBeta = ext.isBetaVersion(); const extensionUri = ext.extensionPath; - + const csp = [ `default-src 'none';`, `img-src ${localhostUrl} ${cspSource} http: https:;`, - `script-src ${isProd ? `'nonce-${nonce}'` : `http://${localServerUrl} http://0.0.0.0:${localPort}`} 'unsafe-eval'`, + `script-src ${ + isProd ? `'nonce-${nonce}'` : `http://${localServerUrl} http://0.0.0.0:${localPort}` + } 'unsafe-eval'`, `style-src ${cspSource} 'self' 'unsafe-inline' http: https:`, - `connect-src https://o1022172.ingest.sentry.io ${isProd ? `` : `ws://${localServerUrl} ws://0.0.0.0:${localPort} http://${localServerUrl} http://0.0.0.0:${localPort}`}`, - `frame-src ${localhostUrl} ${cspSource} http: https:;`, + `connect-src https://o1022172.ingest.sentry.io ${ + isProd + ? `` + : `ws://${localServerUrl} ws://0.0.0.0:${localPort} http://${localServerUrl} http://0.0.0.0:${localPort}` + }`, + `frame-src ${localhostUrl} ${cspSource} http: https:;` ]; - let scriptUri = ""; + let scriptUri = ''; if (isProd) { - scriptUri = webView.webview.asWebviewUri(Uri.joinPath(extensionUri, 'dist', dashboardFile)).toString(); + scriptUri = webView.webview + .asWebviewUri(Uri.joinPath(extensionUri, 'dist', dashboardFile)) + .toString(); } else { - scriptUri = `http://${localServerUrl}/${dashboardFile}`; + scriptUri = `http://${localServerUrl}/${dashboardFile}`; } webView.webview.html = ` @@ -164,9 +176,16 @@ export class Preview { Front Matter Preview -
+
- + `; diff --git a/src/commands/Project.ts b/src/commands/Project.ts index b06f8244..0f134498 100644 --- a/src/commands/Project.ts +++ b/src/commands/Project.ts @@ -1,17 +1,20 @@ import { DEFAULT_CONTENT_TYPE } from './../constants/ContentType'; import { Telemetry } from './../helpers/Telemetry'; -import { workspace, Uri } from "vscode"; -import { join } from "path"; -import { Notifications } from "../helpers/Notifications"; -import { Template } from "./Template"; -import { Folders } from "./Folders"; -import { FrameworkDetector, Logger, Settings } from "../helpers"; -import { SETTING_CONTENT_DEFAULT_FILETYPE, SETTING_TAXONOMY_CONTENT_TYPES, TelemetryEvent } from "../constants"; +import { workspace, Uri } from 'vscode'; +import { join } from 'path'; +import { Notifications } from '../helpers/Notifications'; +import { Template } from './Template'; +import { Folders } from './Folders'; +import { FrameworkDetector, Logger, Settings } from '../helpers'; +import { + SETTING_CONTENT_DEFAULT_FILETYPE, + SETTING_TAXONOMY_CONTENT_TYPES, + TelemetryEvent +} from '../constants'; import { SettingsListener } from '../listeners/dashboard'; import { existsAsync, writeFileAsync } from '../utils'; export class Project { - private static content = `--- title: slug: @@ -42,14 +45,14 @@ categories: [] if (sampleTemplate !== undefined) { await Project.createSampleTemplate(); } else { - Notifications.info("Project initialized successfully."); + Notifications.info('Project initialized successfully.'); } Telemetry.send(TelemetryEvent.initialization); // Check if you can find the framework const wsFolder = Folders.getWorkspaceFolder(); - const framework = await FrameworkDetector.get(wsFolder?.fsPath || ""); + const framework = await FrameworkDetector.get(wsFolder?.fsPath || ''); if (framework) { await SettingsListener.setFramework(framework.name); @@ -57,7 +60,7 @@ categories: [] SettingsListener.getSettings(true); } catch (error: unknown) { - const err = (error as Error) + const err = error as Error; Logger.error(`Project::init: ${err?.message || err}`); Notifications.error(`Sorry, something went wrong - ${err?.message || err}`); } @@ -85,8 +88,10 @@ categories: [] } if (sampleTemplate) { - await writeFileAsync(article.fsPath, Project.content, { encoding: "utf-8" }); - Notifications.info("Sample template created."); + await writeFileAsync(article.fsPath, Project.content, { + encoding: 'utf-8' + }); + Notifications.info('Sample template created.'); } } diff --git a/src/commands/Settings.ts b/src/commands/Settings.ts index 729887ac..24be7cf0 100644 --- a/src/commands/Settings.ts +++ b/src/commands/Settings.ts @@ -1,34 +1,38 @@ import { TaxonomyHelper } from './../helpers/TaxonomyHelper'; import * as vscode from 'vscode'; -import { TaxonomyType } from "../models"; +import { TaxonomyType } from '../models'; import { SETTING_TAXONOMY_TAGS, SETTING_TAXONOMY_CATEGORIES, EXTENSION_NAME } from '../constants'; import { ArticleHelper, Settings as SettingsHelper, FilesHelper } from '../helpers'; import { FrontMatterParser } from '../parsers'; import { Notifications } from '../helpers/Notifications'; export class Settings { - /** * Create a new taxonomy - * - * @param type + * + * @param type */ public static async create(type: TaxonomyType) { const newOption = await vscode.window.showInputBox({ - prompt: `Insert the value of the ${type === TaxonomyType.Tag ? "tag" : "category"} that you want to add to your configuration.`, - placeHolder: `Name of the ${type === TaxonomyType.Tag ? "tag" : "category"}`, + prompt: `Insert the value of the ${ + type === TaxonomyType.Tag ? 'tag' : 'category' + } that you want to add to your configuration.`, + placeHolder: `Name of the ${type === TaxonomyType.Tag ? 'tag' : 'category'}`, ignoreFocusOut: true }); - + if (newOption) { - const configSetting = type === TaxonomyType.Tag ? SETTING_TAXONOMY_TAGS : SETTING_TAXONOMY_CATEGORIES; + const configSetting = + type === TaxonomyType.Tag ? SETTING_TAXONOMY_TAGS : SETTING_TAXONOMY_CATEGORIES; let options = SettingsHelper.get(configSetting, true) as string[]; if (!options) { options = []; } - if (options.find(o => o === newOption)) { - Notifications.info(`The provided ${type === TaxonomyType.Tag ? "tag" : "category"} already exists.`); + if (options.find((o) => o === newOption)) { + Notifications.info( + `The provided ${type === TaxonomyType.Tag ? 'tag' : 'category'} already exists.` + ); return; } @@ -36,13 +40,15 @@ export class Settings { await SettingsHelper.updateTaxonomy(type, options); // Ask if the new term needs to be added to the page - const addToPage = await vscode.window.showQuickPick(["yes", "no"], { - canPickMany: false, - placeHolder: `Do you want to add the new ${type === TaxonomyType.Tag ? "tag" : "category"} to the page?`, + const addToPage = await vscode.window.showQuickPick(['yes', 'no'], { + canPickMany: false, + placeHolder: `Do you want to add the new ${ + type === TaxonomyType.Tag ? 'tag' : 'category' + } to the page?`, ignoreFocusOut: true }); - if (addToPage && addToPage === "yes") { + if (addToPage && addToPage === 'yes') { const editor = vscode.window.activeTextEditor; if (!editor) { return; @@ -53,11 +59,11 @@ export class Settings { return; } - const matterProp: string = type === TaxonomyType.Tag ? "tags" : "categories"; + const matterProp: string = type === TaxonomyType.Tag ? 'tags' : 'categories'; // Add the selected options to the options array if (article.data[matterProp]) { const propData: string[] = article.data[matterProp]; - if (propData && !propData.find(o => o === newOption)) { + if (propData && !propData.find((o) => o === newOption)) { propData.push(newOption); } } else { @@ -69,7 +75,6 @@ export class Settings { } } - /** * Export the tags/categories front matter to the user settings */ @@ -80,78 +85,86 @@ export class Settings { return; } - vscode.window.withProgress({ - location: vscode.ProgressLocation.Notification, - title: `${EXTENSION_NAME}: exporting tags and categories`, - cancellable: false - }, async (progress) => { - // Fetching all tags and categories from MD files - let tags: string[] = []; - let categories: string[] = []; + vscode.window.withProgress( + { + location: vscode.ProgressLocation.Notification, + title: `${EXTENSION_NAME}: exporting tags and categories`, + cancellable: false + }, + async (progress) => { + // Fetching all tags and categories from MD files + let tags: string[] = []; + let categories: string[] = []; - // Set the initial progress - const progressNr = allMdFiles.length/100; - progress.report({ increment: 0}); + // Set the initial progress + const progressNr = allMdFiles.length / 100; + progress.report({ increment: 0 }); - let i = 0; - for (const file of allMdFiles) { - progress.report({ increment: (++i/progressNr) }); - const mdFile = await vscode.workspace.openTextDocument(file); - if (mdFile) { - const txtData = mdFile.getText(); - if (txtData) { - try { - const article = FrontMatterParser.fromFile(txtData); - if (article && article.data) { - const { data } = article; - const mdTags = data["tags"]; - const mdCategories = data["categories"]; - if (mdTags) { - tags = [...tags, ...mdTags]; + let i = 0; + for (const file of allMdFiles) { + progress.report({ increment: ++i / progressNr }); + const mdFile = await vscode.workspace.openTextDocument(file); + if (mdFile) { + const txtData = mdFile.getText(); + if (txtData) { + try { + const article = FrontMatterParser.fromFile(txtData); + if (article && article.data) { + const { data } = article; + const mdTags = data['tags']; + const mdCategories = data['categories']; + if (mdTags) { + tags = [...tags, ...mdTags]; + } + if (mdCategories) { + categories = [...categories, ...mdCategories]; + } } - if (mdCategories) { - categories = [...categories, ...mdCategories]; - } - } - } catch (e) { - // Continue with the next file + } catch (e) { + // Continue with the next file + } } } } + + // Retrieve the currently known tags, and add the new ones + let crntTags: string[] = SettingsHelper.get(SETTING_TAXONOMY_TAGS, true) as string[]; + if (!crntTags) { + crntTags = []; + } + crntTags = [...crntTags, ...tags]; + // Update the tags and filter out the duplicates + crntTags = [...new Set(crntTags)]; + crntTags = crntTags.sort().filter((t) => !!t); + await SettingsHelper.update(SETTING_TAXONOMY_TAGS, crntTags, true); + + // Retrieve the currently known tags, and add the new ones + let crntCategories: string[] = SettingsHelper.get( + SETTING_TAXONOMY_CATEGORIES, + true + ) as string[]; + if (!crntCategories) { + crntCategories = []; + } + crntCategories = [...crntCategories, ...categories]; + // Update the categories and filter out the duplicates + crntCategories = [...new Set(crntCategories)]; + crntCategories = crntCategories.sort().filter((c) => !!c); + await SettingsHelper.update(SETTING_TAXONOMY_CATEGORIES, crntCategories, true); + + // Done + Notifications.info( + `Export completed. Tags: ${crntTags.length} - Categories: ${crntCategories.length}.` + ); } - - // Retrieve the currently known tags, and add the new ones - let crntTags: string[] = SettingsHelper.get(SETTING_TAXONOMY_TAGS, true) as string[]; - if (!crntTags) { crntTags = []; } - crntTags = [...crntTags, ...tags]; - // Update the tags and filter out the duplicates - crntTags = [...new Set(crntTags)]; - crntTags = crntTags.sort().filter(t => !!t); - await SettingsHelper.update(SETTING_TAXONOMY_TAGS, crntTags, true); - - // Retrieve the currently known tags, and add the new ones - let crntCategories: string[] = SettingsHelper.get(SETTING_TAXONOMY_CATEGORIES, true) as string[]; - if (!crntCategories) { crntCategories = []; } - crntCategories = [...crntCategories, ...categories]; - // Update the categories and filter out the duplicates - crntCategories = [...new Set(crntCategories)]; - crntCategories = crntCategories.sort().filter(c => !!c); - await SettingsHelper.update(SETTING_TAXONOMY_CATEGORIES, crntCategories, true); - - // Done - Notifications.info(`Export completed. Tags: ${crntTags.length} - Categories: ${crntCategories.length}.`); - }); + ); } - /** * Remap a tag or category to a new one */ public static async remap() { - const taxType = await vscode.window.showQuickPick([ - "Tag", - "Category" - ], { + const taxType = await vscode.window.showQuickPick(['Tag', 'Category'], { title: `Remap`, placeHolder: `What do you want to remap?`, canPickMany: false, @@ -162,16 +175,16 @@ export class Settings { return; } - const type = taxType === "Tag" ? TaxonomyType.Tag : TaxonomyType.Category; + const type = taxType === 'Tag' ? TaxonomyType.Tag : TaxonomyType.Category; const options = SettingsHelper.getTaxonomy(type); - + if (!options || options.length === 0) { - Notifications.info(`No ${type === TaxonomyType.Tag ? "tags" : "categories"} configured.`); + Notifications.info(`No ${type === TaxonomyType.Tag ? 'tags' : 'categories'} configured.`); return; } - const selectedOption = await vscode.window.showQuickPick(options, { - placeHolder: `Select your ${type === TaxonomyType.Tag ? "tags" : "categories"} to insert`, + const selectedOption = await vscode.window.showQuickPick(options, { + placeHolder: `Select your ${type === TaxonomyType.Tag ? 'tags' : 'categories'} to insert`, canPickMany: false, ignoreFocusOut: true }); @@ -180,27 +193,31 @@ export class Settings { return; } - const newOptionValue = await vscode.window.showInputBox({ - prompt: `Specify the value of the ${type === TaxonomyType.Tag ? "tag" : "category"} with which you want to remap "${selectedOption}". Leave the input if you want to remove the ${type === TaxonomyType.Tag ? "tag" : "category"} from all articles.`, - placeHolder: `Name of the ${type === TaxonomyType.Tag ? "tag" : "category"}`, + const newOptionValue = await vscode.window.showInputBox({ + prompt: `Specify the value of the ${ + type === TaxonomyType.Tag ? 'tag' : 'category' + } with which you want to remap "${selectedOption}". Leave the input if you want to remove the ${ + type === TaxonomyType.Tag ? 'tag' : 'category' + } from all articles.`, + placeHolder: `Name of the ${type === TaxonomyType.Tag ? 'tag' : 'category'}`, ignoreFocusOut: true }); if (!newOptionValue) { - const deleteAnswer = await vscode.window.showQuickPick(["yes", "no"], { - canPickMany: false, - placeHolder: `Delete ${selectedOption} ${type === TaxonomyType.Tag ? "tag" : "category"}?`, + const deleteAnswer = await vscode.window.showQuickPick(['yes', 'no'], { + canPickMany: false, + placeHolder: `Delete ${selectedOption} ${type === TaxonomyType.Tag ? 'tag' : 'category'}?`, ignoreFocusOut: true }); - if (deleteAnswer === "no") { + if (deleteAnswer === 'no') { return; } } if (newOptionValue) { - TaxonomyHelper.process("edit", type, selectedOption, newOptionValue); + TaxonomyHelper.process('edit', type, selectedOption, newOptionValue); } else { - TaxonomyHelper.process("delete", type, selectedOption, undefined); + TaxonomyHelper.process('delete', type, selectedOption, undefined); } } -} \ No newline at end of file +} diff --git a/src/commands/StatusListener.ts b/src/commands/StatusListener.ts index 29b54b60..d60c4082 100644 --- a/src/commands/StatusListener.ts +++ b/src/commands/StatusListener.ts @@ -1,5 +1,11 @@ import { ParsedFrontMatter } from './../parsers/FrontMatterParser'; -import { CONTEXT, NOTIFICATION_TYPE, SETTING_SEO_DESCRIPTION_FIELD, SETTING_SEO_DESCRIPTION_LENGTH, SETTING_SEO_TITLE_LENGTH } from './../constants'; +import { + CONTEXT, + NOTIFICATION_TYPE, + SETTING_SEO_DESCRIPTION_FIELD, + SETTING_SEO_DESCRIPTION_LENGTH, + SETTING_SEO_TITLE_LENGTH +} from './../constants'; import * as vscode from 'vscode'; import { ArticleHelper, Notifications, SeoHelper, Settings } from '../helpers'; import { ExplorerView } from '../explorerView/ExplorerView'; @@ -10,19 +16,21 @@ import { commands } from 'vscode'; import { Field } from '../models'; export class StatusListener { - /** * Update the text of the status bar * * @param frontMatterSB * @param collection */ - public static async verify(frontMatterSB: vscode.StatusBarItem, collection: vscode.DiagnosticCollection) { - const draftMsg = "in draft"; - const publishMsg = "to publish"; + public static async verify( + frontMatterSB: vscode.StatusBarItem, + collection: vscode.DiagnosticCollection + ) { + const draftMsg = 'in draft'; + const publishMsg = 'to publish'; const draft = ContentType.getDraftField(); - if (!draft || draft.type !== "boolean") { + if (!draft || draft.type !== 'boolean') { frontMatterSB.hide(); } @@ -34,11 +42,11 @@ export class StatusListener { const article = ArticleHelper.getFrontMatter(editor); // Update the StatusBar based on the article draft state - if (article && typeof article.data["draft"] !== "undefined") { - if (article.data["draft"] === true) { + if (article && typeof article.data['draft'] !== 'undefined') { + if (article.data['draft'] === true) { frontMatterSB.text = `$(book) ${draftMsg}`; frontMatterSB.show(); - } else if (article.data["draft"] === false) { + } else if (article.data['draft'] === false) { frontMatterSB.text = `$(book) ${publishMsg}`; frontMatterSB.show(); } @@ -49,12 +57,13 @@ export class StatusListener { collection.clear(); // Retrieve the SEO config properties - const titleLength = Settings.get(SETTING_SEO_TITLE_LENGTH) as number || -1; - const descLength = Settings.get(SETTING_SEO_DESCRIPTION_LENGTH) as number || -1; - const fieldName = Settings.get(SETTING_SEO_DESCRIPTION_FIELD) as string || DefaultFields.Description; + const titleLength = (Settings.get(SETTING_SEO_TITLE_LENGTH) as number) || -1; + const descLength = (Settings.get(SETTING_SEO_DESCRIPTION_LENGTH) as number) || -1; + const fieldName = + (Settings.get(SETTING_SEO_DESCRIPTION_FIELD) as string) || DefaultFields.Description; if (article.data.title && titleLength > -1) { - SeoHelper.checkLength(editor, collection, article, "title", titleLength); + SeoHelper.checkLength(editor, collection, article, 'title', titleLength); } if (article.data[fieldName] && descLength > -1) { @@ -91,25 +100,30 @@ export class StatusListener { * @param article * @param collection */ - private static verifyRequiredFields(editor: vscode.TextEditor, article: ParsedFrontMatter, collection: vscode.DiagnosticCollection) { + private static verifyRequiredFields( + editor: vscode.TextEditor, + article: ParsedFrontMatter, + collection: vscode.DiagnosticCollection + ) { // Check for missing fields const emptyFields = ContentType.findEmptyRequiredFields(article); const fieldsToReport = []; if (emptyFields && emptyFields.length > 0) { const text = editor.document.getText(); - const markdown = ArticleHelper.stringifyFrontMatter("", article.data); + const markdown = ArticleHelper.stringifyFrontMatter('', article.data); const editorSpaces = vscode.window.activeTextEditor?.options?.tabSize; const requiredDiagnostics: vscode.Diagnostic[] = []; for (const fields of emptyFields) { let txtIdx = -1; - let fieldName = ""; + let fieldName = ''; let level = 0; for (const field of fields) { - const totalSpaces = level * (typeof editorSpaces === "string" ? parseInt(editorSpaces) : editorSpaces || 2); + const totalSpaces = + level * (typeof editorSpaces === 'string' ? parseInt(editorSpaces) : editorSpaces || 2); const crntIdx = StatusListener.findFieldLine(text, txtIdx, totalSpaces, field); if (crntIdx && crntIdx > txtIdx) { @@ -121,14 +135,16 @@ export class StatusListener { } if (txtIdx !== -1 && txtIdx < markdown.length) { - fieldsToReport.push(fields.map(f => f.title).join("/")); + fieldsToReport.push(fields.map((f) => f.title).join('/')); const posStart = editor.document.positionAt(txtIdx); const posEnd = editor.document.positionAt(txtIdx + 1 + fieldName.length); const diagnostic: vscode.Diagnostic = { code: '', - message: `This ${fields.map(f => f.name).join("/")} field is required to contain a value.`, + message: `This ${fields + .map((f) => f.name) + .join('/')} field is required to contain a value.`, range: new vscode.Range(posStart, posEnd), severity: vscode.DiagnosticSeverity.Error, source: 'Front Matter' @@ -146,7 +162,11 @@ export class StatusListener { } if (fieldsToReport.length > 0) { - Notifications.showIfNotDisabled(NOTIFICATION_TYPE.requiredFieldValidation, "ERROR_ONCE", `The following fields are required to contain a value: ${fieldsToReport.join(", ")}`); + Notifications.showIfNotDisabled( + NOTIFICATION_TYPE.requiredFieldValidation, + 'ERROR_ONCE', + `The following fields are required to contain a value: ${fieldsToReport.join(', ')}` + ); } } } @@ -159,7 +179,12 @@ export class StatusListener { * @param field * @returns */ - private static findFieldLine(text: string, startIdx: number, totalSpaces: number, field: Field): number | undefined { + private static findFieldLine( + text: string, + startIdx: number, + totalSpaces: number, + field: Field + ): number | undefined { const crntIdx = text.indexOf(field.name, startIdx === -1 ? 0 : startIdx); if (crntIdx > -1) { diff --git a/src/commands/Template.ts b/src/commands/Template.ts index da3dcb30..cb1111f7 100644 --- a/src/commands/Template.ts +++ b/src/commands/Template.ts @@ -1,7 +1,11 @@ import { Questions } from './../helpers/Questions'; import * as vscode from 'vscode'; import * as path from 'path'; -import { SETTING_CONTENT_DEFAULT_FILETYPE, SETTING_TEMPLATES_FOLDER, TelemetryEvent } from '../constants'; +import { + SETTING_CONTENT_DEFAULT_FILETYPE, + SETTING_TEMPLATES_FOLDER, + TelemetryEvent +} from '../constants'; import { ArticleHelper, Settings } from '../helpers'; import { Article } from '.'; import { Notifications } from '../helpers/Notifications'; @@ -14,7 +18,6 @@ import { Telemetry } from '../helpers/Telemetry'; import { writeFileAsync, copyFileAsync } from '../utils'; export class Template { - /** * Generate a template */ @@ -39,28 +42,30 @@ export class Template { return; } - const keepContents = await vscode.window.showQuickPick( - ["yes", "no"], - { - title: `Keep contents`, - canPickMany: false, - placeHolder: `Do you want to keep the contents for the template?`, - ignoreFocusOut: true - } - ); + const keepContents = await vscode.window.showQuickPick(['yes', 'no'], { + title: `Keep contents`, + canPickMany: false, + placeHolder: `Do you want to keep the contents for the template?`, + ignoreFocusOut: true + }); if (!keepContents) { - Notifications.warning(`You did not pick any of the options for keeping the template its content.`); + Notifications.warning( + `You did not pick any of the options for keeping the template its content.` + ); return; } await Project.init(false); const templatePath = Project.templatePath(); if (templatePath) { - const fileContents = ArticleHelper.stringifyFrontMatter(keepContents === "no" ? "" : clonedArticle.content, clonedArticle.data); + const fileContents = ArticleHelper.stringifyFrontMatter( + keepContents === 'no' ? '' : clonedArticle.content, + clonedArticle.data + ); const templateFile = path.join(templatePath.fsPath, `${titleValue}.${fileType}`); - await writeFileAsync(templateFile, fileContents, { encoding: "utf-8" }); + await writeFileAsync(templateFile, fileContents, { encoding: 'utf-8' }); Notifications.info(`Template created and is now available in your ${folder} folder.`); } @@ -78,7 +83,10 @@ export class Template { return; } - return await vscode.workspace.findFiles(`${folder}/**/*`, "**/node_modules/**,**/archetypes/**"); + return await vscode.workspace.findFiles( + `${folder}/**/*`, + '**/node_modules/**,**/archetypes/**' + ); } /** @@ -98,11 +106,14 @@ export class Template { return; } - const selectedTemplate = await vscode.window.showQuickPick(templates.map(t => path.basename(t.fsPath)), { - title: `Select a template`, - placeHolder: `Select the content template to use`, - ignoreFocusOut: true - }); + const selectedTemplate = await vscode.window.showQuickPick( + templates.map((t) => path.basename(t.fsPath)), + { + title: `Select a template`, + placeHolder: `Select the content template to use`, + ignoreFocusOut: true + } + ); if (!selectedTemplate) { Notifications.warning(`No template selected.`); return; @@ -114,7 +125,7 @@ export class Template { } // Start the template read - const template = templates.find(t => t.fsPath.endsWith(selectedTemplate)); + const template = templates.find((t) => t.fsPath.endsWith(selectedTemplate)); if (!template) { Notifications.warning(`Content template could not be found.`); return; @@ -123,15 +134,20 @@ export class Template { const templateData = await ArticleHelper.getFrontMatterByPath(template.fsPath); let contentType: IContentType | undefined; if (templateData && templateData.data && templateData.data.type) { - contentType = contentTypes?.find(t => t.name === templateData.data.type); + contentType = contentTypes?.find((t) => t.name === templateData.data.type); } - const fileExtension = extname(template.fsPath).replace(".", ""); - const newFilePath: string | undefined = await ArticleHelper.createContent(contentType, folderPath, titleValue, fileExtension); + const fileExtension = extname(template.fsPath).replace('.', ''); + const newFilePath: string | undefined = await ArticleHelper.createContent( + contentType, + folderPath, + titleValue, + fileExtension + ); if (!newFilePath) { return; } - + // Start the new file creation await copyFileAsync(template.fsPath, newFilePath); @@ -143,11 +159,19 @@ export class Template { } if (frontMatter.data) { - frontMatter.data = await ArticleHelper.updatePlaceholders(frontMatter.data, titleValue, newFilePath); + frontMatter.data = await ArticleHelper.updatePlaceholders( + frontMatter.data, + titleValue, + newFilePath + ); frontMatter = Article.updateDate(frontMatter); - await writeFileAsync(newFilePath, ArticleHelper.stringifyFrontMatter(frontMatter.content, frontMatter.data), { encoding: "utf8" }); + await writeFileAsync( + newFilePath, + ArticleHelper.stringifyFrontMatter(frontMatter.content, frontMatter.data), + { encoding: 'utf8' } + ); await vscode.commands.executeCommand('vscode.open', vscode.Uri.file(newFilePath)); } @@ -172,4 +196,4 @@ export class Template { const folder = Settings.get(SETTING_TEMPLATES_FOLDER); return folder; } -} \ No newline at end of file +} diff --git a/src/commands/Wysiwyg.ts b/src/commands/Wysiwyg.ts index a27d9118..1af18107 100644 --- a/src/commands/Wysiwyg.ts +++ b/src/commands/Wysiwyg.ts @@ -1,6 +1,6 @@ -import { commands, window, Selection, QuickPickItem, TextEditor } from "vscode"; -import { COMMAND_NAME, CONTEXT, SETTING_CONTENT_WYSIWYG } from "../constants"; -import { Settings } from "../helpers"; +import { commands, window, Selection, QuickPickItem, TextEditor } from 'vscode'; +import { COMMAND_NAME, CONTEXT, SETTING_CONTENT_WYSIWYG } from '../constants'; +import { Settings } from '../helpers'; enum MarkupType { bold = 1, @@ -13,18 +13,16 @@ enum MarkupType { unorderedList, orderedList, taskList, - hyperlink, + hyperlink } export class Wysiwyg { - /** * Registers the markup commands for the WYSIWYG controls * @param subscriptions * @returns */ public static async registerCommands(subscriptions: unknown[]) { - const wysiwygEnabled = Settings.get(SETTING_CONTENT_WYSIWYG); if (!wysiwygEnabled) { @@ -34,59 +32,117 @@ export class Wysiwyg { await commands.executeCommand('setContext', CONTEXT.wysiwyg, true); // Surrounding markup - subscriptions.push(commands.registerCommand(COMMAND_NAME.bold, () => this.addMarkup(MarkupType.bold))); - subscriptions.push(commands.registerCommand(COMMAND_NAME.italic, () => this.addMarkup(MarkupType.italic))); - subscriptions.push(commands.registerCommand(COMMAND_NAME.strikethrough, () => this.addMarkup(MarkupType.strikethrough))); - subscriptions.push(commands.registerCommand(COMMAND_NAME.code, () => this.addMarkup(MarkupType.code))); - subscriptions.push(commands.registerCommand(COMMAND_NAME.codeblock, () => this.addMarkup(MarkupType.codeblock))); + subscriptions.push( + commands.registerCommand(COMMAND_NAME.bold, () => this.addMarkup(MarkupType.bold)) + ); + subscriptions.push( + commands.registerCommand(COMMAND_NAME.italic, () => this.addMarkup(MarkupType.italic)) + ); + subscriptions.push( + commands.registerCommand(COMMAND_NAME.strikethrough, () => + this.addMarkup(MarkupType.strikethrough) + ) + ); + subscriptions.push( + commands.registerCommand(COMMAND_NAME.code, () => this.addMarkup(MarkupType.code)) + ); + subscriptions.push( + commands.registerCommand(COMMAND_NAME.codeblock, () => this.addMarkup(MarkupType.codeblock)) + ); // Prefix markup - subscriptions.push(commands.registerCommand(COMMAND_NAME.heading, () => this.addMarkup(MarkupType.heading))); - subscriptions.push(commands.registerCommand(COMMAND_NAME.blockquote, () => this.addMarkup(MarkupType.blockquote))); - subscriptions.push(commands.registerCommand(COMMAND_NAME.unorderedlist, () => this.addMarkup(MarkupType.unorderedList))); - subscriptions.push(commands.registerCommand(COMMAND_NAME.orderedlist, () => this.addMarkup(MarkupType.orderedList))); - subscriptions.push(commands.registerCommand(COMMAND_NAME.taskList, () => this.addMarkup(MarkupType.taskList))); + subscriptions.push( + commands.registerCommand(COMMAND_NAME.heading, () => this.addMarkup(MarkupType.heading)) + ); + subscriptions.push( + commands.registerCommand(COMMAND_NAME.blockquote, () => this.addMarkup(MarkupType.blockquote)) + ); + subscriptions.push( + commands.registerCommand(COMMAND_NAME.unorderedlist, () => + this.addMarkup(MarkupType.unorderedList) + ) + ); + subscriptions.push( + commands.registerCommand(COMMAND_NAME.orderedlist, () => + this.addMarkup(MarkupType.orderedList) + ) + ); + subscriptions.push( + commands.registerCommand(COMMAND_NAME.taskList, () => this.addMarkup(MarkupType.taskList)) + ); // Other markup - subscriptions.push(commands.registerCommand(COMMAND_NAME.hyperlink, () => this.addMarkup(MarkupType.hyperlink))); + subscriptions.push( + commands.registerCommand(COMMAND_NAME.hyperlink, () => this.addMarkup(MarkupType.hyperlink)) + ); // Options - subscriptions.push(commands.registerCommand(COMMAND_NAME.options, async () => { - const qpItems: QuickPickItem[] = [ - { label: "$(list-unordered) Unordered list", detail: "Add an unordered list", alwaysShow: true, }, - { label: "$(list-ordered) Ordered list", detail: "Add an ordered list", alwaysShow: true }, - { label: "$(tasklist) Task list", detail: "Add a task list", alwaysShow: true }, - { label: "$(code) Code", detail: "Add inline code snippet", alwaysShow: true }, - { label: "$(symbol-namespace) Code block", detail: "Add a code block", alwaysShow: true }, - { label: "$(quote) Blockquote", detail: "Add a blockquote", alwaysShow: true }, - { label: "$(symbol-text) Strikethrough", detail: "Add a strikethrough", alwaysShow: true }, - ] + subscriptions.push( + commands.registerCommand(COMMAND_NAME.options, async () => { + const qpItems: QuickPickItem[] = [ + { + label: '$(list-unordered) Unordered list', + detail: 'Add an unordered list', + alwaysShow: true + }, + { + label: '$(list-ordered) Ordered list', + detail: 'Add an ordered list', + alwaysShow: true + }, + { + label: '$(tasklist) Task list', + detail: 'Add a task list', + alwaysShow: true + }, + { + label: '$(code) Code', + detail: 'Add inline code snippet', + alwaysShow: true + }, + { + label: '$(symbol-namespace) Code block', + detail: 'Add a code block', + alwaysShow: true + }, + { + label: '$(quote) Blockquote', + detail: 'Add a blockquote', + alwaysShow: true + }, + { + label: '$(symbol-text) Strikethrough', + detail: 'Add a strikethrough', + alwaysShow: true + } + ]; - const option = await window.showQuickPick([ ...qpItems ], { - title: "WYSIWYG Options", - placeHolder: "Which type of markup would you like to insert?", - canPickMany: false, - ignoreFocusOut: true - }); + const option = await window.showQuickPick([...qpItems], { + title: 'WYSIWYG Options', + placeHolder: 'Which type of markup would you like to insert?', + canPickMany: false, + ignoreFocusOut: true + }); - if (option) { - if (option.label === qpItems[0].label) { - await this.addMarkup(MarkupType.unorderedList); - } else if (option.label === qpItems[1].label) { - await this.addMarkup(MarkupType.orderedList); - } else if (option.label === qpItems[2].label) { - await this.addMarkup(MarkupType.taskList); - } else if (option.label === qpItems[3].label) { - await this.addMarkup(MarkupType.code); - } else if (option.label === qpItems[4].label) { - await this.addMarkup(MarkupType.codeblock); - } else if (option.label === qpItems[5].label) { - await this.addMarkup(MarkupType.blockquote); - } else if (option.label === qpItems[6].label) { - await this.addMarkup(MarkupType.strikethrough); + if (option) { + if (option.label === qpItems[0].label) { + await this.addMarkup(MarkupType.unorderedList); + } else if (option.label === qpItems[1].label) { + await this.addMarkup(MarkupType.orderedList); + } else if (option.label === qpItems[2].label) { + await this.addMarkup(MarkupType.taskList); + } else if (option.label === qpItems[3].label) { + await this.addMarkup(MarkupType.code); + } else if (option.label === qpItems[4].label) { + await this.addMarkup(MarkupType.codeblock); + } else if (option.label === qpItems[5].label) { + await this.addMarkup(MarkupType.blockquote); + } else if (option.label === qpItems[6].label) { + await this.addMarkup(MarkupType.strikethrough); + } } - } - })); + }) + ); } /** @@ -119,7 +175,7 @@ export class Wysiwyg { const selectionText = editor.document.getText(selection); const txt = await this.insertText(markers, type, selectionText); - editor.edit(builder => { + editor.edit((builder) => { builder.replace(selection, txt); }); } else { @@ -127,9 +183,12 @@ export class Wysiwyg { // Insert the markers where cursor is located. const markerLength = this.isMarkupWrapping(type) ? txt.length + 1 : markers.length; - let newPosition = crntSelection.with(crntSelection.line, crntSelection.character + markerLength); + let newPosition = crntSelection.with( + crntSelection.line, + crntSelection.character + markerLength + ); - await editor.edit(builder => { + await editor.edit((builder) => { builder.insert(newPosition, txt); }); @@ -147,20 +206,20 @@ export class Wysiwyg { */ private static async addHyperlink(editor: TextEditor, selection: Selection) { const hasTextSelection = !selection.isEmpty; - const linkText = hasTextSelection ? editor.document.getText(selection) : ""; + const linkText = hasTextSelection ? editor.document.getText(selection) : ''; const link = await window.showInputBox({ - title: "WYSIWYG Hyperlink", - placeHolder: "Enter the URL", - prompt: "Enter the URL", + title: 'WYSIWYG Hyperlink', + placeHolder: 'Enter the URL', + prompt: 'Enter the URL', value: linkText, ignoreFocusOut: true }); const text = await window.showInputBox({ - title: "WYSIWYG Text", - prompt: "Enter the text for the hyperlink", - placeHolder: "Enter the text for the hyperlink", + title: 'WYSIWYG Text', + prompt: 'Enter the text for the hyperlink', + placeHolder: 'Enter the text for the hyperlink', value: linkText, ignoreFocusOut: true }); @@ -169,15 +228,18 @@ export class Wysiwyg { const txt = `[${text || link}](${link})`; if (hasTextSelection) { - editor.edit(builder => { + editor.edit((builder) => { builder.replace(selection, txt); }); } else { const crntSelection = selection.active; const markerLength = txt.length; - const newPosition = crntSelection.with(crntSelection.line, crntSelection.character + markerLength); + const newPosition = crntSelection.with( + crntSelection.line, + crntSelection.character + markerLength + ); - await editor.edit(builder => { + await editor.edit((builder) => { builder.insert(newPosition, txt); }); @@ -204,39 +266,39 @@ export class Wysiwyg { /** * Insert text at the current cursor position */ - private static async insertText(marker: string | undefined, type: MarkupType, text: string | null = null) { + private static async insertText( + marker: string | undefined, + type: MarkupType, + text: string | null = null + ) { const crntText = text || this.lineBreak(type); if (this.isMarkupWrapping(type)) { if (type === MarkupType.heading) { - const headingLvl = await window.showQuickPick([ - "Heading 1", - "Heading 2", - "Heading 3", - "Heading 4", - "Heading 5", - "Heading 6" - ], { - title: "Heading Level", - canPickMany: false, - placeHolder: "Which heading level do you want to insert?", - ignoreFocusOut: true - }); + const headingLvl = await window.showQuickPick( + ['Heading 1', 'Heading 2', 'Heading 3', 'Heading 4', 'Heading 5', 'Heading 6'], + { + title: 'Heading Level', + canPickMany: false, + placeHolder: 'Which heading level do you want to insert?', + ignoreFocusOut: true + } + ); if (headingLvl) { - const headingNr = parseInt(headingLvl.replace("Heading ", "")); + const headingNr = parseInt(headingLvl.replace('Heading ', '')); return `${Array(headingNr + 1).join(marker)} ${crntText}`; } } if (type === MarkupType.unorderedList || type === MarkupType.taskList) { - const lines = crntText.split("\n").map(line => `${marker} ${line}`); - return lines.join("\n"); + const lines = crntText.split('\n').map((line) => `${marker} ${line}`); + return lines.join('\n'); } if (type === MarkupType.orderedList) { - const lines = crntText.split("\n").map((line, idx) => `${idx+1}. ${line}`); - return lines.join("\n"); + const lines = crntText.split('\n').map((line, idx) => `${idx + 1}. ${line}`); + return lines.join('\n'); } return `${marker} ${crntText}`; @@ -254,7 +316,7 @@ export class Wysiwyg { if (type === MarkupType.codeblock) { return `\n\n`; } - return ""; + return ''; } /** @@ -263,7 +325,7 @@ export class Wysiwyg { * @returns */ private static getMarkers(type: MarkupType) { - switch(type) { + switch (type) { case MarkupType.bold: return `**`; case MarkupType.italic: @@ -271,19 +333,19 @@ export class Wysiwyg { case MarkupType.strikethrough: return `~~`; case MarkupType.code: - return "`"; + return '`'; case MarkupType.codeblock: - return "```"; + return '```'; case MarkupType.blockquote: - return ">"; + return '>'; case MarkupType.heading: - return "#"; + return '#'; case MarkupType.unorderedList: - return "-"; + return '-'; case MarkupType.orderedList: - return "1."; + return '1.'; case MarkupType.taskList: - return "- [ ]"; + return '- [ ]'; default: return; } diff --git a/src/components/features/FeatureFlag.tsx b/src/components/features/FeatureFlag.tsx index 2c012aa8..6b6b424a 100644 --- a/src/components/features/FeatureFlag.tsx +++ b/src/components/features/FeatureFlag.tsx @@ -6,9 +6,13 @@ export interface IFeatureFlagProps { alternative?: JSX.Element; } -export const FeatureFlag: React.FunctionComponent = ({ flag, features, alternative, children }: React.PropsWithChildren) => { - - if (!features ||( features.length > 0 && !features.includes(flag))) { +export const FeatureFlag: React.FunctionComponent = ({ + flag, + features, + alternative, + children +}: React.PropsWithChildren) => { + if (!features || (features.length > 0 && !features.includes(flag))) { if (alternative) { return alternative; } @@ -16,11 +20,5 @@ export const FeatureFlag: React.FunctionComponent = ({ flag, return null; } - - - return ( - <> - {children} - - ); -}; \ No newline at end of file + return <>{children}; +}; diff --git a/src/components/icons/CompressIcon.tsx b/src/components/icons/CompressIcon.tsx index 35ee5d66..3cd97cec 100644 --- a/src/components/icons/CompressIcon.tsx +++ b/src/components/icons/CompressIcon.tsx @@ -4,10 +4,22 @@ export interface ICompressIconProps { className?: string; } -export const CompressIcon: React.FunctionComponent = ({className}: React.PropsWithChildren) => { +export const CompressIcon: React.FunctionComponent = ({ + className +}: React.PropsWithChildren) => { return ( -
- +