Skip to content

Commit 529b96a

Browse files
committedJul 24, 2022
Replace astring with estree-util-to-js
1 parent 7d8dc11 commit 529b96a

File tree

3 files changed

+37
-321
lines changed

3 files changed

+37
-321
lines changed
 

Diff for: ‎package-lock.json

+26-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: ‎packages/mdx/lib/plugin/recma-stringify.js

+10-318
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,14 @@
11
/**
2-
* @typedef {import('estree-jsx').Node} Node
32
* @typedef {import('estree-jsx').Program} Program
4-
* @typedef {import('estree-jsx').JSXAttribute} JSXAttribute
5-
* @typedef {import('estree-jsx').JSXClosingElement} JSXClosingElement
6-
* @typedef {import('estree-jsx').JSXClosingFragment} JSXClosingFragment
7-
* @typedef {import('estree-jsx').JSXElement} JSXElement
8-
* @typedef {import('estree-jsx').JSXEmptyExpression} JSXEmptyExpression
9-
* @typedef {import('estree-jsx').JSXExpressionContainer} JSXExpressionContainer
10-
* @typedef {import('estree-jsx').JSXFragment} JSXFragment
11-
* @typedef {import('estree-jsx').JSXIdentifier} JSXIdentifier
12-
* @typedef {import('estree-jsx').JSXMemberExpression} JSXMemberExpression
13-
* @typedef {import('estree-jsx').JSXNamespacedName} JSXNamespacedName
14-
* @typedef {import('estree-jsx').JSXOpeningElement} JSXOpeningElement
15-
* @typedef {import('estree-jsx').JSXOpeningFragment} JSXOpeningFragment
16-
* @typedef {import('estree-jsx').JSXSpreadAttribute} JSXSpreadAttribute
17-
* @typedef {import('estree-jsx').JSXText} JSXText
18-
* @typedef {import('vfile').VFile} VFile
193
* @typedef {typeof import('source-map').SourceMapGenerator} SourceMapGenerator
204
*
21-
* @typedef {Omit<import('astring').State, 'write'> & {write: ((code: string, node?: Node) => void)}} State
22-
*
23-
* @typedef {{[K in Node['type']]: (node: Node, state: State) => void}} Generator
24-
*
255
* @typedef RecmaStringifyOptions
266
* @property {SourceMapGenerator} [SourceMapGenerator]
277
* Generate a source map by passing a `SourceMapGenerator` from `source-map`
288
* in.
299
*/
3010

31-
import {GENERATOR, generate} from 'astring'
11+
import {toJs, jsx} from 'estree-util-to-js'
3212

