Skip to content

Commit

Permalink
feat: bump (dev)Dependencies, fix: consider first jsx node as open ta…
Browse files Browse the repository at this point in the history
…g - close #272 (#273)

* feat: bump (dev)Dependencies, fix related errors

* fix: consider first jsx node as open tag - close #272

the parsed remark-mdx jsx nodes are not precise, but it will be resolved in v2

* chore: lerna config changes

* test: do not use user environment related test cases

* fix: open close tag regex, push remaining nodes

* fix: part of #207, markdown in jsx is still not supported

improve fixtures test case

* test: remove unnecessary fixture

* docs: add comments for // @ts-ignore and never
  • Loading branch information
JounQin authored Feb 20, 2021
1 parent dd0227f commit cb846e9
Show file tree
Hide file tree
Showing 24 changed files with 2,796 additions and 3,529 deletions.
5 changes: 5 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"presets": [
"@1stg"
]
}
5 changes: 2 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@ Hi! 👋 We’re excited that you’re interested in contributing!
This project is a [lerna][] monorepo, so packages releasing is controlled by [lerna][].

1. Make sure you have both GitHub repository and npm write permissions at the same time.
2. You need a GitHub token with a `public_repo` scope as `GH_TOKEN` in the
environment to publish
3. Run `yarn deploy` simply, or `GH_TOKEN=xxx yarn deploy` to export `GH_TOKEN` at one time.
2. You need a GitHub token with a `public_repo` scope as `GH_TOKEN` in the environment to publish
3. Run `yarn release` simply, or `GH_TOKEN=xxx yarn release` to export `GH_TOKEN` at one time.

