@fc-components/monaco-editor 0.1.17 → 0.1.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/sql/sql.ts ADDED
@@ -0,0 +1,250 @@
1
+ export const languageConfiguration = {
2
+ wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,
3
+ comments: {
4
+ lineComment: '--',
5
+ blockComment: ['/*', '*/'] as [string, string],
6
+ },
7
+ brackets: [
8
+ ['{', '}'],
9
+ ['[', ']'],
10
+ ['(', ')'],
11
+ ] as any,
12
+ autoClosingPairs: [
13
+ { open: '{', close: '}' },
14
+ { open: '[', close: ']' },
15
+ { open: '(', close: ')' },
16
+ { open: '"', close: '"' },
17
+ { open: "'", close: "'" },
18
+ { open: '`', close: '`' },
19
+ ] as any,
20
+ surroundingPairs: [
21
+ { open: '{', close: '}' },
22
+ { open: '[', close: ']' },
23
+ { open: '(', close: ')' },
24
+ { open: '"', close: '"' },
25
+ { open: "'", close: "'" },
26
+ { open: '`', close: '`' },
27
+ ] as any,
28
+ folding: {
29
+ offSide: false,
30
+ },
31
+ };
32
+
33
+ // SQL keywords
34
+ const keywords = [
35
+ 'SELECT',
36
+ 'FROM',
37
+ 'WHERE',
38
+ 'AND',
39
+ 'OR',
40
+ 'NOT',
41
+ 'JOIN',
42
+ 'INNER',
43
+ 'LEFT',
44
+ 'RIGHT',
45
+ 'FULL',
46
+ 'OUTER',
47
+ 'ON',
48
+ 'ORDER',
49
+ 'BY',
50
+ 'GROUP',
51
+ 'HAVING',
52
+ 'LIMIT',
53
+ 'OFFSET',
54
+ 'INSERT',
55
+ 'INTO',
56
+ 'VALUES',
57
+ 'UPDATE',
58
+ 'SET',
59
+ 'DELETE',
60
+ 'CREATE',
61
+ 'TABLE',
62
+ 'ALTER',
63
+ 'DROP',
64
+ 'PRIMARY',
65
+ 'KEY',
66
+ 'FOREIGN',
67
+ 'CONSTRAINT',
68
+ 'UNIQUE',
69
+ 'INDEX',
70
+ 'VIEW',
71
+ 'DATABASE',
72
+ 'SCHEMA',
73
+ 'AS',
74
+ 'DISTINCT',
75
+ 'CASE',
76
+ 'WHEN',
77
+ 'THEN',
78
+ 'ELSE',
79
+ 'END',
80
+ 'CAST',
81
+ 'BETWEEN',
82
+ 'IN',
83
+ 'LIKE',
84
+ 'IS',
85
+ 'NULL',
86
+ 'TRUE',
87
+ 'FALSE',
88
+ 'WITH',
89
+ 'UNION',
90
+ 'EXCEPT',
91
+ 'INTERSECT',
92
+ ];
93
+
94
+ export const language = {
95
+ defaultToken: '',
96
+ tokenPostfix: '.sql',
97
+ ignoreCase: true,
98
+
99
+ brackets: [
100
+ { open: '(', close: ')', token: 'delimiter.parenthesis' },
101
+ { open: '{', close: '}', token: 'delimiter.curly' },
102
+ { open: '[', close: ']', token: 'delimiter.square' },
103
+ ],
104
+
105
+ keywords,
106
+
107
+ operators: ['=', '>', '<', '!', '%', '&', '|', '^', '~', '?', ':', '+', '-', '*', '/'],
108
+
109
+ builtinFunctions: [
110
+ 'COUNT',
111
+ 'SUM',
112
+ 'AVG',
113
+ 'MIN',
114
+ 'MAX',
115
+ 'UPPER',
116
+ 'LOWER',
117
+ 'LENGTH',
118
+ 'SUBSTRING',
119
+ 'TRIM',
120
+ 'ROUND',
121
+ 'ABS',
122
+ 'COALESCE',
123
+ 'NULLIF',
124
+ 'IFNULL',
125
+ 'CONCAT',
126
+ 'DATE',
127
+ 'NOW',
128
+ 'YEAR',
129
+ 'MONTH',
130
+ 'DAY',
131
+ 'HOUR',
132
+ 'MINUTE',
133
+ 'SECOND',
134
+ ],
135
+
136
+ escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
137
+
138
+ digits: /\d+(_+\d+)*/,
139
+
140
+ octaldigits: /[0-7]+(_+[0-7]+)*/,
141
+
142
+ hexdigits: /[[0-9a-fA-F]+(_+[0-9a-fA-F]+)*/,
143
+
144
+ regexpctl: /[(){}\[\]\|;,.?*+^$\\]/,
145
+
146
+ regexpattern: /(\{[0-9]+\})|(\{[0-9]*,[0-9]*\})|(\?(?:\?)?|[*+]|\^|\$|\|\\)/,
147
+
148
+ tokenizer: {
149
+ root: [
150
+ { include: '@comments' },
151
+ { include: '@whitespace' },
152
+ { include: '@pseudo-columns' },
153
+ [/[;,.]/, 'delimiter'],
154
+ [/[{}()\[\]]/, '@brackets'],
155
+ { include: '@builtinVariables' },
156
+ { include: '@numbers' },
157
+ { include: '@strings' },
158
+ [/[a-zA-Z_#][a-zA-Z0-9_$#@]*(?=\s*\()/, { cases: { '@builtinFunctions': 'keyword.function', '@default': 'identifier.function' } }],
159
+ [
160
+ /[a-zA-Z_#][a-zA-Z0-9_$#@]*/,
161
+ {
162
+ cases: {
163
+ '@keywords': 'keyword',
164
+ '@default': 'identifier',
165
+ },
166
+ },
167
+ ],
168
+ [/[<>=!%&+\-*/|~^]/, 'operator'],
169
+ ],
170
+
171
+ whitespace: [[/\s+/, 'white']],
172
+
173
+ comments: [
174
+ [/--+.*/, 'comment'],
175
+ [/\/\*/, { token: 'comment.quote', next: '@comment' }],
176
+ ],
177
+
178
+ comment: [
179
+ [/[^*/]+/, 'comment'],
180
+ [/\*\//, { token: 'comment.quote', next: '@pop' }],
181
+ [/./, 'comment'],
182
+ ],
183
+
184
+ 'pseudo-columns': [
185
+ [
186
+ /[$][A-Za-z_][A-Za-z0-9_]*/,
187
+ {
188
+ cases: {
189
+ '@keywords': 'keyword',
190
+ '@default': 'variable',
191
+ },
192
+ },
193
+ ],
194
+ [
195
+ /@[A-Za-z_][A-Za-z0-9_]*/,
196
+ {
197
+ cases: {
198
+ '@keywords': 'keyword',
199
+ '@default': 'variable',
200
+ },
201
+ },
202
+ ],
203
+ ],
204
+
205
+ builtinVariables: [
206
+ [
207
+ /@@?[a-zA-Z_][a-zA-Z0-9_]*/,
208
+ {
209
+ cases: {
210
+ '@keywords': 'keyword',
211
+ '@default': 'variable',
212
+ },
213
+ },
214
+ ],
215
+ ],
216
+
217
+ numbers: [
218
+ [/0[xX][0-9a-fA-F]*[0-9a-fA-F]/, 'number.hex'],
219
+ [/0[0-7]+(?!\d)/, 'number.octal'],
220
+ [/(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?/, 'number'],
221
+ ],
222
+
223
+ strings: [
224
+ [/'/, { token: 'string', next: '@string' }],
225
+ [/"/, { token: 'string.double', next: '@string_double' }],
226
+ [/`/, { token: 'string.backtick', next: '@string_backtick' }],
227
+ ],
228
+
229
+ string: [
230
+ [/[^'\\]+/, 'string'],
231
+ [/@escapes/, 'string.escape'],
232
+ [/\\./, 'string.escape.invalid'],
233
+ [/'/, { token: 'string', next: '@pop' }],
234
+ ],
235
+
236
+ string_double: [
237
+ [/[^"\\]+/, 'string.double'],
238
+ [/@escapes/, 'string.escape'],
239
+ [/\\./, 'string.escape.invalid'],
240
+ [/"/, { token: 'string.double', next: '@pop' }],
241
+ ],
242
+
243
+ string_backtick: [
244
+ [/[^`\\]+/, 'string.backtick'],
245
+ [/@escapes/, 'string.escape'],
246
+ [/\\./, 'string.escape.invalid'],
247
+ [/`/, { token: 'string.backtick', next: '@pop' }],
248
+ ],
249
+ },
250
+ };
@@ -0,0 +1,8 @@
1
+ export interface SqlEditorMarker {
2
+ startLineNumber: number;
3
+ startColumn: number;
4
+ endLineNumber: number;
5
+ endColumn: number;
6
+ message: string;
7
+ severity: 'Error' | 'Warning' | 'Information';
8
+ }
@@ -0,0 +1,92 @@
1
+ import * as monaco from 'monaco-editor';
2
+
3
+ const SQL_LANG_ID = 'sql';
4
+
5
+ export const validateSql = (sql: string): Omit<monaco.editor.IMarker, 'owner' | 'resource'>[] => {
6
+ const markers: Omit<monaco.editor.IMarker, 'owner' | 'resource'>[] = [];
7
+
8
+ if (!sql || sql.trim().length === 0) {
9
+ return markers;
10
+ }
11
+
12
+ // Basic SQL validation - check for common syntax issues
13
+ const lines = sql.split('\n');
14
+
15
+ lines.forEach((line, index) => {
16
+ const lineNumber = index + 1;
17
+
18
+ // Check for incomplete quotes
19
+ const singleQuotes = (line.match(/'/g) || []).length;
20
+ const doubleQuotes = (line.match(/"/g) || []).length;
21
+ const backticks = (line.match(/`/g) || []).length;
22
+
23
+ if (singleQuotes % 2 !== 0) {
24
+ markers.push({
25
+ severity: monaco.MarkerSeverity.Warning,
26
+ startLineNumber: lineNumber,
27
+ startColumn: 1,
28
+ endLineNumber: lineNumber,
29
+ endColumn: line.length + 1,
30
+ message: "Unclosed single quote '",
31
+ code: 'SQL001',
32
+ source: SQL_LANG_ID,
33
+ });
34
+ }
35
+
36
+ if (doubleQuotes % 2 !== 0) {
37
+ markers.push({
38
+ severity: monaco.MarkerSeverity.Warning,
39
+ startLineNumber: lineNumber,
40
+ startColumn: 1,
41
+ endLineNumber: lineNumber,
42
+ endColumn: line.length + 1,
43
+ message: 'Unclosed double quote "',
44
+ code: 'SQL002',
45
+ source: SQL_LANG_ID,
46
+ });
47
+ }
48
+
49
+ if (backticks % 2 !== 0) {
50
+ markers.push({
51
+ severity: monaco.MarkerSeverity.Warning,
52
+ startLineNumber: lineNumber,
53
+ startColumn: 1,
54
+ endLineNumber: lineNumber,
55
+ endColumn: line.length + 1,
56
+ message: 'Unclosed backtick `',
57
+ code: 'SQL003',
58
+ source: SQL_LANG_ID,
59
+ });
60
+ }
61
+
62
+ // Check for unmatched parentheses (basic check)
63
+ const openParens = (line.match(/\(/g) || []).length;
64
+ const closeParens = (line.match(/\)/g) || []).length;
65
+
66
+ if (openParens > closeParens) {
67
+ markers.push({
68
+ severity: monaco.MarkerSeverity.Warning,
69
+ startLineNumber: lineNumber,
70
+ startColumn: 1,
71
+ endLineNumber: lineNumber,
72
+ endColumn: line.length + 1,
73
+ message: 'Unmatched opening parenthesis',
74
+ code: 'SQL004',
75
+ source: SQL_LANG_ID,
76
+ });
77
+ } else if (closeParens > openParens) {
78
+ markers.push({
79
+ severity: monaco.MarkerSeverity.Warning,
80
+ startLineNumber: lineNumber,
81
+ startColumn: 1,
82
+ endLineNumber: lineNumber,
83
+ endColumn: line.length + 1,
84
+ message: 'Unmatched closing parenthesis',
85
+ code: 'SQL005',
86
+ source: SQL_LANG_ID,
87
+ });
88
+ }
89
+ });
90
+
91
+ return markers;
92
+ };