3313
/**
3414
* A plugin that adds an esast compiler: a small wrapper around `astring` to add
@@ -43,304 +23,16 @@ export function recmaStringify(options = {}) {
4323

4424
/** @type {import('unified').CompilerFunction<Program, string>} */
4525
function compiler(tree, file) {
46-
/** @type {InstanceType<SourceMapGenerator>|undefined} */
47-
let sourceMap
48-
49-
if (SourceMapGenerator) {
50-
sourceMap = new SourceMapGenerator({file: file.path || 'unknown.mdx'})
51-
}
52-
53-
const generator = {
54-
...GENERATOR,
55-
JSXAttribute,
56-
JSXClosingElement,
57-
JSXClosingFragment,
58-
JSXElement,
59-
JSXEmptyExpression,
60-
JSXExpressionContainer,
61-
JSXFragment,
62-
JSXIdentifier,
63-
JSXMemberExpression,
64-
JSXNamespacedName,
65-
JSXOpeningElement,
66-
JSXOpeningFragment,
67-
JSXSpreadAttribute,
68-
JSXText
69-
}
70-
71-
const result = generate(tree, {
72-
generator,
73-
comments: true,
74-
sourceMap
75-
})
76-
77-
if (sourceMap) {
78-
file.map = sourceMap.toJSON()
79-
}
80-
81-
return result
82-
}
83-
}
84-
85-
/**
86-
* `attr`
87-
* `attr="something"`
88-
* `attr={1}`
89-
*
90-
* @this {Generator}
91-
* @param {JSXAttribute} node
92-
* @param {State} state
93-
* @returns {void}
94-
*/
95-
function JSXAttribute(node, state) {
96-
this[node.name.type](node.name, state)
97-
98-
if (node.value !== undefined && node.value !== null) {
99-
state.write('=')
100-
101-
// Encode double quotes in attribute values.
102-
if (node.value.type === 'Literal') {
103-
state.write(
104-
'"' + encodeJsx(String(node.value.value)).replace(/"/g, '&quot;') + '"',
105-
node
106-
)
107-
} else {
108-
this[node.value.type](node.value, state)
109-
}
110-
}
111-
}
112-
113-
/**
114-
* `</div>`
115-
*
116-
* @this {Generator}
117-
* @param {JSXClosingElement} node
118-
* @param {State} state
119-
* @returns {void}
120-
*/
121-
function JSXClosingElement(node, state) {
122-
state.write('</')
123-
this[node.name.type](node.name, state)
124-
state.write('>')
125-
}
126-
127-
/**
128-
* `</>`
129-
*
130-
* @this {Generator}
131-
* @param {JSXClosingFragment} node
132-
* @param {State} state
133-
* @returns {void}
134-
*/
135-
function JSXClosingFragment(node, state) {
136-
state.write('</>', node)
137-
}
138-
139-
/**
140-
* `<div />`
141-
* `<div></div>`
142-
*
143-
* @this {Generator}
144-
* @param {JSXElement} node
145-
* @param {State} state
146-
* @returns {void}
147-
*/
148-
function JSXElement(node, state) {
149-
let index = -1
150-
151-
this[node.openingElement.type](node.openingElement, state)
26+
const result = SourceMapGenerator
27+
? toJs(tree, {
28+
filePath: file.path || 'unknown.mdx',
29+
SourceMapGenerator,
30+
handlers: jsx
31+
})
32+
: toJs(tree, {handlers: jsx})
15233

153-
if (node.children) {
154-
while (++index < node.children.length) {
155-
const child = node.children[index]
34+
file.map = result.map
15635

157-
// Supported in types but not by Acorn.
158-
/* c8 ignore next 3 */
159-
if (child.type === 'JSXSpreadChild') {
160-
throw new Error('JSX spread children are not supported')
161-
}
162-
163-
this[child.type](child, state)
164-
}
165-
}
166-
167-
if (node.closingElement) {
168-
this[node.closingElement.type](node.closingElement, state)
36+
return result.value
16937
}
17038
}
171-
172-
/**
173-
* `{}` (always in a `JSXExpressionContainer`, which does the curlies)
174-
*
175-
* @this {Generator}
176-
* @returns {void}
177-
*/
178-
function JSXEmptyExpression() {}
179-
180-
/**
181-
* `{expression}`
182-
*
183-
* @this {Generator}
184-
* @param {JSXExpressionContainer} node
185-
* @param {State} state
186-
* @returns {void}
187-
*/
188-
function JSXExpressionContainer(node, state) {
189-
state.write('{')
190-
this[node.expression.type](node.expression, state)
191-
state.write('}')
192-
}
193-
194-
/**
195-
* `<></>`
196-
*
197-
* @this {Generator}
198-
* @param {JSXFragment} node
199-
* @param {State} state
200-
* @returns {void}
201-
*/
202-
function JSXFragment(node, state) {
203-
let index = -1
204-
205-
this[node.openingFragment.type](node.openingFragment, state)
206-
207-
if (node.children) {
208-
while (++index < node.children.length) {
209-
const child = node.children[index]
210-
211-
// Supported in types but not by Acorn.
212-
/* c8 ignore next 3 */
213-
if (child.type === 'JSXSpreadChild') {
214-
throw new Error('JSX spread children are not supported')
215-
}
216-
217-
this[child.type](child, state)
218-
}
219-
}
220-
221-
this[node.closingFragment.type](node.closingFragment, state)
222-
}
223-
224-
/**
225-
* `div`
226-
*
227-
* @this {Generator}
228-
* @param {JSXIdentifier} node
229-
* @param {State} state
230-
* @returns {void}
231-
*/
232-
function JSXIdentifier(node, state) {
233-
state.write(node.name, node)
234-
}
235-
236-
/**
237-
* `member.expression`
238-
*
239-
* @this {Generator}
240-
* @param {JSXMemberExpression} node
241-
* @param {State} state
242-
* @returns {void}
243-
*/
244-
function JSXMemberExpression(node, state) {
245-
this[node.object.type](node.object, state)
246-
state.write('.')
247-
this[node.property.type](node.property, state)
248-
}
249-
250-
/**
251-
* `ns:name`
252-
*
253-
* @this {Generator}
254-
* @param {JSXNamespacedName} node
255-
* @param {State} state
256-
* @returns {void}
257-
*/
258-
function JSXNamespacedName(node, state) {
259-
this[node.namespace.type](node.namespace, state)
260-
state.write(':')
261-
this[node.name.type](node.name, state)
262-
}
263-
264-
/**
265-
* `<div>`
266-
*
267-
* @this {Generator}
268-
* @param {JSXOpeningElement} node
269-
* @param {State} state
270-
* @returns {void}
271-
*/
272-
function JSXOpeningElement(node, state) {
273-
let index = -1
274-
275-
state.write('<')
276-
this[node.name.type](node.name, state)
277-
278-
if (node.attributes) {
279-
while (++index < node.attributes.length) {
280-
state.write(' ')
281-
this[node.attributes[index].type](node.attributes[index], state)
282-
}
283-
}
284-
285-
state.write(node.selfClosing ? ' />' : '>')
286-
}
287-
288-
/**
289-
* `<>`
290-
*
291-
* @this {Generator}
292-
* @param {JSXOpeningFragment} node
293-
* @param {State} state
294-
* @returns {void}
295-
*/
296-
function JSXOpeningFragment(node, state) {
297-
state.write('<>', node)
298-
}
299-
300-
/**
301-
* `{...argument}`
302-
*
303-
* @this {Generator}
304-
* @param {JSXSpreadAttribute} node
305-
* @param {State} state
306-
* @returns {void}
307-
*/
308-
function JSXSpreadAttribute(node, state) {
309-
state.write('{')
310-
// eslint-disable-next-line new-cap
311-
this.SpreadElement(node, state)
312-
state.write('}')
313-
}
314-
315-
/**
316-
* `!`
317-
*
318-
* @this {Generator}
319-
* @param {JSXText} node
320-
* @param {State} state
321-
* @returns {void}
322-
*/
323-
function JSXText(node, state) {
324-
state.write(
325-
encodeJsx(node.value).replace(/<|{/g, ($0) =>
326-
$0 === '<' ? '&lt;' : '&#123;'
327-
),
328-
node
329-
)
330-
}
331-
332-
/**
333-
* Make sure that character references don’t pop up.
334-
* For example, the text `&copy;` should stay that way, and not turn into `©`.
335-
* We could encode all `&` (easy but verbose) or look for actual valid
336-
* references (complex but cleanest output).
337-
* Looking for the 2nd character gives us a middle ground.
338-
* The `#` is for (decimal and hexadecimal) numeric references, the letters
339-
* are for the named references.
340-
*
341-
* @param {string} value
342-
* @returns {string}
343-
*/
344-
function encodeJsx(value) {
345-
return value.replace(/&(?=[#a-z])/gi, '&amp;')
346-
}

Diff for: ‎packages/mdx/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@
4848
"dependencies": {
4949
"@types/estree-jsx": "^1.0.0",
5050
"@types/mdx": "^2.0.0",
51-
"astring": "^1.6.0",
5251
"estree-util-build-jsx": "^2.0.0",
5352
"estree-util-is-identifier-name": "^2.0.0",
53+
"estree-util-to-js": "^1.1.0",
5454
"estree-walker": "^3.0.0",
5555
"hast-util-to-estree": "^2.0.0",
5656
"markdown-extensions": "^1.0.0",

1 commit comments

Comments
 (1)

vercel[bot] commented on Jul 24, 2022

@vercel[bot]

Successfully deployed to the following URLs:

mdx – ./

mdx-mdx.vercel.app
mdxjs.com
mdx-git-main-mdx.vercel.app
v2.mdxjs.com

Please sign in to comment.