@nethru/ui 1.0.80 → 1.0.81

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.
@@ -2,30 +2,51 @@
2
2
  import { LanguageSupport, StreamLanguage, syntaxTree } from "@codemirror/language";
3
3
  import { nScriptKeywords } from "./nScriptKeywords";
4
4
 
5
- // 현재 코드에서 사용하는 이름: 테마 스타일(색상)이름
5
+ // 토큰 타입별 스타일 색상명
6
6
  var color = {
7
7
  comment: "comment",
8
8
  number: "number",
9
9
  string: "string",
10
+ property: "atom",
11
+ // 곤색 - API 변수 (true, false, 속성)
12
+ function: "keyword",
13
+ // 자색 - API 함수 (while, foreach, map, find)
10
14
  keyword: "keyword",
11
- // 스크립트 변수
12
- variable: "attributeValue",
13
- // API 변수(속성)
14
- function: "propertyName",
15
- // API 함수
16
- customer: "variableName",
17
- // 고객사 변수 (읽기 전용)
18
- operator: "squareBracket",
19
- // 일반 연산자
20
- punctuation: "punctuation" // 범위 관련 연산자
15
+ // 자색 - 디폴트 API (if, else)
16
+ variable: "variable",
17
+ // 흑색 - 스크립트 변수
18
+ tagging: "def",
19
+ // 청색 - 태깅 변수
20
+ namespace: "meta",
21
+ // 회색 - 고객사 네임스페이스 경로, 별칭
22
+ customer: "tagName",
23
+ // 녹색 - 고객사 변수
24
+ operator: "operator",
25
+ // 흑색 - 일반 연산자
26
+ punctuation: "bracket",
27
+ // 흑색 - 범위 관련 연산자
28
+ error: "error" // 적색 - 찾을 수 없는 API
21
29
  };
22
30
 
23
31
  // 기본 키워드
24
32
  var defaultKeywords = ["if", "else"];
33
+
34
+ // 난독화 전처리기 지시문
35
+ var preprocessorKeywords = [{
36
+ k: "using",
37
+ t: "(String)"
38
+ }, {
39
+ k: "as",
40
+ t: "(String)"
41
+ }, {
42
+ k: "obfuscationLog",
43
+ t: "-> String"
44
+ }];
25
45
  var operators = "+-/*%=|&<>~^?!";
26
46
  var punc = ":;,.(){}[]";
27
47
  var regexName = /^[a-zA-Z_]\w*/;
