Skip to content

Commit

Permalink
fix: inline jsx and comment parsing error, close #4, #7
Browse files Browse the repository at this point in the history
  • Loading branch information
JounQin committed Jul 30, 2019
1 parent 35b6a25 commit 5297a0b
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 28 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@rxts/eslint-plugin-mdx",
"version": "0.2.1",
"version": "0.3.0",
"description": "ESLint Parser/Plugin for MDX",
"repository": "git@github.com:rx-ts/eslint-plugin-mdx.git",
"author": "JounQin <admin@1stg.me>",
Expand Down
12 changes: 9 additions & 3 deletions src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ import remarkStringify from 'remark-stringify'
import unified from 'unified'

import { traverse } from './traverse'
import { isComment } from './utils'

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

const transNodePos = (position: Position) => {
const normalizePosition = (position: Position) => {
const start = position.start.offset
const end = position.end.offset
return {
Expand Down Expand Up @@ -67,7 +68,12 @@ export const parseForESLint = (

const rawText = getRawText(code, position)

const node = transNodePos(position)
// fix #4
if (isComment(rawText)) {
return
}

const node = normalizePosition(position)

let program: AST.Program

Expand Down Expand Up @@ -119,7 +125,7 @@ export const parseForESLint = (

return {
ast: {
...transNodePos(root.position),
...normalizePosition(root.position),
comments: [],
body: [],
type: 'Program',
Expand Down
93 changes: 72 additions & 21 deletions src/traverse.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
import {
isOpenTag,
isCloseTag,
isVoidTag,
isComment,
isOpenCloseTag,
} from './utils'

import { Node, Parent } from 'unist'

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

combineJsxNodes(jsxNodes: Node[]): Node {
return {
type: 'jsx',
value: jsxNodes.reduce((acc, { value }) => (acc += value), ''),
position: {
start: jsxNodes[0].position.start,
end: jsxNodes[jsxNodes.length - 1].position.end,
},
}
}

// fix #7
combineInlineJsx(nodes: Node[]) {
let offset = 0
const jsxNodes: Node[] = []
const { length } = nodes
return nodes.reduce((acc, node, index) => {
if (node.type === 'jsx') {
const rawText = node.value as string
if (isOpenTag(rawText as string)) {
offset++
jsxNodes.push(node)
} else {
if (isCloseTag(rawText)) {
offset--
} else if (
!isComment(rawText) &&
!isVoidTag(rawText) &&
!isOpenCloseTag(rawText)
) {
const { start } = node.position
throw Object.assign(
new SyntaxError(
`'Unknown node type: ${JSON.stringify(
node.type,
)}, text: ${JSON.stringify(rawText)}`,
),
{
lineNumber: start.line,
column: start.column,
index: start.offset,
},
)
}

jsxNodes.push(node)

if (!offset || index === length - 1) {
acc.push(this.combineJsxNodes(jsxNodes))
jsxNodes.length = 0
}
}
} else if (offset) {
jsxNodes.push(node)
} else {
acc.push(node)
}
return acc
}, [])
}

traverse(node: Node, parent?: Parent) {
if (!node) {
return
Expand All @@ -21,28 +90,10 @@ export class Traverse {
this._enter(node, parent)

if (node.children) {
/**
* FIXME: inline jsx:
*
* {
type: 'jsx',
value: '<b>',
position: Position { start: [Object], end: [Object], indent: [] }
},
{
type: 'text',
value: 'velit',
position: Position { start: [Object], end: [Object], indent: [] }
},
{
type: 'jsx',
value: '</b>',
position: Position { start: [Object], end: [Object], indent: [] }
}
*/
console.log(node.children)
parent = node as Parent
parent.children.forEach(child => this.traverse(child, parent))
this.combineInlineJsx(parent.children).forEach(child =>
this.traverse(child, parent),
)
}
}
}
Expand Down
38 changes: 38 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// based on https://github.com/mdx-js/mdx/blob/master/packages/remark-mdx/tag.js

const dotAllPolyfill = '[\0-\uFFFF]'
const attributeName = '[a-zA-Z_:][a-zA-Z0-9:._-]*'
const unquoted = '[^"\'=<>`\\u0000-\\u0020]+'
const singleQuoted = "'[^']*'"
const doubleQuoted = '"[^"]*"'
const jsProps = '{.*}'.replace('.', dotAllPolyfill)
const attributeValue =
'(?:' +
unquoted +
'|' +
singleQuoted +
'|' +
doubleQuoted +
'|' +
jsProps +
')'
const attribute =
'(?:\\s+' + attributeName + '(?:\\s*=\\s*' + attributeValue + ')?)'
const openTag = '<[A-Za-z]*[A-Za-z0-9\\.\\-]*' + attribute + '*\\s*>'
const closeTag = '<\\s*\\/[A-Za-z]*[A-Za-z0-9\\.\\-]*\\s*>'
const voidTag = '<[A-Za-z]*[A-Za-z0-9\\.\\-]*' + attribute + '*\\s*\\/?>'
const comment = '<!---->|<!--(?:-?[^>-])(?:-?[^-])*-->'

export const OPEN_TAG_REGEX = new RegExp(`^(?:${openTag})$`)
export const CLOSE_TAG_REGEX = new RegExp(`^(?:${closeTag})$`)
export const OPEN_CLOSE_TAG_REGEX = new RegExp(
`^(?:${openTag + '.*' + closeTag})$`,
)
export const VOID_TAG_REGEX = new RegExp(`^(?:${voidTag})$`)
export const COMMENT_REGEX = new RegExp(`^(?:${comment})$`)

export const isOpenTag = (text: string) => OPEN_TAG_REGEX.test(text)
export const isCloseTag = (text: string) => CLOSE_TAG_REGEX.test(text)
export const isOpenCloseTag = (text: string) => OPEN_CLOSE_TAG_REGEX.test(text)
export const isVoidTag = (text: string) => VOID_TAG_REGEX.test(text)
export const isComment = (text: string) => COMMENT_REGEX.test(text)
4 changes: 1 addition & 3 deletions test/fixture.mdx → test/fixture1.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing **elit**. Ut ac lobortis <b>v
}
```

<Component>
{/* This is a comment */}
</Component>
<Component>{/* This is a comment */}</Component>

## Subtitle

Expand Down
12 changes: 12 additions & 0 deletions test/fixture2.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
name: README
route: /
---

# <!-- markdownlint-disable MD041 -->

import ReadMe from './README.md'

# <!-- markdownlint-enable MD041 -->

<ReadMe />
File renamed without changes.

0 comments on commit 5297a0b

Please sign in to comment.