Skip to content

Commit fbc9800

Browse files
committed
fix attribute deserialization
deserialization-helpers.js was using an older version of unified and related packages, which was causing it not to recognize `mdxJsx*` node types. upgrading in that file would've been difficult, because it would've had to change to an ESM file, as would handlers.js, and many more files in the dependency chain. this is a decent workaround — just define the attribute processor in deserialize-html.mjs, then pass it as an argument through to the deserialization-helper functions to get tests working, i had to add `TRANSLATION_TYPE=human` to the test command, i wasn't able to get mocking the configuration module working
1 parent 2381c34 commit fbc9800

File tree

6 files changed

+80
-52
lines changed

6 files changed

+80
-52
lines changed

codemods/utils/mdxast-builder.js

+5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
const u = require('unist-builder');
22

33
const mdxAttribute = (name, value) => u('mdxAttribute', { name, value });
4+
const mdxJsxAttribute = (name, value) => u('mdxJsxAttribute', { name, value });
45
const mdxValueExpression = (value) => u('mdxValueExpression', value);
6+
const mdxJsxAttributeValueExpression = (value) =>
7+
u('mdxJsxAttributeValueExpression', value);
58
const mdxBlockExpression = (value) => u('mdxBlockExpression', value);
69
const mdxSpanExpression = (value) => u('mdxSpanExpression', value);
710

@@ -16,6 +19,8 @@ const mdxImport = (expression, path) =>
1619

