efront 4.0.11 → 4.0.15

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.
Files changed (50) hide show
  1. package/#/345/233/275/351/231/205/345/214/226.yml +638 -47
  2. package/{docs → apps}/drequest/index.html +11 -1
  3. package/{docs → apps}/drequest/main.js +5 -5
  4. package/coms/basic/#loader.js +2 -1
  5. package/coms/basic/YAML.js +3 -3
  6. package/coms/basic/parseYML.js +4 -1
  7. package/coms/basic/parseYML_test.js +3 -1
  8. package/coms/basic/strings.js +22 -15
  9. package/coms/basic_/readme-en.md +112 -0
  10. package/coms/basic_/readme.md +1 -1
  11. package/coms/compile/Javascript.js +4 -2
  12. package/coms/compile/Program.js +0 -2
  13. package/coms/compile/common.js +1 -0
  14. package/coms/compile/downLevel.js +8 -4
  15. package/coms/compile/translate.js +3 -3
  16. package/coms/compile/unstruct.js +107 -67
  17. package/coms/compile/unstruct_test.js +6 -2
  18. package/coms/docs/helps.js +69 -65
  19. package/coms/zimoli/data.js +10 -10
  20. package/coms/zimoli/table.html +4 -4
  21. package/docs/compare-en.md +327 -0
  22. package/docs/components.jsp +1 -1
  23. package/docs/main.xht +18 -18
  24. package/docs/version-desc.md +11 -0
  25. package/docs/welcome.jsp +1 -1
  26. package/docs//345/221/275/344/273/244.xht +12 -6
  27. package/docs//345/267/245/345/205/267//345/233/275/351/231/205/345/214/226.xht +54 -53
  28. package/docs//345/267/245/345/205/267//345/255/227/347/254/246/351/233/206/346/243/200/346/237/245.xht +7 -7
  29. package/docs//347/273/204/344/273/266.xht +12 -12
  30. package/package.json +1 -1
  31. package/public/efront.js +1 -1
  32. package/readme-en.md +168 -0
  33. package/readme.md +16 -7
  34. package/_envs/setup.bat +0 -10
  35. package/apis/zimoli/file/checkPermission.js +0 -10
  36. package/apis/zimoli/file/info.js +0 -68
  37. package/apis/zimoli/file/root.js +0 -2
  38. package/apis/zimoli/server/count.js +0 -4
  39. package/apis/zimoli/user/login.js +0 -12
  40. package/apis/zimoli/yuanfen/suggest.js +0 -8
  41. package/coms/zimoli/editor.js +0 -85
  42. package/coms/zimoli/editor.less +0 -64
  43. package/data/i18n/zh-cn.json +0 -21
  44. package/docs/canvas/main.js +0 -5
  45. package/docs/compare/index.html +0 -14
  46. package/docs/compare/main.js +0 -7
  47. package/docs/editor/index.html +0 -30
  48. package/docs/editor/main.js +0 -5
  49. package/docs/editor/main.less +0 -0
  50. /package/{docs → apps}/sample/mycolor.html +0 -0
@@ -1,5 +1,6 @@
1
1
  <!Doctype html>
2
2
  <html>
3
+
3
4
  <head>
4
5
  <title>测试请求时间</title>
5
6
  <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
@@ -7,8 +8,17 @@
7
8
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
8
9
  <link rel="Shortcut Icon" href="/favicon.ico" type="image/x-icon" />
9
10
  <meta name="viewport" content="user-scalable=no,initial-scale=1,maximum-scale=1,width=device-width" />
11
+ <style>
12
+ *,
13
+ ::before,
14
+ ::after {
15
+ box-sizing: border-box;
16
+ }
17
+ </style>
10
18
  </head>
19
+
11
20
  <body>
12
- <script src=/main.js></script>
21
+ <script efrontloader deleteoncompile></script>
13
22
  </body>
23
+
14
24
  </html>
@@ -1,11 +1,11 @@
1
1
  titlebar("请求计时工具", [], false);
2
- var _input = createElement(input);
2
+ var _input = input();
3
3
  css(_input, "width:100%;height:50px;margin:10px 0;");
4
- var request_time_count = createElement(_input);
4
+ var request_time_count = _input.cloneNode();
5
5
  request_time_count.setAttribute("placeholder", "输入请求次数");
