Skip to content

Commit 5297a0b

Browse files
committed
fix: inline jsx and comment parsing error, close #4, #7
1 parent 35b6a25 commit 5297a0b

File tree

7 files changed

+133
-28
lines changed

7 files changed

+133
-28
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@rxts/eslint-plugin-mdx",
3-
"version": "0.2.1",
3+
"version": "0.3.0",
44
"description": "ESLint Parser/Plugin for MDX",
55
"repository": "[email protected]:rx-ts/eslint-plugin-mdx.git",
66
"author": "JounQin <[email protected]>",

src/parser.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@ import remarkStringify from 'remark-stringify'
88
import unified from 'unified'
99

1010
import { traverse } from './traverse'
11+
import { isComment } from './utils'
1112

1213
import { Position, Parent } from 'unist'
1314
import { AST, Linter } from 'eslint'
1415

15-
const transNodePos = (position: Position) => {
16+
const normalizePosition = (position: Position) => {
1617
const start = position.start.offset
1718
const end = position.end.offset
1819
return {
@@ -67,7 +68,12 @@ export const parseForESLint = (
6768

6869
const rawText = getRawText(code, position)
6970

70-
const node = transNodePos(position)
71+
// fix #4
72+
if (isComment(rawText)) {
73+
return
74+
}
75+
76+
const node = normalizePosition(position)
7177

7278
let program: AST.Program
7379

@@ -119,7 +125,7 @@ export const parseForESLint = (
119125

120126
return {
121127
ast: {
122-
...transNodePos(root.position),
128+
...normalizePosition(root.position),
123129
comments: [],
124130
body: [],
125131
type: 'Program',

src/traverse.ts

Lines changed: 72 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
import {
2+
isOpenTag,
3+
isCloseTag,
4+
isVoidTag,
5+
isComment,
6+
isOpenCloseTag,
7+
} from './utils'
8+
19
import { Node, Parent } from 'unist'
210

311
export type Traverser = (node: Node, parent?: Parent) => void
@@ -13,6 +21,67 @@ export class Traverse {
1321
this._enter = enter
1422
}
1523

24+
combineJsxNodes(jsxNodes: Node[]): Node {
25+
return {
26+
type: 'jsx',
27+
value: jsxNodes.reduce((acc, { value }) => (acc += value), ''),
28+
position: {
29+
start: jsxNodes[0].position.start,
30+
end: jsxNodes[jsxNodes.length - 1].position.end,
31+
},
32+
}
33+
}
34+
35+
// fix #7
36+
combineInlineJsx(nodes: Node[]) {
37+
let offset = 0
38+
const jsxNodes: Node[] = []
39+
const { length } = nodes
40+
return nodes.reduce((acc, node, index) => {
41+
if (node.type === 'jsx') {
42+
const rawText = node.value as string
43+
if (isOpenTag(rawText as string)) {
44+
offset++
45+
jsxNodes.push(node)
46+
} else {
47+
if (isCloseTag(rawText)) {
48+
offset--
49+
} else if (
50+
!isComment(rawText) &&
51+
!isVoidTag(rawText) &&
52+
!isOpenCloseTag(rawText)
53+
) {
54+
const { start } = node.position
55+
throw Object.assign(
56+
new SyntaxError(
57+
`'Unknown node type: ${JSON.stringify(
58+
node.type,
59+
)}, text: ${JSON.stringify(rawText)}`,
60+
),
61+
{
62+
lineNumber: start.line,
63+
column: start.column,
64+
index: start.offset,
65+
},
66+
)
67+
}
68+
69+
jsxNodes.push(node)
70+
71+
if (!offset || index === length - 1) {
72+
acc.push(this.combineJsxNodes(jsxNodes))
73+
jsxNodes.length = 0
74+
}
75+
}
76+
} else if (offset) {
77+
jsxNodes.push(node)
78+
} else {
79+
acc.push(node)
80+
}
81+
return acc
82+
}, [])
83+
}
84+
1685
traverse(node: Node, parent?: Parent) {
1786
if (!node) {
1887
return
@@ -21,28 +90,10 @@ export class Traverse {
2190
this._enter(node, parent)
2291

2392
if (node.children) {
24-
/**
25-
* FIXME: inline jsx:
26-
*
27-
* {
28-
type: 'jsx',
29-
value: '<b>',
30-
position: Position { start: [Object], end: [Object], indent: [] }
31-
},
32-
{
33-
type: 'text',
34-
value: 'velit',
35-
position: Position { start: [Object], end: [Object], indent: [] }
36-
},
37-
{
38-
type: 'jsx',
39-
value: '</b>',
40-
position: Position { start: [Object], end: [Object], indent: [] }
41-
}
42-
*/
43-
console.log(node.children)
4493
parent = node as Parent
45-
parent.children.forEach(child => this.traverse(child, parent))
94+
this.combineInlineJsx(parent.children).forEach(child =>
95+
this.traverse(child, parent),
96+
)
4697
}
4798
}
4899
}

src/utils.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// based on https://github.com/mdx-js/mdx/blob/master/packages/remark-mdx/tag.js
2+
3+
const dotAllPolyfill = '[\0-\uFFFF]'
4+
const attributeName = '[a-zA-Z_:][a-zA-Z0-9:._-]*'
5+
const unquoted = '[^"\'=<>`\\u0000-\\u0020]+'
6+
const singleQuoted = "'[^']*'"
7+
const doubleQuoted = '"[^"]*"'
8+
const jsProps = '{.*}'.replace('.', dotAllPolyfill)
9+
const attributeValue =
10+
'(?:' +
11+
unquoted +
12+
'|' +
13+
singleQuoted +
14+
'|' +
15+
doubleQuoted +
16+
'|' +
17+
jsProps +
18+
')'
19+
const attribute =
20+
'(?:\\s+' + attributeName + '(?:\\s*=\\s*' + attributeValue + ')?)'
21+
const openTag = '<[A-Za-z]*[A-Za-z0-9\\.\\-]*' + attribute + '*\\s*>'
22+
const closeTag = '<\\s*\\/[A-Za-z]*[A-Za-z0-9\\.\\-]*\\s*>'
23+
const voidTag = '<[A-Za-z]*[A-Za-z0-9\\.\\-]*' + attribute + '*\\s*\\/?>'
24+
const comment = '<!---->|<!--(?:-?[^>-])(?:-?[^-])*-->'
25+
26+
export const OPEN_TAG_REGEX = new RegExp(`^(?:${openTag})$`)
27+
export const CLOSE_TAG_REGEX = new RegExp(`^(?:${closeTag})$`)
28+
export const OPEN_CLOSE_TAG_REGEX = new RegExp(
29+
`^(?:${openTag + '.*' + closeTag})$`,
30+
)
31+
export const VOID_TAG_REGEX = new RegExp(`^(?:${voidTag})$`)
32+
export const COMMENT_REGEX = new RegExp(`^(?:${comment})$`)
33+
34+
export const isOpenTag = (text: string) => OPEN_TAG_REGEX.test(text)
35+
export const isCloseTag = (text: string) => CLOSE_TAG_REGEX.test(text)
36+
export const isOpenCloseTag = (text: string) => OPEN_CLOSE_TAG_REGEX.test(text)
37+
export const isVoidTag = (text: string) => VOID_TAG_REGEX.test(text)
38+
export const isComment = (text: string) => COMMENT_REGEX.test(text)

test/fixture.mdx renamed to test/fixture1.mdx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing **elit**. Ut ac lobortis <b>v
1616
}
1717
```
1818

19-
<Component>
20-
{/* This is a comment */}
21-
</Component>
19+
<Component>{/* This is a comment */}</Component>
2220

2321
## Subtitle
2422

test/fixture2.mdx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
name: README
3+
route: /
4+
---
5+
6+
# <!-- markdownlint-disable MD041 -->
7+
8+
import ReadMe from './README.md'
9+
10+
# <!-- markdownlint-enable MD041 -->
11+
12+
<ReadMe />
File renamed without changes.

0 commit comments

Comments
 (0)