From af0d4d26bba1292bdf187679b01691680400518a Mon Sep 17 00:00:00 2001 From: n00o Date: Wed, 8 Nov 2023 08:49:03 -0500 Subject: [PATCH 1/3] Add Autocomplete + JSON/JavaScript Linting Add JavaScript Autocomplete with all built-in Bruno functions. Add code linting markers for JSON and JavaScript CodeMirror sections. Add a few hotkeys to improve code editing. --- package-lock.json | 459 +++++++++++++++++- packages/bruno-app/package.json | 4 + .../src/components/CodeEditor/index.js | 102 +++- packages/bruno-app/src/pages/Bruno/index.js | 3 + 4 files changed, 559 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index a1e84508..cf7f115a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6459,6 +6459,18 @@ "node": ">= 10.0" } }, + "node_modules/cli": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", + "integrity": "sha512-41U72MB56TfUMGndAKK8vJ78eooOD4Z5NOL4xEfjc0c23s+6EYKXlXsmACBVclLP1yOfWCgEganVzddVrSNoTg==", + "dependencies": { + "exit": "0.1.2", + "glob": "^7.1.1" + }, + "engines": { + "node": ">=0.2.5" + } + }, "node_modules/cli-boxes": { "version": "2.2.1", "dev": true, @@ -6834,6 +6846,14 @@ "typedarray-to-buffer": "^3.1.5" } }, + "node_modules/console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha512-duS7VP5pvfsNLDvL1O4VOEbw37AI3A4ZUQYemvDlnpGrNu9tprR7BYWpDYwC0Xia0Zxz5ZupdiIrUp0GH1aXfg==", + "dependencies": { + "date-now": "^0.1.4" + } + }, "node_modules/content-disposition": { "version": "0.5.4", "license": "MIT", @@ -7211,6 +7231,11 @@ "node": ">=0.10" } }, + "node_modules/date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha512-AsElvov3LoNB7tf5k37H2jYSB+ZZPMT5sG2QjJCcdlV5chIv6htBUBUui2IKRjgtKAKtCBN7Zbwa+MtwLjSeNw==" + }, "node_modules/debounce-fn": { "version": "4.0.0", "license": "MIT", @@ -8175,7 +8200,6 @@ }, "node_modules/exit": { "version": "0.1.2", - "dev": true, "engines": { "node": ">= 0.8.0" } @@ -8424,6 +8448,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/file": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/file/-/file-0.2.2.tgz", + "integrity": "sha512-gwabMtChzdnpDJdPEpz8Vr/PX0pU85KailuPV71Zw/un5yJVKvzukhB3qf6O3lnTwIe5CxlMYLh3jOK3w5xrLA==" + }, "node_modules/file-dialog": { "version": "0.0.8", "license": "MIT" @@ -9190,6 +9219,14 @@ "node": ">=0.10.0" } }, + "node_modules/has-color": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", + "integrity": "sha512-kaNz5OTAYYmt646Hkqw50/qyxP2vFnTVu5AQ1Zmk22Kk5+4Qx6BpO8+u7IKsML5fOsFk0ZT0AcCJNYwcvaLBvw==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/has-flag": { "version": "4.0.0", "license": "MIT", @@ -9513,8 +9550,9 @@ }, "node_modules/husky": { "version": "8.0.3", + "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", + "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", "dev": true, - "license": "MIT", "bin": { "husky": "lib/bin.js" }, @@ -10899,6 +10937,133 @@ "node": ">=4" } }, + "node_modules/jshint": { + "version": "2.13.6", + "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.13.6.tgz", + "integrity": "sha512-IVdB4G0NTTeQZrBoM8C5JFVLjV2KtZ9APgybDA1MK73xb09qFs0jCXyQLnCOp1cSZZZbvhq/6mfXHUTaDkffuQ==", + "dependencies": { + "cli": "~1.0.0", + "console-browserify": "1.1.x", + "exit": "0.1.x", + "htmlparser2": "3.8.x", + "lodash": "~4.17.21", + "minimatch": "~3.0.2", + "strip-json-comments": "1.0.x" + }, + "bin": { + "jshint": "bin/jshint" + } + }, + "node_modules/jshint/node_modules/dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dependencies": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + } + }, + "node_modules/jshint/node_modules/dom-serializer/node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/jshint/node_modules/dom-serializer/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/jshint/node_modules/domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + }, + "node_modules/jshint/node_modules/domhandler": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", + "integrity": "sha512-q9bUwjfp7Eif8jWxxxPSykdRZAb6GkguBGSgvvCrhI9wB71W2K/Kvv4E61CF/mcCfnVJDeDWx/Vb/uAqbDj6UQ==", + "dependencies": { + "domelementtype": "1" + } + }, + "node_modules/jshint/node_modules/domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha512-gSu5Oi/I+3wDENBsOWBiRK1eoGxcywYSqg3rR960/+EfY0CF4EX1VPkgHOZ3WiS/Jg2DtliF6BhWcHlfpYUcGw==", + "dependencies": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "node_modules/jshint/node_modules/entities": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", + "integrity": "sha512-LbLqfXgJMmy81t+7c14mnulFHJ170cM6E+0vMXR9k/ZiZwgX8i5pNgjTCX3SO4VeUsFLV+8InixoretwU+MjBQ==" + }, + "node_modules/jshint/node_modules/htmlparser2": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", + "integrity": "sha512-hBxEg3CYXe+rPIua8ETe7tmG3XDn9B0edOE/e9wH2nLczxzgdu0m0aNHY+5wFZiviLWLdANPJTssa92dMcXQ5Q==", + "dependencies": { + "domelementtype": "1", + "domhandler": "2.3", + "domutils": "1.5", + "entities": "1.0", + "readable-stream": "1.1" + } + }, + "node_modules/jshint/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + }, + "node_modules/jshint/node_modules/minimatch": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", + "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jshint/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/jshint/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" + }, + "node_modules/jshint/node_modules/strip-json-comments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", + "integrity": "sha512-AOPG8EBc5wAikaG1/7uFCNFJwnKOuQwFTpYBdTW6OvWHeZBQBrAA/amefHGrEiOnCPcLFZK6FUPtWVKpQVIRgg==", + "bin": { + "strip-json-comments": "cli.js" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/json-buffer": { "version": "3.0.0", "dev": true, @@ -10950,6 +11115,21 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jsonlint": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/jsonlint/-/jsonlint-1.6.3.tgz", + "integrity": "sha512-jMVTMzP+7gU/IyC6hvKyWpUU8tmTkK5b3BPNuMI9U8Sit+YAWLlZwB6Y6YrdCxfg2kNz05p3XY3Bmm4m26Nv3A==", + "dependencies": { + "JSV": "^4.0.x", + "nomnom": "^1.5.x" + }, + "bin": { + "jsonlint": "lib/cli.js" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/jsprim": { "version": "1.4.2", "dev": true, @@ -10982,6 +11162,14 @@ "extsprintf": "^1.2.0" } }, + "node_modules/JSV": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/JSV/-/JSV-4.0.2.tgz", + "integrity": "sha512-ZJ6wx9xaKJ3yFUhq5/sk82PJMuUyLk277I8mQeyDgCTjGdjWJIvPfaU5LIXaMuaN2UO1X3kZH4+lgphublZUHw==", + "engines": { + "node": "*" + } + }, "node_modules/kew": { "version": "0.7.0", "dev": true, @@ -11874,6 +12062,48 @@ "node": ">= 16.0.0" } }, + "node_modules/nomnom": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz", + "integrity": "sha512-5s0JxqhDx9/rksG2BTMVN1enjWSvPidpoSgViZU4ZXULyTe+7jxcCRLB6f42Z0l1xYJpleCBtSyY6Lwg3uu5CQ==", + "deprecated": "Package no longer supported. Contact support@npmjs.com for more info.", + "dependencies": { + "chalk": "~0.4.0", + "underscore": "~1.6.0" + } + }, + "node_modules/nomnom/node_modules/ansi-styles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", + "integrity": "sha512-3iF4FIKdxaVYT3JqQuY3Wat/T2t7TRbbQ94Fu50ZUCbLy4TFbTzr90NOHQodQkNqmeEGCw8WbeP78WNi6SKYUA==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/nomnom/node_modules/chalk": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", + "integrity": "sha512-sQfYDlfv2DGVtjdoQqxS0cEZDroyG8h6TamA6rvxwlrU5BaSLDx9xhatBYl2pxZ7gmpNaPFVwBtdGdu5rQ+tYQ==", + "dependencies": { + "ansi-styles": "~1.0.0", + "has-color": "~0.1.0", + "strip-ansi": "~0.1.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/nomnom/node_modules/strip-ansi": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", + "integrity": "sha512-behete+3uqxecWlDAm5lmskaSaISA+ThQ4oNNBDTBJt0x2ppR6IPqfZNuj6BLaLJ/Sji4TPZlcRyOis8wXQTLg==", + "bin": { + "strip-ansi": "cli.js" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/normalize-package-data": { "version": "2.5.0", "dev": true, @@ -15370,6 +15600,14 @@ "node": ">= 10" } }, + "node_modules/system": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/system/-/system-2.0.1.tgz", + "integrity": "sha512-BwSUSa8LMHZouGadZ34ck3TsrH5s3oMmTKPK+xHdbBnTCZOZMJ38fHGKLAHkBl0PXru1Z4BsymQU4qqvTxWzdQ==", + "bin": { + "jscat": "bundle.js" + } + }, "node_modules/tailwindcss": { "version": "2.2.19", "license": "MIT", @@ -15927,6 +16165,11 @@ "node": ">=0.8.0" } }, + "node_modules/underscore": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha512-z4o1fvKUojIWh9XuaVLUDdf86RQiq13AC1dmHbTpoyuu+bquHms76v16CjycCbec87J7z0k//SiQVk0sMdFmpQ==" + }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "dev": true, @@ -16729,6 +16972,7 @@ "codemirror-graphql": "^1.2.5", "cookie": "^0.6.0", "escape-html": "^1.0.3", + "file": "^0.2.2", "file-dialog": "^0.0.8", "file-saver": "^2.0.5", "formik": "^2.2.9", @@ -16741,6 +16985,8 @@ "idb": "^7.0.0", "immer": "^9.0.15", "jsesc": "^3.0.2", + "jshint": "^2.13.6", + "jsonlint": "^1.6.3", "know-your-http-well": "^0.5.0", "lodash": "^4.17.21", "markdown-it": "^13.0.2", @@ -16763,6 +17009,7 @@ "react-tooltip": "^5.5.2", "sass": "^1.46.0", "styled-components": "^5.3.3", + "system": "^2.0.1", "tailwindcss": "^2.2.19", "url": "^0.11.3", "xml-formatter": "^3.5.0", @@ -20917,6 +21164,7 @@ "cross-env": "^7.0.3", "css-loader": "^6.5.1", "escape-html": "^1.0.3", + "file": "^0.2.2", "file-dialog": "^0.0.8", "file-loader": "^6.2.0", "file-saver": "^2.0.5", @@ -20932,6 +21180,8 @@ "idb": "^7.0.0", "immer": "^9.0.15", "jsesc": "^3.0.2", + "jshint": "^2.13.6", + "jsonlint": "^1.6.3", "know-your-http-well": "^0.5.0", "lodash": "^4.17.21", "markdown-it": "^13.0.2", @@ -20957,12 +21207,13 @@ "sass": "^1.46.0", "style-loader": "^3.3.1", "styled-components": "^5.3.3", + "system": "^2.0.1", "tailwindcss": "^2.2.19", "url": "^0.11.3", "webpack": "^5.64.4", "webpack-cli": "^4.9.1", "xml-formatter": "^3.5.0", - "yargs-parser": "*", + "yargs-parser": "^21.1.1", "yup": "^0.32.11" }, "dependencies": { @@ -22393,6 +22644,15 @@ "source-map": "~0.6.0" } }, + "cli": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", + "integrity": "sha512-41U72MB56TfUMGndAKK8vJ78eooOD4Z5NOL4xEfjc0c23s+6EYKXlXsmACBVclLP1yOfWCgEganVzddVrSNoTg==", + "requires": { + "exit": "0.1.2", + "glob": "^7.1.1" + } + }, "cli-boxes": { "version": "2.2.1", "dev": true @@ -22634,6 +22894,14 @@ } } }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha512-duS7VP5pvfsNLDvL1O4VOEbw37AI3A4ZUQYemvDlnpGrNu9tprR7BYWpDYwC0Xia0Zxz5ZupdiIrUp0GH1aXfg==", + "requires": { + "date-now": "^0.1.4" + } + }, "content-disposition": { "version": "0.5.4", "requires": { @@ -22869,6 +23137,11 @@ "assert-plus": "^1.0.0" } }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha512-AsElvov3LoNB7tf5k37H2jYSB+ZZPMT5sG2QjJCcdlV5chIv6htBUBUui2IKRjgtKAKtCBN7Zbwa+MtwLjSeNw==" + }, "debounce-fn": { "version": "4.0.0", "requires": { @@ -23505,8 +23778,7 @@ "dev": true }, "exit": { - "version": "0.1.2", - "dev": true + "version": "0.1.2" }, "expect": { "version": "29.3.1", @@ -23680,6 +23952,11 @@ } } }, + "file": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/file/-/file-0.2.2.tgz", + "integrity": "sha512-gwabMtChzdnpDJdPEpz8Vr/PX0pU85KailuPV71Zw/un5yJVKvzukhB3qf6O3lnTwIe5CxlMYLh3jOK3w5xrLA==" + }, "file-dialog": { "version": "0.0.8" }, @@ -24172,6 +24449,11 @@ } } }, + "has-color": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", + "integrity": "sha512-kaNz5OTAYYmt646Hkqw50/qyxP2vFnTVu5AQ1Zmk22Kk5+4Qx6BpO8+u7IKsML5fOsFk0ZT0AcCJNYwcvaLBvw==" + }, "has-flag": { "version": "4.0.0" }, @@ -24371,6 +24653,8 @@ }, "husky": { "version": "8.0.3", + "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", + "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", "dev": true }, "icon-gen": { @@ -25235,6 +25519,116 @@ "jsesc": { "version": "2.5.2" }, + "jshint": { + "version": "2.13.6", + "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.13.6.tgz", + "integrity": "sha512-IVdB4G0NTTeQZrBoM8C5JFVLjV2KtZ9APgybDA1MK73xb09qFs0jCXyQLnCOp1cSZZZbvhq/6mfXHUTaDkffuQ==", + "requires": { + "cli": "~1.0.0", + "console-browserify": "1.1.x", + "exit": "0.1.x", + "htmlparser2": "3.8.x", + "lodash": "~4.17.21", + "minimatch": "~3.0.2", + "strip-json-comments": "1.0.x" + }, + "dependencies": { + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" + }, + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" + } + } + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + }, + "domhandler": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", + "integrity": "sha512-q9bUwjfp7Eif8jWxxxPSykdRZAb6GkguBGSgvvCrhI9wB71W2K/Kvv4E61CF/mcCfnVJDeDWx/Vb/uAqbDj6UQ==", + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha512-gSu5Oi/I+3wDENBsOWBiRK1eoGxcywYSqg3rR960/+EfY0CF4EX1VPkgHOZ3WiS/Jg2DtliF6BhWcHlfpYUcGw==", + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "entities": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", + "integrity": "sha512-LbLqfXgJMmy81t+7c14mnulFHJ170cM6E+0vMXR9k/ZiZwgX8i5pNgjTCX3SO4VeUsFLV+8InixoretwU+MjBQ==" + }, + "htmlparser2": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", + "integrity": "sha512-hBxEg3CYXe+rPIua8ETe7tmG3XDn9B0edOE/e9wH2nLczxzgdu0m0aNHY+5wFZiviLWLdANPJTssa92dMcXQ5Q==", + "requires": { + "domelementtype": "1", + "domhandler": "2.3", + "domutils": "1.5", + "entities": "1.0", + "readable-stream": "1.1" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + }, + "minimatch": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", + "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" + }, + "strip-json-comments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", + "integrity": "sha512-AOPG8EBc5wAikaG1/7uFCNFJwnKOuQwFTpYBdTW6OvWHeZBQBrAA/amefHGrEiOnCPcLFZK6FUPtWVKpQVIRgg==" + } + } + }, "json-buffer": { "version": "3.0.0", "dev": true @@ -25267,6 +25661,15 @@ "universalify": "^2.0.0" } }, + "jsonlint": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/jsonlint/-/jsonlint-1.6.3.tgz", + "integrity": "sha512-jMVTMzP+7gU/IyC6hvKyWpUU8tmTkK5b3BPNuMI9U8Sit+YAWLlZwB6Y6YrdCxfg2kNz05p3XY3Bmm4m26Nv3A==", + "requires": { + "JSV": "^4.0.x", + "nomnom": "^1.5.x" + } + }, "jsprim": { "version": "1.4.2", "dev": true, @@ -25292,6 +25695,11 @@ } } }, + "JSV": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/JSV/-/JSV-4.0.2.tgz", + "integrity": "sha512-ZJ6wx9xaKJ3yFUhq5/sk82PJMuUyLk277I8mQeyDgCTjGdjWJIvPfaU5LIXaMuaN2UO1X3kZH4+lgphublZUHw==" + }, "kew": { "version": "0.7.0", "dev": true @@ -25854,6 +26262,37 @@ "tv4": "^1.3.0" } }, + "nomnom": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz", + "integrity": "sha512-5s0JxqhDx9/rksG2BTMVN1enjWSvPidpoSgViZU4ZXULyTe+7jxcCRLB6f42Z0l1xYJpleCBtSyY6Lwg3uu5CQ==", + "requires": { + "chalk": "~0.4.0", + "underscore": "~1.6.0" + }, + "dependencies": { + "ansi-styles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", + "integrity": "sha512-3iF4FIKdxaVYT3JqQuY3Wat/T2t7TRbbQ94Fu50ZUCbLy4TFbTzr90NOHQodQkNqmeEGCw8WbeP78WNi6SKYUA==" + }, + "chalk": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", + "integrity": "sha512-sQfYDlfv2DGVtjdoQqxS0cEZDroyG8h6TamA6rvxwlrU5BaSLDx9xhatBYl2pxZ7gmpNaPFVwBtdGdu5rQ+tYQ==", + "requires": { + "ansi-styles": "~1.0.0", + "has-color": "~0.1.0", + "strip-ansi": "~0.1.0" + } + }, + "strip-ansi": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", + "integrity": "sha512-behete+3uqxecWlDAm5lmskaSaISA+ThQ4oNNBDTBJt0x2ppR6IPqfZNuj6BLaLJ/Sji4TPZlcRyOis8wXQTLg==" + } + } + }, "normalize-package-data": { "version": "2.5.0", "dev": true, @@ -28056,6 +28495,11 @@ } } }, + "system": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/system/-/system-2.0.1.tgz", + "integrity": "sha512-BwSUSa8LMHZouGadZ34ck3TsrH5s3oMmTKPK+xHdbBnTCZOZMJ38fHGKLAHkBl0PXru1Z4BsymQU4qqvTxWzdQ==" + }, "tailwindcss": { "version": "2.2.19", "requires": { @@ -28406,6 +28850,11 @@ "version": "3.17.4", "optional": true }, + "underscore": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha512-z4o1fvKUojIWh9XuaVLUDdf86RQiq13AC1dmHbTpoyuu+bquHms76v16CjycCbec87J7z0k//SiQVk0sMdFmpQ==" + }, "unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "dev": true diff --git a/packages/bruno-app/package.json b/packages/bruno-app/package.json index d5ba0b1a..eef5e518 100644 --- a/packages/bruno-app/package.json +++ b/packages/bruno-app/package.json @@ -26,6 +26,7 @@ "codemirror-graphql": "^1.2.5", "cookie": "^0.6.0", "escape-html": "^1.0.3", + "file": "^0.2.2", "file-dialog": "^0.0.8", "file-saver": "^2.0.5", "formik": "^2.2.9", @@ -38,6 +39,8 @@ "idb": "^7.0.0", "immer": "^9.0.15", "jsesc": "^3.0.2", + "jshint": "^2.13.6", + "jsonlint": "^1.6.3", "know-your-http-well": "^0.5.0", "lodash": "^4.17.21", "markdown-it": "^13.0.2", @@ -60,6 +63,7 @@ "react-tooltip": "^5.5.2", "sass": "^1.46.0", "styled-components": "^5.3.3", + "system": "^2.0.1", "tailwindcss": "^2.2.19", "url": "^0.11.3", "xml-formatter": "^3.5.0", diff --git a/packages/bruno-app/src/components/CodeEditor/index.js b/packages/bruno-app/src/components/CodeEditor/index.js index 0bfd6fdd..29f3dbc1 100644 --- a/packages/bruno-app/src/components/CodeEditor/index.js +++ b/packages/bruno-app/src/components/CodeEditor/index.js @@ -10,12 +10,83 @@ import isEqual from 'lodash/isEqual'; import { getEnvironmentVariables } from 'utils/collections'; import { defineCodeMirrorBrunoVariablesMode } from 'utils/common/codemirror'; import StyledWrapper from './StyledWrapper'; +import jsonlint from 'jsonlint'; +import { JSHINT } from 'jshint'; let CodeMirror; const SERVER_RENDERED = typeof navigator === 'undefined' || global['PREVENT_CODEMIRROR_RENDER'] === true; if (!SERVER_RENDERED) { CodeMirror = require('codemirror'); + window.jsonlint = jsonlint; + window.JSHINT = JSHINT; + //This should be done dynamically if possible + const hintWords = [ + 'res', + 'res.status', + 'res.statusText', + 'res.headers', + 'res.body', + 'res.getStatus()', + 'res.getHeader(name)', + 'res.getHeaders()', + 'res.getBody()', + 'req', + 'req.url', + 'req.method', + 'req.headers', + 'req.body', + 'req.timeout', + 'req.getUrl()', + 'req.setUrl(url)', + 'req.getMethod()', + 'req.setMethod(method)', + 'req.getHeader(name)', + 'req.getHeaders()', + 'req.setHeader(name, value)', + 'req.setHeaders(data)', + 'req.getBody()', + 'req.setBody(data)', + 'req.setMaxRedirects(maxRedirects)', + 'req.getTimeout()', + 'req.setTimeout(timeout)', + 'bru', + 'bru.cwd()', + 'bru.getEnvName(key)', + 'bru.getProcessEnv(key)', + 'bru.getEnvVar(key)', + 'bru.setEnvVar(key,value)', + 'bru.getVar(key)', + 'bru.setVar(key,value)' + ]; + CodeMirror.registerHelper('hint', 'brunoJS', (editor, options) => { + const cursor = editor.getCursor(); + const currentLine = editor.getLine(cursor.line); + let startBru = cursor.ch; + let endBru = startBru; + while (endBru < currentLine.length && /[\w.]/.test(currentLine.charAt(endBru))) ++endBru; + while (startBru && /[\w.]/.test(currentLine.charAt(startBru - 1))) --startBru; + let curWordBru = startBru != endBru && currentLine.slice(startBru, endBru); + + let start = cursor.ch; + let end = start; + while (end < currentLine.length && /[\w]/.test(currentLine.charAt(end))) ++end; + while (start && /[\w]/.test(currentLine.charAt(start - 1))) --start; + const jsHinter = CodeMirror.hint.javascript; + let result = jsHinter(editor) || { list: [] }; + result.to = CodeMirror.Pos(cursor.line, end); + result.from = CodeMirror.Pos(cursor.line, start); + hintWords.forEach((h) => { + if (h.includes('.') == curWordBru.includes('.') && h.startsWith(curWordBru)) { + result.list.push(curWordBru.includes('.') ? h.split('.')[1] : h); + } + }); + result.list = result.list?.sort(); + return result; + }); + CodeMirror.commands.autocomplete = (cm, hint, options) => { + cm.showHint({ hint, ...options }); + }; } export default class CodeEditor extends React.Component { @@ -41,7 +112,10 @@ export default class CodeEditor extends React.Component { matchBrackets: true, showCursorWhenSelecting: true, foldGutter: true, - gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'], + gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter', 'CodeMirror-lint-markers'], + lint: { + esversion: 11 + }, readOnly: this.props.readOnly, scrollbarStyle: 'overlay', theme: this.props.theme === 'dark' ? 'monokai' : 'default', @@ -68,9 +142,10 @@ export default class CodeEditor extends React.Component { }, 'Cmd-F': 'findPersistent', 'Ctrl-F': 'findPersistent', - Tab: function (cm) { - cm.replaceSelection(' ', 'end'); - }, + 'Cmd-H': 'replace', + 'Ctrl-H': 'replace', + Tab: 'indentMore', + 'Shift-Tab': 'indentLess', 'Ctrl-Y': 'foldAll', 'Cmd-Y': 'foldAll', 'Ctrl-I': 'unfoldAll', @@ -106,6 +181,25 @@ export default class CodeEditor extends React.Component { editor.on('change', this._onEdit); this.addOverlay(); } + if (this.props.mode == 'javascript') { + editor.on('keyup', function (cm, event) { + const cursor = editor.getCursor(); + const currentLine = editor.getLine(cursor.line); + let start = cursor.ch; + let end = start; + while (end < currentLine.length && /[\w\."'\/`]/.test(currentLine.charAt(end))) ++end; + while (start && /[\w\."'\/`]/.test(currentLine.charAt(start - 1))) --start; + let curWord = start != end && currentLine.slice(start, end); + //Qualify if autocomplete will be shown + if ( + /^(?!Shift|Tab|Enter|ArrowUp|ArrowDown|ArrowLeft|ArrowRight|\s)\w*/.test(event.key) && + curWord.length > 1 && + /^(?!"'\d`)[a-zA-Z\.]/.test(curWord) + ) { + CodeMirror.commands.autocomplete(cm, CodeMirror.hint.brunoJS, { completeSingle: false }); + } + }); + } } componentDidUpdate(prevProps) { diff --git a/packages/bruno-app/src/pages/Bruno/index.js b/packages/bruno-app/src/pages/Bruno/index.js index f899933b..75b07f0f 100644 --- a/packages/bruno-app/src/pages/Bruno/index.js +++ b/packages/bruno-app/src/pages/Bruno/index.js @@ -22,8 +22,11 @@ if (!SERVER_RENDERED) { require('codemirror/addon/fold/brace-fold'); require('codemirror/addon/fold/foldgutter'); require('codemirror/addon/fold/xml-fold'); + require('codemirror/addon/hint/javascript-hint'); require('codemirror/addon/hint/show-hint'); require('codemirror/addon/lint/lint'); + require('codemirror/addon/lint/javascript-lint'); + require('codemirror/addon/lint/json-lint'); require('codemirror/addon/mode/overlay'); require('codemirror/addon/scroll/simplescrollbars'); require('codemirror/addon/search/jump-to-line'); From 8ed88d42c0d1a9ddc7b59000893af315da9f0616 Mon Sep 17 00:00:00 2001 From: n00o Date: Fri, 10 Nov 2023 00:28:17 -0500 Subject: [PATCH 2/3] Fix Crashes and improve AutoComplete logic Fix crash when autocomplete pops up and then is deleted. Fix autocomplete from appearing inside interpolation or strings. Fix JSON linting when its empty and not lint when mode is undefined (Code Generation). Improve tab to indent on full line or multiple lines selected. --- .../src/components/CodeEditor/index.js | 37 ++++++++++++------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/packages/bruno-app/src/components/CodeEditor/index.js b/packages/bruno-app/src/components/CodeEditor/index.js index 29f3dbc1..565e3ec8 100644 --- a/packages/bruno-app/src/components/CodeEditor/index.js +++ b/packages/bruno-app/src/components/CodeEditor/index.js @@ -76,12 +76,14 @@ if (!SERVER_RENDERED) { let result = jsHinter(editor) || { list: [] }; result.to = CodeMirror.Pos(cursor.line, end); result.from = CodeMirror.Pos(cursor.line, start); - hintWords.forEach((h) => { - if (h.includes('.') == curWordBru.includes('.') && h.startsWith(curWordBru)) { - result.list.push(curWordBru.includes('.') ? h.split('.')[1] : h); - } - }); - result.list = result.list?.sort(); + if (curWordBru) { + hintWords.forEach((h) => { + if (h.includes('.') == curWordBru.includes('.') && h.startsWith(curWordBru)) { + result.list.push(curWordBru.includes('.') ? h.split('.')[1] : h); + } + }); + result.list?.sort(); + } return result; }); CodeMirror.commands.autocomplete = (cm, hint, options) => { @@ -113,9 +115,7 @@ export default class CodeEditor extends React.Component { showCursorWhenSelecting: true, foldGutter: true, gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter', 'CodeMirror-lint-markers'], - lint: { - esversion: 11 - }, + lint: { esversion: 11 }, readOnly: this.props.readOnly, scrollbarStyle: 'overlay', theme: this.props.theme === 'dark' ? 'monokai' : 'default', @@ -144,8 +144,14 @@ export default class CodeEditor extends React.Component { 'Ctrl-F': 'findPersistent', 'Cmd-H': 'replace', 'Ctrl-H': 'replace', - Tab: 'indentMore', + Tab: function (cm) { + cm.getSelection().includes('\n') || editor.getLine(cm.getCursor().line) == cm.getSelection() + ? cm.execCommand('indentMore') + : cm.replaceSelection(' ', 'end'); + }, 'Shift-Tab': 'indentLess', + 'Ctrl-Space': 'autocomplete', + 'Cmd-Space': 'autocomplete', 'Ctrl-Y': 'foldAll', 'Cmd-Y': 'foldAll', 'Ctrl-I': 'unfoldAll', @@ -178,6 +184,7 @@ export default class CodeEditor extends React.Component { } })); if (editor) { + editor.setOption('lint', this.props.mode && editor.getValue().trim().length > 0 ? { esversion: 11 } : false); editor.on('change', this._onEdit); this.addOverlay(); } @@ -187,14 +194,15 @@ export default class CodeEditor extends React.Component { const currentLine = editor.getLine(cursor.line); let start = cursor.ch; let end = start; - while (end < currentLine.length && /[\w\."'\/`]/.test(currentLine.charAt(end))) ++end; - while (start && /[\w\."'\/`]/.test(currentLine.charAt(start - 1))) --start; + while (end < currentLine.length && /[^{}();\s\[\]\,]/.test(currentLine.charAt(end))) ++end; + while (start && /[^{}();\s\[\]\,]/.test(currentLine.charAt(start - 1))) --start; let curWord = start != end && currentLine.slice(start, end); //Qualify if autocomplete will be shown if ( /^(?!Shift|Tab|Enter|ArrowUp|ArrowDown|ArrowLeft|ArrowRight|\s)\w*/.test(event.key) && - curWord.length > 1 && - /^(?!"'\d`)[a-zA-Z\.]/.test(curWord) + curWord.length > 0 && + !/\/\/|\/\*|.*{{|`[^$]*{|`[^{]*$/.test(currentLine.slice(0, end)) && + /(? { if (!this.ignoreChangeEvent && this.editor) { + this.editor.setOption('lint', this.editor.getValue().trim().length > 0 ? { esversion: 11 } : false); this.cachedValue = this.editor.getValue(); if (this.props.onEdit) { this.props.onEdit(this.cachedValue); From 353386b4da8e2b440c4b44c8cb7266cba1a0bec7 Mon Sep 17 00:00:00 2001 From: n00o Date: Fri, 17 Nov 2023 09:18:14 -0500 Subject: [PATCH 3/3] Add dependencies --- package-lock.json | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 62e35cd1..b615e95b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14352,6 +14352,7 @@ }, "node_modules/react-is": { "version": "18.2.0", + "dev": true, "license": "MIT" }, "node_modules/react-pdf": { @@ -21727,7 +21728,7 @@ "nanoid": "3.3.4", "next": "12.3.3", "path": "^0.12.7", - "pdfjs-dist": "3.11.174", + "pdfjs-dist": "^3.11.174", "platform": "^1.3.6", "posthog-node": "^2.1.0", "prettier": "^2.7.1", @@ -26986,6 +26987,46 @@ "tv4": "^1.3.0" } }, + "nomnom": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz", + "integrity": "sha512-5s0JxqhDx9/rksG2BTMVN1enjWSvPidpoSgViZU4ZXULyTe+7jxcCRLB6f42Z0l1xYJpleCBtSyY6Lwg3uu5CQ==", + "requires": { + "chalk": "~0.4.0", + "underscore": "~1.6.0" + }, + "dependencies": { + "ansi-styles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", + "integrity": "sha512-3iF4FIKdxaVYT3JqQuY3Wat/T2t7TRbbQ94Fu50ZUCbLy4TFbTzr90NOHQodQkNqmeEGCw8WbeP78WNi6SKYUA==" + }, + "chalk": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", + "integrity": "sha512-sQfYDlfv2DGVtjdoQqxS0cEZDroyG8h6TamA6rvxwlrU5BaSLDx9xhatBYl2pxZ7gmpNaPFVwBtdGdu5rQ+tYQ==", + "requires": { + "ansi-styles": "~1.0.0", + "has-color": "~0.1.0", + "strip-ansi": "~0.1.0" + } + }, + "strip-ansi": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", + "integrity": "sha512-behete+3uqxecWlDAm5lmskaSaISA+ThQ4oNNBDTBJt0x2ppR6IPqfZNuj6BLaLJ/Sji4TPZlcRyOis8wXQTLg==" + } + } + }, + "nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "optional": true, + "requires": { + "abbrev": "1" + } + }, "normalize-package-data": { "version": "2.5.0", "dev": true, @@ -28135,7 +28176,8 @@ "requires": {} }, "react-is": { - "version": "18.2.0" + "version": "18.2.0", + "dev": true }, "react-pdf": { "version": "7.5.1",