astro-eslint-parser 0.0.0 → 0.0.3

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/README.md CHANGED
@@ -11,6 +11,7 @@ You can check it on [Online DEMO](https://ota-meshi.github.io/astro-eslint-parse
11
11
  [![NPM downloads](https://img.shields.io/npm/dy/astro-eslint-parser.svg)](http://www.npmtrends.com/astro-eslint-parser)
12
12
  [![NPM downloads](https://img.shields.io/npm/dt/astro-eslint-parser.svg)](http://www.npmtrends.com/astro-eslint-parser)
13
13
  [![Build Status](https://github.com/ota-meshi/astro-eslint-parser/workflows/CI/badge.svg?branch=main)](https://github.com/ota-meshi/astro-eslint-parser/actions?query=workflow%3ACI)
14
+ [![Coverage Status](https://coveralls.io/repos/github/ota-meshi/astro-eslint-parser/badge.svg?branch=main)](https://coveralls.io/github/ota-meshi/astro-eslint-parser?branch=main)
14
15
 
15
16
  This parser is in the ***experimental stages*** of development.
16
17
 
@@ -133,9 +134,20 @@ Example **.vscode/settings.json**:
133
134
  }
134
135
  ```
135
136
 
137
+ ## Compatibility With Existing ESLint Rules
138
+
139
+ Most of the rules in the ESLint core work for the script part, but some rules are incompatible.
140
+ For example, the [semi] rule doesn't work.
141
+ This parser will generate a JSX compatible AST for most of the HTML part of the Astro component. Therefore, some rules of [eslint-plugin-react] may work.
142
+ For example, the [react/jsx-no-target-blank] rule works fine.
143
+
144
+ [semi]: https://eslint.org/docs/rules/semi
145
+ [eslint-plugin-react]: https://github.com/jsx-eslint/eslint-plugin-react/
146
+ [react/jsx-no-target-blank]: https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-no-target-blank.md
147
+
136
148
  ## Usage for Custom Rules / Plugins
137
149
 
138
- - TBD
150
+ - TBA
139
151
 
140
152
  <!-- - [AST.md](./docs/AST.md) is AST specification. You can check it on the [Online DEMO](https://ota-meshi.github.io/astro-eslint-parser/). -->
141
153
  <!-- - I have already [implemented some rules] in the [`@ota-meshi/eslint-plugin-astro`]. The source code for these rules will be helpful to you. -->
@@ -1,11 +1,6 @@
1
- import type { ParseResult } from "@astrojs/compiler";
2
1
  import type { Context } from ".";
3
2
  import type { ESLintExtendedProgram } from "../parser";
4
3
  import type { TSESTree } from "@typescript-eslint/types";
5
- /**
6
- * Process the template to generate a ScriptContext.
7
- */
8
- export declare function processTemplate(ctx: Context, resultTemplate: ParseResult): ScriptContext;
9
4
  export declare class ScriptContext {
10
5
  private readonly ctx;
11
6
  script: string;
@@ -1,214 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ScriptContext = exports.processTemplate = void 0;
3
+ exports.ScriptContext = void 0;
4
4
  const traverse_1 = require("../traverse");
5
- const types_1 = require("@typescript-eslint/types");
6
5
  const errors_1 = require("../errors");
7
- const astro_1 = require("../astro");
8
- /**
9
- * Process the template to generate a ScriptContext.
10
- */
11
- function processTemplate(ctx, resultTemplate) {
12
- const script = new ScriptContext(ctx);
13
- const frontmatter = resultTemplate.ast.children.find((n) => n.type === "frontmatter");
14
- let fragmentOpened = false;
15
- if (!frontmatter) {
16
- script.appendScript("<>");
17
- fragmentOpened = true;
18
- }
19
- (0, astro_1.walkElements)(resultTemplate.ast, (node, parent) => {
20
- if (node.type === "frontmatter") {
21
- const start = node.position.start.offset;
22
- script.appendOriginal(start);
23
- script.skipOriginalOffset(3);
24
- const end = node.position.end.offset;
25
- script.appendOriginal(end - 3);
26
- script.appendScript(";<>");
27
- fragmentOpened = true;
28
- script.skipOriginalOffset(3);
29
- script.addRestoreNodeProcess((_scriptNode, result) => {
30
- for (let index = 0; index < result.ast.body.length; index++) {
31
- const st = result.ast.body[index];
32
- if (st.type === types_1.AST_NODE_TYPES.EmptyStatement) {
33
- if (st.range[0] === end - 3 && st.range[1] === end) {
34
- result.ast.body.splice(index, 1);
35
- break;
36
- }
37
- }
38
- }
39
- return true;
40
- });
41
- script.addToken(types_1.AST_TOKEN_TYPES.Punctuator, [
42
- node.position.start.offset,
43
- node.position.start.offset + 3,
44
- ]);
45
- script.addToken(types_1.AST_TOKEN_TYPES.Punctuator, [end - 3, end]);
46
- }
47
- else if ((0, astro_1.isTag)(node)) {
48
- for (const attr of node.attributes) {
49
- if (attr.kind === "shorthand") {
50
- const start = attr.position.start.offset;
51
- script.appendOriginal(start);
52
- script.appendScript(`${attr.name}=`);
53
- script.addRestoreNodeProcess((scriptNode) => {
54
- if (scriptNode.type === types_1.AST_NODE_TYPES.JSXAttribute &&
55
- scriptNode.range[0] === start) {
56
- const attrNode = scriptNode;
57
- attrNode.type = "AstroShorthandAttribute";
58
- const locs = ctx.getLocations(...attrNode.value.expression.range);
59
- attrNode.name.range = locs.range;
60
- attrNode.name.loc = locs.loc;
61
- return true;
62
- }
63
- return false;
64
- });
65
- }
66
- else if (attr.kind === "template-literal") {
67
- const start = (0, astro_1.getAttributeValueStartOffset)(attr, ctx.code);
68
- const end = (0, astro_1.getAttributeEndOffset)(attr, ctx.code);
69
- script.appendOriginal(start);
70
- script.appendScript("{");
71
- script.appendOriginal(end);
72
- script.appendScript("}");
73
- script.addRestoreNodeProcess((scriptNode) => {
74
- if (scriptNode.type === types_1.AST_NODE_TYPES.JSXAttribute &&
75
- scriptNode.range[0] === start) {
76
- const attrNode = scriptNode;
77
- attrNode.type = "AstroTemplateLiteralAttribute";
78
- return true;
79
- }
80
- return false;
81
- });
82
- }
83
- }
84
- const end = getVoidSelfClosingTag(node, parent, ctx);
85
- if (end && end.end === ">") {
86
- script.appendOriginal(end.offset - 1);
87
- script.appendScript("/");
88
- }
89
- if (node.name === "script" || node.name === "style") {
90
- const text = node.children[0];
91
- if (text && text.type === "text") {
92
- const styleNodeStart = node.position.start.offset;
93
- const start = text.position.start.offset;
94
- script.appendOriginal(start);
95
- script.skipOriginalOffset(text.value.length);
96
- script.addRestoreNodeProcess((scriptNode) => {
97
- if (scriptNode.type === types_1.AST_NODE_TYPES.JSXElement &&
98
- scriptNode.range[0] === styleNodeStart) {
99
- const textNode = Object.assign({ type: types_1.AST_NODE_TYPES.JSXText, value: text.value, raw: text.value, parent: scriptNode }, ctx.getLocations(start, start + text.value.length));
100
- scriptNode.children = [textNode];
101
- return true;
102
- }
103
- return false;
104
- });
105
- script.addToken(types_1.AST_TOKEN_TYPES.JSXText, [
106
- start,
107
- start + text.value.length,
108
- ]);
109
- }
110
- }
111
- }
112
- else if (node.type === "comment") {
113
- const start = node.position.start.offset;
114
- const length = 4 + node.value.length + 3;
115
- script.appendOriginal(start);
116
- let targetType;
117
- if (fragmentOpened) {
118
- script.appendScript(`<></>`);
119
- targetType = types_1.AST_NODE_TYPES.JSXFragment;
120
- }
121
- else {
122
- script.appendScript(`0;`);
123
- targetType = types_1.AST_NODE_TYPES.ExpressionStatement;
124
- }
125
- script.skipOriginalOffset(length);
126
- script.addRestoreNodeProcess((scriptNode) => {
127
- if (scriptNode.range[0] === start &&
128
- scriptNode.type === targetType) {
129
- delete scriptNode.children;
130
- delete scriptNode.openingFragment;
131
- delete scriptNode.closingFragment;
132
- delete scriptNode.expression;
133
- const commentNode = scriptNode;
134
- commentNode.type = "AstroHTMLComment";
135
- commentNode.value = node.value;
136
- return true;
137
- }
138
- return false;
139
- });
140
- script.addToken("HTMLComment", [
141
- start,
142
- start + length,
143
- ]);
144
- }
145
- else if (node.type === "doctype") {
146
- const start = node.position.start.offset;
147
- const end = node.position.end.offset;
148
- script.appendOriginal(start);
149
- let targetType;
150
- if (fragmentOpened) {
151
- script.appendScript(`<></>`);
152
- targetType = types_1.AST_NODE_TYPES.JSXFragment;
153
- }
154
- else {
155
- script.appendScript(`0;`);
156
- targetType = types_1.AST_NODE_TYPES.ExpressionStatement;
157
- }
158
- script.skipOriginalOffset(end - start);
159
- script.addRestoreNodeProcess((scriptNode) => {
160
- if (scriptNode.range[0] === start &&
161
- scriptNode.type === targetType) {
162
- delete scriptNode.children;
163
- delete scriptNode.openingFragment;
164
- delete scriptNode.closingFragment;
165
- delete scriptNode.expression;
166
- const doctypeNode = scriptNode;
167
- doctypeNode.type = "AstroDoctype";
168
- return true;
169
- }
170
- return false;
171
- });
172
- script.addToken("HTMLDocType", [start, end]);
173
- }
174
- });
175
- script.appendOriginal(ctx.code.length);
176
- script.appendScript("</>");
177
- return script;
178
- }
179
- exports.processTemplate = processTemplate;
180
- /**
181
- * If the given tag is a void tag, get the self-closing tag.
182
- */
183
- function getVoidSelfClosingTag(node, parent, ctx) {
184
- if (node.type === "fragment") {
185
- return false;
186
- }
187
- if (node.children.length > 0) {
188
- return false;
189
- }
190
- const code = ctx.code;
191
- let nextElementIndex = code.length;
192
- const childIndex = parent.children.indexOf(node);
193
- if (childIndex === parent.children.length - 1) {
194
- // last
195
- nextElementIndex = parent.position.end.offset;
196
- nextElementIndex = code.lastIndexOf("</", nextElementIndex);
197
- }
198
- else {
199
- const next = parent.children[childIndex + 1];
200
- nextElementIndex = next.position.start.offset;
201
- }
202
- const endOffset = (0, astro_1.getStartTagEndOffset)(node, code);
203
- if (code.slice(endOffset, nextElementIndex).trim()) {
204
- // has end tag
205
- return null;
206
- }
207
- return {
208
- offset: endOffset,
209
- end: code.slice(endOffset - 2, endOffset) === "/>" ? "/>" : ">",
210
- };
211
- }
212
6
  class ScriptContext {
213
7
  constructor(ctx) {
214
8
  this.script = "";
@@ -252,6 +46,11 @@ class ScriptContext {
252
46
  if (last.expression.type !== "JSXFragment") {
253
47
  throw new errors_1.ParseError("Unknown state error: Expected JSXFragment", last.expression.range[0], this.ctx);
254
48
  }
49
+ // Process for Astro
50
+ const rootFragment = (result.ast.body[result.ast.body.length - 1] = last.expression);
51
+ delete rootFragment.closingFragment;
52
+ delete rootFragment.openingFragment;
53
+ rootFragment.type = "AstroRootFragment";
255
54
  // remap locations
256
55
  const traversed = new Set();
257
56
  (0, traverse_1.traverseNodes)(result.ast, {
@@ -278,11 +77,6 @@ class ScriptContext {
278
77
  for (const token of result.ast.comments || []) {
279
78
  this.remapLocation(token);
280
79
  }
281
- // Process for Astro
282
- delete last.expression.closingFragment;
283
- delete last.expression.openingFragment;
284
- last.expression.type =
285
- "AstroRootFragment";
286
80
  let restoreNodeProcesses = this.restoreNodeProcesses;
287
81
  for (const node of traversed) {
288
82
  restoreNodeProcesses = restoreNodeProcesses.filter((proc) => !proc(node, result));
@@ -41,9 +41,7 @@ exports.parse = parse;
41
41
  function fixLocations(node, code) {
42
42
  // FIXME: Adjust because the parser does not return the correct location.
43
43
  let start = 0;
44
- (0, astro_1.walk)(node,
45
- // eslint-disable-next-line complexity -- ignore
46
- (node) => {
44
+ (0, astro_1.walk)(node, (node) => {
47
45
  if (node.type === "frontmatter") {
48
46
  start = node.position.start.offset = tokenIndex(code, "---", start);
49
47
  start = node.position.end.offset =
@@ -58,11 +56,7 @@ function fixLocations(node, code) {
58
56
  }
59
57
  start = node.position.start.offset = tokenIndex(code, "<", start);
60
58
  start += 1;
61
- if (node.type === "element" ||
62
- node.type === "component" ||
63
- node.type === "custom-element") {
64
- start += node.name.length;
65
- }
59
+ start += node.name.length;
66
60
  if (!node.attributes.length) {
67
61
  start = (0, astro_1.getStartTagEndOffset)(node, code);
68
62
  }
@@ -106,20 +100,18 @@ function fixLocations(node, code) {
106
100
  if (node.type === "expression") {
107
101
  start = tokenIndex(code, "}", start) + 1;
108
102
  }
109
- else if (node.type === "fragment") {
110
- start = tokenIndex(code, "</>", start) + 3;
111
- }
112
- else if (node.type === "element" ||
103
+ else if (node.type === "fragment" ||
104
+ node.type === "element" ||
113
105
  node.type === "component" ||
114
106
  node.type === "custom-element") {
115
107
  if (!node.position.end) {
116
108
  return;
117
109
  }
118
- start =
119
- tokenIndex(code, `</${node.name}`, start) +
120
- 2 +
121
- node.name.length;
122
- start = tokenIndex(code, ">", start) + 1;
110
+ const closeTagStart = tokenIndexSafe(code, `</${node.name}`, start);
111
+ if (closeTagStart != null) {
112
+ start = closeTagStart + 2 + node.name.length;
113
+ start = tokenIndex(code, ">", start) + 1;
114
+ }
123
115
  }
124
116
  else {
125
117
  return;
@@ -159,9 +151,20 @@ function fixLocationForAttr(node, code, start) {
159
151
  * Get token index
160
152
  */
161
153
  function tokenIndex(string, token, position) {
154
+ const index = tokenIndexSafe(string, token, position);
155
+ if (index == null) {
156
+ const start = token.trim() === token ? (0, astro_1.skipSpaces)(string, position) : position;
157
+ throw new Error(`Unknown token at ${start}, expected: ${JSON.stringify(token)}, actual: ${JSON.stringify(string.slice(start, start + 10))}`);
158
+ }
159
+ return index;
160
+ }
161
+ /**
162
+ * Get token index
163
+ */
164
+ function tokenIndexSafe(string, token, position) {
162
165
  const index = token.trim() === token ? (0, astro_1.skipSpaces)(string, position) : position;
163
166
  if (string.startsWith(token, index)) {
164
167
  return index;
165
168
  }
166
- throw new Error(`Unknown token at ${index}, expected: ${JSON.stringify(token)}, actual: ${JSON.stringify(string.slice(index, index + 10))}`);
169
+ return null;
167
170
  }
@@ -8,7 +8,7 @@ const script_1 = require("./script");
8
8
  const sort_1 = require("./sort");
9
9
  const errors_1 = require("../errors");
10
10
  const parse_1 = require("./astro-parser/parse");
11
- const script_2 = require("../context/script");
11
+ const process_template_1 = require("./process-template");
12
12
  /**
13
13
  * Parse source code
14
14
  */
@@ -21,7 +21,7 @@ function parseForESLint(code, options) {
21
21
  }
22
22
  const ctx = new context_1.Context(code, parserOptions);
23
23
  const resultTemplate = parseTemplate(ctx.code, ctx);
24
- const scriptContext = (0, script_2.processTemplate)(ctx, resultTemplate);
24
+ const scriptContext = (0, process_template_1.processTemplate)(ctx, resultTemplate);
25
25
  const resultScript = (0, script_1.parseScript)(scriptContext.script, ctx);
26
26
  scriptContext.restore(resultScript);
27
27
  (0, sort_1.sort)(resultScript.ast.comments);
@@ -0,0 +1,7 @@
1
+ import type { ParseResult } from "@astrojs/compiler";
2
+ import type { Context } from "../context";
3
+ import { ScriptContext } from "../context/script";
4
+ /**
5
+ * Process the template to generate a ScriptContext.
6
+ */
7
+ export declare function processTemplate(ctx: Context, resultTemplate: ParseResult): ScriptContext;
@@ -0,0 +1,263 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.processTemplate = void 0;
4
+ const types_1 = require("@typescript-eslint/types");
5
+ const astro_1 = require("../astro");
6
+ const script_1 = require("../context/script");
7
+ /**
8
+ * Process the template to generate a ScriptContext.
9
+ */
10
+ function processTemplate(ctx, resultTemplate) {
11
+ const script = new script_1.ScriptContext(ctx);
12
+ const frontmatter = resultTemplate.ast.children.find((n) => n.type === "frontmatter");
13
+ let fragmentOpened = false;
14
+ if (!frontmatter) {
15
+ script.appendScript("<>");
16
+ fragmentOpened = true;
17
+ }
18
+ // eslint-disable-next-line complexity -- X(
19
+ (0, astro_1.walkElements)(resultTemplate.ast, (node, parent) => {
20
+ if (node.type === "frontmatter") {
21
+ const start = node.position.start.offset;
22
+ script.appendOriginal(start);
23
+ script.skipOriginalOffset(3);
24
+ const end = node.position.end.offset;
25
+ script.appendOriginal(end - 3);
26
+ script.appendScript(";<>");
27
+ fragmentOpened = true;
28
+ script.skipOriginalOffset(3);
29
+ script.addRestoreNodeProcess((_scriptNode, result) => {
30
+ for (let index = 0; index < result.ast.body.length; index++) {
31
+ const st = result.ast.body[index];
32
+ if (st.type === types_1.AST_NODE_TYPES.EmptyStatement) {
33
+ if (st.range[0] === end - 3 && st.range[1] === end) {
34
+ result.ast.body.splice(index, 1);
35
+ break;
36
+ }
37
+ }
38
+ }
39
+ return true;
40
+ });
41
+ script.addToken(types_1.AST_TOKEN_TYPES.Punctuator, [
42
+ node.position.start.offset,
43
+ node.position.start.offset + 3,
44
+ ]);
45
+ script.addToken(types_1.AST_TOKEN_TYPES.Punctuator, [end - 3, end]);
46
+ }
47
+ else if ((0, astro_1.isTag)(node)) {
48
+ for (const attr of node.attributes) {
49
+ if ((node.type === "component" || node.type === "fragment") &&
50
+ (attr.kind === "quoted" ||
51
+ attr.kind === "empty" ||
52
+ attr.kind === "expression" ||
53
+ attr.kind === "template-literal")) {
54
+ const colonIndex = attr.name.indexOf(":");
55
+ if (colonIndex >= 0) {
56
+ const start = attr.position.start.offset;
57
+ script.appendOriginal(start + colonIndex);
58
+ script.skipOriginalOffset(1);
59
+ script.appendScript(`_`);
60
+ script.addToken(types_1.AST_TOKEN_TYPES.JSXIdentifier, [
61
+ start,
62
+ start + colonIndex,
63
+ ]);
64
+ script.addToken(types_1.AST_TOKEN_TYPES.Punctuator, [
65
+ start + colonIndex,
66
+ start + colonIndex + 1,
67
+ ]);
68
+ script.addToken(types_1.AST_TOKEN_TYPES.JSXIdentifier, [
69
+ start + colonIndex + 1,
70
+ start + attr.name.length,
71
+ ]);
72
+ script.addRestoreNodeProcess((scriptNode, result) => {
73
+ if (scriptNode.type ===
74
+ types_1.AST_NODE_TYPES.JSXAttribute &&
75
+ scriptNode.range[0] === start) {
76
+ const baseNameNode = scriptNode.name;
77
+ const nsn = Object.assign(Object.assign({}, baseNameNode), { type: types_1.AST_NODE_TYPES.JSXNamespacedName, namespace: Object.assign({ type: types_1.AST_NODE_TYPES.JSXIdentifier, name: attr.name.slice(0, colonIndex) }, ctx.getLocations(baseNameNode.range[0], baseNameNode.range[0] + colonIndex)), name: Object.assign({ type: types_1.AST_NODE_TYPES.JSXIdentifier, name: attr.name.slice(colonIndex + 1) }, ctx.getLocations(baseNameNode.range[0] +
78
+ colonIndex +
79
+ 1, baseNameNode.range[1])) });
80
+ scriptNode.name = nsn;
81
+ nsn.namespace.parent = nsn;
82
+ nsn.name.parent = nsn;
83
+ const tokens = result.ast.tokens || [];
84
+ for (let index = 0; index < tokens.length; index++) {
85
+ const token = tokens[index];
86
+ if (token.range[0] ===
87
+ baseNameNode.range[0] &&
88
+ token.range[1] === baseNameNode.range[1]) {
89
+ tokens.splice(index, 1);
90
+ break;
91
+ }
92
+ }
93
+ return true;
94
+ }
95
+ return false;
96
+ });
97
+ }
98
+ }
99
+ if (attr.kind === "shorthand") {
100
+ const start = attr.position.start.offset;
101
+ script.appendOriginal(start);
102
+ script.appendScript(`${attr.name}=`);
103
+ script.addRestoreNodeProcess((scriptNode) => {
104
+ if (scriptNode.type === types_1.AST_NODE_TYPES.JSXAttribute &&
105
+ scriptNode.range[0] === start) {
106
+ const attrNode = scriptNode;
107
+ attrNode.type = "AstroShorthandAttribute";
108
+ const locs = ctx.getLocations(...attrNode.value.expression.range);
109
+ attrNode.name.range = locs.range;
110
+ attrNode.name.loc = locs.loc;
111
+ return true;
112
+ }
113
+ return false;
114
+ });
115
+ }
116
+ else if (attr.kind === "template-literal") {
117
+ const attrStart = attr.position.start.offset;
118
+ const start = (0, astro_1.getAttributeValueStartOffset)(attr, ctx.code);
119
+ const end = (0, astro_1.getAttributeEndOffset)(attr, ctx.code);
120
+ script.appendOriginal(start);
121
+ script.appendScript("{");
122
+ script.appendOriginal(end);
123
+ script.appendScript("}");
124
+ script.addRestoreNodeProcess((scriptNode) => {
125
+ if (scriptNode.type === types_1.AST_NODE_TYPES.JSXAttribute &&
126
+ scriptNode.range[0] === attrStart) {
127
+ const attrNode = scriptNode;
128
+ attrNode.type = "AstroTemplateLiteralAttribute";
129
+ return true;
130
+ }
131
+ return false;
132
+ });
133
+ }
134
+ }
135
+ const end = getVoidSelfClosingTag(node, parent, ctx);
136
+ if (end && end.end === ">") {
137
+ script.appendOriginal(end.offset - 1);
138
+ script.appendScript("/");
139
+ }
140
+ if (node.name === "script" || node.name === "style") {
141
+ const text = node.children[0];
142
+ if (text && text.type === "text") {
143
+ const styleNodeStart = node.position.start.offset;
144
+ const start = text.position.start.offset;
145
+ script.appendOriginal(start);
146
+ script.skipOriginalOffset(text.value.length);
147
+ script.addRestoreNodeProcess((scriptNode) => {
148
+ if (scriptNode.type === types_1.AST_NODE_TYPES.JSXElement &&
149
+ scriptNode.range[0] === styleNodeStart) {
150
+ const textNode = Object.assign({ type: types_1.AST_NODE_TYPES.JSXText, value: text.value, raw: text.value, parent: scriptNode }, ctx.getLocations(start, start + text.value.length));
151
+ scriptNode.children = [textNode];
152
+ return true;
153
+ }
154
+ return false;
155
+ });
156
+ script.addToken(types_1.AST_TOKEN_TYPES.JSXText, [
157
+ start,
158
+ start + text.value.length,
159
+ ]);
160
+ }
161
+ }
162
+ }
163
+ else if (node.type === "comment") {
164
+ const start = node.position.start.offset;
165
+ const length = 4 + node.value.length + 3;
166
+ script.appendOriginal(start);
167
+ let targetType;
168
+ if (fragmentOpened) {
169
+ script.appendScript(`<></>`);
170
+ targetType = types_1.AST_NODE_TYPES.JSXFragment;
171
+ }
172
+ else {
173
+ script.appendScript(`0;`);
174
+ targetType = types_1.AST_NODE_TYPES.ExpressionStatement;
175
+ }
176
+ script.skipOriginalOffset(length);
177
+ script.addRestoreNodeProcess((scriptNode) => {
178
+ if (scriptNode.range[0] === start &&
179
+ scriptNode.type === targetType) {
180
+ delete scriptNode.children;
181
+ delete scriptNode.openingFragment;
182
+ delete scriptNode.closingFragment;
183
+ delete scriptNode.expression;
184
+ const commentNode = scriptNode;
185
+ commentNode.type = "AstroHTMLComment";
186
+ commentNode.value = node.value;
187
+ return true;
188
+ }
189
+ return false;
190
+ });
191
+ script.addToken("HTMLComment", [
192
+ start,
193
+ start + length,
194
+ ]);
195
+ }
196
+ else if (node.type === "doctype") {
197
+ const start = node.position.start.offset;
198
+ const end = node.position.end.offset;
199
+ script.appendOriginal(start);
200
+ let targetType;
201
+ if (fragmentOpened) {
202
+ script.appendScript(`<></>`);
203
+ targetType = types_1.AST_NODE_TYPES.JSXFragment;
204
+ }
205
+ else {
206
+ script.appendScript(`0;`);
207
+ targetType = types_1.AST_NODE_TYPES.ExpressionStatement;
208
+ }
209
+ script.skipOriginalOffset(end - start);
210
+ script.addRestoreNodeProcess((scriptNode) => {
211
+ if (scriptNode.range[0] === start &&
212
+ scriptNode.type === targetType) {
213
+ delete scriptNode.children;
214
+ delete scriptNode.openingFragment;
215
+ delete scriptNode.closingFragment;
216
+ delete scriptNode.expression;
217
+ const doctypeNode = scriptNode;
218
+ doctypeNode.type = "AstroDoctype";
219
+ return true;
220
+ }
221
+ return false;
222
+ });
223
+ script.addToken("HTMLDocType", [start, end]);
224
+ }
225
+ });
226
+ script.appendOriginal(ctx.code.length);
227
+ script.appendScript("</>");
228
+ return script;
229
+ }
230
+ exports.processTemplate = processTemplate;
231
+ /**
232
+ * If the given tag is a void tag, get the self-closing tag.
233
+ */
234
+ function getVoidSelfClosingTag(node, parent, ctx) {
235
+ var _a;
236
+ const children = node.children.filter((c) => c.type !== "text" || c.value.trim());
237
+ if (children.length > 0) {
238
+ return false;
239
+ }
240
+ const code = ctx.code;
241
+ let nextElementIndex = code.length;
242
+ const childIndex = parent.children.indexOf(node);
243
+ if (childIndex === parent.children.length - 1) {
244
+ // last
245
+ if ((_a = parent.position) === null || _a === void 0 ? void 0 : _a.end) {
246
+ nextElementIndex = parent.position.end.offset;
247
+ nextElementIndex = code.lastIndexOf("</", nextElementIndex);
248
+ }
249
+ }
250
+ else {
251
+ const next = parent.children[childIndex + 1];
252
+ nextElementIndex = next.position.start.offset;
253
+ }
254
+ const endOffset = (0, astro_1.getStartTagEndOffset)(node, code);
255
+ if (code.slice(endOffset, nextElementIndex).trim()) {
256
+ // has end tag
257
+ return null;
258
+ }
259
+ return {
260
+ offset: endOffset,
261
+ end: code.slice(endOffset - 2, endOffset) === "/>" ? "/>" : ">",
262
+ };
263
+ }
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "astro-eslint-parser",
3
- "version": "0.0.0",
3
+ "version": "0.0.3",
4
4
  "description": "Astro parser for ESLint",
5
5
  "main": "lib/index.js",
6
6
  "files": [
7
7
  "lib"
8
8
  ],
9
9
  "engines": {
10
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
10
+ "node": "^14.17.0 || >=16.0.0"
11
11
  },
12
12
  "scripts": {
13
13
  "prebuild": "npm run -s clean",
@@ -43,7 +43,6 @@
43
43
  "dependencies": {
44
44
  "@astrojs/compiler": "^0.14.2",
45
45
  "debug": "^4.3.4",
46
- "eslint-scope": "^7.0.0",
47
46
  "eslint-visitor-keys": "^3.0.0",
48
47
  "espree": "^9.0.0"
49
48
  },
@@ -63,7 +62,7 @@
63
62
  "benchmark": "^2.1.4",
64
63
  "chai": "^4.3.4",
65
64
  "code-red": "^0.2.3",
66
- "eslint": "^8.2.0",
65
+ "eslint": "^8.14.0",
67
66
  "eslint-config-prettier": "^8.3.0",
68
67
  "eslint-formatter-codeframe": "^7.32.1",
69
68
  "eslint-plugin-eslint-comments": "^3.2.0",
@@ -72,12 +71,13 @@
72
71
  "eslint-plugin-node": "^11.1.0",
73
72
  "eslint-plugin-node-dependencies": "^0.8.0",
74
73
  "eslint-plugin-prettier": "^4.0.0",
74
+ "eslint-plugin-react": "^7.29.4",
75
75
  "eslint-plugin-regexp": "^1.5.0",
76
76
  "eslint-plugin-vue": "^8.0.3",
77
77
  "estree-walker": "^3.0.0",
78
78
  "locate-character": "^2.0.5",
79
79
  "magic-string": "^0.26.0",
80
- "mocha": "^9.1.3",
80
+ "mocha": "^10.0.0",
81
81
  "mocha-chai-jest-snapshot": "^1.1.3",
82
82
  "nyc": "^15.1.0",
83
83
  "prettier": "^2.0.5",