From 51d4dbd69b9a4f6c9588de47c52f697b2a9419fa Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Fri, 5 Jan 2024 16:11:33 +0530 Subject: [PATCH] fix(#1214): fixed code mirror lint issues --- .../src/components/CodeEditor/index.js | 12 ++- packages/bruno-app/src/pages/Bruno/index.js | 2 +- .../src/utils/codemirror/javascript-lint.js | 92 +++++++++++++++++++ 3 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 packages/bruno-app/src/utils/codemirror/javascript-lint.js diff --git a/packages/bruno-app/src/components/CodeEditor/index.js b/packages/bruno-app/src/components/CodeEditor/index.js index ce8187deb..837ddd2d1 100644 --- a/packages/bruno-app/src/components/CodeEditor/index.js +++ b/packages/bruno-app/src/components/CodeEditor/index.js @@ -103,6 +103,12 @@ export default class CodeEditor extends React.Component { // unnecessary updates during the update lifecycle. this.cachedValue = props.value || ''; this.variables = {}; + + this.lintOptions = { + esversion: 11, + expr: true, + asi: true + }; } componentDidMount() { @@ -118,7 +124,7 @@ export default class CodeEditor extends React.Component { showCursorWhenSelecting: true, foldGutter: true, gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter', 'CodeMirror-lint-markers'], - lint: { esversion: 11 }, + lint: this.lintOptions, readOnly: this.props.readOnly, scrollbarStyle: 'overlay', theme: this.props.theme === 'dark' ? 'monokai' : 'default', @@ -209,7 +215,7 @@ export default class CodeEditor extends React.Component { return found; }); if (editor) { - editor.setOption('lint', this.props.mode && editor.getValue().trim().length > 0 ? { esversion: 11 } : false); + editor.setOption('lint', this.props.mode && editor.getValue().trim().length > 0 ? this.lintOptions : false); editor.on('change', this._onEdit); this.addOverlay(); } @@ -299,7 +305,7 @@ export default class CodeEditor extends React.Component { _onEdit = () => { if (!this.ignoreChangeEvent && this.editor) { - this.editor.setOption('lint', this.editor.getValue().trim().length > 0 ? { esversion: 11 } : false); + this.editor.setOption('lint', this.editor.getValue().trim().length > 0 ? this.lintOptions : false); this.cachedValue = this.editor.getValue(); if (this.props.onEdit) { this.props.onEdit(this.cachedValue); diff --git a/packages/bruno-app/src/pages/Bruno/index.js b/packages/bruno-app/src/pages/Bruno/index.js index 75b07f0fc..87231a07a 100644 --- a/packages/bruno-app/src/pages/Bruno/index.js +++ b/packages/bruno-app/src/pages/Bruno/index.js @@ -25,7 +25,6 @@ if (!SERVER_RENDERED) { 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'); @@ -41,6 +40,7 @@ if (!SERVER_RENDERED) { require('codemirror-graphql/mode'); require('utils/codemirror/brunoVarInfo'); + require('utils/codemirror/javascript-lint'); } export default function Main() { diff --git a/packages/bruno-app/src/utils/codemirror/javascript-lint.js b/packages/bruno-app/src/utils/codemirror/javascript-lint.js new file mode 100644 index 000000000..a3a56857e --- /dev/null +++ b/packages/bruno-app/src/utils/codemirror/javascript-lint.js @@ -0,0 +1,92 @@ +/** + * MIT License + * https://github.com/codemirror/codemirror5/blob/master/LICENSE + * + * Copyright (C) 2017 by Marijn Haverbeke and others + */ + +let CodeMirror; +const SERVER_RENDERED = typeof navigator === 'undefined' || global['PREVENT_CODEMIRROR_RENDER'] === true; + +if (!SERVER_RENDERED) { + CodeMirror = require('codemirror'); + const { filter } = require('lodash'); + + function validator(text, options) { + if (!window.JSHINT) { + if (window.console) { + window.console.error('Error: window.JSHINT not defined, CodeMirror JavaScript linting cannot run.'); + } + return []; + } + if (!options.indent) + // JSHint error.character actually is a column index, this fixes underlining on lines using tabs for indentation + options.indent = 1; // JSHint default value is 4 + JSHINT(text, options, options.globals); + var errors = JSHINT.data().errors, + result = []; + + /* + * Filter out errors due to top level awaits + * See https://github.com/usebruno/bruno/issues/1214 + * + * Once JSHINT top level await support is added, this file can be removed + * and we can use the default javascript-lint addon from codemirror + */ + errors = filter(errors, (error) => { + if (error.code === 'E058') { + if ( + error.evidence && + error.evidence.includes('await') && + error.reason === 'Missing semicolon.' && + error.scope === '(main)' + ) { + return false; + } + + return true; + } + + return true; + }); + + if (errors) parseErrors(errors, result); + + return result; + } + + CodeMirror.registerHelper('lint', 'javascript', validator); + + function parseErrors(errors, output) { + for (var i = 0; i < errors.length; i++) { + var error = errors[i]; + if (error) { + if (error.line <= 0) { + if (window.console) { + window.console.warn('Cannot display JSHint error (invalid line ' + error.line + ')', error); + } + continue; + } + + var start = error.character - 1, + end = start + 1; + if (error.evidence) { + var index = error.evidence.substring(start).search(/.\b/); + if (index > -1) { + end += index; + } + } + + // Convert to format expected by validation service + var hint = { + message: error.reason, + severity: error.code ? (error.code.startsWith('W') ? 'warning' : 'error') : 'error', + from: CodeMirror.Pos(error.line - 1, start), + to: CodeMirror.Pos(error.line - 1, end) + }; + + output.push(hint); + } + } + } +}