1720
module.exports = {
1821
mdxAttribute,
22+
mdxJsxAttribute,
23+
mdxJsxAttributeValueExpression,
1924
mdxBlockElement,
2025
mdxBlockExpression,
2126
mdxImport,

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@
215215
"start:full": "NODE_OPTIONS='--max-old-space-size=5120' yarn develop",
216216
"start": "NODE_OPTIONS='--max-old-space-size=5120' BUILD_LANG=en yarn develop",
217217
"test": "jest -i",
218-
"test:esm": "NODE_OPTIONS=--loader=esmock uvu . __esm-tests__",
218+
"test:esm": "TRANSLATION_TYPE=human NODE_OPTIONS=--loader=esmock uvu . __esm-tests__",
219219
"trigger-i18n-merge": "node scripts/actions/trigger-i18n-merge.js",
220220
"update-attribute-dictionary-json": "node scripts/actions/update-attribute-dictionary-json.mjs",
221221
"verify-install-page": "node scripts/verifyInstallPage.js",

scripts/actions/__esm-tests__/deserialize-html.test.mjs

+20-12
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,12 @@ import path, { dirname } from 'path';
33
import { expect } from 'expect';
44
import { fileURLToPath } from 'url';
55
import { test } from 'uvu';
6-
// import { mock } from 'node:test';
76

8-
// import { configuration } from '../configuration.js';
97
import deserializeHTML from '../deserialize-html.mjs';
108
import serializeMDX from '../serialize-mdx.js';
119

1210
const __dirname = dirname(fileURLToPath(import.meta.url));
1311

14-
// mock('../configuration', () => ({
15-
// configuration: {
16-
// TRANSLATION: {
17-
// TYPE: 'human',
18-
// },
19-
// },
20-
// }));
21-
2212
test('deserializes mdx with DoNotTranslate', async () => {
2313
const input = `
2414
<DoNotTranslate>
@@ -101,7 +91,16 @@ test('deserializes components with text props', async () => {
10191

10292
test('deserializes components with text props as JSX expressions', async () => {
10393
const input = `
104-
<Collapser title={<><InlineCode>agent.send_custom_event</InlineCode> API</>}>
94+
<Collapser
95+
title={<>
96+
<InlineCode>
97+
agent.send_custom_event
98+
</InlineCode>
99+
100+
API
101+
</>
102+
}
103+
>
105104
All about that API
106105
</Collapser>
107106
`;
@@ -114,7 +113,16 @@ test('deserializes components with text props as JSX expressions', async () => {
114113
test('deserializes components with children', async () => {
115114
const input = `
116115
<CollapserGroup>
117-
<Collapser title={<><InlineCode>agent.send_custom_event</InlineCode> API</>}>
116+
<Collapser
117+
title={<>
118+
<InlineCode>
119+
agent.send_custom_event
120+
</InlineCode>
121+
122+
API
123+
</>
124+
}
125+
>
118126
All about that API
119127
</Collapser>
120128
</CollapserGroup>

scripts/actions/__tests__/kitchen-sink.mdx

+14-3
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,19 @@ def handler(event, context):
173173
</Collapser>
174174
</CollapserGroup>
175175

176-
<InlineCode>hiii</InlineCode>
177-
178-
<Collapser title={<><InlineCode>agent.send_custom_event</InlineCode> API</>}>
176+
<InlineCode>
177+
hiii
178+
</InlineCode>
179+
180+
<Collapser
181+
title={<>
182+
<InlineCode>
183+
agent.send_custom_event
184+
</InlineCode>
185+
186+
API
187+
</>
188+
}
189+
>
179190
All about that API
180191
</Collapser>

scripts/actions/deserialize-html.mjs

+24-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { defaultHandlers } from 'hast-util-to-mdast9';
99
import u from 'unist-builder';
1010
import last from 'lodash/last.js';
1111
import yaml from 'js-yaml';
12+
import { visit } from 'unist-util-visit4';
1213
import { configuration } from './configuration.js';
1314

1415
/**
@@ -36,7 +37,7 @@ const component = (state, node) => {
3637
);
3738
}
3839

39-
return handler.deserialize(state, node);
40+
return handler.deserialize(state, node, undefined, attributeProcessor);
4041
};
4142

4243
const headingWithCustomId = (state, node) => {
@@ -88,6 +89,28 @@ const stripTranslateFrontmatter = () => {
8889
return transformer;
8990
};
9091

92+
const inlineCodeAttribute = () => (tree) => {
93+
visit(tree, 'inlineCode', (node) => {
94+
node.type = 'mdxJsxSpanElement';
95+
node.name = 'InlineCode';
96+
node.children = [u('text', node.value)];
97+
});
98+
};
99+
100+
// previously, this processor was defined in `deserialization-helpers`.
101+
// upgrading unified there would have involved changing a lot of CJS modules to ESM.
102+
// this is a sort of workaround to avoid doing all that,
103+
// but still allow attribute deserialization to work with the new node types
104+
// introduced in newer versions of remarkMDX. (`mdxJsx*` nodes vs `mdx*` nodes.)
105+
const attributeProcessor = unified()
106+
.use(stringify, {
107+
bullet: '*',
108+
fences: true,
109+
listItemIndent: '1',
110+
})
111+
.use(remarkMdx)
112+
.use(inlineCodeAttribute);
113+
91114
const processor = unified()
92115
.use(parse)
93116
.use(rehype2remark, {

scripts/actions/utils/deserialization-helpers.js

+16-35
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,22 @@
1-
const deserializeJSValue = (value) => JSON.parse(Buffer.from(value, 'base64'));
2-
const all = require('hast-util-to-mdast/lib/all');
3-
const remarkMdx = require('remark-mdx');
4-
const remarkMdxjs = require('remark-mdxjs');
5-
const stringify = require('remark-stringify');
6-
const unified = require('unified');
71
const {
8-
mdxAttribute,
9-
mdxValueExpression,
2+
mdxJsxAttribute,
3+
mdxJsxAttributeValueExpression,
104
} = require('../../../codemods/utils/mdxast-builder');
11-
const visit = require('unist-util-visit');
12-
const u = require('unist-builder');
135

146
const hasChildren = (node) => node.children && node.children.length;
157

16-
const inlineCodeAttribute = () => (tree) => {
17-
visit(tree, 'inlineCode', (node) => {
18-
node.type = 'mdxSpanElement';
19-
node.name = 'InlineCode';
20-
node.children = [u('text', node.value)];
21-
});
22-
};
23-
24-
const attributeProcessor = unified()
25-
.use(stringify, {
26-
bullet: '*',
27-
fences: true,
28-
listItemIndent: '1',
29-
})
30-
.use(remarkMdx)
31-
.use(remarkMdxjs)
32-
.use(inlineCodeAttribute);
8+
const deserializeJSValue = (value) => JSON.parse(Buffer.from(value, 'base64'));
339

34-
const deserializeAttributeValue = (h, node) => {
10+
const deserializeAttributeValue = (state, node, processor) => {
3511
if (node.type === 'text') {
3612
return node.value;
3713
}
3814

3915
if (node.type === 'element') {
40-
const tree = deserializeComponent(h, node, { type: 'mdxJsxTextElement' });
41-
const transformedTree = attributeProcessor.runSync(tree);
16+
const tree = deserializeComponent(state, node);
17+
const transformedTree = processor.runSync(tree);
4218

43-
return mdxValueExpression(attributeProcessor.stringify(transformedTree));
19+
return mdxJsxAttributeValueExpression(processor.stringify(transformedTree));
4420
}
4521

4622
throw new Error('Unable to deserialize attribute');
@@ -49,7 +25,8 @@ const deserializeAttributeValue = (h, node) => {
4925
const deserializeComponent = (
5026
state,
5127
node,
52-
{ type, hasChildrenProp = true } = {}
28+
{ type, hasChildrenProp = true } = {},
29+
attributeProcessor
5330
) => {
5431
const { dataComponent, dataProps } = node.properties;
5532
const name = dataComponent || node.tagName;
@@ -75,14 +52,18 @@ const deserializeComponent = (
7552

7653
const attributes = textProps.reduce((attributes, node) => {
7754
const { dataProp: name } = node.properties;
78-
const value = deserializeAttributeValue(state, node.children[0]);
55+
const value = deserializeAttributeValue(
56+
state,
57+
node.children[0],
58+
attributeProcessor
59+
);
7960
const idx = attributes.findIndex((attr) => attr.name === name);
8061

8162
return idx === -1
82-
? [...attributes, mdxAttribute(name, value)]
63+
? [...attributes, mdxJsxAttribute(name, value)]
8364
: [
8465
...attributes.slice(0, idx),
85-
mdxAttribute(name, value),
66+
mdxJsxAttribute(name, value),
8667
...attributes.slice(idx + 1),
8768
];
8869
}, props);

0 commit comments

Comments
 (0)