From d05b88c230a7ce4e1db0612896e118dd20fbb9bf Mon Sep 17 00:00:00 2001 From: astandrik Date: Mon, 23 Dec 2024 15:17:57 +0300 Subject: [PATCH] fix: better syntax --- .../SqlHighlighter/SqlHighlighter.tsx | 36 +--- src/components/SqlHighlighter/keywords.ts | 13 ++ src/components/SqlHighlighter/yql.ts | 159 ++++++++++++++++++ 3 files changed, 176 insertions(+), 32 deletions(-) create mode 100644 src/components/SqlHighlighter/keywords.ts create mode 100644 src/components/SqlHighlighter/yql.ts diff --git a/src/components/SqlHighlighter/SqlHighlighter.tsx b/src/components/SqlHighlighter/SqlHighlighter.tsx index 62024f021..e3705d5db 100644 --- a/src/components/SqlHighlighter/SqlHighlighter.tsx +++ b/src/components/SqlHighlighter/SqlHighlighter.tsx @@ -1,41 +1,13 @@ import {useThemeValue} from '@gravity-ui/uikit'; import {PrismLight as SyntaxHighlighter} from 'react-syntax-highlighter'; -import plsql from 'react-syntax-highlighter/dist/esm/languages/prism/plsql'; -import { - vscDarkPlus as darkTheme, - materialLight as lightTheme, -} from 'react-syntax-highlighter/dist/esm/styles/prism'; - -// Create custom themes with transparent backgrounds -const light = { - ...lightTheme, - 'pre[class*="language-"]': { - ...lightTheme['pre[class*="language-"]'], - background: 'transparent', - }, - 'code[class*="language-"]': { - ...lightTheme['code[class*="language-"]'], - background: 'transparent', - }, -}; - -const dark = { - ...darkTheme, - 'pre[class*="language-"]': { - ...darkTheme['pre[class*="language-"]'], - background: 'transparent', - }, - 'code[class*="language-"]': { - ...darkTheme['code[class*="language-"]'], - background: 'transparent', - }, -}; import {cn} from '../../utils/cn'; +import {dark, light, yql} from './yql'; + import './SqlHighlighter.scss'; -SyntaxHighlighter.registerLanguage('plsql', plsql); +SyntaxHighlighter.registerLanguage('yql', yql); const b = cn('sql-highlighter'); @@ -50,7 +22,7 @@ export const SqlHighlighter = ({children, className}: SqlHighlighterProps) => { return (
- + {children}
diff --git a/src/components/SqlHighlighter/keywords.ts b/src/components/SqlHighlighter/keywords.ts new file mode 100644 index 000000000..b20bc2da0 --- /dev/null +++ b/src/components/SqlHighlighter/keywords.ts @@ -0,0 +1,13 @@ +export const keywords = + '$row|$rows|action|add|all|alter|and|any|as|asc|assume|async|bigserial|serial|smallserial|serial8|serial4|serial2|begin|bernoulli|between|by|case|changefeed|column|columns|commit|compact|create|cross|cube|declare|define|delete|desc|dict|discard|distinct|do|drop|else|empty_action|end|erase|evaluate|exclusion|exists|export|family|flatten|for|from|full|global|group|grouping|having|if|ignore|ilike|import|in|index|inner|insert|into|is|join|key|left|like|limit|list|match|not|null|nulls|offset|on|only|optional|or|order|over|partition|pragma|presort|primary|process|reduce|regexp|repeatable|replace|respect|result|return|right|rlike|rollup|sample|schema|select|semi|set|sets|stream|subquery|sync|table|tablesample|then|truncate|union|intersect|except|update|upsert|use|using|values|view|when|where|window|with|without|xor|callable|resource|tagged|generic|unit|void|emptylist|emptydict|flow|callable|resource|tagged|generic|unit|void|emptylist|emptydict|flow'.split( + '|', + ); +export const typeKeywords = + 'bool|date|datetime|decimal|double|float|int16|int32|int64|int8|interval|json|jsondocument|string|timestamp|tzdate|tzdatetime|tztimestamp|uint16|uint32|uint64|uint8|utf8|uuid|yson|text|bytes'.split( + '|', + ); + +export const builtinFunctions = + 'abs|aggregate_by|aggregate_list|aggregate_list_distinct|agg_list|agg_list_distinct|as_table|avg|avg_if|adaptivedistancehistogram|adaptivewardhistogram|adaptiveweighthistogram|addmember|addtimezone|aggregateflatten|aggregatetransforminput|aggregatetransformoutput|aggregationfactory|asatom|asdict|asdictstrict|asenum|aslist|asliststrict|asset|assetstrict|asstruct|astagged|astuple|asvariant|atomcode|bitcast|bit_and|bit_or|bit_xor|bool_and|bool_or|bool_xor|bottom|bottom_by|blockwardhistogram|blockweighthistogram|cast|coalesce|concat|concat_strict|correlation|count|count_if|covariance|covariance_population|covariance_sample|callableargument|callableargumenttype|callableresulttype|callabletype|callabletypecomponents|callabletypehandle|choosemembers|combinemembers|countdistinctestimate|currentauthenticateduser|currentoperationid|currentoperationsharedid|currenttzdate|currenttzdatetime|currenttztimestamp|currentutcdate|currentutcdatetime|currentutctimestamp|dense_rank|datatype|datatypecomponents|datatypehandle|dictaggregate|dictcontains|dictcreate|dicthasitems|dictitems|dictkeytype|dictkeys|dictlength|dictlookup|dictpayloadtype|dictpayloads|dicttype|dicttypecomponents|dicttypehandle|each|each_strict|emptydicttype|emptydicttypehandle|emptylisttype|emptylisttypehandle|endswith|ensure|ensureconvertibleto|ensuretype|enum|evaluateatom|evaluatecode|evaluateexpr|evaluatetype|expandstruct|filter|filter_strict|find|first_value|folder|filecontent|filepath|flattenmembers|forceremovemember|forceremovemembers|forcerenamemembers|forcespreadmembers|formatcode|formattype|frombytes|frompg|funccode|greatest|grouping|gathermembers|generictype|histogram|hll|hoppingwindowpgcast|hyperloglog|if|if_strict|instanceof|json_exists|json_query|json_value|jointablerow|just|lag|last_value|lead|least|len|length|like|likely|like_strict|lambdaargumentscount|lambdacode|lambdaoptionalargumentscount|linearhistogram|listaggregate|listall|listany|listavg|listcode|listcollect|listconcat|listcreate|listdistinct|listenumerate|listextend|listextendstrict|listextract|listfilter|listflatmap|listflatten|listfold|listfold1|listfold1map|listfoldmap|listfromrange|listfromtuple|listhas|listhasitems|listhead|listindexof|listitemtype|listlast|listlength|listmap|listmax|listmin|listnotnull|listreplicate|listreverse|listskip|listskipwhile|listskipwhileinclusive|listsort|listsortasc|listsortdesc|listsum|listtake|listtakewhile|listtakewhileinclusive|listtop|listtopsort|listtopasc|listtopdesc|listtopsortasc|listtopsortdesc|listtotuple|listtype|listtypehandle|listunionall|listuniq|listzip|listzipall|loghistogram|logarithmichistogram|max|max_by|max_of|median|min|min_by|min_of|mode|multi_aggregate_by|nanvl|nvl|nothing|nulltype|nulltypehandle|optionalitemtype|optionaltype|optionaltypehandle|percentile|parsefile|parsetype|parsetypehandle|pgand|pgarray|pgcall|pgconst|pgnot|pgop|pgor|pickle|quotecode|range|range_strict|rank|regexp|regexp_strict|rfind|row_number|random|randomnumber|randomuuid|removemember|removemembers|removetimezone|renamemembers|replacemember|reprcode|resourcetype|resourcetypehandle|resourcetypetag|some|stddev|stddev_population|stddev_sample|substring|sum|sum_if|sessionstart|sessionwindow|setcreate|setdifference|setincludes|setintersection|setisdisjoint|setsymmetricdifference|setunion|spreadmembers|stablepickle|startswith|staticmap|staticzip|streamitemtype|streamtype|streamtypehandle|structmembertype|structmembers|structtypecomponents|structtypehandle|subqueryextend|subqueryextendfor|subquerymerge|subquerymergefor|subqueryunionall|subqueryunionallfor|subqueryunionmerge|subqueryunionmergefor|top|topfreq|top_by|tablename|tablepath|tablerecordindex|tablerow|tablerows|taggedtype|taggedtypecomponents|taggedtypehandle|tobytes|todict|tomultidict|topg|toset|tosorteddict|tosortedmultidict|trymember|tupleelementtype|tupletype|tupletypecomponents|tupletypehandle|typehandle|typekind|typeof|udaf|udf|unittype|unpickle|untag|unwrap|variance|variance_population|variance_sample|variant|varianttype|varianttypehandle|variantunderlyingtype|voidtype|voidtypehandle|way|worldcode|weakfield'.split( + '|', + ); diff --git a/src/components/SqlHighlighter/yql.ts b/src/components/SqlHighlighter/yql.ts new file mode 100644 index 000000000..93bbb0789 --- /dev/null +++ b/src/components/SqlHighlighter/yql.ts @@ -0,0 +1,159 @@ +import { + vscDarkPlus as darkTheme, + materialLight as lightTheme, +} from 'react-syntax-highlighter/dist/esm/styles/prism'; + +import {builtinFunctions, keywords, typeKeywords} from './keywords'; + +export const light = { + ...lightTheme, + 'pre[class*="language-"]': { + ...lightTheme['pre[class*="language-"]'], + background: 'transparent', + }, + 'code[class*="language-"]': { + ...lightTheme['code[class*="language-"]'], + background: 'transparent', + }, + comment: { + color: '#969896', + }, + string: { + color: '#a31515', + }, + tablepath: { + color: '#338186', + }, + function: { + color: '#7a3e9d', + }, + udf: { + color: '#7a3e9d', + }, + type: { + color: '#4d932d', + }, + boolean: { + color: '#608b4e', + }, + constant: { + color: '#608b4e', + }, + variable: { + color: '#001188', + }, +}; + +export const dark = { + ...darkTheme, + 'pre[class*="language-"]': { + ...darkTheme['pre[class*="language-"]'], + background: 'transparent', + }, + 'code[class*="language-"]': { + ...darkTheme['code[class*="language-"]'], + background: 'transparent', + }, + comment: { + color: '#969896', + }, + string: { + color: '#ce9178', + }, + tablepath: { + color: '#338186', + }, + function: { + color: '#9e7bb0', + }, + udf: { + color: '#9e7bb0', + }, + type: { + color: '#6A8759', + }, + boolean: { + color: '#608b4e', + }, + constant: { + color: '#608b4e', + }, + variable: { + color: '#74b0df', + }, +}; + +export function yql(Prism: any) { + // Define YQL language + Prism.languages.yql = { + comment: [ + { + pattern: /--.*$/m, + greedy: true, + }, + { + pattern: /\/\*[\s\S]*?(?:\*\/|$)/, + greedy: true, + }, + ], + tablepath: { + pattern: /(`[\w/]+`\s*\.\s*)?`[^`]+`/, + greedy: true, + }, + string: [ + { + pattern: /'(?:\\[\s\S]|[^\\'])*'/, + greedy: true, + }, + { + pattern: /"(?:\\[\s\S]|[^\\"])*"/, + greedy: true, + }, + { + pattern: /@@(?:[^@]|@(?!@))*@@/, + greedy: true, + }, + ], + variable: [ + { + pattern: /\$[a-zA-Z_]\w*/, + greedy: true, + }, + ], + function: { + pattern: new RegExp(`\\b(?:${builtinFunctions.join('|')})\\b`, 'i'), + greedy: true, + }, + keyword: { + pattern: new RegExp(`\\b(?:${keywords.join('|')})\\b`, 'i'), + greedy: true, + }, + udf: { + pattern: /[A-Za-z_]\w*::[A-Za-z_]\w*/, + greedy: true, + }, + type: { + pattern: new RegExp(`\\b(?:${typeKeywords.join('|')})\\b`, 'i'), + greedy: true, + }, + boolean: { + pattern: /\b(?:true|false|null)\b/i, + greedy: true, + }, + number: { + pattern: /[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?/i, + greedy: true, + }, + operator: { + pattern: /[-+*/%<>!=&|^~]+|\b(?:and|or|not|is|like|ilike|rlike|in|between)\b/i, + greedy: true, + }, + punctuation: { + pattern: /[;[\](){}.,]/, + greedy: true, + }, + }; +} + +yql.displayName = 'yql'; +yql.aliases = ['yql'] as string[];