ts-gem-plugin 0.0.6 → 0.0.8
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/dist/index.js +113 -90
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -158,11 +158,14 @@ var Configuration = class {
|
|
|
158
158
|
}
|
|
159
159
|
};
|
|
160
160
|
|
|
161
|
+
// src/constants.ts
|
|
162
|
+
var NAME = "gem-plugin";
|
|
163
|
+
|
|
161
164
|
// src/context.ts
|
|
162
|
-
var import_vscode_html_languageservice2 = require("@mantou/vscode-html-languageservice");
|
|
163
|
-
var import_standard_template_source_helper = __toESM(require("@mantou/typescript-template-language-service-decorator/lib/standard-template-source-helper"));
|
|
164
165
|
var import_standard_script_source_helper = __toESM(require("@mantou/typescript-template-language-service-decorator/lib/standard-script-source-helper"));
|
|
166
|
+
var import_standard_template_source_helper = __toESM(require("@mantou/typescript-template-language-service-decorator/lib/standard-template-source-helper"));
|
|
165
167
|
var import_vscode_css_languageservice = require("@mantou/vscode-css-languageservice");
|
|
168
|
+
var import_vscode_html_languageservice2 = require("@mantou/vscode-html-languageservice");
|
|
166
169
|
|
|
167
170
|
// ../duoyun-ui/lib/map.js
|
|
168
171
|
var StringWeakMap = class {
|
|
@@ -188,12 +191,83 @@ var StringWeakMap = class {
|
|
|
188
191
|
}
|
|
189
192
|
};
|
|
190
193
|
|
|
194
|
+
// ../duoyun-ui/lib/cache.js
|
|
195
|
+
var Cache = class {
|
|
196
|
+
#max;
|
|
197
|
+
#maxAge;
|
|
198
|
+
#renewal;
|
|
199
|
+
#map = /* @__PURE__ */ new Map();
|
|
200
|
+
#reverseMap = /* @__PURE__ */ new Map();
|
|
201
|
+
#addedLinked = new LinkedList();
|
|
202
|
+
constructor({ max = Infinity, maxAge = Infinity, renewal = false } = {}) {
|
|
203
|
+
this.#max = max;
|
|
204
|
+
this.#maxAge = maxAge;
|
|
205
|
+
this.#renewal = renewal;
|
|
206
|
+
}
|
|
207
|
+
setOptions(options) {
|
|
208
|
+
this.#max = options.max ?? this.#max;
|
|
209
|
+
this.#maxAge = options.maxAge ?? this.#maxAge;
|
|
210
|
+
this.#renewal = options.renewal ?? this.#renewal;
|
|
211
|
+
}
|
|
212
|
+
#trim() {
|
|
213
|
+
for (let i = this.#addedLinked.size - this.#max; i > 0; i--) {
|
|
214
|
+
const value = this.#addedLinked.get();
|
|
215
|
+
const key = this.#reverseMap.get(value);
|
|
216
|
+
this.#reverseMap.delete(value);
|
|
217
|
+
this.#map.delete(key);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
set(key, value) {
|
|
221
|
+
this.#addedLinked.add(value);
|
|
222
|
+
this.#reverseMap.set(value, key);
|
|
223
|
+
this.#map.set(key, { value, timestamp: Date.now() });
|
|
224
|
+
this.#trim();
|
|
225
|
+
return value;
|
|
226
|
+
}
|
|
227
|
+
get(key, init) {
|
|
228
|
+
const cache = this.#map.get(key);
|
|
229
|
+
if (!cache) {
|
|
230
|
+
return init && this.set(key, init(key));
|
|
231
|
+
}
|
|
232
|
+
const { timestamp, value } = cache;
|
|
233
|
+
if (Date.now() - timestamp > this.#maxAge) {
|
|
234
|
+
this.#addedLinked.delete(value);
|
|
235
|
+
this.#reverseMap.delete(value);
|
|
236
|
+
this.#map.delete(key);
|
|
237
|
+
return init && this.set(key, init(key));
|
|
238
|
+
}
|
|
239
|
+
if (this.#renewal) {
|
|
240
|
+
cache.timestamp = Date.now();
|
|
241
|
+
}
|
|
242
|
+
this.#addedLinked.add(value);
|
|
243
|
+
return value;
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
// src/cache.ts
|
|
248
|
+
var LRUCache = class {
|
|
249
|
+
#bucket;
|
|
250
|
+
constructor(args) {
|
|
251
|
+
this.#bucket = new Cache({ max: 25, renewal: true, ...args });
|
|
252
|
+
}
|
|
253
|
+
#genKey(context, position) {
|
|
254
|
+
return [context.fileName, position?.line, position?.character, context.text].join(";");
|
|
255
|
+
}
|
|
256
|
+
get(context, position, init) {
|
|
257
|
+
return this.#bucket.get(this.#genKey(context, position), init);
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
// src/data-provider.ts
|
|
262
|
+
var import_vscode_html_languageservice = require("@mantou/vscode-html-languageservice");
|
|
263
|
+
|
|
191
264
|
// src/utils.ts
|
|
192
265
|
function isCustomElementTag(tag) {
|
|
193
266
|
return tag.includes("-");
|
|
194
267
|
}
|
|
195
268
|
function isDepElement(node) {
|
|
196
|
-
|
|
269
|
+
const { fileName } = node.getSourceFile();
|
|
270
|
+
return ["/node_modules/", "/dist/", ".d.ts"].some((s) => fileName.includes(s));
|
|
197
271
|
}
|
|
198
272
|
function bindMemberFunction(o, keys2 = Object.keys(o)) {
|
|
199
273
|
return Object.fromEntries(keys2.map((key) => [key, o[key].bind?.(o)]));
|
|
@@ -265,12 +339,6 @@ function decorate(origin, cb) {
|
|
|
265
339
|
return result;
|
|
266
340
|
}
|
|
267
341
|
|
|
268
|
-
// src/data-provider.ts
|
|
269
|
-
var import_vscode_html_languageservice = require("@mantou/vscode-html-languageservice");
|
|
270
|
-
|
|
271
|
-
// src/constants.ts
|
|
272
|
-
var NAME = "gem-plugin";
|
|
273
|
-
|
|
274
342
|
// src/data-provider.ts
|
|
275
343
|
var dataProvider = (0, import_vscode_html_languageservice.getDefaultHTMLDataProvider)();
|
|
276
344
|
var HTMLDataProvider = class {
|
|
@@ -373,73 +441,6 @@ function getDocComment(typescript, declaration) {
|
|
|
373
441
|
return commentStrings?.join("\n\n");
|
|
374
442
|
}
|
|
375
443
|
|
|
376
|
-
// ../duoyun-ui/lib/cache.js
|
|
377
|
-
var Cache = class {
|
|
378
|
-
#max;
|
|
379
|
-
#maxAge;
|
|
380
|
-
#renewal;
|
|
381
|
-
#map = /* @__PURE__ */ new Map();
|
|
382
|
-
#reverseMap = /* @__PURE__ */ new Map();
|
|
383
|
-
#addedLinked = new LinkedList();
|
|
384
|
-
constructor({ max = Infinity, maxAge = Infinity, renewal = false } = {}) {
|
|
385
|
-
this.#max = max;
|
|
386
|
-
this.#maxAge = maxAge;
|
|
387
|
-
this.#renewal = renewal;
|
|
388
|
-
}
|
|
389
|
-
setOptions(options) {
|
|
390
|
-
this.#max = options.max ?? this.#max;
|
|
391
|
-
this.#maxAge = options.maxAge ?? this.#maxAge;
|
|
392
|
-
this.#renewal = options.renewal ?? this.#renewal;
|
|
393
|
-
}
|
|
394
|
-
#trim() {
|
|
395
|
-
for (let i = this.#addedLinked.size - this.#max; i > 0; i--) {
|
|
396
|
-
const value = this.#addedLinked.get();
|
|
397
|
-
const key = this.#reverseMap.get(value);
|
|
398
|
-
this.#reverseMap.delete(value);
|
|
399
|
-
this.#map.delete(key);
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
set(key, value) {
|
|
403
|
-
this.#addedLinked.add(value);
|
|
404
|
-
this.#reverseMap.set(value, key);
|
|
405
|
-
this.#map.set(key, { value, timestamp: Date.now() });
|
|
406
|
-
this.#trim();
|
|
407
|
-
return value;
|
|
408
|
-
}
|
|
409
|
-
get(key, init) {
|
|
410
|
-
const cache = this.#map.get(key);
|
|
411
|
-
if (!cache) {
|
|
412
|
-
return init && this.set(key, init(key));
|
|
413
|
-
}
|
|
414
|
-
const { timestamp, value } = cache;
|
|
415
|
-
if (Date.now() - timestamp > this.#maxAge) {
|
|
416
|
-
this.#addedLinked.delete(value);
|
|
417
|
-
this.#reverseMap.delete(value);
|
|
418
|
-
this.#map.delete(key);
|
|
419
|
-
return init && this.set(key, init(key));
|
|
420
|
-
}
|
|
421
|
-
if (this.#renewal) {
|
|
422
|
-
cache.timestamp = Date.now();
|
|
423
|
-
}
|
|
424
|
-
this.#addedLinked.add(value);
|
|
425
|
-
return value;
|
|
426
|
-
}
|
|
427
|
-
};
|
|
428
|
-
|
|
429
|
-
// src/cache.ts
|
|
430
|
-
var LRUCache = class {
|
|
431
|
-
#bucket;
|
|
432
|
-
constructor(args) {
|
|
433
|
-
this.#bucket = new Cache({ max: 25, renewal: true, ...args });
|
|
434
|
-
}
|
|
435
|
-
#genKey(context, position) {
|
|
436
|
-
return [context.fileName, position?.line, position?.character, context.text].join(";");
|
|
437
|
-
}
|
|
438
|
-
get(context, position, init) {
|
|
439
|
-
return this.#bucket.get(this.#genKey(context, position), init);
|
|
440
|
-
}
|
|
441
|
-
};
|
|
442
|
-
|
|
443
444
|
// src/context.ts
|
|
444
445
|
var Context = class {
|
|
445
446
|
elements;
|
|
@@ -582,7 +583,7 @@ function getSubstitution(templateString, start, end) {
|
|
|
582
583
|
function isValidCSSTemplate(typescript, node, callName) {
|
|
583
584
|
switch (node.kind) {
|
|
584
585
|
case typescript.SyntaxKind.NoSubstitutionTemplateLiteral:
|
|
585
|
-
case typescript.SyntaxKind.TemplateExpression:
|
|
586
|
+
case typescript.SyntaxKind.TemplateExpression: {
|
|
586
587
|
const parent = node.parent;
|
|
587
588
|
if (typescript.isCallExpression(parent) && parent.expression.getText() === callName) {
|
|
588
589
|
return true;
|
|
@@ -594,6 +595,7 @@ function isValidCSSTemplate(typescript, node, callName) {
|
|
|
594
595
|
}
|
|
595
596
|
}
|
|
596
597
|
return false;
|
|
598
|
+
}
|
|
597
599
|
default:
|
|
598
600
|
return false;
|
|
599
601
|
}
|
|
@@ -662,8 +664,6 @@ function translationCompletionItemKind(context, kind) {
|
|
|
662
664
|
return typescript.ScriptElementKind.alias;
|
|
663
665
|
case vscode.CompletionItemKind.File:
|
|
664
666
|
return typescript.ScriptElementKind.moduleElement;
|
|
665
|
-
case vscode.CompletionItemKind.Snippet:
|
|
666
|
-
case vscode.CompletionItemKind.Text:
|
|
667
667
|
default:
|
|
668
668
|
return typescript.ScriptElementKind.unknown;
|
|
669
669
|
}
|
|
@@ -727,11 +727,11 @@ function genDefaultCompletionEntryDetails(context, name) {
|
|
|
727
727
|
}
|
|
728
728
|
function toDisplayParts(text, isDoc = false) {
|
|
729
729
|
if (!text) return [];
|
|
730
|
-
const
|
|
730
|
+
const escapeText = (unsafe) => unsafe.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'").replaceAll(" ", " ").replaceAll("\n", " \n").replaceAll(" ", " ");
|
|
731
731
|
return [
|
|
732
732
|
{
|
|
733
733
|
kind: "unknown",
|
|
734
|
-
text: typeof text !== "string" ? text.value : isDoc ?
|
|
734
|
+
text: typeof text !== "string" ? text.value : isDoc ? escapeText(text) : text
|
|
735
735
|
}
|
|
736
736
|
];
|
|
737
737
|
}
|
|
@@ -1010,7 +1010,8 @@ var HTMLLanguageService = class {
|
|
|
1010
1010
|
const diagnostics = [];
|
|
1011
1011
|
forEachNode(vHtml.roots, (node) => {
|
|
1012
1012
|
if (!node.tag) return;
|
|
1013
|
-
|
|
1013
|
+
const customElementTagDecl = this.#ctx.elements.get(node.tag);
|
|
1014
|
+
if (isCustomElementTag(node.tag) && !customElementTagDecl) {
|
|
1014
1015
|
diagnostics.push({
|
|
1015
1016
|
category: context.typescript.DiagnosticCategory.Warning,
|
|
1016
1017
|
code: 101 /* UnknownTag */,
|
|
@@ -1021,13 +1022,13 @@ var HTMLLanguageService = class {
|
|
|
1021
1022
|
source: NAME
|
|
1022
1023
|
});
|
|
1023
1024
|
}
|
|
1024
|
-
const tagDeclaration =
|
|
1025
|
+
const tagDeclaration = customElementTagDecl || this.#ctx.builtInElements.get(node.tag);
|
|
1025
1026
|
if (!tagDeclaration) return;
|
|
1026
1027
|
for (const [attributeName, { value, start, end }] of node.attributesMap) {
|
|
1027
1028
|
if (attributeName.startsWith("_")) continue;
|
|
1028
1029
|
const hasValueSpan = value?.startsWith("_");
|
|
1029
1030
|
const attrInfo = getAttrName(attributeName);
|
|
1030
|
-
const propType = getPropType(typeChecker, tagDeclaration, attrInfo);
|
|
1031
|
+
const propType = getPropType(typeChecker, tagDeclaration, !customElementTagDecl, attrInfo);
|
|
1031
1032
|
const diagnostic = {
|
|
1032
1033
|
category: context.typescript.DiagnosticCategory.Warning,
|
|
1033
1034
|
file,
|
|
@@ -1082,7 +1083,7 @@ var HTMLLanguageService = class {
|
|
|
1082
1083
|
if (hasValueSpan) {
|
|
1083
1084
|
const spanType = getSpanType(this.#ctx.ts, typeChecker, file, offset, end);
|
|
1084
1085
|
switch (attrInfo.decorate) {
|
|
1085
|
-
case "?":
|
|
1086
|
+
case "?": {
|
|
1086
1087
|
const boolType = getUnionType(typeChecker, [
|
|
1087
1088
|
typeChecker.getBooleanType(),
|
|
1088
1089
|
typeChecker.getUndefinedType(),
|
|
@@ -1092,6 +1093,7 @@ var HTMLLanguageService = class {
|
|
|
1092
1093
|
diagnostics.push(diagnostic);
|
|
1093
1094
|
}
|
|
1094
1095
|
continue;
|
|
1096
|
+
}
|
|
1095
1097
|
case ".":
|
|
1096
1098
|
case "@":
|
|
1097
1099
|
if (!typeChecker.isTypeAssignableTo(spanType, propType)) {
|
|
@@ -1121,7 +1123,6 @@ var HTMLLanguageService = class {
|
|
|
1121
1123
|
} else if (types.every((t) => !typeChecker.isTypeAssignableTo(t, propType))) {
|
|
1122
1124
|
diagnostics.push(diagnostic);
|
|
1123
1125
|
}
|
|
1124
|
-
continue;
|
|
1125
1126
|
}
|
|
1126
1127
|
}
|
|
1127
1128
|
});
|
|
@@ -1186,35 +1187,57 @@ function getSpanType(typescript, typeChecker, file, htmlOffset, attrNameEnd) {
|
|
|
1186
1187
|
const spanExp = getSpanExpression(typescript, file, valueOffset);
|
|
1187
1188
|
return typeChecker.getTypeAtLocation(spanExp);
|
|
1188
1189
|
}
|
|
1189
|
-
|
|
1190
|
+
var buildInElementNoGlobalAttrPropMap = /* @__PURE__ */ new Map([
|
|
1191
|
+
["crossorigin", "crossOrigin"],
|
|
1192
|
+
["rowspan", "rowSpan"],
|
|
1193
|
+
["colspan", "colSpan"],
|
|
1194
|
+
// <input> list: string
|
|
1195
|
+
["list", "ariaLabelledby"]
|
|
1196
|
+
]);
|
|
1197
|
+
function getPropType(typeChecker, tagClassDeclaration, isBuiltInTag, attrInfo) {
|
|
1190
1198
|
const classType = typeChecker.getTypeAtLocation(tagClassDeclaration);
|
|
1191
1199
|
if (attrInfo.attr.startsWith("data-")) {
|
|
1192
1200
|
return typeChecker.getStringType();
|
|
1193
1201
|
}
|
|
1194
|
-
const propName = kebabToCamelCase(attrInfo.attr);
|
|
1202
|
+
const propName = isBuiltInTag ? buildInElementNoGlobalAttrPropMap.get(attrInfo.attr) || kebabToCamelCase(attrInfo.attr) : kebabToCamelCase(attrInfo.attr);
|
|
1195
1203
|
switch (propName) {
|
|
1196
1204
|
case "class":
|
|
1197
1205
|
case "style":
|
|
1198
1206
|
case "part":
|
|
1199
1207
|
case "exportparts":
|
|
1208
|
+
case "xmlns":
|
|
1209
|
+
case "viewBox":
|
|
1210
|
+
case "ariaLabelledby":
|
|
1200
1211
|
return typeChecker.getStringType();
|
|
1201
1212
|
case "tabindex":
|
|
1202
1213
|
return typeChecker.getNumberType();
|
|
1203
|
-
case "
|
|
1214
|
+
case "ariaAtomic":
|
|
1215
|
+
case "ariaBusy":
|
|
1204
1216
|
case "ariaChecked":
|
|
1217
|
+
case "ariaDisabled":
|
|
1218
|
+
case "ariaExpanded":
|
|
1219
|
+
case "ariaGrabbed":
|
|
1205
1220
|
case "ariaHidden":
|
|
1221
|
+
case "ariaModal":
|
|
1222
|
+
case "ariaMultiline":
|
|
1223
|
+
case "ariaMultiselectable":
|
|
1224
|
+
case "ariaReadonly":
|
|
1225
|
+
case "ariaRequired":
|
|
1226
|
+
case "ariaPressed":
|
|
1227
|
+
case "ariaSelected":
|
|
1206
1228
|
return getUnionType(typeChecker, [
|
|
1207
1229
|
typeChecker.getStringType(),
|
|
1208
1230
|
typeChecker.getBooleanType(),
|
|
1209
1231
|
typeChecker.getUndefinedType()
|
|
1210
1232
|
]);
|
|
1211
|
-
default:
|
|
1233
|
+
default: {
|
|
1212
1234
|
const isEvent = attrInfo.decorate === "@";
|
|
1213
1235
|
const propSymbol = classType.getProperty(propName);
|
|
1214
1236
|
const propType = propSymbol && typeChecker.getTypeOfSymbol(propSymbol);
|
|
1215
1237
|
if (!isEvent) return propType;
|
|
1216
1238
|
const eventHandleType = getEmitterHandleType(typeChecker, classType, propType);
|
|
1217
1239
|
return getUnionType(typeChecker, [eventHandleType, typeChecker.getUndefinedType()]);
|
|
1240
|
+
}
|
|
1218
1241
|
}
|
|
1219
1242
|
}
|
|
1220
1243
|
function getEmitterHandleType(typeChecker, classType, propType) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ts-gem-plugin",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8",
|
|
4
4
|
"description": "Typescript language service plugin for Gem",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"gem",
|
|
@@ -14,17 +14,17 @@
|
|
|
14
14
|
"prepublishOnly": "pnpm run build"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@mantou/gem": "^2.2.
|
|
17
|
+
"@mantou/gem": "^2.2.1",
|
|
18
18
|
"@mantou/typescript-template-language-service-decorator": "^2.3.4",
|
|
19
19
|
"@mantou/vscode-css-languageservice": "^6.3.3",
|
|
20
20
|
"@mantou/vscode-emmet-helper": "^2.9.3",
|
|
21
|
-
"@mantou/vscode-html-languageservice": "^5.3.
|
|
22
|
-
"duoyun-ui": "^2.2.
|
|
21
|
+
"@mantou/vscode-html-languageservice": "^5.3.6",
|
|
22
|
+
"duoyun-ui": "^2.2.1",
|
|
23
23
|
"vscode-languageserver-textdocument": "^1.0.12",
|
|
24
24
|
"vscode-languageserver-types": "^3.17.5"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
|
-
"@gemjs/config": "^2.1.
|
|
27
|
+
"@gemjs/config": "^2.1.1",
|
|
28
28
|
"typescript": "^5.6.2"
|
|
29
29
|
},
|
|
30
30
|
"author": "mantou132",
|