mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Console] Add theme and more lexer rules (#178757)
## Summary This PR adds a theme for the Console language in Monaco editor and adds more lexer rules to bring the highlighting of the input closed to the original in Ace editor. ### Screenshots Monaco editor <img width="682" alt="Screenshot 2024-03-19 at 12 38 07" src="98a1acc7
-3a8a-4ad9-a79e-5236091c4c39"> Ace editor <img width="651" alt="Screenshot 2024-03-19 at 12 37 52" src="37935a68
-923b-493c-ac56-ef4982f27fdf"> ### How to test 1. Add `console.dev.enableMonaco: true` to `kibana.dev.yml`` 2. Type different requests into Console and check that the highlighting works the same as in Ace. For example, use the following requests ``` GET ${pathVariable}/_search { "query": { "match": { "${bodyNameVariable}": "${bodyValueVariable}", "number_property": 1234, "array_property": ["test1", 1234, false], "boolean_property": true, "text_property": "text_value", "triple_quote": """ inside triple quote """ // line comment /* block comment */ } } } // line comment /* block comment */ GET _sql { "query": """ SELECT "field" FROM "index-*" WHERE "column" = "value" """ } ``` 3. To check that `xjson` highlighting still works a. Navigate to Ingest pipelines and click the "create from csv" button b. Load a valid csv file, for example this [one](https://github.com/kgeller/ecs-mapper/blob/master/example/mapping.csv) #### Known issues that will be addressed in follow up PRs - SQL highlighting needs to be re-implemented (added to the follow up list in https://github.com/elastic/kibana/issues/176926) - Strings inside triple quotes are not using italics (added to the follow up list in https://github.com/elastic/kibana/issues/176926) - Font size needs to be set via settings and the default value provided (fixed via https://github.com/elastic/kibana/pull/178982) - Font family: do we want to use the same font as for other Monaco languages are use the one for Ace? (added to the follow up list in https://github.com/elastic/kibana/issues/176926) - In the future, we might want to use the same theme for `xjson` and Console (added to the follow up list in https://github.com/elastic/kibana/issues/176926) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
f320d560b1
commit
c59016ed9a
15 changed files with 305 additions and 51 deletions
|
@ -32,4 +32,4 @@ import { registerLanguage } from './src/helpers';
|
|||
export { BarePluginApi, registerLanguage };
|
||||
export * from './src/types';
|
||||
|
||||
export { CONSOLE_LANG_ID } from './src/console';
|
||||
export { CONSOLE_LANG_ID, CONSOLE_THEME_ID } from './src/console';
|
||||
|
|
16
packages/kbn-monaco/src/common/theme.ts
Normal file
16
packages/kbn-monaco/src/common/theme.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export const themeRuleGroupBuilderFactory =
|
||||
(postfix: string = '') =>
|
||||
(tokens: string[], color: string, isBold: boolean = false) =>
|
||||
tokens.map((i) => ({
|
||||
token: i + postfix,
|
||||
foreground: color,
|
||||
fontStyle: isBold ? 'bold' : '',
|
||||
}));
|
|
@ -7,3 +7,5 @@
|
|||
*/
|
||||
|
||||
export const CONSOLE_LANG_ID = 'console';
|
||||
export const CONSOLE_THEME_ID = 'consoleTheme';
|
||||
export const CONSOLE_POSTFIX = '.console';
|
||||
|
|
|
@ -15,7 +15,9 @@ import type { LangModuleType } from '../types';
|
|||
import { CONSOLE_LANG_ID } from './constants';
|
||||
import { lexerRules, languageConfiguration } from './lexer_rules';
|
||||
|
||||
export { CONSOLE_LANG_ID } from './constants';
|
||||
export { CONSOLE_LANG_ID, CONSOLE_THEME_ID } from './constants';
|
||||
|
||||
export { buildConsoleTheme } from './theme';
|
||||
|
||||
export const ConsoleLang: LangModuleType = {
|
||||
ID: CONSOLE_LANG_ID,
|
||||
|
|
|
@ -7,46 +7,191 @@
|
|||
*/
|
||||
|
||||
import { monaco } from '../../monaco_imports';
|
||||
import { globals } from '../../common/lexer_rules';
|
||||
import { buildXjsonRules } from '../../xjson/lexer_rules/xjson';
|
||||
|
||||
export const languageConfiguration: monaco.languages.LanguageConfiguration = {};
|
||||
export const languageConfiguration: monaco.languages.LanguageConfiguration = {
|
||||
brackets: [
|
||||
['{', '}'],
|
||||
['[', ']'],
|
||||
],
|
||||
autoClosingPairs: [
|
||||
{ open: '{', close: '}' },
|
||||
{ open: '[', close: ']' },
|
||||
{ open: '"', close: '"' },
|
||||
],
|
||||
};
|
||||
|
||||
/*
|
||||
util function to build the action object
|
||||
*/
|
||||
const addNextStateToAction = (tokens: string[], nextState?: string) => {
|
||||
return tokens.map((token, index) => {
|
||||
// only last action needs to specify the next state
|
||||
if (index === tokens.length - 1 && nextState) {
|
||||
return { token, next: nextState };
|
||||
}
|
||||
return token;
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
if regex is matched, tokenize as "token" and move to the state "nextState" if defined
|
||||
*/
|
||||
const matchToken = (token: string, regex: string | RegExp, nextState?: string) => {
|
||||
if (nextState) {
|
||||
return { regex, action: { token, next: nextState } };
|
||||
}
|
||||
return { regex, action: { token } };
|
||||
};
|
||||
|
||||
/*
|
||||
if regex is matched, tokenize as "tokens" consecutively and move to the state "nextState"
|
||||
regex needs to have the same number of capturing group as the number of tokens
|
||||
*/
|
||||
const matchTokens = (tokens: string[], regex: string | RegExp, nextState?: string) => {
|
||||
const action = addNextStateToAction(tokens, nextState);
|
||||
return {
|
||||
regex,
|
||||
action,
|
||||
};
|
||||
};
|
||||
|
||||
const matchTokensWithEOL = (
|
||||
tokens: string | string[],
|
||||
regex: string | RegExp,
|
||||
nextIfEOL: string,
|
||||
normalNext?: string
|
||||
) => {
|
||||
if (Array.isArray(tokens)) {
|
||||
const endOfLineAction = addNextStateToAction(tokens, nextIfEOL);
|
||||
const action = addNextStateToAction(tokens, normalNext);
|
||||
return {
|
||||
regex,
|
||||
action: {
|
||||
cases: {
|
||||
'@eos': endOfLineAction,
|
||||
'@default': action,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
return {
|
||||
regex,
|
||||
action: {
|
||||
cases: {
|
||||
'@eos': { token: tokens, next: nextIfEOL },
|
||||
'@default': { token: tokens, next: normalNext },
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const xjsonRules = { ...buildXjsonRules('json_root') };
|
||||
// @ts-expect-error include comments into json
|
||||
xjsonRules.json_root = [{ include: '@comments' }, ...xjsonRules.json_root];
|
||||
xjsonRules.json_root = [
|
||||
// @ts-expect-error include variables into json
|
||||
matchToken('variable.template', /("\${\w+}")/),
|
||||
...xjsonRules.json_root,
|
||||
];
|
||||
|
||||
export const lexerRules: monaco.languages.IMonarchLanguage = {
|
||||
...(globals as any),
|
||||
|
||||
defaultToken: 'invalid',
|
||||
regex_method: /get|post|put|patch|delete/,
|
||||
regex_url: /.*$/,
|
||||
// C# style strings
|
||||
escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
|
||||
ignoreCase: true,
|
||||
tokenizer: {
|
||||
root: [
|
||||
// whitespace
|
||||
{ include: '@rule_whitespace' },
|
||||
// start a multi-line comment
|
||||
{ include: '@rule_start_multi_comment' },
|
||||
// a one-line comment
|
||||
[/\/\/.*$/, 'comment'],
|
||||
// warning comment
|
||||
matchToken('warning', '#!.*$'),
|
||||
// comments
|
||||
{ include: '@comments' },
|
||||
// start of json
|
||||
matchToken('paren.lparen', '{', 'json_root'),
|
||||
// method
|
||||
[/@regex_method/, 'keyword'],
|
||||
// url
|
||||
[/@regex_url/, 'identifier'],
|
||||
matchTokensWithEOL('method', /([a-zA-Z]+)/, 'root', 'method_sep'),
|
||||
// whitespace
|
||||
matchToken('whitespace', '\\s+'),
|
||||
// text
|
||||
matchToken('text', '.+?'),
|
||||
],
|
||||
rule_whitespace: [[/[ \t\r\n]+/, 'WHITESPACE']],
|
||||
rule_start_multi_comment: [[/\/\*/, 'comment', '@rule_multi_comment']],
|
||||
rule_multi_comment: [
|
||||
method_sep: [
|
||||
// protocol host with slash
|
||||
matchTokensWithEOL(
|
||||
['whitespace', 'url.protocol_host', 'url.slash'],
|
||||
/(\s+)(https?:\/\/[^?\/,]+)(\/)/,
|
||||
'root',
|
||||
'url'
|
||||
),
|
||||
// variable template
|
||||
matchTokensWithEOL(['whitespace', 'variable.template'], /(\s+)(\${\w+})/, 'root', 'url'),
|
||||
// protocol host
|
||||
matchTokensWithEOL(
|
||||
['whitespace', 'url.protocol_host'],
|
||||
/(\s+)(https?:\/\/[^?\/,]+)/,
|
||||
'root',
|
||||
'url'
|
||||
),
|
||||
// slash
|
||||
matchTokensWithEOL(['whitespace', 'url.slash'], /(\s+)(\/)/, 'root', 'url'),
|
||||
// whitespace
|
||||
matchTokensWithEOL('whitespace', /(\s+)/, 'root', 'url'),
|
||||
],
|
||||
url: [
|
||||
// variable template
|
||||
matchTokensWithEOL('variable.template', /(\${\w+})/, 'root'),
|
||||
// pathname
|
||||
matchTokensWithEOL('url.part', /([^?\/,\s]+)\s*/, 'root'),
|
||||
// comma
|
||||
matchTokensWithEOL('url.comma', /(,)/, 'root'),
|
||||
// slash
|
||||
matchTokensWithEOL('url.slash', /(\/)/, 'root'),
|
||||
// question mark
|
||||
matchTokensWithEOL('url.questionmark', /(\?)/, 'root', 'urlParams'),
|
||||
// comment
|
||||
matchTokensWithEOL(
|
||||
['whitespace', 'comment.punctuation', 'comment.line'],
|
||||
/(\s+)(\/\/)(.*$)/,
|
||||
'root'
|
||||
),
|
||||
],
|
||||
urlParams: [
|
||||
// param with variable template
|
||||
matchTokensWithEOL(
|
||||
['url.param', 'url.equal', 'variable.template'],
|
||||
/([^&=]+)(=)(\${\w+})/,
|
||||
'root'
|
||||
),
|
||||
// param with value
|
||||
matchTokensWithEOL(['url.param', 'url.equal', 'url.value'], /([^&=]+)(=)([^&]*)/, 'root'),
|
||||
// param
|
||||
matchTokensWithEOL('url.param', /([^&=]+)/, 'root'),
|
||||
// ampersand
|
||||
matchTokensWithEOL('url.amp', /(&)/, 'root'),
|
||||
// comment
|
||||
matchTokensWithEOL(
|
||||
['whitespace', 'comment.punctuation', 'comment.line'],
|
||||
/(\s+)(\/\/)(.*$)/,
|
||||
'root'
|
||||
),
|
||||
],
|
||||
comments: [
|
||||
// line comment indicated by #
|
||||
matchTokens(['comment.punctuation', 'comment.line'], /(#)(.*$)/),
|
||||
// start a block comment indicated by /*
|
||||
matchToken('comment.punctuation', /\/\*/, 'block_comment'),
|
||||
// line comment indicated by //
|
||||
matchTokens(['comment.punctuation', 'comment.line'], /(\/\/)(.*$)/),
|
||||
],
|
||||
block_comment: [
|
||||
// match everything on a single line inside the comment except for chars / and *
|
||||
[/[^\/*]+/, 'comment'],
|
||||
// start a nested comment by going 1 level down
|
||||
[/\/\*/, 'comment', '@push'],
|
||||
// match the closing of the comment and return 1 level up
|
||||
['\\*/', 'comment', '@pop'],
|
||||
matchToken('comment', /[^\/*]+/),
|
||||
// end block comment
|
||||
matchToken('comment.punctuation', /\*\//, '@pop'),
|
||||
// match individual chars inside a multi-line comment
|
||||
[/[\/*]/, 'comment'],
|
||||
],
|
||||
string: [
|
||||
[/[^\\"]+/, 'string'],
|
||||
[/@escapes/, 'string.escape'],
|
||||
[/\\./, 'string.escape.invalid'],
|
||||
[/"/, { token: 'string.quote', bracket: '@close', next: '@pop' }],
|
||||
matchToken('comment', /[\/*]/),
|
||||
],
|
||||
// include json rules
|
||||
...xjsonRules,
|
||||
},
|
||||
};
|
||||
|
|
54
packages/kbn-monaco/src/console/theme.ts
Normal file
54
packages/kbn-monaco/src/console/theme.ts
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { makeHighContrastColor } from '@elastic/eui';
|
||||
import { darkMode, euiThemeVars } from '@kbn/ui-theme';
|
||||
|
||||
import { themeRuleGroupBuilderFactory } from '../common/theme';
|
||||
import { monaco } from '../monaco_imports';
|
||||
|
||||
const buildRuleGroup = themeRuleGroupBuilderFactory();
|
||||
|
||||
const background = euiThemeVars.euiColorLightestShade;
|
||||
const methodTextColor = '#DD0A73';
|
||||
const urlTextColor = '#00A69B';
|
||||
const stringTextColor = '#009926';
|
||||
const commentTextColor = '#4C886B';
|
||||
const variableTextColor = '#0079A5';
|
||||
const booleanTextColor = '#585CF6';
|
||||
const numericTextColor = variableTextColor;
|
||||
export const buildConsoleTheme = (): monaco.editor.IStandaloneThemeData => {
|
||||
return {
|
||||
base: darkMode ? 'vs-dark' : 'vs',
|
||||
inherit: true,
|
||||
rules: [
|
||||
...buildRuleGroup(['method'], makeHighContrastColor(methodTextColor)(background)),
|
||||
...buildRuleGroup(['url'], makeHighContrastColor(urlTextColor)(background)),
|
||||
...buildRuleGroup(
|
||||
['string', 'string-literal', 'multi-string', 'punctuation.end-triple-quote'],
|
||||
makeHighContrastColor(stringTextColor)(background)
|
||||
),
|
||||
...buildRuleGroup(['comment'], makeHighContrastColor(commentTextColor)(background)),
|
||||
...buildRuleGroup(['variable'], makeHighContrastColor(variableTextColor)(background)),
|
||||
...buildRuleGroup(
|
||||
['constant.language.boolean'],
|
||||
makeHighContrastColor(booleanTextColor)(background)
|
||||
),
|
||||
...buildRuleGroup(['constant.numeric'], makeHighContrastColor(numericTextColor)(background)),
|
||||
],
|
||||
colors: {
|
||||
'editor.background': background,
|
||||
// color of the line numbers
|
||||
'editorLineNumber.foreground': euiThemeVars.euiColorDarkShade,
|
||||
// color of the active line number
|
||||
'editorLineNumber.activeForeground': euiThemeVars.euiColorDarkShade,
|
||||
// background of the line numbers side panel
|
||||
'editorGutter.background': euiThemeVars.euiColorEmptyShade,
|
||||
},
|
||||
};
|
||||
};
|
|
@ -7,15 +7,11 @@
|
|||
*/
|
||||
|
||||
import { euiThemeVars, darkMode } from '@kbn/ui-theme';
|
||||
import { themeRuleGroupBuilderFactory } from '../../../common/theme';
|
||||
import { ESQL_TOKEN_POSTFIX } from '../constants';
|
||||
import { monaco } from '../../../monaco_imports';
|
||||
|
||||
const buildRuleGroup = (tokens: string[], color: string, isBold: boolean = false) =>
|
||||
tokens.map((i) => ({
|
||||
token: i + ESQL_TOKEN_POSTFIX,
|
||||
foreground: color,
|
||||
fontStyle: isBold ? 'bold' : '',
|
||||
}));
|
||||
const buildRuleGroup = themeRuleGroupBuilderFactory(ESQL_TOKEN_POSTFIX);
|
||||
|
||||
export const buildESQlTheme = (): monaco.editor.IStandaloneThemeData => ({
|
||||
base: darkMode ? 'vs-dark' : 'vs',
|
||||
|
|
|
@ -13,7 +13,7 @@ import { monaco } from './monaco_imports';
|
|||
import { ESQL_THEME_ID, ESQLLang, buildESQlTheme } from './esql';
|
||||
import { YAML_LANG_ID } from './yaml';
|
||||
import { registerLanguage, registerTheme } from './helpers';
|
||||
import { ConsoleLang } from './console';
|
||||
import { ConsoleLang, CONSOLE_THEME_ID, buildConsoleTheme } from './console';
|
||||
|
||||
export const DEFAULT_WORKER_ID = 'default';
|
||||
const langSpecificWorkerIds = [
|
||||
|
@ -38,6 +38,7 @@ registerLanguage(ConsoleLang);
|
|||
* Register custom themes
|
||||
*/
|
||||
registerTheme(ESQL_THEME_ID, buildESQlTheme());
|
||||
registerTheme(CONSOLE_THEME_ID, buildConsoleTheme());
|
||||
|
||||
const monacoBundleDir = (window as any).__kbnPublicPath__?.['kbn-monaco'];
|
||||
|
||||
|
|
|
@ -8,16 +8,11 @@
|
|||
|
||||
import { monaco } from '../../monaco_imports';
|
||||
|
||||
import { globals } from './shared';
|
||||
import { globals } from '../../common/lexer_rules';
|
||||
|
||||
export const lexerRules: monaco.languages.IMonarchLanguage = {
|
||||
...(globals as any),
|
||||
|
||||
defaultToken: 'invalid',
|
||||
tokenPostfix: '',
|
||||
|
||||
tokenizer: {
|
||||
root: [
|
||||
export const buildXjsonRules = (root: string = 'root') => {
|
||||
return {
|
||||
[root]: [
|
||||
[
|
||||
/("(?:[^"]*_)?script"|"inline"|"source")(\s*?)(:)(\s*?)(""")/,
|
||||
[
|
||||
|
@ -106,7 +101,15 @@ export const lexerRules: monaco.languages.IMonarchLanguage = {
|
|||
[/\\""""/, { token: 'punctuation.end_triple_quote', next: '@pop' }],
|
||||
[/./, { token: 'multi_string' }],
|
||||
],
|
||||
},
|
||||
};
|
||||
};
|
||||
export const lexerRules: monaco.languages.IMonarchLanguage = {
|
||||
...(globals as any),
|
||||
|
||||
defaultToken: 'invalid',
|
||||
tokenPostfix: '',
|
||||
|
||||
tokenizer: { ...buildXjsonRules() },
|
||||
};
|
||||
|
||||
export const languageConfiguration: monaco.languages.LanguageConfiguration = {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
import React, { FunctionComponent, useState } from 'react';
|
||||
import { CodeEditor } from '@kbn/code-editor';
|
||||
import { css } from '@emotion/react';
|
||||
import { CONSOLE_LANG_ID } from '@kbn/monaco';
|
||||
import { CONSOLE_LANG_ID, CONSOLE_THEME_ID } from '@kbn/monaco';
|
||||
import { useEditorReadContext } from '../../../contexts';
|
||||
|
||||
export const MonacoEditor: FunctionComponent = () => {
|
||||
|
@ -31,6 +31,7 @@ export const MonacoEditor: FunctionComponent = () => {
|
|||
options={{
|
||||
fontSize: settings.fontSize,
|
||||
wordWrap: settings.wrapMode === true ? 'on' : 'off',
|
||||
theme: CONSOLE_THEME_ID,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -31,11 +31,12 @@ export function addEOL(
|
|||
export const mergeTokens = (...args: any[]) => [].concat.apply([], args);
|
||||
|
||||
const TextHighlightRules = ace.acequire('ace/mode/text_highlight_rules').TextHighlightRules;
|
||||
|
||||
// translating this to monaco
|
||||
export class InputHighlightRules extends TextHighlightRules {
|
||||
constructor() {
|
||||
super();
|
||||
this.$rules = {
|
||||
// TODO
|
||||
'start-sql': [
|
||||
{ token: 'whitespace', regex: '\\s+' },
|
||||
{ token: 'paren.lparen', regex: '{', next: 'json-sql', push: true },
|
||||
|
@ -43,16 +44,22 @@ export class InputHighlightRules extends TextHighlightRules {
|
|||
],
|
||||
start: mergeTokens(
|
||||
[
|
||||
// done
|
||||
{ token: 'warning', regex: '#!.*$' },
|
||||
// done
|
||||
{ include: 'comments' },
|
||||
// done
|
||||
{ token: 'paren.lparen', regex: '{', next: 'json', push: true },
|
||||
],
|
||||
// done
|
||||
addEOL(['method'], /([a-zA-Z]+)/, 'start', 'method_sep'),
|
||||
[
|
||||
// done
|
||||
{
|
||||
token: 'whitespace',
|
||||
regex: '\\s+',
|
||||
},
|
||||
// done
|
||||
{
|
||||
token: 'text',
|
||||
regex: '.+?',
|
||||
|
@ -60,39 +67,58 @@ export class InputHighlightRules extends TextHighlightRules {
|
|||
]
|
||||
),
|
||||
method_sep: mergeTokens(
|
||||
// done
|
||||
addEOL(
|
||||
['whitespace', 'url.protocol_host', 'url.slash'],
|
||||
/(\s+)(https?:\/\/[^?\/,]+)(\/)/,
|
||||
'start',
|
||||
'url'
|
||||
),
|
||||
// done
|
||||
addEOL(['whitespace', 'variable.template'], /(\s+)(\${\w+})/, 'start', 'url'),
|
||||
// done
|
||||
addEOL(['whitespace', 'url.protocol_host'], /(\s+)(https?:\/\/[^?\/,]+)/, 'start', 'url'),
|
||||
// done
|
||||
addEOL(['whitespace', 'url.slash'], /(\s+)(\/)/, 'start', 'url'),
|
||||
// done
|
||||
addEOL(['whitespace'], /(\s+)/, 'start', 'url')
|
||||
),
|
||||
url: mergeTokens(
|
||||
// done
|
||||
addEOL(['variable.template'], /(\${\w+})/, 'start'),
|
||||
// TODO
|
||||
addEOL(['url.part'], /(_sql)/, 'start-sql', 'url-sql'),
|
||||
// done
|
||||
addEOL(['url.part'], /([^?\/,\s]+)/, 'start'),
|
||||
// done
|
||||
addEOL(['url.comma'], /(,)/, 'start'),
|
||||
// done
|
||||
addEOL(['url.slash'], /(\/)/, 'start'),
|
||||
// done
|
||||
addEOL(['url.questionmark'], /(\?)/, 'start', 'urlParams'),
|
||||
// done
|
||||
addEOL(['whitespace', 'comment.punctuation', 'comment.line'], /(\s+)(\/\/)(.*$)/, 'start')
|
||||
),
|
||||
urlParams: mergeTokens(
|
||||
// done
|
||||
addEOL(['url.param', 'url.equal', 'variable.template'], /([^&=]+)(=)(\${\w+})/, 'start'),
|
||||
// done
|
||||
addEOL(['url.param', 'url.equal', 'url.value'], /([^&=]+)(=)([^&]*)/, 'start'),
|
||||
// done
|
||||
addEOL(['url.param'], /([^&=]+)/, 'start'),
|
||||
// done
|
||||
addEOL(['url.amp'], /(&)/, 'start'),
|
||||
// done
|
||||
addEOL(['whitespace', 'comment.punctuation', 'comment.line'], /(\s+)(\/\/)(.*$)/, 'start')
|
||||
),
|
||||
// TODO
|
||||
'url-sql': mergeTokens(
|
||||
addEOL(['url.part'], /([^?\/,\s]+)/, 'start-sql'),
|
||||
addEOL(['url.comma'], /(,)/, 'start-sql'),
|
||||
addEOL(['url.slash'], /(\/)/, 'start-sql'),
|
||||
addEOL(['url.questionmark'], /(\?)/, 'start-sql', 'urlParams-sql')
|
||||
),
|
||||
// TODO
|
||||
'urlParams-sql': mergeTokens(
|
||||
addEOL(['url.param', 'url.equal', 'url.value'], /([^&=]+)(=)([^&]*)/, 'start-sql'),
|
||||
addEOL(['url.param'], /([^&=]+)/, 'start-sql'),
|
||||
|
@ -108,27 +134,32 @@ export class InputHighlightRules extends TextHighlightRules {
|
|||
comments: [
|
||||
{
|
||||
// Capture a line comment, indicated by #
|
||||
// done
|
||||
token: ['comment.punctuation', 'comment.line'],
|
||||
regex: /(#)(.*$)/,
|
||||
},
|
||||
{
|
||||
// Begin capturing a block comment, indicated by /*
|
||||
// done
|
||||
token: 'comment.punctuation',
|
||||
regex: /\/\*/,
|
||||
push: [
|
||||
{
|
||||
// Finish capturing a block comment, indicated by */
|
||||
// done
|
||||
token: 'comment.punctuation',
|
||||
regex: /\*\//,
|
||||
next: 'pop',
|
||||
},
|
||||
{
|
||||
// done
|
||||
defaultToken: 'comment.block',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
// Capture a line comment, indicated by //
|
||||
// done
|
||||
token: ['comment.punctuation', 'comment.line'],
|
||||
regex: /(\/\/)(.*$)/,
|
||||
},
|
||||
|
|
|
@ -16,6 +16,7 @@ import { mockManagementPlugin } from '../../mocks';
|
|||
import { createComponentWithContext } from '../test_utils';
|
||||
|
||||
jest.mock('@elastic/eui', () => ({
|
||||
...jest.requireActual('@elastic/eui'),
|
||||
EuiBasicTable: 'eui-basic-table',
|
||||
EuiButton: 'eui-button',
|
||||
EuiButtonEmpty: 'eui-button-empty',
|
||||
|
|
|
@ -11,6 +11,7 @@ import { shallow } from 'enzyme';
|
|||
import { SplitByTermsUI } from './terms';
|
||||
|
||||
jest.mock('@elastic/eui', () => ({
|
||||
...jest.requireActual('@elastic/eui'),
|
||||
htmlIdGenerator: jest.fn(() => () => '42'),
|
||||
EuiFlexGroup: jest.requireActual('@elastic/eui').EuiFlexGroup,
|
||||
EuiFlexItem: jest.requireActual('@elastic/eui').EuiFlexItem,
|
||||
|
|
|
@ -17,6 +17,7 @@ jest.mock('../../context/step_context');
|
|||
jest.mock('./content_wrapper');
|
||||
|
||||
jest.mock('@elastic/eui', () => ({
|
||||
...jest.requireActual('@elastic/eui'),
|
||||
EuiFlexGroup: ({ children, onClick }: EuiFlexGroupProps) => {
|
||||
return (
|
||||
// eslint-disable-next-line jsx-a11y/click-events-have-key-events
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue