Skip to content

Commit

Permalink
fix: jsx name could be namespace or member expression (#460)
Browse files Browse the repository at this point in the history
  • Loading branch information
JounQin authored May 4, 2023
1 parent 296a319 commit 58639a0
Show file tree
Hide file tree
Showing 5 changed files with 1,894 additions and 18 deletions.
5 changes: 5 additions & 0 deletions .changeset/eight-emus-lay.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"eslint-mdx": patch
---

fix: jsx name could be namespace or member expression
84 changes: 66 additions & 18 deletions packages/eslint-mdx/src/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,14 @@ import type {
Program,
SpreadElement,
} from 'estree'
import type { JSXClosingElement, JSXElement, JSXFragment } from 'estree-jsx'
import type {
JSXClosingElement,
JSXElement,
JSXFragment,
JSXIdentifier,
JSXMemberExpression,
JSXNamespacedName,
} from 'estree-jsx'
import type {
BlockContent,
PhrasingContent,
Expand Down Expand Up @@ -289,6 +296,58 @@ runAsWorker(
raw: text.slice(start, end),
})

const handleJsxName = (
nodeName: string,
start: number,
): JSXIdentifier | JSXMemberExpression | JSXNamespacedName => {
const name = nodeName.trim()
const nameIndex = nodeName.indexOf(name)

const colonIndex = nodeName.indexOf(':')
if (colonIndex !== -1) {
const [fullNamespace, fullName] = nodeName.split(':')
return {
...normalizeNode(
start + nameIndex,
start + nameIndex + name.length,
),
type: 'JSXNamespacedName',
namespace: handleJsxName(fullNamespace, start) as JSXIdentifier,
name: handleJsxName(
fullName,
start + colonIndex + 1,
) as JSXIdentifier,
}
}

const lastPointIndex = nodeName.lastIndexOf('.')
if (lastPointIndex === -1) {
return {
...normalizeNode(
start + nameIndex,
start + nameIndex + name.length,
),
type: 'JSXIdentifier',
name,
}
}

const objectName = nodeName.slice(0, lastPointIndex)
const propertyName = nodeName.slice(lastPointIndex + 1)

return {
...normalizeNode(start + nameIndex, start + nameIndex + name.length),
type: 'JSXMemberExpression',
object: handleJsxName(objectName, start) as
| JSXIdentifier
| JSXMemberExpression,
property: handleJsxName(
propertyName,
start + lastPointIndex + 1,
) as JSXIdentifier,
}
}

visit(root, node => {
if (
processed.has(node) ||
Expand Down Expand Up @@ -374,20 +433,16 @@ runAsWorker(
if (!selfClosing) {
const prevOffset = prevCharOffset(lastCharOffset)
const slashOffset = prevCharOffset(prevOffset - nodeNameLength)
assert(text[slashOffset] === '/')
assert(
text[slashOffset] === '/',
`expect \`${text[slashOffset]}\` to be \`/\`, the node is ${node.name}`,
)
const tagStartOffset = prevCharOffset(slashOffset - 1)
assert(text[tagStartOffset] === '<')
closingElement = {
...normalizeNode(tagStartOffset, nodeEnd),
type: 'JSXClosingElement',
name: {
...normalizeNode(
prevOffset + 1 - nodeNameLength,
prevOffset + 1,
),
type: 'JSXIdentifier',
name: node.name,
},
name: handleJsxName(node.name, prevOffset + 1 - nodeNameLength),
}
}

Expand All @@ -396,14 +451,7 @@ runAsWorker(
type: 'JSXElement',
openingElement: {
type: 'JSXOpeningElement',
name: {
...normalizeNode(
nodeNameStart,
nodeNameStart + nodeNameLength,
),
type: 'JSXIdentifier',
name: node.name,
},
name: handleJsxName(node.name, nodeNameStart),
attributes: node.attributes.map(attr => {
if (attr.type === 'mdxJsxExpressionAttribute') {
assert(attr.data)
Expand Down
16 changes: 16 additions & 0 deletions test/__snapshots__/fixtures.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,22 @@ exports[`fixtures should match all snapshots: 429.mdx 1`] = `
]
`;
exports[`fixtures should match all snapshots: 445.mdx 1`] = `
[
{
"column": 2,
"endColumn": 3,
"endLine": 9,
"line": 9,
"message": "'A' is not defined.",
"messageId": "undefined",
"nodeType": "JSXIdentifier",
"ruleId": "react/jsx-no-undef",
"severity": 2,
},
]
`;
exports[`fixtures should match all snapshots: 450.mdx 1`] = `
[
{
Expand Down
Loading

0 comments on commit 58639a0

Please sign in to comment.