[contributing]: https://mdxjs.com/contributing
[lerna]: https://github.com/lerna/lerna
10 changes: 4 additions & 6 deletions lerna.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,14 @@
"allowBranch": [
"develop",
"master"
],
"conventionalCommits": true,
"gitReset": false,
"message": "chore(release): %s"
]
},
"publish": {
"ignoreChanges": [
"**/test/**",
"*.md"
]
"**/*.md"
],
"message": "chore: release package(s)"
}
}
}
31 changes: 16 additions & 15 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,41 +14,42 @@
"build:r": "r -p",
"build:ts": "tsc -b",
"clean": "rimraf packages/*/{lib,*.tsbuildinfo}",
"deploy": "lerna publish --create-release github --yes",
"lint": "run-p lint:*",
"lint:es": "cross-env PARSER_NO_WATCH=true eslint . --cache --ext js,md,ts -f friendly",
"lint:ts": "tslint -p . -t stylish",
"lint:tsc": "tsc",
"postinstall": "yarn-deduplicate || exit 0",
"predeploy": "yarn build",
"prelint": "yarn build",
"prelint": "yarn build:ts",
"prerelease": "yarn build",
"pretest": "yarn clean",
"release": "lerna publish --conventional-commits --create-release github --yes",
"test": "ts-node --skip-ignore node_modules/.bin/jest",
"type-coverage": "type-coverage --cache --detail --ignore-catch --ignore-files '**/*.d.ts' --strict --update"
},
"devDependencies": {
"@1stg/lib-config": "^0.5.5",
"@1stg/tslint-config": "^0.9.2",
"@types/eslint": "^7.2.0",
"@1stg/lib-config": "^1.0.5",
"@1stg/tslint-config": "^1.0.0",
"@types/eslint": "^7.2.6",
"@types/jest": "^26.0.20",
"@types/node": "^14.14.22",
"@types/react": "^16.14.2",
"@types/node": "^14.14.31",
"@types/react": "^17.0.2",
"@types/rebass": "^4.0.7",
"@types/unist": "^2.0.3",
"eslint-mdx": "link:packages/eslint-mdx/src",
"eslint-plugin-mdx": "link:packages/eslint-plugin-mdx/src",
"lerna": "^3.22.1",
"npm-run-all": "^4.1.5",
"react": "^16.14.0",
"ts-jest": "^26.5.0",
"ts-node": "^8.10.2",
"react": "^17.0.1",
"ts-jest": "^26.5.1",
"ts-node": "^9.1.1",
"tslint": "^6.1.3",
"type-coverage": "^2.14.8",
"typescript": "^3.9.7",
"yarn-deduplicate": "^2.1.1"
"type-coverage": "^2.15.1",
"typescript": "^4.3.0-dev.20210220",
"yarn-deduplicate": "^3.1.0"
},
"resolutions": {
"prettier": "^2.2.1"
"prettier": "^2.2.1",
"tslib": "^2.1.0"
},
"commitlint": {
"extends": [
Expand Down
2 changes: 1 addition & 1 deletion packages/eslint-mdx/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"espree": "^7.3.1",
"remark-mdx": "^1.6.22",
"remark-parse": "^8.0.3",
"tslib": "^2.0.1",
"tslib": "^2.1.0",
"unified": "^9.1.0"
}
}
33 changes: 16 additions & 17 deletions packages/eslint-mdx/src/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {

export const FALLBACK_PARSERS = [
'@typescript-eslint/parser',
'@babel/eslint-parser',
'babel-eslint',
] as const

Expand Down Expand Up @@ -89,33 +90,31 @@ export interface BaseNode {
range?: [number, number]
}

export function restoreNodeLocation<T extends BaseNode>(
export const maybeBaseNode = (node: unknown): node is BaseNode =>
typeof node === 'object' && 'loc' in node && 'range' in node

export function restoreNodeLocation<T>(
node: T,
startLine: number,
offset: number,
): T {
if (!node || !node.loc || !node.range) {
if (!maybeBaseNode(node)) {
return node
}

Object.entries(node).forEach(([key, value]) => {
for (const entry of Object.entries(node)) {
const [key, value] = entry as [keyof BaseNode, BaseNode[keyof BaseNode]]

if (!value) {
return
continue
}

if (Array.isArray(value)) {
node[key as keyof T] = (value.map(child =>
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
restoreNodeLocation(child, startLine, offset),
) as unknown) as T[keyof T]
} else {
node[key as keyof T] = restoreNodeLocation(
value,
startLine,
offset,
) as T[keyof T]
}
})
// ts doesn't understand the relationship between `key` and restored `value`
// @ts-ignore
node[key] = Array.isArray(value)
? value.map(child => restoreNodeLocation(child, startLine, offset))
: restoreNodeLocation(value, startLine, offset)
}

const {
loc: { start: startLoc, end: endLoc },
Expand Down
22 changes: 12 additions & 10 deletions packages/eslint-mdx/src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,12 @@ export class Parser {
position: {
start: { line, column, offset: startOffset },
},
data,
} = node

Object.assign(node, {
data: {
...node.data,
...data,
jsxType: 'JSXElementWithHTMLComments',
comments,
// jsx in paragraph is considered as plain html in mdx, what means html style comments are valid
Expand Down Expand Up @@ -154,6 +155,7 @@ export class Parser {
return this.parseForESLint(code, options).ast
}

// eslint-disable-next-line sonarjs/cognitive-complexity
parseForESLint(code: string, options: ParserOptions) {
const extname = path.extname(options.filePath)
const isMdx = DEFAULT_EXTENSIONS.concat(options.extensions || []).includes(
Expand Down Expand Up @@ -191,7 +193,9 @@ export class Parser {

let normalized = this.normalizeJsxNode(node, parent, options)
normalized = Array.isArray(normalized) ? normalized : [normalized]
normalized.forEach(_node => this._nodeToAst(_node, options))
for (const normalizedNode of normalized) {
this._nodeToAst(normalizedNode, options)
}
},
})
}
Expand Down Expand Up @@ -288,6 +292,7 @@ export class Parser {
position: {
start: { line, offset },
},
data,
} = node

return expression.children.reduce<Node[]>((nodes, jsNode) => {
Expand All @@ -311,7 +316,7 @@ export class Parser {
const endOffset = range[1] - OFFSET
nodes.push({
type: 'jsx',
data: nodes.length > 0 ? null : node.data,
data: nodes.length > 0 ? null : data,
value: value.slice(startOffset, endOffset),
position: {
start: {
Expand Down Expand Up @@ -371,16 +376,13 @@ export class Parser {

const offset = start - program.range[0]

AST_PROPS.forEach(prop =>
for (const prop of AST_PROPS)
this._ast[prop].push(
// unfortunately, TS complains about incompatible signature
// @ts-ignore
...program[prop].map(item =>
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
// ts doesn't understand the mixed type
...program[prop].map((item: never) =>
restoreNodeLocation(item, startLine, offset),
),
),
)
)
}
}

Expand Down
16 changes: 9 additions & 7 deletions packages/eslint-mdx/src/regexp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,22 @@ export const commentContent = `${commentOpen}([\\s\\S]*?)${commentClose}`
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 + '[\\s\\S]*' + closeTag})$`,
`^(?:${openTag + '[^<]*' + closeTag})$`,
)
export const SELF_CLOSING_TAG_REGEX = new RegExp(`^(?:${selfClosingTag})$`)
export const COMMENT_REGEX = new RegExp(`^(?:${comment})$`)
export const COMMENT_CONTENT_REGEX = new RegExp(commentContent)
export const COMMENT_CONTENT_REGEX_GLOBAL = new RegExp(commentContent, 'g')

export const isOpenTag = (text: string) => OPEN_TAG_REGEX.test(text)
export const isCloseTag = (text: string) => CLOSE_TAG_REGEX.test(text)
export const isComment = (text: string) => COMMENT_REGEX.test(text)
export const isOpenTag = (text: string) => OPEN_TAG_REGEX.test(text.trim())
export const isCloseTag = (text: string) => CLOSE_TAG_REGEX.test(text.trim())
export const isComment = (text: string) => COMMENT_REGEX.test(text.trim())

// the following functions are only declared for robustness and should never be called
/* istanbul ignore next */
export const isOpenCloseTag = (text: string) => OPEN_CLOSE_TAG_REGEX.test(text)
// prettier-ignore
export const isOpenCloseTag = (text: string) =>
OPEN_CLOSE_TAG_REGEX.test(text.trim())

/* istanbul ignore next */
export const isSelfClosingTag = (text: string) => SELF_CLOSING_TAG_REGEX.test(text)
export const isSelfClosingTag = (text: string) =>
SELF_CLOSING_TAG_REGEX.test(text.trim())
58 changes: 38 additions & 20 deletions packages/eslint-mdx/src/traverse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export class Traverse {
// fix #7
combineJsxNodes(nodes: Node[], parent?: Parent) {
let offset = 0
let hasOpenTag = false
const jsxNodes: Node[] = []
const { length } = nodes
// eslint-disable-next-line sonarjs/cognitive-complexity
Expand All @@ -45,6 +46,7 @@ export class Traverse {
const value = node.value as string
if (isOpenTag(value)) {
offset++
hasOpenTag = true
jsxNodes.push(node)
} else {
if (
Expand All @@ -56,40 +58,54 @@ export class Traverse {
// prettier-ignore
/* istanbul ignore next */
else if (
!isComment(value) &&
!isSelfClosingTag(value) &&
!isOpenCloseTag(value)
isComment(value) ||
isSelfClosingTag(value) ||
isOpenCloseTag(value)
) {
jsxNodes.push(node)
} else {
// #272, we consider the first jsx node as open tag although it's not precise
if (!index) {
offset++
hasOpenTag = true
}
try {
// fix #138
const nodes = parser.normalizeJsxNode(node, parent)
jsxNodes.push(...(Array.isArray(nodes) ? nodes : [nodes]))
} catch {
// should never happen, just for robustness
const { start } = node.position
throw Object.assign(
new SyntaxError('unknown jsx node: ' + JSON.stringify(value)),
{
lineNumber: start.line,
column: start.column,
index: start.offset,
},
)
// #272 related
if (offset) {
jsxNodes.push(node)
} else {
// should never happen, just for robustness
const { start } = node.position
throw Object.assign(
new SyntaxError('unknown jsx node: ' + JSON.stringify(value)),
{
lineNumber: start.line,
column: start.column,
index: start.offset,
},
)
}
}
} else {
jsxNodes.push(node)
}

if (!offset) {
// fix #158
const firstOpenTagIndex = jsxNodes.findIndex(node =>
isOpenTag(node.value as string),
const firstOpenTagIndex = jsxNodes.findIndex(
node => typeof node.value === 'string' && isOpenTag(node.value),
)
if (firstOpenTagIndex === -1) {
acc.push(...jsxNodes)
if (hasOpenTag) {
acc.push(this.combineLeftJsxNodes(jsxNodes))
} else {
acc.push(...jsxNodes)
}
} else {
acc.push(...jsxNodes.slice(0, firstOpenTagIndex))
acc.push(
...jsxNodes.slice(0, firstOpenTagIndex),
this.combineLeftJsxNodes(jsxNodes.slice(firstOpenTagIndex)),
)
}
Expand Down Expand Up @@ -120,7 +136,9 @@ export class Traverse {
if (children) {
const parent = node as Parent
children = node.children = this.combineJsxNodes(children, parent)
children.forEach(child => this.traverse(child, parent))
for (const child of children) {
this.traverse(child, parent)
}
}

this._enter(node, parent)
Expand Down
6 changes: 3 additions & 3 deletions packages/eslint-plugin-mdx/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@
"dependencies": {
"cosmiconfig": "^7.0.0",
"eslint-mdx": "^1.8.2",
"eslint-plugin-react": "^7.21.2",
"eslint-plugin-react": "^7.22.0",
"remark-mdx": "^1.6.22",
"remark-parse": "^8.0.3",
"remark-stringify": "^8.1.1",
"tslib": "^2.0.1",
"tslib": "^2.1.0",
"unified": "^9.1.0",
"vfile": "^4.1.1"
"vfile": "^4.2.1"
},
"optionalDependencies": {
"rebass": "^4.0.7"
Expand Down
Loading

0 comments on commit cb846e9

Please sign in to comment.