0
0
mirror of https://github.com/PostHog/posthog.git synced 2024-11-21 13:39:22 +01:00

feat(hog): syntax highlighting for monaco (#23043)

This commit is contained in:
Marius Andra 2024-06-18 12:56:44 +02:00 committed by GitHub
parent 412dc78217
commit 5ec6d44b4c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 1153 additions and 27 deletions

View File

@ -1,8 +1,10 @@
import './CodeEditor.scss'
import MonacoEditor, { type EditorProps } from '@monaco-editor/react'
import MonacoEditor, { type EditorProps, Monaco } from '@monaco-editor/react'
import { useValues } from 'kea'
import { Spinner } from 'lib/lemon-ui/Spinner'
import * as hog from 'lib/monaco/hog'
import * as hogQL from 'lib/monaco/hogql'
import { inStorybookTestRunner } from 'lib/utils'
import { useEffect, useRef, useState } from 'react'
import AutoSizer from 'react-virtualized/dist/es/AutoSizer'
@ -11,9 +13,26 @@ import { themeLogic } from '~/layout/navigation-3000/themeLogic'
export type CodeEditorProps = Omit<EditorProps, 'loading' | 'theme'>
export function CodeEditor({ options, ...editorProps }: CodeEditorProps): JSX.Element {
const { isDarkModeOn } = useValues(themeLogic)
function registerHog(monaco: Monaco): void {
if (monaco.languages.getLanguages().some(({ id }) => id === 'hog')) {
return
}
monaco.languages.register({ id: 'hog', extensions: ['.hog'], mimetypes: ['application/hog'] })
monaco.languages.setLanguageConfiguration('hog', hog.conf)
monaco.languages.setMonarchTokensProvider('hog', hog.language)
}
function registerHogQL(monaco: Monaco): void {
if (monaco.languages.getLanguages().some(({ id }) => id === 'hogql')) {
return
}
monaco.languages.register({ id: 'hogql', extensions: ['.sql', '.hogql'], mimetypes: ['application/hog+ql'] })
monaco.languages.setLanguageConfiguration('hogql', hogQL.conf)
monaco.languages.setMonarchTokensProvider('hogql', hogQL.language)
}
export function CodeEditor({ options, onMount, ...editorProps }: CodeEditorProps): JSX.Element {
const { isDarkModeOn } = useValues(themeLogic)
const scrollbarRendering = !inStorybookTestRunner() ? 'auto' : 'hidden'
return (
@ -22,6 +41,12 @@ export function CodeEditor({ options, ...editorProps }: CodeEditorProps): JSX.El
loading={<Spinner />}
options={{
// :TRICKY: We need to declare all options here, as omitting something will carry its value from one <CodeEditor> to another.
minimap: {
enabled: false,
},
scrollBeyondLastLine: false,
automaticLayout: true,
fixedOverflowWidgets: true,
wordWrap: 'off',
lineNumbers: 'on',
...options,
@ -33,6 +58,17 @@ export function CodeEditor({ options, ...editorProps }: CodeEditorProps): JSX.El
},
}}
{...editorProps}
onMount={(editor, monaco) => {
if (editorProps?.language === 'hog') {
registerHog(monaco)
}
if (editorProps?.language === 'hogql') {
registerHogQL(monaco)
}
if (onMount) {
onMount(editor, monaco)
}
}}
/>
)
}

View File

@ -0,0 +1,245 @@
// eslint-disable-next-line eslint-comments/disable-enable-pair
/* eslint-disable no-useless-escape */
// Adapted from: https://raw.githubusercontent.com/microsoft/monaco-editor/main/src/basic-languages/typescript/typescript.ts
import { languages } from 'monaco-editor'
export const conf: languages.LanguageConfiguration = {
wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,
comments: {
lineComment: '//',
blockComment: ['/*', '*/'],
},
brackets: [
['{', '}'],
['[', ']'],
['(', ')'],
],
onEnterRules: [
{
// e.g. /** | */
beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,
afterText: /^\s*\*\/$/,
action: {
indentAction: languages.IndentAction.IndentOutdent,
appendText: ' * ',
},
},
{
// e.g. /** ...|
beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,
action: {
indentAction: languages.IndentAction.None,
appendText: ' * ',
},
},
{
// e.g. * ...|
beforeText: /^(\t|(\ \ ))*\ \*(\ ([^\*]|\*(?!\/))*)?$/,
action: {
indentAction: languages.IndentAction.None,
appendText: '* ',
},
},
{
// e.g. */|
beforeText: /^(\t|(\ \ ))*\ \*\/\s*$/,
action: {
indentAction: languages.IndentAction.None,
removeText: 1,
},
},
],
autoClosingPairs: [
{ open: '{', close: '}' },
{ open: '[', close: ']' },
{ open: '(', close: ')' },
{ open: '"', close: '"', notIn: ['string'] },
{ open: "'", close: "'", notIn: ['string', 'comment'] },
{ open: '`', close: '`', notIn: ['string', 'comment'] },
{ open: '/**', close: ' */', notIn: ['string'] },
],
folding: {
markers: {
start: new RegExp('^\\s*//\\s*#?region\\b'),
end: new RegExp('^\\s*//\\s*#?endregion\\b'),
},
},
}
export const language: languages.IMonarchLanguage = {
// Set defaultToken to invalid to see what you do not tokenize yet
defaultToken: 'invalid',
tokenPostfix: '.hog',
keywords: [
'fn',
'let',
'if',
'else',
'return',
'true',
'false',
'null',
'for',
'while',
'like',
'ilike',
'not',
'and',
'or',
'in',
],
operators: [
'<=',
'>=',
'==',
'!=',
'=>',
'+',
'-',
'**',
'*',
'/',
'%',
'<<',
'</',
'>>',
'>>>',
'&',
'|',
'^',
'!',
'~',
'||',
'??',
'?',
':',
'=',
':=',
'+=',
'-=',
'*=',
'*=~',
'!=',
'!=~',
],
// we include these common regular expressions
symbols: /[=><!~?:&|+\-*\/\^%]+/,
escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
digits: /\d+(_+\d+)*/,
// The main tokenizer for our languages
tokenizer: {
root: [[/[{}]/, 'delimiter.bracket'], { include: 'common' }],
common: [
// whitespace
{ include: '@whitespace' },
// delimiters and operators
[/[()\[\]]/, '@brackets'],
[/[<>](?!@symbols)/, '@brackets'],
[/!(?=([^=]|$))/, 'delimiter'],
[
/@symbols/,
{
cases: {
'@operators': 'delimiter',
'@default': '',
},
},
],
// numbers
[/(@digits)[eE]([\-+]?(@digits))?/, 'number.float'],
[/(@digits)\.(@digits)([eE][\-+]?(@digits))?/, 'number.float'],
[/(@digits)n?/, 'number'],
// delimiter: after number because of .\d floats
[/[;,.]/, 'delimiter'],
// strings that are actually fields, show as type.identifier to highlight
[/"([^"\\]|\\.)*$/, 'type.identifier.invalid'], // non-teminated type.identifier
[/'([^'\\]|\\.)*$/, 'type.identifier.invalid'], // non-teminated type.identifier
[/"/, 'type.identifier', '@string_double'],
[/`/, 'type.identifier', '@string_backtick'],
// strings
[/f'/, 'string', '@string_format'],
[/'/, 'string', '@string_single'],
// identifiers and keywords
[
/#?[a-z_$][\w$]*/,
{
cases: {
'@keywords': 'keyword',
'@default': 'identifier',
},
},
],
],
whitespace: [
[/[ \t\r\n]+/, ''],
[/\/\*\*(?!\/)/, 'comment.doc', '@jsdoc'],
[/\/\*/, 'comment', '@comment'],
[/\/\/.*$/, 'comment'],
[/--.*$/, 'comment'],
],
comment: [
[/[^\/*]+/, 'comment'],
[/\*\//, 'comment', '@pop'],
[/[\/*]/, 'comment'],
],
jsdoc: [
[/[^\/*]+/, 'comment.doc'],
[/\*\//, 'comment.doc', '@pop'],
[/[\/*]/, 'comment.doc'],
],
string_double: [
[/[^\\"]+/, 'type.identifier'],
[/@escapes/, 'type.identifier.escape'],
[/\\./, 'type.identifier.escape.invalid'],
[/"/, 'type.identifier', '@pop'],
],
string_backtick: [
[/[^\\`]+/, 'type.identifier'],
[/@escapes/, 'type.identifier.escape'],
[/\\./, 'type.identifier.escape.invalid'],
[/`/, 'type.identifier', '@pop'],
],
string_single: [
[/[^\\']+/, 'string'],
[/@escapes/, 'string.escape'],
[/\\./, 'string.escape.invalid'],
[/'/, 'string', '@pop'],
],
string_format: [
[/\{/, { token: 'delimiter.bracket', next: '@bracketCounting' }],
[/[^\\'{]+/, 'string'],
[/@escapes/, 'string.escape'],
[/\\./, 'string.escape.invalid'],
[/'/, 'string', '@pop'],
],
bracketCounting: [
[/\{/, 'delimiter.bracket', '@bracketCounting'],
[/\}/, 'delimiter.bracket', '@pop'],
{ include: 'common' },
],
},
}

View File

@ -0,0 +1,847 @@
// Adapted from https://raw.githubusercontent.com/microsoft/monaco-editor/main/src/basic-languages/mysql/mysql.ts
import { languages } from 'monaco-editor'
export const conf: languages.LanguageConfiguration = {
comments: {
lineComment: '--',
blockComment: ['/*', '*/'],
},
brackets: [
['{', '}'],
['[', ']'],
['(', ')'],
],
autoClosingPairs: [
{ open: '{', close: '}' },
{ open: '[', close: ']' },
{ open: '(', close: ')' },
{ open: '"', close: '"' },
{ open: "'", close: "'" },
],
surroundingPairs: [
{ open: '{', close: '}' },
{ open: '[', close: ']' },
{ open: '(', close: ')' },
{ open: '"', close: '"' },
{ open: "'", close: "'" },
],
}
export const language: languages.IMonarchLanguage = {
defaultToken: '',
tokenPostfix: '.sql',
ignoreCase: true,
brackets: [
{ open: '[', close: ']', token: 'delimiter.square' },
{ open: '(', close: ')', token: 'delimiter.parenthesis' },
],
keywords: [
'ALL',
'ANTI',
'ANY',
'ARRAY',
'AS',
'ASCENDING',
'ASOF',
'BOTH',
'BY',
'CASE',
'CAST',
'COHORT',
'COLLATE',
'CROSS',
'CUBE',
'CURRENT',
'DATE',
'DAY',
'DESC',
'DESCENDING',
'DISTINCT',
'ELSE',
'END',
'EXTRACT',
'FINAL',
'FIRST',
'FN',
'FOLLOWING',
'FOR',
'FROM',
'FULL',
'GROUP',
'HAVING',
'HOUR',
'ID',
'IF',
'INF',
'INTERVAL',
'KEY',
'LAST',
'LEADING',
'LET',
'LIMIT',
'MINUTE',
'MONTH',
'NAN_SQL',
'NULL_SQL',
'NULLS',
'OFFSET',
'ON',
'ORDER',
'OVER',
'PARTITION',
'PRECEDING',
'PREWHERE',
'QUARTER',
'RANGE',
'RETURN',
'ROLLUP',
'ROW',
'ROWS',
'SAMPLE',
'SECOND',
'SELECT',
'SEMI',
'SETTINGS',
'SUBSTRING',
'THEN',
'TIES',
'TO',
'TOP',
'TOTALS',
'TRAILING',
'TRIM',
'TRUNCATE',
'UNBOUNDED',
'USING',
'WEEK',
'WHEN',
'WHERE',
'WHILE',
'WINDOW',
'WITH',
'YEAR',
],
operators: [
'AND',
'BETWEEN',
'IN',
'LIKE',
'ILIKE',
'NOT',
'OR',
'IS',
'NULL',
'UNION',
'INNER',
'JOIN',
'LEFT',
'OUTER',
'RIGHT',
],
builtinFunctions: [
'plus',
'minus',
'multiply',
'divide',
'intDiv',
'intDivOrZero',
'modulo',
'moduloOrZero',
'positiveModulo',
'negate',
'abs',
'gcd',
'lcm',
'max2',
'min2',
'multiplyDecimal',
'divideDecimal',
'empty',
'notEmpty',
'length',
'reverse',
'array',
'range',
'arrayConcat',
'arrayElement',
'has',
'hasAll',
'hasAny',
'hasSubstr',
'indexOf',
'arrayCount',
'countEqual',
'arrayEnumerate',
'arrayEnumerateUniq',
'arrayPopBack',
'arrayPopFront',
'arrayPushBack',
'arrayPushFront',
'arrayResize',
'arraySlice',
'arraySort',
'arrayReverseSort',
'arrayUniq',
'arrayJoin',
'arrayDifference',
'arrayDistinct',
'arrayEnumerateDense',
'arrayIntersect',
'arrayReverse',
'arrayFilter',
'arrayFlatten',
'arrayCompact',
'arrayZip',
'arrayAUC',
'arrayMap',
'arrayFill',
'arraySplit',
'arrayReverseFill',
'arrayReverseSplit',
'arrayExists',
'arrayAll',
'arrayFirst',
'arrayLast',
'arrayFirstIndex',
'arrayLastIndex',
'arrayMin',
'arrayMax',
'arraySum',
'arrayAvg',
'arrayCumSum',
'arrayCumSumNonNegative',
'arrayProduct',
'equals',
'notEquals',
'less',
'greater',
'lessOrEquals',
'greaterOrEquals',
'and',
'or',
'xor',
'not',
'hex',
'unhex',
'reinterpretAsUInt8',
'reinterpretAsUInt16',
'reinterpretAsUInt32',
'reinterpretAsUInt64',
'reinterpretAsUInt128',
'reinterpretAsUInt256',
'reinterpretAsInt8',
'reinterpretAsInt16',
'reinterpretAsInt32',
'reinterpretAsInt64',
'reinterpretAsInt128',
'reinterpretAsInt256',
'reinterpretAsFloat32',
'reinterpretAsFloat64',
'toInt',
'_toInt64',
'toFloat',
'toDecimal',
'toDate',
'toDateTime',
'toUUID',
'toString',
'toJSONString',
'parseDateTime',
'parseDateTimeBestEffort',
'toTypeName',
'toTimeZone',
'timeZoneOf',
'timeZoneOffset',
'toYear',
'toQuarter',
'toMonth',
'toDayOfYear',
'toDayOfMonth',
'toDayOfWeek',
'toHour',
'toMinute',
'toSecond',
'toUnixTimestamp',
'toUnixTimestamp64Milli',
'toStartOfYear',
'toStartOfISOYear',
'toStartOfQuarter',
'toStartOfMonth',
'toLastDayOfMonth',
'toMonday',
'toStartOfWeek',
'toStartOfDay',
'toLastDayOfWeek',
'toStartOfHour',
'toStartOfMinute',
'toStartOfSecond',
'toStartOfFiveMinutes',
'toStartOfTenMinutes',
'toStartOfFifteenMinutes',
'toTime',
'toISOYear',
'toISOWeek',
'toWeek',
'toYearWeek',
'age',
'dateDiff',
'dateTrunc',
'dateAdd',
'dateSub',
'timeStampAdd',
'timeStampSub',
'now',
'nowInBlock',
'rowNumberInAllBlocks',
'today',
'yesterday',
'timeSlot',
'toYYYYMM',
'toYYYYMMDD',
'toYYYYMMDDhhmmss',
'addYears',
'addMonths',
'addWeeks',
'addDays',
'addHours',
'addMinutes',
'addSeconds',
'addQuarters',
'subtractYears',
'subtractMonths',
'subtractWeeks',
'subtractDays',
'subtractHours',
'subtractMinutes',
'subtractSeconds',
'subtractQuarters',
'timeSlots',
'formatDateTime',
'dateName',
'monthName',
'fromUnixTimestamp',
'toModifiedJulianDay',
'fromModifiedJulianDay',
'toIntervalSecond',
'toIntervalMinute',
'toIntervalHour',
'toIntervalDay',
'toIntervalWeek',
'toIntervalMonth',
'toIntervalQuarter',
'toIntervalYear',
'left',
'right',
'lengthUTF8',
'leftPad',
'rightPad',
'leftPadUTF8',
'rightPadUTF8',
'lower',
'upper',
'lowerUTF8',
'upperUTF8',
'isValidUTF8',
'toValidUTF8',
'repeat',
'format',
'reverseUTF8',
'concat',
'substring',
'substringUTF8',
'appendTrailingCharIfAbsent',
'convertCharset',
'base58Encode',
'base58Decode',
'tryBase58Decode',
'base64Encode',
'base64Decode',
'tryBase64Decode',
'endsWith',
'startsWith',
'trim',
'trimLeft',
'trimRight',
'encodeXMLComponent',
'decodeXMLComponent',
'extractTextFromHTML',
'ascii',
'concatWithSeparator',
'position',
'positionCaseInsensitive',
'positionUTF8',
'positionCaseInsensitiveUTF8',
'multiSearchAllPositions',
'multiSearchAllPositionsUTF8',
'multiSearchFirstPosition',
'multiSearchFirstIndex',
'multiSearchAny',
'match',
'multiMatchAny',
'multiMatchAnyIndex',
'multiMatchAllIndices',
'multiFuzzyMatchAny',
'multiFuzzyMatchAnyIndex',
'multiFuzzyMatchAllIndices',
'extract',
'extractAll',
'extractAllGroupsHorizontal',
'extractAllGroupsVertical',
'like',
'ilike',
'notLike',
'notILike',
'ngramDistance',
'ngramSearch',
'countSubstrings',
'countSubstringsCaseInsensitive',
'countSubstringsCaseInsensitiveUTF8',
'countMatches',
'regexpExtract',
'replace',
'replaceAll',
'replaceOne',
'replaceRegexpAll',
'replaceRegexpOne',
'regexpQuoteMeta',
'translate',
'translateUTF8',
'if',
'multiIf',
'e',
'pi',
'exp',
'log',
'ln',
'exp2',
'log2',
'exp10',
'log10',
'sqrt',
'cbrt',
'erf',
'erfc',
'lgamma',
'tgamma',
'sin',
'cos',
'tan',
'asin',
'acos',
'atan',
'pow',
'power',
'intExp2',
'intExp10',
'cosh',
'acosh',
'sinh',
'asinh',
'atanh',
'atan2',
'hypot',
'log1p',
'sign',
'degrees',
'radians',
'factorial',
'width_bucket',
'floor',
'ceil',
'trunc',
'round',
'roundBankers',
'roundToExp2',
'roundDuration',
'roundAge',
'roundDown',
'map',
'mapFromArrays',
'mapAdd',
'mapSubtract',
'mapPopulateSeries',
'mapContains',
'mapKeys',
'mapValues',
'mapContainsKeyLike',
'mapExtractKeyLike',
'mapApply',
'mapFilter',
'mapUpdate',
'splitByChar',
'splitByString',
'splitByRegexp',
'splitByWhitespace',
'splitByNonAlpha',
'arrayStringConcat',
'alphaTokens',
'extractAllGroups',
'ngrams',
'tokens',
'bitAnd',
'bitOr',
'bitXor',
'bitNot',
'bitShiftLeft',
'bitShiftRight',
'bitRotateLeft',
'bitRotateRight',
'bitSlice',
'bitTest',
'bitTestAll',
'bitTestAny',
'bitCount',
'bitHammingDistance',
'bitmapBuild',
'bitmapToArray',
'bitmapSubsetInRange',
'bitmapSubsetLimit',
'subBitmap',
'bitmapContains',
'bitmapHasAny',
'bitmapHasAll',
'bitmapCardinality',
'bitmapMin',
'bitmapMax',
'bitmapTransform',
'bitmapAnd',
'bitmapOr',
'bitmapXor',
'bitmapAndnot',
'bitmapAndCardinality',
'bitmapOrCardinality',
'bitmapXorCardinality',
'bitmapAndnotCardinality',
'protocol',
'domain',
'domainWithoutWWW',
'topLevelDomain',
'firstSignificantSubdomain',
'cutToFirstSignificantSubdomain',
'cutToFirstSignificantSubdomainWithWWW',
'port',
'path',
'pathFull',
'queryString',
'fragment',
'queryStringAndFragment',
'extractURLParameter',
'extractURLParameters',
'extractURLParameterNames',
'URLHierarchy',
'URLPathHierarchy',
'encodeURLComponent',
'decodeURLComponent',
'encodeURLFormComponent',
'decodeURLFormComponent',
'netloc',
'cutWWW',
'cutQueryString',
'cutFragment',
'cutQueryStringAndFragment',
'cutURLParameter',
'isValidJSON',
'JSONHas',
'JSONLength',
'JSONArrayLength',
'JSONType',
'JSONExtractUInt',
'JSONExtractInt',
'JSONExtractFloat',
'JSONExtractBool',
'JSONExtractString',
'JSONExtractKey',
'JSONExtractKeys',
'JSONExtractRaw',
'JSONExtractArrayRaw',
'JSONExtractKeysAndValues',
'JSONExtractKeysAndValuesRaw',
'in',
'notIn',
'greatCircleDistance',
'geoDistance',
'greatCircleAngle',
'pointInEllipses',
'pointInPolygon',
'geohashEncode',
'geohashDecode',
'geohashesInBox',
'isnull',
'isNotNull',
'coalesce',
'ifnull',
'nullif',
'assumeNotNull',
'toNullable',
'tuple',
'tupleElement',
'untuple',
'tupleHammingDistance',
'tupleToNameValuePairs',
'tuplePlus',
'tupleMinus',
'tupleMultiply',
'tupleDivide',
'tupleNegate',
'tupleMultiplyByNumber',
'tupleDivideByNumber',
'dotProduct',
'isFinite',
'isInfinite',
'ifNotFinite',
'isNaN',
'bar',
'transform',
'formatReadableDecimalSize',
'formatReadableSize',
'formatReadableQuantity',
'formatReadableTimeDelta',
'least',
'greatest',
'tumble',
'hop',
'tumbleStart',
'tumbleEnd',
'hopStart',
'hopEnd',
'L1Norm',
'L2Norm',
'LinfNorm',
'LpNorm',
'L1Distance',
'L2Distance',
'LinfDistance',
'LpDistance',
'L1Normalize',
'L2Normalize',
'LinfNormalize',
'LpNormalize',
'cosineDistance',
'rank',
'dense_rank',
'row_number',
'first_value',
'last_value',
'nth_value',
'lagInFrame',
'leadInFrame',
'equals',
'notEquals',
'less',
'greater',
'lessOrEquals',
'greaterOrEquals',
'like',
'ilike',
'notLike',
'notILike',
'in',
'notIn',
'count',
'countIf',
'countDistinctIf',
'min',
'minIf',
'max',
'maxIf',
'sum',
'sumIf',
'avg',
'avgIf',
'any',
'anyIf',
'stddevPop',
'stddevPopIf',
'stddevSamp',
'stddevSampIf',
'varPop',
'varPopIf',
'varSamp',
'varSampIf',
'covarPop',
'covarPopIf',
'covarSamp',
'covarSampIf',
'corr',
'anyHeavy',
'anyHeavyIf',
'anyLast',
'anyLastIf',
'argMin',
'argMinIf',
'argMax',
'argMaxIf',
'argMinMerge',
'argMaxMerge',
'avgState',
'avgMerge',
'avgWeighted',
'avgWeightedIf',
'avgArray',
'groupArray',
'groupUniqArray',
'groupUniqArrayIf',
'groupArrayInsertAt',
'groupArrayInsertAtIf',
'groupArrayMovingAvg',
'groupArrayMovingAvgIf',
'groupArrayMovingSum',
'groupArrayMovingSumIf',
'groupBitAnd',
'groupBitAndIf',
'groupBitOr',
'groupBitOrIf',
'groupBitXor',
'groupBitXorIf',
'groupBitmap',
'groupBitmapIf',
'groupBitmapAnd',
'groupBitmapAndIf',
'groupBitmapOr',
'groupBitmapOrIf',
'groupBitmapXor',
'groupBitmapXorIf',
'sumWithOverflow',
'sumWithOverflowIf',
'deltaSum',
'deltaSumIf',
'deltaSumTimestamp',
'deltaSumTimestampIf',
'sumMap',
'sumMapIf',
'sumMapMerge',
'minMap',
'minMapIf',
'maxMap',
'maxMapIf',
'medianArray',
'skewSamp',
'skewSampIf',
'skewPop',
'skewPopIf',
'kurtSamp',
'kurtSampIf',
'kurtPop',
'kurtPopIf',
'uniq',
'uniqIf',
'uniqExact',
'uniqExactIf',
'uniqHLL12',
'uniqHLL12If',
'uniqTheta',
'uniqThetaIf',
'median',
'medianIf',
'medianExact',
'medianExactIf',
'medianExactLow',
'medianExactLowIf',
'medianExactHigh',
'medianExactHighIf',
'medianExactWeighted',
'medianExactWeightedIf',
'medianTiming',
'medianTimingIf',
'medianTimingWeighted',
'medianTimingWeightedIf',
'medianDeterministic',
'medianDeterministicIf',
'medianTDigest',
'medianTDigestIf',
'medianTDigestWeighted',
'medianTDigestWeightedIf',
'medianBFloat16',
'medianBFloat16If',
'quantile',
'quantileIf',
'quantiles',
'quantilesIf',
'simpleLinearRegression',
'simpleLinearRegressionIf',
'contingency',
'contingencyIf',
'cramersV',
'cramersVIf',
'cramersVBiasCorrected',
'cramersVBiasCorrectedIf',
'theilsU',
'theilsUIf',
'maxIntersections',
'maxIntersectionsIf',
'maxIntersectionsPosition',
'maxIntersectionsPositionIf',
],
builtinVariables: [],
tokenizer: {
root: [
{ include: '@comments' },
{ include: '@whitespace' },
{ include: '@numbers' },
{ include: '@strings' },
{ include: '@complexIdentifiers' },
{ include: '@scopes' },
[/[;,.]/, 'delimiter'],
[/[()]/, '@brackets'],
[
/[\w@]+/,
{
cases: {
'@operators': 'operator',
'@builtinVariables': 'predefined',
'@builtinFunctions': 'predefined',
'@keywords': 'keyword',
'@default': 'identifier',
},
},
],
[/[<>=!%&+\-*/|~^]/, 'operator'],
],
whitespace: [[/\s+/, 'white']],
comments: [
[/--+.*/, 'comment'],
[/#+.*/, 'comment'],
[/\/\*/, { token: 'comment.quote', next: '@comment' }],
],
comment: [
[/[^*/]+/, 'comment'],
// Not supporting nested comments, as nested comments seem to not be standard?
// i.e. http://stackoverflow.com/questions/728172/are-there-multiline-comment-delimiters-in-sql-that-are-vendor-agnostic
// [/\/\*/, { token: 'comment.quote', next: '@push' }], // nested comment not allowed :-(
[/\*\//, { token: 'comment.quote', next: '@pop' }],
[/./, 'comment'],
],
numbers: [
[/0[xX][0-9a-fA-F]*/, 'number'],
[/[$][+-]*\d*(\.\d*)?/, 'number'],
[/((\d+(\.\d*)?)|(\.\d+))([eE][-+]?\d+)?/, 'number'],
],
strings: [
[/'/, { token: 'string', next: '@string' }],
[/"/, { token: 'string.double', next: '@stringDouble' }],
],
string: [
[/\\'/, 'string'],
[/[^']+/, 'string'],
[/''/, 'string'],
[/'/, { token: 'string', next: '@pop' }],
],
stringDouble: [
[/[^"]+/, 'string.double'],
[/""/, 'string.double'],
[/"/, { token: 'string.double', next: '@pop' }],
],
complexIdentifiers: [[/`/, { token: 'identifier.quote', next: '@quotedIdentifier' }]],
quotedIdentifier: [
[/[^`]+/, 'identifier'],
[/``/, 'identifier'],
[/`/, { token: 'identifier.quote', next: '@pop' }],
],
scopes: [
// NOT SUPPORTED
],
},
}

