safe-mdx 1.3.1 → 1.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -14
- package/dist/assets/HtmlToJsxConverter-Ds0bTjpw.js +24 -0
- package/dist/assets/_commonjsHelpers-CqkleIqs.js +1 -0
- package/dist/assets/index-B5fPOjPt.css +1 -0
- package/dist/assets/index-B7ATSoRE.js +9 -0
- package/dist/assets/index-BwZ2FTRd.js +146 -0
- package/dist/assets/index-R1UqLMGJ.js +1 -0
- package/dist/assets/index-c0qeY2gs.js +9 -0
- package/dist/assets/jsx-runtime-BhZZLbvw.js +9 -0
- package/dist/assets/jsx-runtime-NArryeSM.js +1 -0
- package/dist/assets/react-Ca6JzGpx.js +1 -0
- package/dist/assets/react-dom-BYRHYqYl.js +1 -0
- package/dist/dynamic-esm-component.d.ts.map +1 -1
- package/dist/dynamic-esm-component.js +16 -1
- package/dist/dynamic-esm-component.js.map +1 -1
- package/dist/html/attributes.d.ts +19 -0
- package/dist/html/attributes.d.ts.map +1 -0
- package/dist/html/attributes.js +289 -0
- package/dist/html/attributes.js.map +1 -0
- package/dist/html/convert-attributes.d.ts +6 -0
- package/dist/html/convert-attributes.d.ts.map +1 -0
- package/dist/html/convert-attributes.js +43 -0
- package/dist/html/convert-attributes.js.map +1 -0
- package/dist/html/domparser-browser.d.ts +4 -0
- package/dist/html/domparser-browser.d.ts.map +1 -0
- package/dist/html/domparser-browser.js +7 -0
- package/dist/html/domparser-browser.js.map +1 -0
- package/dist/html/domparser.d.ts +2 -0
- package/dist/html/domparser.d.ts.map +1 -0
- package/dist/html/domparser.js +5 -0
- package/dist/html/domparser.js.map +1 -0
- package/dist/html/html-to-mdx-ast.d.ts +23 -0
- package/dist/html/html-to-mdx-ast.d.ts.map +1 -0
- package/dist/html/html-to-mdx-ast.js +227 -0
- package/dist/html/html-to-mdx-ast.js.map +1 -0
- package/dist/html/html-to-mdx-ast.test.d.ts +2 -0
- package/dist/html/html-to-mdx-ast.test.d.ts.map +1 -0
- package/dist/html/html-to-mdx-ast.test.js +324 -0
- package/dist/html/html-to-mdx-ast.test.js.map +1 -0
- package/dist/html/remark-mdx-jsx-normalize.d.ts +10 -0
- package/dist/html/remark-mdx-jsx-normalize.d.ts.map +1 -0
- package/dist/html/remark-mdx-jsx-normalize.js +117 -0
- package/dist/html/remark-mdx-jsx-normalize.js.map +1 -0
- package/dist/html/valid-html-elements.d.ts +10 -0
- package/dist/html/valid-html-elements.d.ts.map +1 -0
- package/dist/html/valid-html-elements.js +50 -0
- package/dist/html/valid-html-elements.js.map +1 -0
- package/dist/index.html +19 -0
- package/dist/parse.d.ts +2 -0
- package/dist/parse.d.ts.map +1 -1
- package/dist/parse.js +2 -0
- package/dist/parse.js.map +1 -1
- package/dist/safe-mdx.d.ts +2 -2
- package/dist/safe-mdx.d.ts.map +1 -1
- package/dist/safe-mdx.js +39 -77
- package/dist/safe-mdx.js.map +1 -1
- package/dist/safe-mdx.test.js +161 -8
- package/dist/safe-mdx.test.js.map +1 -1
- package/package.json +27 -6
- package/src/dynamic-esm-component.tsx +40 -10
- package/src/html/README +17 -0
- package/src/html/attributes.ts +297 -0
- package/src/html/convert-attributes.ts +59 -0
- package/src/html/domparser-browser.ts +6 -0
- package/src/html/domparser.ts +5 -0
- package/src/html/html-to-mdx-ast.test.ts +365 -0
- package/src/html/html-to-mdx-ast.ts +304 -0
- package/src/html/remark-mdx-jsx-normalize.ts +128 -0
- package/src/html/valid-html-elements.ts +65 -0
- package/src/parse.ts +3 -0
- package/src/safe-mdx.test.tsx +178 -12
- package/src/safe-mdx.tsx +61 -93
- package/dist/HtmlToJsxConverter.d.ts +0 -10
- package/dist/HtmlToJsxConverter.d.ts.map +0 -1
- package/dist/HtmlToJsxConverter.js +0 -22
- package/dist/HtmlToJsxConverter.js.map +0 -1
- package/dist/plugins.d.ts +0 -12
- package/dist/plugins.d.ts.map +0 -1
- package/dist/plugins.js +0 -68
- package/dist/plugins.js.map +0 -1
- package/src/HtmlToJsxConverter.tsx +0 -37
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
// The following element listings are taken from the facebook/react repository.
|
|
2
|
+
// https://github.com/facebook/react/blob/main/packages/react-dom/src/shared/DOMProperty.js
|
|
3
|
+
|
|
4
|
+
// A few React string attributes have a different name.
|
|
5
|
+
// This is a mapping from React prop names to the attribute names.
|
|
6
|
+
export const renamedAttributes = new Map([
|
|
7
|
+
["accept-charset", "acceptCharset"],
|
|
8
|
+
["class", "className"],
|
|
9
|
+
["for", "htmlFor"],
|
|
10
|
+
["http-equiv", "httpEquiv"],
|
|
11
|
+
]);
|
|
12
|
+
|
|
13
|
+
// These are "enumerated" HTML attributes that accept "true" and "false".
|
|
14
|
+
// In React, we let users pass `true` and `false` even though technically
|
|
15
|
+
// these aren't boolean attributes (they are coerced to strings).
|
|
16
|
+
export const coerceToBooleanAttributes = [
|
|
17
|
+
"allowFullScreen",
|
|
18
|
+
"async",
|
|
19
|
+
"autoFocus",
|
|
20
|
+
"autoPlay",
|
|
21
|
+
"checked",
|
|
22
|
+
"contentEditable",
|
|
23
|
+
"controls",
|
|
24
|
+
"default",
|
|
25
|
+
"defer",
|
|
26
|
+
"disabled",
|
|
27
|
+
"disablePictureInPicture",
|
|
28
|
+
"disableRemotePlayback",
|
|
29
|
+
"draggable",
|
|
30
|
+
"formNoValidate",
|
|
31
|
+
"hidden",
|
|
32
|
+
"itemScope",
|
|
33
|
+
"loop",
|
|
34
|
+
"multiple",
|
|
35
|
+
"muted",
|
|
36
|
+
"noModule",
|
|
37
|
+
"noValidate",
|
|
38
|
+
"open",
|
|
39
|
+
"playsInline",
|
|
40
|
+
"readOnly",
|
|
41
|
+
"required",
|
|
42
|
+
"reversed",
|
|
43
|
+
"scoped",
|
|
44
|
+
"seamless",
|
|
45
|
+
"selected",
|
|
46
|
+
"spellCheck",
|
|
47
|
+
"value",
|
|
48
|
+
|
|
49
|
+
// These accept other values than true and false which are just left as is.
|
|
50
|
+
// true and false will get converted to booleans.
|
|
51
|
+
"capture",
|
|
52
|
+
"download",
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
// These are "enumerated" SVG attributes that accept "true" and "false".
|
|
56
|
+
// In React, we let users pass `true` and `false` even though technically
|
|
57
|
+
// these aren't boolean attributes (they are coerced to strings).
|
|
58
|
+
// Since these are SVG attributes, their attribute names are case-sensitive.
|
|
59
|
+
export const svgCoerceToBooleanAttributes = [
|
|
60
|
+
"autoReverse",
|
|
61
|
+
"externalResourcesRequired",
|
|
62
|
+
"focusable",
|
|
63
|
+
"preserveAlpha",
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
// These are HTML attributes that must be positive numbers.
|
|
67
|
+
export const numberAttributes = [
|
|
68
|
+
"border",
|
|
69
|
+
"cellPadding",
|
|
70
|
+
"cellSpacing",
|
|
71
|
+
"cols",
|
|
72
|
+
"marginHeight",
|
|
73
|
+
"marginWidth",
|
|
74
|
+
"maxLength",
|
|
75
|
+
"minLength",
|
|
76
|
+
"rows",
|
|
77
|
+
"rowSpan",
|
|
78
|
+
"size",
|
|
79
|
+
"span",
|
|
80
|
+
"start",
|
|
81
|
+
"tabIndex",
|
|
82
|
+
];
|
|
83
|
+
|
|
84
|
+
// These properties are SVG and have to be camelized.
|
|
85
|
+
// The second value in the array determines should be converted to a number if
|
|
86
|
+
// possible.
|
|
87
|
+
export const svgCamelizedAttributes = [
|
|
88
|
+
["accent-height", false],
|
|
89
|
+
["alignment-baseline", false],
|
|
90
|
+
["arabic-form", false],
|
|
91
|
+
["baseline-shift", false],
|
|
92
|
+
["cap-height", true],
|
|
93
|
+
["clip-path", false],
|
|
94
|
+
["clip-rule", false],
|
|
95
|
+
["color-interpolation-filters", false],
|
|
96
|
+
["color-interpolation", false],
|
|
97
|
+
["color-profile", false],
|
|
98
|
+
["color-rendering", false],
|
|
99
|
+
["dominant-baseline", false],
|
|
100
|
+
["enable-background", false],
|
|
101
|
+
["fill-opacity", false],
|
|
102
|
+
["fill-rule", false],
|
|
103
|
+
["flood-color", false],
|
|
104
|
+
["flood-opacity", false],
|
|
105
|
+
["font-family", false],
|
|
106
|
+
["font-size-adjust", true],
|
|
107
|
+
["font-size", true],
|
|
108
|
+
["font-stretch", false],
|
|
109
|
+
["font-style", false],
|
|
110
|
+
["font-variant", false],
|
|
111
|
+
["font-weight", true],
|
|
112
|
+
["glyph-name", false],
|
|
113
|
+
["glyph-orientation-horizontal", false],
|
|
114
|
+
["glyph-orientation-vertical", false],
|
|
115
|
+
["horiz-adv-x", true],
|
|
116
|
+
["horiz-origin-x", true],
|
|
117
|
+
["image-rendering", false],
|
|
118
|
+
["letter-spacing", true],
|
|
119
|
+
["lighting-color", false],
|
|
120
|
+
["marker-end", false],
|
|
121
|
+
["marker-mid", false],
|
|
122
|
+
["marker-start", false],
|
|
123
|
+
["overline-position", true],
|
|
124
|
+
["overline-thickness", true],
|
|
125
|
+
["paint-order", false],
|
|
126
|
+
["panose-1", false],
|
|
127
|
+
["pointer-events", false],
|
|
128
|
+
["rendering-intent", false],
|
|
129
|
+
["shape-rendering", false],
|
|
130
|
+
["stop-color", false],
|
|
131
|
+
["stop-opacity", false],
|
|
132
|
+
["strikethrough-position", true],
|
|
133
|
+
["strikethrough-thickness", true],
|
|
134
|
+
["stroke-dasharray", false],
|
|
135
|
+
["stroke-dashoffset", true],
|
|
136
|
+
["stroke-linecap", false],
|
|
137
|
+
["stroke-linejoin", false],
|
|
138
|
+
["stroke-miterlimit", true],
|
|
139
|
+
["stroke-opacity", false],
|
|
140
|
+
["stroke-width", true],
|
|
141
|
+
["text-anchor", false],
|
|
142
|
+
["text-decoration", false],
|
|
143
|
+
["text-rendering", false],
|
|
144
|
+
["underline-position", true],
|
|
145
|
+
["underline-thickness", true],
|
|
146
|
+
["unicode-bidi", false],
|
|
147
|
+
["unicode-range", false],
|
|
148
|
+
["units-per-em", true],
|
|
149
|
+
["v-alphabetic", true],
|
|
150
|
+
["v-hanging", true],
|
|
151
|
+
["v-ideographic", true],
|
|
152
|
+
["v-mathematical", true],
|
|
153
|
+
["vector-effect", false],
|
|
154
|
+
["vert-adv-y", true],
|
|
155
|
+
["vert-origin-x", true],
|
|
156
|
+
["vert-origin-y", true],
|
|
157
|
+
["word-spacing", true],
|
|
158
|
+
["writing-mode", false],
|
|
159
|
+
["x-height", true],
|
|
160
|
+
["xmlns:xlink", false],
|
|
161
|
+
];
|
|
162
|
+
|
|
163
|
+
// Supported event attributes in React, taken from
|
|
164
|
+
// https://reactjs.org/docs/events.html
|
|
165
|
+
export const eventHandlerAttributes = [
|
|
166
|
+
"onAbort",
|
|
167
|
+
"onAnimationEnd",
|
|
168
|
+
"onAnimationIteration",
|
|
169
|
+
"onAnimationStart",
|
|
170
|
+
"onBlur",
|
|
171
|
+
"onCanPlay",
|
|
172
|
+
"onCanPlayThrough",
|
|
173
|
+
"onChange",
|
|
174
|
+
"onClick",
|
|
175
|
+
"onCompositionEnd",
|
|
176
|
+
"onCompositionStart",
|
|
177
|
+
"onCompositionUpdate",
|
|
178
|
+
"onContextMenu",
|
|
179
|
+
"onCopy",
|
|
180
|
+
"onCut",
|
|
181
|
+
"onDoubleClick",
|
|
182
|
+
"onDrag",
|
|
183
|
+
"onDragEnd",
|
|
184
|
+
"onDragEnter",
|
|
185
|
+
"onDragExit",
|
|
186
|
+
"onDragLeave",
|
|
187
|
+
"onDragOver",
|
|
188
|
+
"onDragStart",
|
|
189
|
+
"onDrop",
|
|
190
|
+
"onDurationChange",
|
|
191
|
+
"onEmptied",
|
|
192
|
+
"onEncrypted",
|
|
193
|
+
"onEnded",
|
|
194
|
+
"onError",
|
|
195
|
+
"onError",
|
|
196
|
+
"onFocus",
|
|
197
|
+
"onGotPointerCapture",
|
|
198
|
+
"onInput",
|
|
199
|
+
"onInvalid",
|
|
200
|
+
"onKeyDown",
|
|
201
|
+
"onKeyPress",
|
|
202
|
+
"onKeyUp",
|
|
203
|
+
"onLoad",
|
|
204
|
+
"onLoadedData",
|
|
205
|
+
"onLoadedMetadata",
|
|
206
|
+
"onLoadStart",
|
|
207
|
+
"onLostPointerCapture",
|
|
208
|
+
"onMouseDown",
|
|
209
|
+
"onMouseEnter",
|
|
210
|
+
"onMouseLeave",
|
|
211
|
+
"onMouseMove",
|
|
212
|
+
"onMouseOut",
|
|
213
|
+
"onMouseOver",
|
|
214
|
+
"onMouseUp",
|
|
215
|
+
"onPaste",
|
|
216
|
+
"onPause",
|
|
217
|
+
"onPlay",
|
|
218
|
+
"onPlaying",
|
|
219
|
+
"onPointerCancel",
|
|
220
|
+
"onPointerDown",
|
|
221
|
+
"onPointerEnter",
|
|
222
|
+
"onPointerLeave",
|
|
223
|
+
"onPointerMove",
|
|
224
|
+
"onPointerOut",
|
|
225
|
+
"onPointerOver",
|
|
226
|
+
"onPointerUp",
|
|
227
|
+
"onProgress",
|
|
228
|
+
"onRateChange",
|
|
229
|
+
"onReset",
|
|
230
|
+
"onScroll",
|
|
231
|
+
"onSeeked",
|
|
232
|
+
"onSeeking",
|
|
233
|
+
"onSelect",
|
|
234
|
+
"onStalled",
|
|
235
|
+
"onSubmit",
|
|
236
|
+
"onSuspend",
|
|
237
|
+
"onTimeUpdate",
|
|
238
|
+
"onToggle",
|
|
239
|
+
"onTouchCancel",
|
|
240
|
+
"onTouchEnd",
|
|
241
|
+
"onTouchMove",
|
|
242
|
+
"onTouchStart",
|
|
243
|
+
"onTransitionEnd",
|
|
244
|
+
"onVolumeChange",
|
|
245
|
+
"onWaiting",
|
|
246
|
+
"onWheel",
|
|
247
|
+
];
|
|
248
|
+
|
|
249
|
+
// List of attributes that are lower-cased in HTML but have to be camel-cased in
|
|
250
|
+
// JSX code. Taken from https://reactjs.org/docs/dom-elements.html
|
|
251
|
+
export const lowercasedAttributes = [
|
|
252
|
+
"accessKey",
|
|
253
|
+
"autoComplete",
|
|
254
|
+
"charSet",
|
|
255
|
+
"classID",
|
|
256
|
+
"colSpan",
|
|
257
|
+
"cellSpacing",
|
|
258
|
+
"cellMargin",
|
|
259
|
+
"contextMenu",
|
|
260
|
+
"controlsList",
|
|
261
|
+
"crossOrigin",
|
|
262
|
+
"dateTime",
|
|
263
|
+
"encType",
|
|
264
|
+
"formAction",
|
|
265
|
+
"formEncType",
|
|
266
|
+
"formMethod",
|
|
267
|
+
"formTarget",
|
|
268
|
+
"frameBorder",
|
|
269
|
+
"hrefLang",
|
|
270
|
+
"inputMode",
|
|
271
|
+
"keyParams",
|
|
272
|
+
"keyType",
|
|
273
|
+
"mediaGroup",
|
|
274
|
+
"radioGroup",
|
|
275
|
+
"srcDoc",
|
|
276
|
+
"srcLang",
|
|
277
|
+
"srcSet",
|
|
278
|
+
"useMap",
|
|
279
|
+
];
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Don't strip the px suffix from these style attributes
|
|
283
|
+
* because they can contain both length (e.g. `13px`) and
|
|
284
|
+
* unitless values (e.g. `3`), which have different
|
|
285
|
+
* meanings.
|
|
286
|
+
*
|
|
287
|
+
* (Background: React automatically adds a `px` to unitless
|
|
288
|
+
* numbers specified in style attributes, so these attributes
|
|
289
|
+
* should not be included in `px` stripping).
|
|
290
|
+
*/
|
|
291
|
+
export const styleDontStripPx = [
|
|
292
|
+
"line-height",
|
|
293
|
+
"flex",
|
|
294
|
+
"mask-border-outset",
|
|
295
|
+
"mask-box-outset",
|
|
296
|
+
"mask-border-width",
|
|
297
|
+
];
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
|
|
2
|
+
import {
|
|
3
|
+
coerceToBooleanAttributes,
|
|
4
|
+
eventHandlerAttributes,
|
|
5
|
+
lowercasedAttributes,
|
|
6
|
+
numberAttributes,
|
|
7
|
+
renamedAttributes,
|
|
8
|
+
styleDontStripPx,
|
|
9
|
+
svgCamelizedAttributes,
|
|
10
|
+
svgCoerceToBooleanAttributes,
|
|
11
|
+
} from "./attributes.js";
|
|
12
|
+
|
|
13
|
+
// Export function to convert HTML attribute name to JSX attribute name
|
|
14
|
+
export function convertAttributeNameToJSX(htmlName: string): string {
|
|
15
|
+
// Check renamed attributes
|
|
16
|
+
for (const [html, jsx] of renamedAttributes) {
|
|
17
|
+
if (html === htmlName) {
|
|
18
|
+
return jsx;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Check event handler attributes
|
|
23
|
+
for (const jsxAttribute of eventHandlerAttributes) {
|
|
24
|
+
if (htmlName === jsxAttribute.toLowerCase()) {
|
|
25
|
+
return jsxAttribute;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Check lowercased attributes
|
|
30
|
+
for (const jsxAttribute of lowercasedAttributes) {
|
|
31
|
+
if (htmlName === jsxAttribute.toLowerCase()) {
|
|
32
|
+
return jsxAttribute;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Check SVG camelized attributes
|
|
37
|
+
for (const [jsxAttribute] of svgCamelizedAttributes) {
|
|
38
|
+
if (htmlName === jsxAttribute) {
|
|
39
|
+
return camelize(htmlName);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return htmlName;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const CAMELIZE = /[\-\:]([a-z])/g;
|
|
47
|
+
const capitalize = (token: string) => token[1]!.toUpperCase();
|
|
48
|
+
|
|
49
|
+
const IS_CSS_VARIBLE = /^--\w+/;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Converts kebab-case or colon:case to camelCase
|
|
53
|
+
*/
|
|
54
|
+
export function camelize(string: string) {
|
|
55
|
+
// Skip the attribute if it is a css variable.
|
|
56
|
+
// It looks something like this: style="--bgColor: red"
|
|
57
|
+
if (IS_CSS_VARIBLE.test(string)) return `"${string}"`;
|
|
58
|
+
return string.replace(CAMELIZE, capitalize);
|
|
59
|
+
}
|