28
- var regexColon = /[\s:]+/;
48
+ var regexPath = /^['"][a-zA-Z_][\w.$]*['"]/;
49
+ var regexColon = /^\s*:\s*/;
29
50
 
30
51
  // 기본 토큰 처리기
31
52
  function tokenBase(stream, state, prev) {
@@ -48,35 +69,42 @@ function tokenBase(stream, state, prev) {
48
69
  stream.match(/^\d+/);
49
70
  return color.number;
50
71
  }
72
+ // 태깅 변수
73
+ if (ch == '{') {
74
+ if (stream.match("{{")) {
75
+ state.tokenize.push(tokenTaggingVariable);
76
+ return color.punctuation;
77
+ }
78
+ }
51
79
  // 스크립트 변수
52
80
  if (ch == '@' || ch == '#') {
53
81
  stream.next();
54
- stream.match(regexName);
55
- stream.match(regexColon);
56
- stream.match(regexName);
57
- return color.variable;
82
+ let puncColor = color.variable;
83
+ state.tokenize.push(tokenVariable('c', false, color.variable, puncColor));
84
+ return puncColor;
58
85
  }
59
86
  // 테이블 변수
60
87
  if (ch == '`') {
61
88
  stream.next();
62
- stream.match(regexName);
63
- return color.variable;
89
+ let puncColor = color.variable;
90
+ state.tokenize.push(tokenVariable('v', false, color.variable, puncColor));
91
+ return puncColor;
64
92
  }
65
93
  // 고객사 변수
66
94
  if (ch == '$') {
67
95
  stream.next();
68
- stream.match(regexName);
69
- stream.match(regexColon);
70
- stream.match(regexName);
71
- return color.customer;
96
+ let puncColor = color.customer;
97
+ state.tokenize.push(tokenVariable('c', true, color.customer, puncColor));
98
+ return puncColor;
72
99
  }
73
- // 빠른 문자열 매개변수
100
+ // 빠른 매개변수
74
101
  if (ch == ':') {
75
102
  stream.next();
76
- stream.eatSpace();
77
- stream.match(regexName);
78
- return color.string;
103
+ state.tokenize.push(tokenClass);
104
+ return color.punctuation;
79
105
  }
106
+ // 널 병합 연산자
107
+ if (stream.match("?:")) return color.operator;
80
108
  // 일반 연산자
81
109
  if (operators.indexOf(ch) > -1) {
82
110
  stream.next();
@@ -97,82 +125,134 @@ function tokenBase(stream, state, prev) {
97
125
  }
98
126
  // 예약어
99
127
  if (stream.match(regexName)) {
128
+ // 난독화 전처리기
100
129
  var ident = stream.current();
101
- var api = nScriptKeywords.find(api => api.k === ident);
130
+ var pre = preprocessorKeywords.find(key => key.k === ident);
131
+ if (pre) {
132
+ if (pre.t.at(0) == '-') return color.property;
133
+ state.tokenize.push(tokenNamespace);
134
+ return color.customer;
135
+ }
136
+ // API (대소문자 구별 안 함)
137
+ var lower = stream.current().toLowerCase();
138
+ var api = nScriptKeywords.find(api => api.k.toLowerCase() === lower);
102
139
  if (api) {
103
- if (api.t.at(0) == '-') return color.keyword;else return color.function;
140
+ if (api.t.at(0) == '-') return color.property;else return color.function;
104
141
  }
105
- if (defaultKeywords.find(key => key === ident)) return color.keyword;
106
- return null;
142
+ // 키워드
143
+ if (defaultKeywords.find(key => key === lower)) return color.keyword;
144
+ return color.error;
107
145
  }
108
146
  stream.next();
109
147
  return null;
110
148
  }
111
149
 
112
- // 문자열 템플릿 토큰 처리기
113
- function tokenUntilClosingParen() {
114
- var depth = 0;
115
- return function (stream, state, prev) {
116
- var inner = tokenBase(stream, state, prev);
117
- if (inner == color.punctuation) {
118
- let cur = stream.current();
119
- if (cur == "(" || cur == "{") {
120
- // 소괄호 중괄호 모두 지원
121
- ++depth;
122
- } else if (cur == ")" || cur == "}") {
123
- // 소괄호 중괄호 모두 지원
124
- if (depth == 0) {
125
- stream.backUp(1);
126
- state.tokenize.pop();
127
- return state.tokenize[state.tokenize.length - 1](stream, state);
128
- } else --depth;
129
- }
150
+ // 주석 토큰 처리기
151
+ function tokenComment(stream, state) {
152
+ var ch;
153
+ while (ch = stream.next()) {
154
+ if (ch === "*" && stream.eat("/")) {
155
+ state.tokenize.pop();
156
+ break;
130
157
  }
131
- return inner;
132
- };
158
+ }
159
+ return color.comment;
133
160
  }
134
161
 
135
162
  // 문자열 토큰 처리기
136
163
  function tokenString(openQuote, stream, state) {
137
- var singleLine = openQuote.length == 1;
138
164
  var ch,
139
165
  escaped = false;
140
166
  while (ch = stream.peek()) {
141
167
  if (escaped) {
142
168
  stream.next();
169
+ // 스위프트 방식 문자열 템플릿
143
170
  if (ch == "(" || ch == "{") {
144
- // 소괄호 중괄호 모두 지원
145
171
  state.tokenize.push(tokenUntilClosingParen());
146
172
  return color.string;
147
173
  }
148
174
  escaped = false;
149
175
  } else if (stream.match(openQuote)) {
176
+ // 문자열 종료
150
177
  state.tokenize.pop();
151
178
  return color.string;
179
+ } else if (stream.match(/\$[\(\{]/)) {
180
+ // 코틀린 방식 문자열 템플릿
181
+ state.tokenize.push(tokenUntilClosingParen());
182
+ return color.string;
152
183
  } else {
153
184
  stream.next();
154
- escaped = ch == "$"; // 코틀린 방식 문자열 템플릿
185
+ // 이스케이프 시퀀스
186
+ escaped = ch == "\\";
155
187
  }
156
188
  }
157
-
158
- if (singleLine) {
159
- state.tokenize.pop();
160
- }
161
189
  return color.string;
162
190
  }
163
191
 
164
- // 주석 토큰 처리기
165
- function tokenComment(stream, state) {
166
- var ch;
167
- while (ch = stream.next()) {
168
- if (ch === "/" && stream.eat("*")) {
169
- state.tokenize.push(tokenComment);
170
- } else if (ch === "*" && stream.eat("/")) {
192
+ // 문자열 템플릿 토큰 처리기
193
+ function tokenUntilClosingParen() {
194
+ var depth = 0;
195
+ return function (stream, state, prev) {
196
+ var inner = tokenBase(stream, state, prev);
197
+ if (inner == color.punctuation) {
198
+ let cur = stream.current();
199
+ if (cur == "(" || cur == "{" || cur == "[") {
200
+ ++depth;
201
+ } else if (cur == ")" || cur == "}" || cur == "]") {
202
+ if (depth == 0) {
203
+ stream.backUp(1);
204
+ state.tokenize.pop();
205
+ return state.tokenize[state.tokenize.length - 1](stream, state);
206
+ } else --depth;
207
+ }
208
+ }
209
+ return inner;
210
+ };
211
+ }
212
+
213
+ // 전처리기 토큰 처리기
214
+ function tokenNamespace(stream, state) {
215
+ stream.match(/^\s*['"]?[\w.*/$]+['"]?\s*/);
216
+ state.tokenize.pop();
217
+ return color.namespace;
218
+ }
219
+
220
+ // 클래스 매개변수
221
+ function tokenClass(stream, state) {
222
+ stream.eatSpace();
223
+ state.tokenize.pop();
224
+ if (stream.match(regexName) || stream.match(regexPath)) return color.string;else return color.punctuation;
225
+ }
226
+
227
+ // 모든 변수
228
+ function tokenVariable(firstScope, usePath, nameColor, puncColor) {
229
+ var scope = firstScope;
230
+ return function (stream, state, prev) {
231
+ if (scope == 'c') {
232
+ stream.eatSpace();
233
+ stream.match(regexName) || usePath && stream.match(regexPath);
234
+ scope = ':';
235
+ return nameColor;
236
+ } else if (scope == ':') {
237
+ if (stream.match(regexColon)) scope = 'v';else state.tokenize.pop();
238
+ return puncColor;
239
+ } else {
240
+ stream.eatSpace();
241
+ stream.match(regexName) || usePath && stream.match(regexPath);
171
242
  state.tokenize.pop();
172
- break;
243
+ return nameColor;
173
244
  }
245
+ };
246
+ }
247
+
248
+ // 태깅 변수 토큰 처리기
249
+ function tokenTaggingVariable(stream, state) {
250
+ var ch = stream.next();
251
+ if (ch === "}" && stream.eat("}")) {
252
+ state.tokenize.pop();
253
+ return color.punctuation;
174
254
  }
175
- return color.comment;
255
+ return color.tagging;
176
256
  }
177
257
  function Context(prev, align, indented) {
178
258
  this.prev = prev;
@@ -229,15 +309,31 @@ export const nScriptParser = {
229
309
  close: "*/"
230
310
  }
231
311
  },
232
- //closeBrackets: {brackets: ["(", "[", "{", "'", '"', "`"]}
233
312
  closeBrackets: {
234
313
  brackets: ["(", "[", "{", "'", '"']
235
314
  }
236
315
  }
237
316
  };
238
317
  export const nScriptLanguage = StreamLanguage.define(nScriptParser);
318
+ let nScriptOptions = [...nScriptKeywords.map(it => ({
319
+ label: it.k,
320
+ type: it.t.at(0) == '-' ? it.t.at(3) == 'c' ? "constant" : "variable" : "function",
321
+ detail: it.t,
322
+ info: it.i + "." + it.k + " " + it.t + " " + it.d,
323
+ boost: 1
324
+ })), ...defaultKeywords.map(it => ({
325
+ label: it,
326
+ type: "keyword",
327
+ boost: 0
328
+ })), ...preprocessorKeywords.map(it => ({
329
+ label: it.k,
330
+ type: it.t.at(0) == '-' ? "variable" : "keyword",
331
+ detial: it.t,
332
+ info: it.k + " " + it.t,
333
+ boost: 1
334
+ }))];
239
335
 
240
- // nScript 자동 완성 메인 처리기
336
+ // nScript 자동 완성 처리기
241
337
  function nScriptCompletion(context) {
242
338
  const {
243
339
  state,
@@ -245,27 +341,16 @@ function nScriptCompletion(context) {
245
341
  } = context;
246
342
  const nodeBefore = syntaxTree(state).resolveInner(pos, -1);
247
343
  const typeName = nodeBefore.type.name;
248
- //console.log(typeName);
344
+
345
+ //console.log(nodeBefore, typeName);
249
346
 
250
347
  // 주석이나 문자열 등은 스킵
251
- if (typeName === color.comment || typeName === color.string || typeName === color.variable || typeName === color.customer) return null;
348
+ if (typeName === color.comment || typeName === color.string || typeName === color.variable || typeName === "variableName" || typeName === "variableName.definition" || typeName === color.customer || typeName === color.namespace) return null;
252
349
  let word = context.matchBefore(/\w*/);
253
350
  if (word.from == word.to && !context.explicit) return null;
254
351
  return {
255
352
  from: word.from,
256
- options: [...nScriptKeywords.map(it => ({
257
- //section: it.i,
258
- //displayLabel: it.i + "." + it.k,
259
- label: it.k,
260
- type: it.t.at(0) == '-' ? it.t.at(3) == 'c' ? "constant" : "variable" : "function",
261
- detail: it.t,
262
- info: it.i + "." + it.k + it.t + " " + it.d,
263
- boost: 1
264
- })), ...defaultKeywords.map(it => ({
265
- label: it,
266
- type: "keyword",
267
- boost: 0
268
- }))]
353
+ options: nScriptOptions
269
354
  };
270
355
  }
271
356
  export const nScriptExtension = nScriptLanguage.data.of({