View File

@ -223,7 +223,7 @@ export function HogQLQueryEditor(props: HogQLQueryEditorProps): JSX.Element {
<div ref={editorRef} className="resize-y overflow-hidden" style={{ height: EDITOR_HEIGHT }}>
<CodeEditor
className="border rounded overflow-hidden h-full"
language="mysql"
language="hogql"
value={queryInput}
onChange={(v) => setQueryInput(v ?? '')}
height="100%"

View File

@ -44,7 +44,7 @@ export function HogQueryEditor(props: HogQueryEditorProps): JSX.Element {
<div className="resize-y overflow-hidden" style={{ height: 222 }}>
<CodeEditor
className="border rounded overflow-hidden h-full"
language="rust"
language="hog"
value={queryInput}
onChange={(v) => setQueryInput(v ?? '')}
height="100%"

View File

@ -309,7 +309,7 @@ export function PipelineHogFunctionConfiguration({
</LemonButton>
</div>
<CodeEditorResizeable
language="rust"
language="hog"
value={value ?? ''}
onChange={(v) => onChange(v ?? '')}
options={{

View File

@ -75,7 +75,7 @@
"@lottiefiles/react-lottie-player": "^3.4.7",
"@medv/finder": "^3.1.0",
"@microlink/react-json-view": "^1.21.3",
"@monaco-editor/react": "4.4.6",
"@monaco-editor/react": "4.6.0",
"@posthog/icons": "0.7.0",
"@posthog/plugin-scaffold": "^1.4.4",
"@react-hook/size": "^2.1.2",
@ -140,7 +140,7 @@
"kea-window-values": "^3.0.0",
"maplibre-gl": "^3.5.1",
"md5": "^2.3.0",
"monaco-editor": "^0.39.0",
"monaco-editor": "^0.49.0",
"natural-orderby": "^3.0.2",
"papaparse": "^5.4.1",
"pmtiles": "^2.11.0",

View File

@ -47,8 +47,8 @@ dependencies:
specifier: ^1.21.3
version: 1.22.2(@types/react@17.0.52)(react-dom@18.2.0)(react@18.2.0)
'@monaco-editor/react':
specifier: 4.4.6
version: 4.4.6(monaco-editor@0.39.0)(react-dom@18.2.0)(react@18.2.0)
specifier: 4.6.0
version: 4.6.0(monaco-editor@0.49.0)(react-dom@18.2.0)(react@18.2.0)
'@posthog/icons':
specifier: 0.7.0
version: 0.7.0(react-dom@18.2.0)(react@18.2.0)
@ -242,8 +242,8 @@ dependencies:
specifier: ^2.3.0
version: 2.3.0
monaco-editor:
specifier: ^0.39.0
version: 0.39.0
specifier: ^0.49.0
version: 0.49.0
natural-orderby:
specifier: ^3.0.2
version: 3.0.2
@ -353,7 +353,7 @@ dependencies:
optionalDependencies:
fsevents:
specifier: ^2.3.2
version: 2.3.3
version: 2.3.2
devDependencies:
'@babel/core':
@ -634,7 +634,7 @@ devDependencies:
version: 3.0.5
monaco-editor-webpack-plugin:
specifier: ^7.0.1
version: 7.0.1(monaco-editor@0.39.0)(webpack@5.88.2)
version: 7.0.1(monaco-editor@0.49.0)(webpack@5.88.2)
msw:
specifier: ^0.49.0
version: 0.49.0(typescript@4.9.5)
@ -5250,25 +5250,24 @@ packages:
- encoding
dev: false
/@monaco-editor/loader@1.3.3(monaco-editor@0.39.0):
resolution: {integrity: sha512-6KKF4CTzcJiS8BJwtxtfyYt9shBiEv32ateQ9T4UVogwn4HM/uPo9iJd2Dmbkpz8CM6Y0PDUpjnZzCwC+eYo2Q==}
/@monaco-editor/loader@1.4.0(monaco-editor@0.49.0):
resolution: {integrity: sha512-00ioBig0x642hytVspPl7DbQyaSWRaolYie/UFNjoTdvoKPzo6xrXLhTk9ixgIKcLH5b5vDOjVNiGyY+uDCUlg==}
peerDependencies:
monaco-editor: '>= 0.21.0 < 1'
dependencies:
monaco-editor: 0.39.0
monaco-editor: 0.49.0
state-local: 1.0.7
dev: false
/@monaco-editor/react@4.4.6(monaco-editor@0.39.0)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-Gr3uz3LYf33wlFE3eRnta4RxP5FSNxiIV9ENn2D2/rN8KgGAD8ecvcITRtsbbyuOuNkwbuHYxfeaz2Vr+CtyFA==}
/@monaco-editor/react@4.6.0(monaco-editor@0.49.0)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-RFkU9/i7cN2bsq/iTkurMWOEErmYcY6JiQI3Jn+WeR/FGISH8JbHERjpS9oRuSOPvDMJI0Z8nJeKkbOs9sBYQw==}
peerDependencies:
monaco-editor: '>= 0.25.0 < 1'
react: ^16.8.0 || ^17.0.0 || ^18.0.0
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
dependencies:
'@monaco-editor/loader': 1.3.3(monaco-editor@0.39.0)
monaco-editor: 0.39.0
prop-types: 15.8.1
'@monaco-editor/loader': 1.4.0(monaco-editor@0.49.0)
monaco-editor: 0.49.0
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
dev: false
@ -13079,7 +13078,6 @@ packages:
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
os: [darwin]
requiresBuild: true
dev: true
optional: true
/fsevents@2.3.3:
@ -16066,19 +16064,19 @@ packages:
/moment@2.29.4:
resolution: {integrity: sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==}
/monaco-editor-webpack-plugin@7.0.1(monaco-editor@0.39.0)(webpack@5.88.2):
/monaco-editor-webpack-plugin@7.0.1(monaco-editor@0.49.0)(webpack@5.88.2):
resolution: {integrity: sha512-M8qIqizltrPlIbrb73cZdTWfU9sIsUVFvAZkL3KGjAHmVWEJ0hZKa/uad14JuOckc0GwnCaoGHvMoYtJjVyCzw==}
peerDependencies:
monaco-editor: '>= 0.31.0'
webpack: ^4.5.0 || 5.x
dependencies:
loader-utils: 2.0.4
monaco-editor: 0.39.0
monaco-editor: 0.49.0
webpack: 5.88.2(@swc/core@1.3.93)(esbuild@0.19.8)(webpack-cli@5.1.4)
dev: true
/monaco-editor@0.39.0:
resolution: {integrity: sha512-zhbZ2Nx93tLR8aJmL2zI1mhJpsl87HMebNBM6R8z4pLfs8pj604pIVIVwyF1TivcfNtIPpMXL+nb3DsBmE/x6Q==}
/monaco-editor@0.49.0:
resolution: {integrity: sha512-2I8/T3X/hLxB2oPHgqcNYUVdA/ZEFShT7IAujifIPMfKkNbLOqY8XCoyHCXrsdjb36dW9MwoTwBCFpXKMwNwaQ==}
/moo-color@1.0.3:
resolution: {integrity: sha512-i/+ZKXMDf6aqYtBhuOcej71YSlbjT3wCO/4H1j8rPvxDJEifdwgg5MaFyu6iYAT8GBZJg2z0dkgK4YMzvURALQ==}