From 5a51c140bff409f23e06b851bdac38be981dc9d3 Mon Sep 17 00:00:00 2001 From: Jon Combe Date: Thu, 28 May 2026 12:25:41 +0700 Subject: [PATCH] Use bundled version of Ace editor config --- .gitignore | 1 + package.json | 5 +- src/components/SQLEditor/SQLEditor.tsx | 11 +- src/components/SQLEditor/mode-cratedb.js | 525 ++++++++++++----------- 4 files changed, 280 insertions(+), 262 deletions(-) diff --git a/.gitignore b/.gitignore index b799a964..7e73bae7 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ /node_modules /.pnp .pnp.js +.pnpm-store # testing /coverage diff --git a/package.json b/package.json index ea5e85fe..fecd5bcd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@cratedb/crate-gc-admin", - "version": "0.25.2", + "version": "0.25.3", "author": "cratedb", "private": false, "type": "module", @@ -29,7 +29,8 @@ "./styles/theme.css": "./dist/styles/theme.css" }, "sideEffects": [ - "**/*.css" + "**/*.css", + "**/mode-cratedb.js" ], "files": [ "./dist" diff --git a/src/components/SQLEditor/SQLEditor.tsx b/src/components/SQLEditor/SQLEditor.tsx index b746d2a8..42a15975 100644 --- a/src/components/SQLEditor/SQLEditor.tsx +++ b/src/components/SQLEditor/SQLEditor.tsx @@ -1,6 +1,7 @@ // sort-imports-ignore import 'ace-builds/src-min-noconflict/ace'; import 'ace-builds/src-min-noconflict/ext-language_tools'; +import 'ace-builds/src-min-noconflict/mode-sql'; import 'ace-builds/src-min-noconflict/theme-github'; import { @@ -23,7 +24,9 @@ import { useSchemaTree } from 'src/swr/jwt'; import { QueryStatus } from 'types/query'; import { Button } from 'components'; import { crateDbCompleter } from './cratedbCompleter'; -import './mode-cratedb'; +import { getCrateDbMode, registerCrateDbMode } from './mode-cratedb'; + +registerCrateDbMode(); export type SQLEditorProps = { value?: string | undefined | null; @@ -357,8 +360,12 @@ function SQLEditor({ height="100%" highlightActiveLine onChange={onValueChange} - mode="cratedb" + mode="sql" onLoad={editor => { + const CrateDbMode = getCrateDbMode(); + if (CrateDbMode) { + editor.getSession().setMode(new CrateDbMode()); + } editor.completers = [crateDbCompleter]; setAce(editor); }} diff --git a/src/components/SQLEditor/mode-cratedb.js b/src/components/SQLEditor/mode-cratedb.js index ac17f259..6a9aef71 100644 --- a/src/components/SQLEditor/mode-cratedb.js +++ b/src/components/SQLEditor/mode-cratedb.js @@ -4,274 +4,283 @@ import { keywords, } from '../../constants/cratedbEditorKeywords'; -// try / catch to prevent tests failing -// i've wasted a lot of time on trying to get this to work without success -// this works fine in the app, and we can improve it in future if we get chance to -try { - ace.define( - 'ace/mode/sql_highlight_rules', - ['require', 'exports', 'module', 'ace/lib/oop', 'ace/mode/text_highlight_rules'], - function (require, exports, module) { - 'use strict'; - var oop = require('../lib/oop'); - var TextHighlightRules = require('./text_highlight_rules').TextHighlightRules; - var SqlHighlightRules = function () { - var builtinConstants = 'true|false'; - var keywordMapper = this.createKeywordMapper( - { - 'support.function': builtinFunctions, - keyword: keywords, - 'constant.language': builtinConstants, - 'storage.type': dataTypes, - }, - 'identifier', - true, - ); - this.$rules = { - start: [ - { - token: 'comment', - regex: '--.*$', - }, - { - token: 'comment', - start: '/\\*', - end: '\\*/', - }, - { - token: 'identifier', // " string - regex: '".*?"', - }, - { - token: 'string', // ' string - regex: "'.*?'", - }, - { - token: 'string', // ` string (apache drill) - regex: '`.*?`', - }, - { - token: 'constant.numeric', // float - regex: '[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b', - }, - { - token: keywordMapper, - regex: '[a-zA-Z_$][a-zA-Z0-9_$]*\\b', - }, - { - token: 'keyword.operator', - regex: '\\+|\\-|\\/|\\/\\/|%|<@>|@>|<@|&|\\^|~|<|>|<=|=>|==|!=|<>|=', - }, - { - token: 'paren.lparen', - regex: '[\\(]', - }, - { - token: 'paren.rparen', - regex: '[\\)]', - }, +let registered = false; + +// try / catch to prevent tests failing when ace is unavailable +export function registerCrateDbMode() { + if (registered || typeof ace === 'undefined') { + return; + } + + try { + ace.define( + 'ace/mode/sql_highlight_rules', + ['require', 'exports', 'module', 'ace/lib/oop', 'ace/mode/text_highlight_rules'], + function (require, exports, module) { + 'use strict'; + var oop = require('../lib/oop'); + var TextHighlightRules = require('./text_highlight_rules').TextHighlightRules; + var SqlHighlightRules = function () { + var builtinConstants = 'true|false'; + var keywordMapper = this.createKeywordMapper( { - token: 'text', - regex: '\\s+', + 'support.function': builtinFunctions, + keyword: keywords, + 'constant.language': builtinConstants, + 'storage.type': dataTypes, }, - ], + 'identifier', + true, + ); + this.$rules = { + start: [ + { + token: 'comment', + regex: '--.*$', + }, + { + token: 'comment', + start: '/\\*', + end: '\\*/', + }, + { + token: 'identifier', // " string + regex: '".*?"', + }, + { + token: 'string', // ' string + regex: "'.*?'", + }, + { + token: 'string', // ` string (apache drill) + regex: '`.*?`', + }, + { + token: 'constant.numeric', // float + regex: '[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b', + }, + { + token: keywordMapper, + regex: '[a-zA-Z_$][a-zA-Z0-9_$]*\\b', + }, + { + token: 'keyword.operator', + regex: '\\+|\\-|\\/|\\/\\/|%|<@>|@>|<@|&|\\^|~|<|>|<=|=>|==|!=|<>|=', + }, + { + token: 'paren.lparen', + regex: '[\\(]', + }, + { + token: 'paren.rparen', + regex: '[\\)]', + }, + { + token: 'text', + regex: '\\s+', + }, + ], + }; + this.normalizeRules(); }; - this.normalizeRules(); - }; - oop.inherits(SqlHighlightRules, TextHighlightRules); - exports.SqlHighlightRules = SqlHighlightRules; - }, - ); + oop.inherits(SqlHighlightRules, TextHighlightRules); + exports.SqlHighlightRules = SqlHighlightRules; + }, + ); - ace.define( - 'ace/mode/folding/cstyle', - [ - 'require', - 'exports', - 'module', - 'ace/lib/oop', - 'ace/range', - 'ace/mode/folding/fold_mode', - ], - function (require, exports, module) { - 'use strict'; - var oop = require('../../lib/oop'); - var Range = require('../../range').Range; - var BaseFoldMode = require('./fold_mode').FoldMode; - var FoldMode = (exports.FoldMode = function (commentRegex) { - if (commentRegex) { - this.foldingStartMarker = new RegExp( - this.foldingStartMarker.source.replace( - /\|[^|]*?$/, - '|' + commentRegex.start, - ), - ); - this.foldingStopMarker = new RegExp( - this.foldingStopMarker.source.replace( - /\|[^|]*?$/, - '|' + commentRegex.end, - ), - ); - } - }); - oop.inherits(FoldMode, BaseFoldMode); - (function () { - this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/; - this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/; - this.singleLineBlockCommentRe = /^\s*(\/\*).*\*\/\s*$/; - this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/; - this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/; - this._getFoldWidgetBase = this.getFoldWidget; - this.getFoldWidget = function (session, foldStyle, row) { - var line = session.getLine(row); - if (this.singleLineBlockCommentRe.test(line)) { - if ( - !this.startRegionRe.test(line) && - !this.tripleStarBlockCommentRe.test(line) - ) - return ''; + ace.define( + 'ace/mode/folding/cstyle', + [ + 'require', + 'exports', + 'module', + 'ace/lib/oop', + 'ace/range', + 'ace/mode/folding/fold_mode', + ], + function (require, exports, module) { + 'use strict'; + var oop = require('../../lib/oop'); + var Range = require('../../range').Range; + var BaseFoldMode = require('./fold_mode').FoldMode; + var FoldMode = (exports.FoldMode = function (commentRegex) { + if (commentRegex) { + this.foldingStartMarker = new RegExp( + this.foldingStartMarker.source.replace( + /\|[^|]*?$/, + '|' + commentRegex.start, + ), + ); + this.foldingStopMarker = new RegExp( + this.foldingStopMarker.source.replace( + /\|[^|]*?$/, + '|' + commentRegex.end, + ), + ); } - var fw = this._getFoldWidgetBase(session, foldStyle, row); - if (!fw && this.startRegionRe.test(line)) return 'start'; // lineCommentRegionStart - return fw; - }; - this.getFoldWidgetRange = function ( - session, - foldStyle, - row, - forceMultiline, - ) { - var line = session.getLine(row); - if (this.startRegionRe.test(line)) - return this.getCommentRegionBlock(session, line, row); - var match = line.match(this.foldingStartMarker); - if (match) { - var i = match.index; - if (match[1]) return this.openingBracketBlock(session, match[1], row, i); - var range = session.getCommentFoldRange(row, i + match[0].length, 1); - if (range && !range.isMultiLine()) { - if (forceMultiline) { - range = this.getSectionRange(session, row); - } else if (foldStyle != 'all') range = null; + }); + oop.inherits(FoldMode, BaseFoldMode); + (function () { + this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/; + this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/; + this.singleLineBlockCommentRe = /^\s*(\/\*).*\*\/\s*$/; + this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/; + this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/; + this._getFoldWidgetBase = this.getFoldWidget; + this.getFoldWidget = function (session, foldStyle, row) { + var line = session.getLine(row); + if (this.singleLineBlockCommentRe.test(line)) { + if ( + !this.startRegionRe.test(line) && + !this.tripleStarBlockCommentRe.test(line) + ) + return ''; } - return range; - } - if (foldStyle === 'markbegin') return; - var match = line.match(this.foldingStopMarker); - if (match) { - var i = match.index + match[0].length; - if (match[1]) return this.closingBracketBlock(session, match[1], row, i); - return session.getCommentFoldRange(row, i, -1); - } - }; - this.getSectionRange = function (session, row) { - var line = session.getLine(row); - var startIndent = line.search(/\S/); - var startRow = row; - var startColumn = line.length; - row = row + 1; - var endRow = row; - var maxRow = session.getLength(); - while (++row < maxRow) { - line = session.getLine(row); - var indent = line.search(/\S/); - if (indent === -1) continue; - if (startIndent > indent) break; - var subRange = this.getFoldWidgetRange(session, 'all', row); - if (subRange) { - if (subRange.start.row <= startRow) { - break; - } else if (subRange.isMultiLine()) { - row = subRange.end.row; - } else if (startIndent == indent) { - break; + var fw = this._getFoldWidgetBase(session, foldStyle, row); + if (!fw && this.startRegionRe.test(line)) return 'start'; // lineCommentRegionStart + return fw; + }; + this.getFoldWidgetRange = function ( + session, + foldStyle, + row, + forceMultiline, + ) { + var line = session.getLine(row); + if (this.startRegionRe.test(line)) + return this.getCommentRegionBlock(session, line, row); + var match = line.match(this.foldingStartMarker); + if (match) { + var i = match.index; + if (match[1]) return this.openingBracketBlock(session, match[1], row, i); + var range = session.getCommentFoldRange(row, i + match[0].length, 1); + if (range && !range.isMultiLine()) { + if (forceMultiline) { + range = this.getSectionRange(session, row); + } else if (foldStyle != 'all') range = null; } + return range; } - endRow = row; - } - return new Range( - startRow, - startColumn, - endRow, - session.getLine(endRow).length, - ); - }; - this.getCommentRegionBlock = function (session, line, row) { - var startColumn = line.search(/\s*$/); - var maxRow = session.getLength(); - var startRow = row; - var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/; - var depth = 1; - while (++row < maxRow) { - line = session.getLine(row); - var m = re.exec(line); - if (!m) continue; - if (m[1]) depth--; - else depth++; - if (!depth) break; - } - var endRow = row; - if (endRow > startRow) { - return new Range(startRow, startColumn, endRow, line.length); - } + if (foldStyle === 'markbegin') return; + var match = line.match(this.foldingStopMarker); + if (match) { + var i = match.index + match[0].length; + if (match[1]) return this.closingBracketBlock(session, match[1], row, i); + return session.getCommentFoldRange(row, i, -1); + } + }; + this.getSectionRange = function (session, row) { + var line = session.getLine(row); + var startIndent = line.search(/\S/); + var startRow = row; + var startColumn = line.length; + row = row + 1; + var endRow = row; + var maxRow = session.getLength(); + while (++row < maxRow) { + line = session.getLine(row); + var indent = line.search(/\S/); + if (indent === -1) continue; + if (startIndent > indent) break; + var subRange = this.getFoldWidgetRange(session, 'all', row); + if (subRange) { + if (subRange.start.row <= startRow) { + break; + } else if (subRange.isMultiLine()) { + row = subRange.end.row; + } else if (startIndent == indent) { + break; + } + } + endRow = row; + } + return new Range( + startRow, + startColumn, + endRow, + session.getLine(endRow).length, + ); + }; + this.getCommentRegionBlock = function (session, line, row) { + var startColumn = line.search(/\s*$/); + var maxRow = session.getLength(); + var startRow = row; + var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/; + var depth = 1; + while (++row < maxRow) { + line = session.getLine(row); + var m = re.exec(line); + if (!m) continue; + if (m[1]) depth--; + else depth++; + if (!depth) break; + } + var endRow = row; + if (endRow > startRow) { + return new Range(startRow, startColumn, endRow, line.length); + } + }; + }).call(FoldMode.prototype); + }, + ); + + ace.define( + 'ace/mode/folding/sql', + ['require', 'exports', 'module', 'ace/lib/oop', 'ace/mode/folding/cstyle'], + function (require, exports, module) { + 'use strict'; + var oop = require('../../lib/oop'); + var BaseFoldMode = require('./cstyle').FoldMode; + var FoldMode = (exports.FoldMode = function () {}); + oop.inherits(FoldMode, BaseFoldMode); + (function () {}).call(FoldMode.prototype); + }, + ); + + ace.define( + 'ace/mode/cratedb', + [ + 'require', + 'exports', + 'module', + 'ace/lib/oop', + 'ace/mode/text', + 'ace/mode/sql_highlight_rules', + 'ace/mode/folding/sql', + ], + function (require, exports, module) { + 'use strict'; + var oop = require('../lib/oop'); + var TextMode = require('./text').Mode; + var SqlHighlightRules = require('./sql_highlight_rules').SqlHighlightRules; + var SqlFoldMode = require('./folding/sql').FoldMode; + var Mode = function () { + this.HighlightRules = SqlHighlightRules; + this.foldingRules = new SqlFoldMode(); + this.$behaviour = this.$defaultBehaviour; }; - }).call(FoldMode.prototype); - }, - ); + oop.inherits(Mode, TextMode); + (function () { + this.lineCommentStart = '--'; + this.blockComment = { start: '/*', end: '*/' }; + this.$id = 'ace/mode/cratedb'; + this.snippetFileId = 'ace/snippets/sql'; + }).call(Mode.prototype); + exports.Mode = Mode; + }, + ); - ace.define( - 'ace/mode/folding/sql', - ['require', 'exports', 'module', 'ace/lib/oop', 'ace/mode/folding/cstyle'], - function (require, exports, module) { - 'use strict'; - var oop = require('../../lib/oop'); - var BaseFoldMode = require('./cstyle').FoldMode; - var FoldMode = (exports.FoldMode = function () {}); - oop.inherits(FoldMode, BaseFoldMode); - (function () {}).call(FoldMode.prototype); - }, - ); + registered = true; + } catch (error) { + // + } +} - ace.define( - 'ace/mode/cratedb', - [ - 'require', - 'exports', - 'module', - 'ace/lib/oop', - 'ace/mode/text', - 'ace/mode/sql_highlight_rules', - 'ace/mode/folding/sql', - ], - function (require, exports, module) { - 'use strict'; - var oop = require('../lib/oop'); - var TextMode = require('./text').Mode; - var SqlHighlightRules = require('./sql_highlight_rules').SqlHighlightRules; - var SqlFoldMode = require('./folding/sql').FoldMode; - var Mode = function () { - this.HighlightRules = SqlHighlightRules; - this.foldingRules = new SqlFoldMode(); - this.$behaviour = this.$defaultBehaviour; - }; - oop.inherits(Mode, TextMode); - (function () { - this.lineCommentStart = '--'; - this.blockComment = { start: '/*', end: '*/' }; - this.$id = 'ace/mode/sql'; - this.snippetFileId = 'ace/snippets/sql'; - }).call(Mode.prototype); - exports.Mode = Mode; - }, - ); +export function getCrateDbMode() { + registerCrateDbMode(); + if (typeof ace === 'undefined') { + return undefined; + } - (function () { - ace.require(['ace/mode/cratedb'], function (m) { - if (typeof module == 'object' && typeof exports == 'object' && module) { - exports['default'] = m; - } - }); - })(); -} catch (error) { - // + return ace.require('ace/mode/cratedb').Mode; }