Skip to content

Commit 6a71e25

Browse files
committed
feat: traverse ast nodes
1 parent 33ec2a2 commit 6a71e25

File tree

5 files changed

+84
-66
lines changed

5 files changed

+84
-66
lines changed

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@
44
"description": "ESLint Parser/Plugin for MDX",
55
"repository": "[email protected]:rx-ts/eslint-plugin-mdx.git",
66
"author": "JounQin <[email protected]>",
7-
"main": "./dist",
7+
"main": "dist",
88
"license": "MIT",
99
"files": [
10-
"dist"
10+
"dist",
11+
"types.d.ts"
1112
],
1213
"scripts": {
1314
"prepublishOnly": "yarn build",
@@ -20,7 +21,6 @@
2021
},
2122
"dependencies": {
2223
"@mdx-js/mdx": "^1.1.0",
23-
"eslint-utils": "^1.4.0",
2424
"eslint-visitor-keys": "^1.0.0",
2525
"remark-mdx": "^1.1.0",
2626
"remark-parse": "^7.0.0",

src/parser.ts

Lines changed: 49 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
// eslint-disable-next-line @typescript-eslint/no-triple-slash-reference
2-
/// <reference path="../shim.d.ts" />
2+
/// <reference path="../types.d.ts" />
33

44
import { parse as esParse } from 'espree'
55
import remarkMdx from 'remark-mdx'
66
import remarkParse from 'remark-parse'
77
import remarkStringify from 'remark-stringify'
88
import unified from 'unified'
99

10+
import { traverse } from './traverse'
11+
1012
import { Position, Parent } from 'unist'
1113
import { AST, Linter } from 'eslint'
12-
import { Statement, ModuleDeclaration } from 'estree'
1314

1415
const transNodePos = (position: Position) => {
1516
const start = position.start.offset
@@ -39,73 +40,61 @@ export const parseForESLint = (
3940

4041
const tokens: AST.Token[] = []
4142

42-
return {
43-
ast: {
44-
...transNodePos(root.position),
45-
comments: [],
46-
body: root.children.reduce<Array<Statement | ModuleDeclaration>>(
47-
(nodes, { position, type }) => {
48-
if (!['export', 'import', 'jsx'].includes(type)) {
49-
return nodes
50-
}
51-
52-
const rawText = getRawText(code, position)
43+
traverse(root, {
44+
enter({ position, type }) {
45+
if (!['export', 'import', 'jsx'].includes(type)) {
46+
return
47+
}
5348

54-
let node = {
55-
...transNodePos(position),
56-
value: rawText,
57-
}
49+
const rawText = getRawText(code, position)
5850

59-
const { tokens: esTokens, ...AST } = esParse(
60-
rawText,
61-
options,
62-
) as AST.Program
51+
const node = transNodePos(position)
6352

64-
const offset = node.start - AST.range[0]
53+
const { tokens: esTokens, ...AST } = esParse(
54+
rawText,
55+
options,
56+
) as AST.Program
6557

66-
node = {
67-
...AST,
68-
...node,
69-
}
58+
const offset = node.start - AST.range[0]
7059

71-
nodes.push(node as any)
72-
tokens.push(
73-
...esTokens.map(token => {
74-
const {
75-
loc: { start: tokenStart, end: tokenEnd },
76-
} = token
77-
const start = token.range[0] + offset
78-
const end = token.range[1] + offset
79-
const startLine = node.loc.start.line + tokenStart.line - 1
80-
const startColumn = node.loc.start.column + tokenStart.column - 1
81-
return {
82-
...token,
83-
start,
84-
end,
85-
range: [start, end],
86-
loc: {
87-
start: {
88-
line: startLine,
89-
column: startColumn,
90-
},
91-
end: {
92-
line: startLine + tokenEnd.line - 1,
93-
column: startLine + tokenEnd.column - 1,
94-
},
95-
},
96-
} as AST.Token
97-
}),
98-
)
60+
tokens.push(
61+
...esTokens.map(token => {
62+
const {
63+
loc: { start: tokenStart, end: tokenEnd },
64+
} = token
65+
const start = token.range[0] + offset
66+
const end = token.range[1] + offset
67+
const startLine = node.loc.start.line + tokenStart.line - 1
68+
const startColumn = node.loc.start.column + tokenStart.column - 1
69+
return {
70+
...token,
71+
start,
72+
end,
73+
range: [start, end],
74+
loc: {
75+
start: {
76+
line: startLine,
77+
column: startColumn,
78+
},
79+
end: {
80+
line: startLine + tokenEnd.line - 1,
81+
column: startLine + tokenEnd.column - 1,
82+
},
83+
},
84+
} as AST.Token
85+
}),
86+
)
87+
},
88+
})
9989

100-
return nodes
101-
},
102-
[],
103-
),
90+
return {
91+
ast: {
92+
...transNodePos(root.position),
93+
comments: [],
94+
body: [],
10495
type: 'Program',
10596
sourceType: 'module',
10697
tokens,
10798
},
108-
scopeManager: null,
109-
visitorKeys: null,
11099
}
111100
}

src/traverse.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { Node, Parent } from 'unist'
2+
3+
export type Traverser = (node: Node, parent?: Parent) => void
4+
5+
export interface TraverseOptions {
6+
enter: Traverser
7+
}
8+
9+
export class Traverse {
10+
private _enter: Traverser
11+
12+
constructor({ enter }: TraverseOptions) {
13+
this._enter = enter
14+
}
15+
16+
traverse(node: Node, parent?: Parent) {
17+
if (!node) {
18+
return
19+
}
20+
21+
this._enter(node, parent)
22+
23+
if (node.children) {
24+
parent = node as Parent
25+
parent.children.forEach(child => this.traverse(child, parent))
26+
}
27+
}
28+
}
29+
30+
export const traverse = (root: Parent, options: TraverseOptions) =>
31+
new Traverse(options).traverse(root)

shim.d.ts renamed to types.d.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
declare module 'eslint-utils' {}
2-
31
declare module 'espree' {
42
import * as estree from 'estree'
53

yarn.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1405,7 +1405,7 @@ eslint-scope@^5.0.0:
14051405
esrecurse "^4.1.0"
14061406
estraverse "^4.1.1"
14071407

1408-
eslint-utils@^1.3.0, eslint-utils@^1.3.1, eslint-utils@^1.4.0:
1408+
eslint-utils@^1.3.0, eslint-utils@^1.3.1:
14091409
version "1.4.0"
14101410
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.0.tgz#e2c3c8dba768425f897cf0f9e51fe2e241485d4c"
14111411
integrity sha512-7ehnzPaP5IIEh1r1tkjuIrxqhNkzUJa9z3R92tLJdZIVdWaczEhr3EbhGtsMrVxi1KeR8qA7Off6SWc5WNQqyQ==

0 commit comments

Comments
 (0)