xmlui 0.5.2-beta.4 → 0.6.0-beta.5

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.
@@ -209,7 +209,8 @@ class Parser {
209
209
  declarationProps = {
210
210
  objectDestruct,
211
211
  };
212
- endToken = objectDestruct.length > 0 ? objectDestruct[objectDestruct.length - 1].endToken : endToken;
212
+ endToken =
213
+ objectDestruct.length > 0 ? objectDestruct[objectDestruct.length - 1].endToken : endToken;
213
214
  }
214
215
  else if (declStart.type === Token_1.TokenType.LSquare) {
215
216
  // --- This is array destructure
@@ -220,7 +221,8 @@ class Parser {
220
221
  declarationProps = {
221
222
  arrayDestruct,
222
223
  };
223
- endToken = arrayDestruct.length > 0 ? arrayDestruct[arrayDestruct.length - 1].endToken : endToken;
224
+ endToken =
225
+ arrayDestruct.length > 0 ? arrayDestruct[arrayDestruct.length - 1].endToken : endToken;
224
226
  }
225
227
  else if (declStart.type === Token_1.TokenType.Identifier) {
226
228
  endToken = this._lexer.get();
@@ -282,7 +284,8 @@ class Parser {
282
284
  declarationProps = {
283
285
  objectDestruct,
284
286
  };
285
- endToken = objectDestruct.length > 0 ? objectDestruct[objectDestruct.length - 1].endToken : endToken;
287
+ endToken =
288
+ objectDestruct.length > 0 ? objectDestruct[objectDestruct.length - 1].endToken : endToken;
286
289
  }
287
290
  else if (declStart.type === Token_1.TokenType.LSquare) {
288
291
  // --- This is array destructure
@@ -293,7 +296,8 @@ class Parser {
293
296
  declarationProps = {
294
297
  arrayDestruct,
295
298
  };
296
- endToken = arrayDestruct.length > 0 ? arrayDestruct[arrayDestruct.length - 1].endToken : endToken;
299
+ endToken =
300
+ arrayDestruct.length > 0 ? arrayDestruct[arrayDestruct.length - 1].endToken : endToken;
297
301
  }
298
302
  else if (declStart.type === Token_1.TokenType.Identifier) {
299
303
  endToken = this._lexer.get();
@@ -1153,7 +1157,9 @@ class Parser {
1153
1157
  * ;
1154
1158
  */
1155
1159
  parseExpr(allowSequence = true) {
1156
- return allowSequence ? this.parseSequenceExpression() : this.parseCondOrSpreadOrAsgnOrArrowExpr();
1160
+ return allowSequence
1161
+ ? this.parseSequenceExpression()
1162
+ : this.parseCondOrSpreadOrAsgnOrArrowExpr();
1157
1163
  }
1158
1164
  /**
1159
1165
  * sequenceExpr
@@ -1851,6 +1857,8 @@ class Parser {
1851
1857
  isGlobal: true,
1852
1858
  }, idToken, idToken);
1853
1859
  }
1860
+ case Token_1.TokenType.Backtick:
1861
+ return this.parseTemplateLiteral();
1854
1862
  case Token_1.TokenType.False:
1855
1863
  case Token_1.TokenType.True:
1856
1864
  this._lexer.get();
@@ -1901,6 +1909,34 @@ class Parser {
1901
1909
  }
1902
1910
  return null;
1903
1911
  }
1912
+ parseTemplateLiteral() {
1913
+ const startToken = this._lexer.get();
1914
+ this._lexer.setStartingPhaseToTemplateLiteral();
1915
+ const segments = [];
1916
+ loop: while (true) {
1917
+ let nextToken = this._lexer.peek();
1918
+ switch (nextToken.type) {
1919
+ case Token_1.TokenType.StringLiteral:
1920
+ this._lexer.get();
1921
+ const str = this.parseStringLiteral(nextToken, false);
1922
+ segments.push(str);
1923
+ break;
1924
+ case Token_1.TokenType.DollarLBrace:
1925
+ this._lexer.get();
1926
+ const innerExpr = this.parseExpr();
1927
+ segments.push(innerExpr);
1928
+ this.expectToken(Token_1.TokenType.RBrace, "W004");
1929
+ this._lexer.setStartingPhaseToTemplateLiteral();
1930
+ break;
1931
+ case Token_1.TokenType.Backtick:
1932
+ break loop;
1933
+ default:
1934
+ this.reportError("W004");
1935
+ }
1936
+ }
1937
+ const endToken = this._lexer.get();
1938
+ return this.createExpressionNode("TempLitE", { segments }, startToken, endToken);
1939
+ }
1904
1940
  /**
1905
1941
  * Parses an array literal
1906
1942
  */
@@ -1949,7 +1985,9 @@ class Parser {
1949
1985
  if (!nameExpr) {
1950
1986
  return null;
1951
1987
  }
1952
- if (nameExpr.type !== "IdE" && nameExpr.type !== "LitE" && nameExpr.type !== "SpreadE") {
1988
+ if (nameExpr.type !== "IdE" &&
1989
+ nameExpr.type !== "LitE" &&
1990
+ nameExpr.type !== "SpreadE") {
1953
1991
  this.reportError("W007");
1954
1992
  return null;
1955
1993
  }
@@ -2000,7 +2038,8 @@ class Parser {
2000
2038
  let valueExpr = null;
2001
2039
  if (nameType === "IdE") {
2002
2040
  const nameFollowerToken = this._lexer.peek();
2003
- if (nameFollowerToken.type === Token_1.TokenType.Comma || nameFollowerToken.type === Token_1.TokenType.RBrace) {
2041
+ if (nameFollowerToken.type === Token_1.TokenType.Comma ||
2042
+ nameFollowerToken.type === Token_1.TokenType.RBrace) {
2004
2043
  valueExpr = Object.assign({}, nameExpr);
2005
2044
  }
2006
2045
  }
@@ -2288,8 +2327,11 @@ class Parser {
2288
2327
  * Converts a string token to intrinsic string
2289
2328
  * @param token Literal token
2290
2329
  */
2291
- parseStringLiteral(token) {
2292
- const input = token.text.length < 2 ? "" : token.text.substring(1, token.text.length - 1);
2330
+ parseStringLiteral(token, quoteSurrounded = true) {
2331
+ let input = token.text;
2332
+ if (quoteSurrounded) {
2333
+ input = token.text.length < 2 ? "" : input.substring(1, input.length - 1);
2334
+ }
2293
2335
  let result = "";
2294
2336
  let state = StrParseState.Normal;
2295
2337
  let collect = 0;
@@ -2346,7 +2388,7 @@ class Parser {
2346
2388
  state = StrParseState.UX1;
2347
2389
  break;
2348
2390
  default:
2349
- result += "\\" + ch;
2391
+ result += ch;
2350
2392
  break;
2351
2393
  }
2352
2394
  break;
@@ -2645,3 +2687,4 @@ class Parser {
2645
2687
  }
2646
2688
  }
2647
2689
  exports.Parser = Parser;
2690
+ "TypeError: Cannot read properties of undefined (reading 'canBeUnary')\n at Parser.parseUnaryOrPrefixExpr (/home/ez/code/work/xmlui/xmlui/src/parsers/scripting/Parser.ts:2041:38)\n at Parser.parseExponentialExpr (/home/ez/code/work/xmlui/xmlui/src/parsers/scripting/Parser.ts:1985:25)\n at Parser.parseMultExpr (/home/ez/code/work/xmlui/xmlui/src/parsers/scripting/Parser.ts:1951:25)\n at Parser.parseAddExpr (/home/ez/code/work/xmlui/xmlui/src/parsers/scripting/Parser.ts:1917:25)\n at Par…nExpr (/home/ez/code/work/xmlui/xmlui/src/parsers/scripting/Parser.ts:1835:25)\n at Parser.parseEquExpr (/home/ez/code/work/xmlui/xmlui/src/parsers/scripting/Parser.ts:1793:25)\n at Parser.parseBitwiseAndExpr (/home/ez/code/work/xmlui/xmlui/src/parsers/scripting/Parser.ts:1760:25)\n at Parser.parseBitwiseXorExpr (/home/ez/code/work/xmlui/xmlui/src/parsers/scripting/Parser.ts:1727:25)\n at Parser.parseBitwiseOrExpr (/home/ez/code/work/xmlui/xmlui/src/parsers/scripting/Parser.ts:1694:25)";
@@ -6,6 +6,8 @@ const Token_1 = require("../../abstractions/scripting/Token");
6
6
  exports.tokenTraits = {
7
7
  [Token_1.TokenType.Eof]: {},
8
8
  [Token_1.TokenType.Ws]: {},
9
+ [Token_1.TokenType.DollarLBrace]: {},
10
+ [Token_1.TokenType.Backtick]: { expressionStart: true },
9
11
  [Token_1.TokenType.BlockComment]: {},
10
12
  [Token_1.TokenType.EolComment]: {},
11
13
  [Token_1.TokenType.Unknown]: {},
@@ -169,15 +169,16 @@ function parseXmlUiMarkup(text) {
169
169
  startNode();
170
170
  const attrNames = [];
171
171
  while (!atAnyOf([syntax_kind_1.SyntaxKind.EndOfFileToken, syntax_kind_1.SyntaxKind.NodeEnd, syntax_kind_1.SyntaxKind.NodeClose])) {
172
- if (at(syntax_kind_1.SyntaxKind.Identifier)) {
173
- parseAttr(attrNames);
174
- }
175
- else {
176
- const atTagLike = errRecover(diagnostics_1.Diag_Attr_Identifier_Expected, firstSetTagLike);
177
- if (atTagLike) {
178
- parseTagLike();
179
- }
180
- }
172
+ parseAttr(attrNames);
173
+ // todo: was this usefuel?
174
+ // if (at(SyntaxKind.Identifier)) {
175
+ // parseAttr(attrNames);
176
+ // } else {
177
+ // const atTagLike = errRecover(Diag_Attr_Identifier_Expected, firstSetTagLike);
178
+ // if (atTagLike) {
179
+ // parseTagLike();
180
+ // }
181
+ // }
181
182
  }
182
183
  if (node.children.length === 0) {
183
184
  abandonNode();
@@ -187,38 +188,63 @@ function parseXmlUiMarkup(text) {
187
188
  }
188
189
  }
189
190
  function parseAttr(attrNames) {
190
- //todo: make this recovery set actualy true (like implement handling cdata ,...)
191
- const attrListFollow = [
192
- // FOLLOW(AttrList) when a Tag is correct
193
- syntax_kind_1.SyntaxKind.NodeClose,
194
- syntax_kind_1.SyntaxKind.NodeEnd,
195
- // FOLLOW(AttrList) when a Tag contains incorrect, but still parsed tokens for resilience
196
- syntax_kind_1.SyntaxKind.CData,
197
- // todo
198
- // SyntaxKind.ScriptLiteral,
199
- syntax_kind_1.SyntaxKind.OpenNodeStart,
200
- ];
201
- const attrFollow = attrListFollow.concat(syntax_kind_1.SyntaxKind.Identifier);
202
- const attrIdent = peek();
203
- const attrName = getText(attrIdent);
204
- if (attrNames.includes(attrName)) {
205
- errorAt(MakeErr.duplAttr(attrName), attrIdent.pos, attrIdent.end);
206
- }
207
- else if (attrName[0] >= "A" && attrName[0] <= "Z") {
208
- errorAt(MakeErr.uppercaseAttr(attrName), attrIdent.pos, attrIdent.end);
191
+ startNode();
192
+ if (at(syntax_kind_1.SyntaxKind.Identifier)) {
193
+ parseAttrName(attrNames);
209
194
  }
210
195
  else {
211
- attrNames.push(attrName);
196
+ const attrNameFollow = [syntax_kind_1.SyntaxKind.Equal];
197
+ const eqFollows = errRecover(diagnostics_1.Diag_Attr_Identifier_Expected, attrNameFollow);
198
+ if (!eqFollows) {
199
+ return;
200
+ }
212
201
  }
213
- startNode();
214
- bump(syntax_kind_1.SyntaxKind.Identifier);
215
202
  if (eat(syntax_kind_1.SyntaxKind.Equal)) {
216
203
  if (!eat(syntax_kind_1.SyntaxKind.StringLiteral) && !eat(syntax_kind_1.SyntaxKind.Identifier)) {
217
- errRecover(diagnostics_1.Diag_Attr_Value_Expected, attrFollow);
204
+ const attrFollowWithoutIdent = [syntax_kind_1.SyntaxKind.NodeEnd, syntax_kind_1.SyntaxKind.NodeClose];
205
+ errRecover(diagnostics_1.Diag_Attr_Value_Expected, attrFollowWithoutIdent);
218
206
  }
219
207
  }
220
208
  completeNode(syntax_kind_1.SyntaxKind.AttributeNode);
221
209
  }
210
+ function parseAttrName(attrNames) {
211
+ const nameIdent = peek();
212
+ let nsIdent = undefined;
213
+ startNode();
214
+ bump(syntax_kind_1.SyntaxKind.Identifier);
215
+ if (eat(syntax_kind_1.SyntaxKind.Colon)) {
216
+ if (at(syntax_kind_1.SyntaxKind.Identifier)) {
217
+ nsIdent = bump(syntax_kind_1.SyntaxKind.Identifier);
218
+ }
219
+ else {
220
+ errRecover(diagnostics_1.Diag_Attr_Identifier_Expected, [
221
+ syntax_kind_1.SyntaxKind.NodeClose,
222
+ syntax_kind_1.SyntaxKind.NodeEnd,
223
+ syntax_kind_1.SyntaxKind.Equal,
224
+ ]);
225
+ }
226
+ }
227
+ checkAttrName(attrNames, { nsIdent, nameIdent });
228
+ completeNode(syntax_kind_1.SyntaxKind.AttributeKeyNode);
229
+ }
230
+ /** emits errors when the attribute name is incorrect. Otherwise adds the attribute name to the list of valid names*/
231
+ function checkAttrName(attrNames, { nameIdent, nsIdent }) {
232
+ const attrName = getText(nameIdent);
233
+ const attrNs = nsIdent === undefined ? undefined : getText(nsIdent);
234
+ const attrKeyMatches = ({ ns, name }) => name === attrName && ns === attrNs;
235
+ const isDuplicate = attrNames.findIndex(attrKeyMatches) !== -1;
236
+ const nameStartsWithUppercase = "A" <= attrName[0] && attrName[0] <= "Z";
237
+ const faultyName = isDuplicate || nameStartsWithUppercase;
238
+ if (isDuplicate) {
239
+ errorAt(MakeErr.duplAttr(attrName), nameIdent.pos, nameIdent.end);
240
+ }
241
+ if (nameStartsWithUppercase) {
242
+ errorAt(MakeErr.uppercaseAttr(attrName), nameIdent.pos, nameIdent.end);
243
+ }
244
+ if (!faultyName) {
245
+ attrNames.push({ name: attrName });
246
+ }
247
+ }
222
248
  function at(kindToCheck) {
223
249
  return peek().kind === kindToCheck;
224
250
  }
@@ -233,8 +259,9 @@ function parseXmlUiMarkup(text) {
233
259
  return kinds.includes(peek().kind);
234
260
  }
235
261
  /**
236
- * @param recoveryTokens the [FollowSet](https://www.geeksforgeeks.org/follow-set-in-syntax-analysis/) of the parsed InnerNode
237
- * @returns true if the current token is in the recovery set, otherwise false
262
+ * report an error and skip the next token if it isn't in the recoveryTokens. EoF isn't skipped.
263
+ * @param recoveryTokens the [FollowSet](https://www.geeksforgeeks.org/follow-set-in-syntax-analysis/) of the parsed InnerNode. These tokens (or the EoF token) won't be skipped
264
+ * @returns true if the current token is in the recovery set or EoF
238
265
  * */
239
266
  function errRecover(errCodeAndMsg, recoveryTokens) {
240
267
  if (atAnyOf(recoveryTokens) || at(syntax_kind_1.SyntaxKind.EndOfFileToken)) {
@@ -364,6 +391,7 @@ function parseXmlUiMarkup(text) {
364
391
  if (token.kind !== kind) {
365
392
  throw new Error(`expected ${(0, syntax_kind_1.getSyntaxKindStrRepr)(kind)}, bumped a ${(0, syntax_kind_1.getSyntaxKindStrRepr)(token.kind)}`);
366
393
  }
394
+ return token;
367
395
  }
368
396
  function bumpAny() {
369
397
  if (peekedToken) {
@@ -454,6 +482,7 @@ function parseXmlUiMarkup(text) {
454
482
  }
455
483
  }
456
484
  }
485
+ /** Bumps over the next token and marks it as an error node while adding an error to the error list*/
457
486
  function errorAndBump(errCodeAndMsg) {
458
487
  errRecover(errCodeAndMsg, []);
459
488
  }
@@ -4,6 +4,7 @@ exports.SyntaxKind = void 0;
4
4
  exports.isTrivia = isTrivia;
5
5
  exports.isInnerNode = isInnerNode;
6
6
  exports.getSyntaxKindStrRepr = getSyntaxKindStrRepr;
7
+ /** tokens and nodes combined. Order is significant since the functions below use the numeric values of this enum to check for a range of possible values*/
7
8
  var SyntaxKind;
8
9
  (function (SyntaxKind) {
9
10
  SyntaxKind[SyntaxKind["Unknown"] = 0] = "Unknown";
@@ -34,14 +35,15 @@ var SyntaxKind;
34
35
  // Syntax node types
35
36
  SyntaxKind[SyntaxKind["ElementNode"] = 21] = "ElementNode";
36
37
  SyntaxKind[SyntaxKind["AttributeNode"] = 22] = "AttributeNode";
37
- SyntaxKind[SyntaxKind["ContentListNode"] = 23] = "ContentListNode";
38
- SyntaxKind[SyntaxKind["AttributeListNode"] = 24] = "AttributeListNode";
39
- SyntaxKind[SyntaxKind["TagNameNode"] = 25] = "TagNameNode";
38
+ SyntaxKind[SyntaxKind["AttributeKeyNode"] = 23] = "AttributeKeyNode";
39
+ SyntaxKind[SyntaxKind["ContentListNode"] = 24] = "ContentListNode";
40
+ SyntaxKind[SyntaxKind["AttributeListNode"] = 25] = "AttributeListNode";
41
+ SyntaxKind[SyntaxKind["TagNameNode"] = 26] = "TagNameNode";
40
42
  // should be the last syntax node type
41
- SyntaxKind[SyntaxKind["ErrorNode"] = 26] = "ErrorNode";
43
+ SyntaxKind[SyntaxKind["ErrorNode"] = 27] = "ErrorNode";
42
44
  })(SyntaxKind || (exports.SyntaxKind = SyntaxKind = {}));
43
45
  function isTrivia(token) {
44
- return (token >= SyntaxKind.CommentTrivia && token <= SyntaxKind.WhitespaceTrivia);
46
+ return token >= SyntaxKind.CommentTrivia && token <= SyntaxKind.WhitespaceTrivia;
45
47
  }
46
48
  function isInnerNode(token) {
47
49
  return token >= SyntaxKind.ElementNode && token <= SyntaxKind.ErrorNode;
@@ -49,58 +51,64 @@ function isInnerNode(token) {
49
51
  function getSyntaxKindStrRepr(kind) {
50
52
  switch (kind) {
51
53
  case SyntaxKind.Unknown:
52
- return 'Unknown';
54
+ return "Unknown";
53
55
  case SyntaxKind.EndOfFileToken:
54
- return 'EndOfFileToken';
56
+ return "EndOfFileToken";
55
57
  case SyntaxKind.CommentTrivia:
56
- return 'CommentTrivia';
58
+ return "CommentTrivia";
57
59
  case SyntaxKind.NewLineTrivia:
58
- return 'NewLineTrivia';
60
+ return "NewLineTrivia";
59
61
  case SyntaxKind.WhitespaceTrivia:
60
- return 'WhitespaceTrivia';
62
+ return "WhitespaceTrivia";
61
63
  case SyntaxKind.Identifier:
62
- return 'Identifier';
64
+ return "Identifier";
63
65
  case SyntaxKind.OpenNodeStart:
64
- return 'OpenNodeStart';
66
+ return "OpenNodeStart";
65
67
  case SyntaxKind.CloseNodeStart:
66
- return 'CloseNodeStart';
68
+ return "CloseNodeStart";
67
69
  case SyntaxKind.NodeEnd:
68
- return 'NodeEnd';
70
+ return "NodeEnd";
69
71
  case SyntaxKind.NodeClose:
70
- return 'NodeClose';
72
+ return "NodeClose";
71
73
  case SyntaxKind.Colon:
72
- return 'Colon';
74
+ return "Colon";
73
75
  case SyntaxKind.Equal:
74
- return 'Equal';
76
+ return "Equal";
75
77
  case SyntaxKind.StringLiteral:
76
- return 'StringLiteral';
78
+ return "StringLiteral";
77
79
  case SyntaxKind.CData:
78
- return 'CData';
80
+ return "CData";
79
81
  case SyntaxKind.Script:
80
- return 'Script';
82
+ return "Script";
81
83
  case SyntaxKind.AmpersandEntity:
82
- return 'AmpersandEntity';
84
+ return "AmpersandEntity";
83
85
  case SyntaxKind.LessThanEntity:
84
- return 'LessThanEntity';
86
+ return "LessThanEntity";
85
87
  case SyntaxKind.GreaterThanEntity:
86
- return 'GreaterThanEntity';
88
+ return "GreaterThanEntity";
87
89
  case SyntaxKind.SingleQuoteEntity:
88
- return 'SingleQuoteEntity';
90
+ return "SingleQuoteEntity";
89
91
  case SyntaxKind.DoubleQuoteEntity:
90
- return 'DoubleQuoteEntity';
92
+ return "DoubleQuoteEntity";
91
93
  case SyntaxKind.ElementNode:
92
- return 'ElementNode';
94
+ return "ElementNode";
93
95
  case SyntaxKind.AttributeNode:
94
- return 'AttributeNode';
96
+ return "AttributeNode";
95
97
  case SyntaxKind.TextNode:
96
- return 'TextNode';
98
+ return "TextNode";
97
99
  case SyntaxKind.ContentListNode:
98
- return 'ContentListNode';
100
+ return "ContentListNode";
99
101
  case SyntaxKind.AttributeListNode:
100
- return 'AttributeListNode';
102
+ return "AttributeListNode";
101
103
  case SyntaxKind.TagNameNode:
102
- return 'TagNameNode';
104
+ return "TagNameNode";
103
105
  case SyntaxKind.ErrorNode:
104
- return 'ErrorNode';
106
+ return "ErrorNode";
107
+ case SyntaxKind.AttributeKeyNode:
108
+ return "AttributeKeyNode";
105
109
  }
110
+ return assertUnreachable(kind);
111
+ }
112
+ function assertUnreachable(x) {
113
+ throw new Error("Didn't expect to get here");
106
114
  }
@@ -558,13 +558,18 @@ function nodeToComponentDef(node, originalGetText, fileId, moduleResolver = () =
558
558
  return getText(name);
559
559
  }
560
560
  function segmentAttr(attr) {
561
- let key = getText(attr.children[0]);
562
- const segments = key.split(".");
561
+ let key = attr.children[0];
562
+ const hasNamespace = key.children.length === 3;
563
+ let namespace;
564
+ if (hasNamespace) {
565
+ namespace = getText(key.children[0]);
566
+ }
567
+ let name = getText(key.children[key.children.length - 1]);
568
+ const segments = name.split(".");
563
569
  if (segments.length > 2) {
564
570
  reportError("T007", attr, key);
565
571
  }
566
572
  let startSegment;
567
- let name = key;
568
573
  if (segments.length === 2) {
569
574
  startSegment = segments[0];
570
575
  name = segments[1];
@@ -831,7 +836,10 @@ function createTextNodeCDataElement(textValue) {
831
836
  {
832
837
  kind: syntax_kind_1.SyntaxKind.AttributeNode,
833
838
  children: [
834
- { kind: syntax_kind_1.SyntaxKind.Identifier, text: "value" },
839
+ {
840
+ kind: syntax_kind_1.SyntaxKind.AttributeKeyNode,
841
+ children: [{ kind: syntax_kind_1.SyntaxKind.Identifier, text: "value" }],
842
+ },
835
843
  { kind: syntax_kind_1.SyntaxKind.Equal },
836
844
  { kind: syntax_kind_1.SyntaxKind.Identifier, text: `"${textValue}"` },
837
845
  ],
@@ -857,7 +865,10 @@ function createTextNodeElement(textValue) {
857
865
  {
858
866
  kind: syntax_kind_1.SyntaxKind.AttributeNode,
859
867
  children: [
860
- { kind: syntax_kind_1.SyntaxKind.Identifier, text: "value" },
868
+ {
869
+ kind: syntax_kind_1.SyntaxKind.AttributeKeyNode,
870
+ children: [{ kind: syntax_kind_1.SyntaxKind.Identifier, text: "value" }],
871
+ },
861
872
  { kind: syntax_kind_1.SyntaxKind.Equal },
862
873
  { kind: syntax_kind_1.SyntaxKind.Identifier, text: `"${textValue}"` },
863
874
  ],