Skip to content

Commit

Permalink
feat(richtext-lexical): more lenient MDX JSON object parser that allo…
Browse files Browse the repository at this point in the history
…ws unquoted property keys (#10205)

Previously, the following MDX could not be parsed by lexical:

```tsx
<RestExamples
  data={[
    {
      operation: "Find"
    }
]}
```

Instead, it had to be converted into valid JSON:

```tsx
<RestExamples
  data={[
    {
      "operation": "Find"
    }
]}
```

This PR permits using the first example, as it swaps out JSON.parse with
them ore lenient [json5](https://www.npmjs.com/package/json5) package
parser
  • Loading branch information
AlessioGr authored Dec 27, 2024
1 parent cf8c0ae commit a46609e
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 56 deletions.
1 change: 1 addition & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const defaultESLintIgnores = [
'**/build/',
'**/node_modules/',
'**/temp/',
'**/*.spec.ts',
]

/** @typedef {import('eslint').Linter.Config} Config */
Expand Down
1 change: 1 addition & 0 deletions packages/richtext-lexical/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,7 @@
"bson-objectid": "2.0.4",
"dequal": "2.0.3",
"escape-html": "1.0.3",
"json5": "^2.2.3",
"lexical": "0.20.0",
"mdast-util-from-markdown": "2.0.2",
"mdast-util-mdx-jsx": "3.1.3",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import JSON5Import from 'json5'

const JSON5 = ('default' in JSON5Import ? JSON5Import.default : JSON5Import) as typeof JSON5Import

/**
* Turns a JSX props string into an object.
*
Expand Down Expand Up @@ -78,7 +82,7 @@ function handleArray(propsString: string, startIndex: number): { newIndex: numbe
i++
}

return { newIndex: i, value: JSON.parse(`[${value}]`) }
return { newIndex: i, value: JSON5.parse(`[${value}]`) }
}

function handleQuotedString(
Expand Down Expand Up @@ -116,10 +120,10 @@ function handleObject(propsString: string, startIndex: number): { newIndex: numb

function parseObject(objString: string): Record<string, any> {
if (objString[0] !== '{') {
return JSON.parse(objString)
return JSON5.parse(objString)
}

const result = JSON.parse(objString.replace(/(\w+):/g, '"$1":'))
const result = JSON5.parse(objString.replace(/(\w+):/g, '"$1":'))

return result
}
Expand Down
15 changes: 14 additions & 1 deletion packages/richtext-lexical/src/utilities/jsx/jsx.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ import { propsToJSXString } from './jsx.js'

describe('jsx', () => {
describe('prop string to object', () => {
const INPUT_AND_OUTPUT = [
const INPUT_AND_OUTPUT: {
input: string
inputFromOutput?: string
output: Record<string, any>
}[] = [
{
input: 'key="value"',
output: {
Expand Down Expand Up @@ -112,6 +116,15 @@ describe('jsx', () => {
update: true,
},
},
{
// Test if unquoted property keys in objects within arrays are supprted. This is
// supported through the more lenient json5 parser, instead of using JSON.parse()
input: 'key={[1, 2, { hello: "there" }]}',
inputFromOutput: 'key={[1, 2, { "hello": "there" }]}',
output: {
key: [1, 2, { hello: 'there' }],
},
},
]

for (const { input, output } of INPUT_AND_OUTPUT) {
Expand Down
81 changes: 29 additions & 52 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit a46609e

Please sign in to comment.