6
- var request_time_url = createElement(_input);
6
+ var request_time_url = _input.cloneNode();
7
7
  request_time_url.setAttribute("placeholder", "输入url");
8
- var request_time_label = createElement(div);
8
+ var request_time_label = div();
9
9
  var request_time_button = button("请求");
10
10
  var request_stop_button = button("停止");
11
11
  css(request_time_button, "background-color:#f34;width:100%;height:50px;margin:10px 0;color:#fff;")
@@ -45,7 +45,7 @@ onclick(request_time_button, request)
45
45
  onclick(request_stop_button, function () {
46
46
  stoped = true;
47
47
  });
48
- var page = createElement(div);
48
+ var page = div();
49
49
  css(page, "padding-top:50px;");
50
50
  appendChild(page, request_time_count, request_time_label, request_time_url, request_time_button, request_stop_button);
51
51
  function main() {
@@ -633,7 +633,8 @@ var init = function (url, then, prebuilds) {
633
633
  return res;
634
634
  };
635
635
  var forceRequest = {
636
- Promise: true
636
+ Promise: true,
637
+ i18n: true
637
638
  };
638
639
  var removeGlobalProperty = function (property) {
639
640
  forceRequest[property] = true;
@@ -1,6 +1,6 @@
1
1
  var string = function (a) {
2
- if (/^#|\s#|\:\s|\[\]\{\}\'\"/i.test(a)) {
3
- a = strings.encode(a);
2
+ if (/^#|\s#|\:(\s|$)|[\[\]\{\}\'\",\r\n\u2028\u2029]/i.test(a)) {
3
+ a = strings.encode(a, '"', false);
4
4
  }
5
5
  return a;
6
6
  }
@@ -24,7 +24,7 @@ var stringify = function (data) {
24
24
  }
25
25
  result.push(v);
26
26
  };
27
- var circelError = new Error("YAML无法处理环形数据,请使用JSAM代替!");
27
+ var circelError = new Error(i18n`YAML无法处理环形数据,请使用JSAM代替!`);
28
28
  loop: while (objpath.length) {
29
29
  var data = objpath[objpath.length - 1];
30
30
  if (isArray(data)) {
@@ -26,7 +26,10 @@ var scan = function (text) {
26
26
  prop = strings.decode(data);
27
27
  data = '';
28
28
  }
29
- if (!value) value = eval2(data);
29
+ if (!value) {
30
+ if (/^['"]$/.test(rowtype)) data = rowtype + data + rowtype;
31
+ value = eval2(data);
32
+ }
30
33
  data = '';
31
34
  while (parents.length) {
32
35
  if (parents[parents.length - 1]) break;
@@ -36,7 +36,9 @@ var text = [
36
36
  `{"a":-12.e-61}`,
37
37
  `{"a":+12.e-61}`,
38
38
  `{"a":12.e-61}`,
39
- `{"a":"[b,c,\\"d]"}`,
39
+ `{"a":"[b,c,\r\n\\"d]"}`,
40
+ ` - zh-CN: "跳过了缺少参数的请求:$1 $2 $3\\r\\n缺少参数:$4"
41
+ en: "Skipped request with missing parameters: $1 $2 $3"`,
40
42
  text
41
43
  ];
42
44
  var test = function (text) {
@@ -5,24 +5,31 @@ var escapeMap = {
5
5
  "\b": "\\b",
6
6
  "\f": "\\f",
7
7
  "\v": "\\u000b",
8
+ "\u2028": "\\u2028",
9
+ "\u2029": "\\u2029",
10
+ };
11
+ var unescapeReg = new RegExp(`[${Object.keys(escapeMap).map(a => escapeMap[a]).join('')}]`, 'g');
12
+ var unescapeFun = a => escapeMap[a];
13
+ var unescapeUnc = function (a) {
14
+ if (escapeMap.hasOwnProperty(a)) return escapeMap[a];
15
+ var code = a.charCodeAt(0).toString(16);
16
+ switch (code.length) {
17
+ case 1:
18
+ return "\\u000" + code;
19
+ case 2:
20
+ return "\\u00" + code;
21
+ case 3:
22
+ return "\\u0" + code;
23
+ }
24
+ return "\\u" + code;
8
25
  };
9
26
  var unescapeMap = {};
10
27
  for (var k in escapeMap) unescapeMap[escapeMap[k]] = k;
11
-
12
- function encode(str, q = "\"") {
13
- return q + str.replace(new RegExp(`[\\\\${q}]`, 'g'), "\\$&").replace(/[\r\n\t\v\f\u0008\u0000-\u001f\u007f-\uffff]/g, a => {
14
- if (escapeMap.hasOwnProperty(a)) return escapeMap[a];
15
- var code = a.charCodeAt(0).toString(16);
16
- switch (code.length) {
17
- case 1:
18
- return "\\u000" + code;
19
- case 2:
20
- return "\\u00" + code;
21
- case 3:
22
- return "\\u0" + code;
23
- }
24
- return "\\u" + code;
25
- }) + q;
28
+ function encode(str, q = "\"", escapeUnicode = true) {
29
+ str = str.replace(new RegExp(`[\\\\${q}]`, 'g'), "\\$&");
30
+ if (escapeUnicode) str = str.replace(/[\r\n\t\v\f\u0008\u0000-\u001f\u007f-\uffff]/g, unescapeUnc);
31
+ else str = str.replace(unescapeReg, unescapeFun);
32
+ return q + str + q;
26
33
  }
27
34
  function decode(s) {
28
35
  var r = /^(['"`])([\s\S]*)\1$/.exec(s);
@@ -0,0 +1,112 @@
1
+ # efront compatibility instructions
2
+ * The code for the directory `coms/basic_` is all non-standard implementations. If you want to be compatible with lower versions of the runtime environment, try to avoid using advanced features as much as possible
3
+ * 3.x and previous versions of `efront` used `typescript` for code downgrade, so the description of some issues in the following text may accidentally harm `typescript`, so it's not surprising.
4
+ * The syntax that is known to differ from advanced versions after conversion to lower version code is as follows:
5
+ 1. ```javascript
6
+ class ... extends Array {...}
7
+ ```
8
+ Because if one level of prototype is added, the characteristics of the array will disappear, and `efront` has not yet implemented a perfect downgrade plan, and the possibility of future implementation is also unlikely. After similar statements are converted by `typescript`, the newly defined methods will be lost. `efront` uses `class extends Array2 {...}` will be replaced, and `Array2` will mount the defined method to the newly generated object.
9
+
10
+ 2. ```javascript
11
+ import(...)
12
+ ```
13
+ The result imported with `import (...)`, efront will not actively wrap a layer of Promise. If you use `await` in the root scope of the module, the returned result is an instance of `Promise`. Otherwise, what you export in the imported file will be the result of this `import(...)`. If you are unsure about the content of the imported file and do not blindly use methods such as `import(...).then (...)`, you can use `await import(...)` to wait for the import to complete.
14
+ 3. ```javascript
15
+ (function (a){
16
+ if (a === void 0) a = 1;
17
+ a = 1;
18
+ console.log(arguments[0])// 1
19
+ }(0));
20
+ (function (a){"use strict"
21
+ if (a === void 0) a = 1;
22
+ a = 1;
23
+ console.log(arguments[0])// 0
24
+ }(0));
25
+ (function (a = 1){
26
+ a = 1;
27
+ console.log(arguments[0])// 0
28
+ }(0));
29
+ ```
30
+ `arguments` that are not in strict mode and do not have default values will be changed by statements in the code, while the other two cases will not. When the `efront` and `typescript` move the default value assignment statement into the function body, they do not handle this detail, that is, the original read-only `arguments` may be changed by the statement inside the function. Some of the components provided in efront may also have issues that prevent them from being downgraded for use. If you find any related issues, please feel free to provide feedback to me and I will handle them as soon as possible.
31
+
32
+ 4. ```javascript
33
+ async function () {
34
+ await ...;
35
+ arguments;
36
+ }
37
+ // 或
38
+ function* (){
39
+ yield ...;
40
+ arguments;
41
+ }
42
+ ```
43
+ After converting these two types of new functions with `typescript`, the content of the `arguments` object is incorrect. This is not a difficult problem to solve, it should just be a problem that `typescript` has discovered but is unwilling to solve. During downgrade compilation, use variable renaming to temporarily replace the `arguments` in the code to make its content consistent with the native high-level code.
44
+
45
+ 5. ```javascript
46
+ Object.keys
47
+ Object.create
48
+ Array.prototype.map
49
+ Array.prototype.forEach
50
+ Array.prototype.filter
51
+ Array.prototype.indexOf
52
+ String.prototype.trim// Inconsistent implementation in different support environments, and inconsistent understanding of whitespace by major manufacturers
53
+ Function.prototype.bind
54
+ ```
55
+ The above methods are supported by the `ie9+` series of browsers, but not by the 'ie8' and the following versions. If the `--no-polyfill` parameter is not specified, the methods provided in `[]map.js` will be used to patch during the downgrade compile time. These methods will be initialized when the loader detects that the browser does not support `[].map`
56
+
57
+ 1. ```javascript
58
+ Array.prototype.fill
59
+ Array(3).fill(0) // Similar to this will become a constant array of [0,0,0]
60
+ var [a,b,c]=Array(3).fill(0).map((_,i)=>i+1) // Similar to those used to generate constants and assign values, they will directly become assignment statements: var a=1,b=2,c=3
61
+ Array(3).fill(a)// A statement similar to ArrayFill(3, a) will replace a very large quantity like this
62
+ ```
63
+ `Array(...).fill(...).map(...)` is often used by `efront` developers to generate self increasing assignment sequences, and not all runtime environments support it. Therefore, several other writing methods that explicitly use `Array.prototype.fill` will be replaced. For the sake of the performance of the Object code, this replacement must be executed before the automatic constant. Therefore, the switch `polyfill` is no longer supported. If you want to turn off, please use the parameter `--no-autoeval` to turn off the automatic constant function together.
64
+
65
+ 2. ```javascript
66
+ Object.assign
67
+ ```
68
+ Object.assign and `ie` series browsers are not supported. Because they are often used by `efront` developers, during the downgrade Compile time period, if the '--no-polyfill' parameter is not specified, `efront` will be processed as a substitute [extend](../basic/extend.js)
69
+
70
+ 3. ```javascript
71
+ Promise
72
+ Promise.prototype.then
73
+ Promise.prototype.catch
74
+ Promise.all
75
+ Promise.race
76
+ Promise.reject
77
+ Promise.resolve
78
+ ```
79
+ The `Promise` object is also not supported by the IE series of browsers. The `Promise` implemented by `efront` is not consistent with the native features and is only replaced when the runtime environment does not support it. For example, the execution order of methods triggered by `.then` and `setTimeout` may differ from the advanced runtime environment, but they will also remain executed in the current context before executing the relevant statements. The `Promise` related methods not mentioned above are not supported, such as `Promise.prototype.finally`. If you use these missing features, you can only implement them yourself or find similar [core js](https://github.com/zloirock/core-js). The library is filled with
80
+
81
+ 4. ```javascript
82
+ obj.if
83
+ obj.catch
84
+ obj.for
85
+ ```
86
+ Similar to this. As the attribute name is the same as the Reserved word of 'js', the browser such as `ie6` will report an error, but you can use it safely in the environment provided by `efront`. Because `efront` itself will process statements that retrieve attributes.
87
+
88
+ 1. There are some features in `IE8` and below browsers that are different from modern 'js' standards, and the components provided by `efront` may not be compatible. When developing applications for such environments, it is important to avoid using them.
89
+ ```javascript
90
+ Object.defineProperty(...);
91
+ ({
92
+ get a(){},
93
+ set a(){}
94
+ });
95
+ class {
96
+ get a(){}
97
+ set a(){}
98
+ }
99
+ ```
100
+ `IE8` and below browsers do not support `Object.defineProperty` well or at all, and there is currently no compatibility solution for `efront` to implement this type of function. If you want to be compatible with the corresponding environment, please temporarily avoid using related statements and do not use libraries that use these features.
101
+
102
+ ```javascript
103
+ Array.prototype.slice.call(objNodeList,...)
104
+ ```
105
+ `IE8` and below browsers do not support dom objects such as 'NodeList' to call, and the current `efront` and previously used `typescript` conversion code do not handle this detail. Therefore, do not use high-level syntax such as `[...aaa]`, `{...aaa}` , and `function (...args) {}` in dom operation related statements temporarily to avoid problems with the converted code.
106
+
107
+ ```javascript
108
+ var div = document.createElement("div");
109
+ div.innerHTML = `<abcd><span></span></abcd>`;
110
+ console.log(div.innerHTML); // <SPAN></SPAN>
111
+ ```
112
+ `IE8` and below browsers cannot correctly set custom labels through the `innerHTML` attribute, and most of the components provided by `efront` use this feature. In the `efront` example project, [ie8.js](../../apps/kugou/ie8.js) can achieve the adaptation of setting `innerHTML` on `ie8`, but it cannot guarantee the normal style. For browsers under `ie7` and below, do not use the components related to elements provided by `efront` temporarily.
@@ -97,7 +97,7 @@
97
97
  ```javascript
98
98
  Array.prototype.slice.call(objNodeList,...)
99
99
  ```
100
- `ie8`及以下浏览器不支持call`NodeList`等dom对象,而当前`efront`和内部使用的`typescript`转换的代码都没有处理这一细节,所以暂时不要在dom操作相关的语句中使用类似`[...aaa]`,`{...aaa}`,`function(...args){}`的高级语法,以避免转换后的代码出问题。
100
+ `ie8`及以下浏览器不支持call`NodeList`等dom对象,而当前`efront`和之前内部使用的`typescript`转换的代码都没有处理这一细节,所以暂时不要在dom操作相关的语句中使用类似`[...aaa]`,`{...aaa}`,`function(...args){}`的高级语法,以避免转换后的代码出问题。
101
101
  ```javascript
102
102
  var div = document.createElement("div");
103
103
  div.innerHTML = `<abcd><span></span></abcd>`;
@@ -35,7 +35,7 @@ instanceof`.trim().split(/[,\s]+/);
35
35
  class Javascript extends Program {
36
36
  straps = straps;
37
37
  value_reg = /^(false|true|null|Infinity|NaN|undefined|eval)$/
38
- transive_reg = /^(new|var|let|const|yield|void|in|of|typeof|delete|case|return|await|export|default|instanceof|throw|extends|import|from)$/
38
+ transive_reg = /^(new|var|let|const|yield|void|in|of|typeof|delete|case|return|await|default|instanceof|throw|extends|import|from)$/
39
39
  strapexp_reg = /^(new|void|typeof|delete|class|function|await)/;
40
40
  forceend_reg = /^(return|yield|break|continue|debugger)$/;
41
41
  classstrap_reg = /^(class|function|async)$/;
@@ -571,7 +571,9 @@ var removeExport = function (c, i, code) {
571
571
  code.splice(i + 1, 0, ...scan(`=`));
572
572
  var nn = n.next;
573
573
  var d = nn.text;
574
- if (used[d]) used[d].forEach(a => a.text = `exports.${d}`);
574
+ if (used[d]) used[d].forEach(a => {
575
+ if (!a.kind) a.text = `exports.${d}`;
576
+ });
575
577
  delete used[d];
576
578
  delete envs[d];
577
579
  return;
@@ -151,7 +151,6 @@ class Program {
151
151
  forceend_reg = /^(return|break|continue)$/;
152
152
  classstrap_reg = /^(class)$/;
153
153
  extends_reg = /^(extends)$/;
154
- export_reg = /^(export)$/;
155
154
  spaces = spaceDefined;
156
155
  nocase = false
157
156
  lastIndex = 0
@@ -585,7 +584,6 @@ class Program {
585
584
  }
586
585
  else if (last.type === STRAP) {
587
586
  if (last.isend);
588
- else if (this.export_reg.test(last.text));
589
587
  else scope.isObject = queue.inExpress;
590
588
  }
591
589
  }
@@ -753,6 +753,7 @@ var createScoped = function (parsed, wash) {
753
753
  if (scoped.length) _scoped.push(scoped);
754
754
  }
755
755
  if (isArrow) {
756
+ scoped.isArrow = true;
756
757
  if (!thisscope.insett && used.this) thisscope.insett = true;
757
758
  if (!argscope.inseta && used.arguments) argscope.inseta = true;
758
759
  }
@@ -1,7 +1,7 @@
1
1
  var scanner2 = require("./scanner2");
2
2
  var strings = require("../basic/strings");
3
3
  var Program = scanner2.Program;
4
- var { STAMP, SCOPED, STRAP, EXPRESS, COMMENT, SPACE, PROPERTY, VALUE, LABEL, QUOTED, rename, getDeclared, skipAssignment, createScoped, createString, splice, relink, snapExpressHead } = require("./common");
4
+ var { STAMP, SCOPED, STRAP, EXPRESS, COMMENT, SPACE, PROPERTY, VALUE, LABEL, QUOTED, rename, getDeclared, skipAssignment, createScoped, createString, splice, relink, snapExpressHead, needBreakBetween } = require("./common");
5
5
  var splice2 = function (q, from, to, ...a) {
6
6
  var cx = q.indexOf(from);
7
7
  if (cx < 0) throw console.log(splice2.caller, console.format('\r\n<red2>自</red2>'), from && createString([from]), console.format('\r\n<yellow>至</yellow>'), to && createString([to]), console.format(`\r\n<cyan>码列</cyan>`), createString(q)), '结构异常';
@@ -652,10 +652,14 @@ var killspr = function (body, i, _getobjname, killobj) {
652
652
  var cx = body.lastIndexOf(r, i);
653
653
  var dx = body.indexOf(p, cx) + 1;
654
654
  var h1 = h[h.length - 1];
655
+ var h0 = h[0];
656
+ if (r.prev && needBreakBetween(r.prev, r)) {
657
+ h.unshift({ type: STAMP, text: ';' });
658
+ }
655
659
  splice(h1, h1.length, 0, ...splice(body, cx, dx - cx, ...h));
656
660
  i += cx - dx + h.length;
657
661
  if (p.type === EXPRESS && !p.text) {
658
- var cx = h[0].lastIndexOf(p);
662
+ var cx = h0.lastIndexOf(p);
659
663
  if (cx >= 0) splice(h1, cx, 1);
660
664
  }
661
665
  }
@@ -1326,13 +1330,13 @@ var down = function (scoped) {
1326
1330
  };
1327
1331
 
1328
1332
  var markcodes = [];
1329
- if (scoped.isfunc && scoped.used.this && (funcMark || scoped.insett)) {
1333
+ if (scoped.isfunc && scoped.used.this && (funcMark && !scoped.isArrow || scoped.insett)) {
1330
1334
  let tn = _getname("this_");
1331
1335
  rename(scoped.used, "this", tn);
1332
1336
  scoped.used.this.forEach(o => o.origin = 'this');
1333
1337
  markcodes.push(`${tn}=this`);
1334
1338
  }
1335
- if (scoped.isfunc && scoped.used.arguments && (funcMark || scoped.inseta)) {
1339
+ if (scoped.isfunc && scoped.used.arguments && (funcMark && !scoped.isArrow || scoped.inseta)) {
1336
1340
  let an = _getname("arguments_");
1337
1341
  scoped.used.arguments.forEach(o => o.origin = 'arguments');
1338
1342
  rename(scoped.used, "arguments", an);
@@ -4,11 +4,11 @@ var strings = require("../basic/strings");
4
4
  var program = null;
5
5
  var patchTranslate = function (c) {
6
6
  if (c.length) {
7
- c.translate = c.map((o, i) => o.type === PIECE ? strings.decode(`\`${o.text}\``) : `$${i + 1 >> 1}`).join('');
7
+ c.translate = c.map((o, i) => o.type === PIECE ? strings.decode(`\`${o.text}\``) : `$${i + 1 >> 1}`).join('').replace(/\r\n|\r|\n/g, '\r\n');
8
8
  }
9
9
  else {
10
10
  if (/^['"`]/.test(c.text) && c.text.length > 2) {
11
- var text = strings.decode(c.text);
11
+ var text = strings.decode(c.text).replace(/\r\n|\r|\n/g, '\r\n');
12
12
  c.translate = text;
13
13
  }
14
14
  }
@@ -89,7 +89,7 @@ function translate([imap, supports], code) {
89
89
  var getm = function (tt) {
90
90
  tt = tt.trim();
91
91
  if (!imap[tt]) {
92
- console.warn(`<yellow>国际化翻译缺失:</yellow>${tt}`);
92
+ console.warn(`<yellow>${i18n`国际化翻译缺失:`}</yellow>${tt}`);
93
93
  imap[tt] = supports.map(_ => tt);
94
94
  }
95
95
  return imap[tt].map(m => strings.encode(m || tt, '`'));