safe-mdx 0.0.1 → 0.0.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/dist/index.js +1 -17
- package/dist/index.js.map +1 -1
- package/dist/safe-mdx.d.ts +3 -1
- package/dist/safe-mdx.d.ts.map +1 -1
- package/dist/safe-mdx.js +106 -124
- package/dist/safe-mdx.js.map +1 -1
- package/dist/safe-mdx.test.js +305 -211
- package/dist/safe-mdx.test.js.map +1 -1
- package/package.json +11 -3
- package/src/safe-mdx.test.tsx +287 -184
- package/src/safe-mdx.tsx +83 -64
package/src/safe-mdx.tsx
CHANGED
|
@@ -151,7 +151,9 @@ export class MdastToJsx {
|
|
|
151
151
|
return null
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
-
let attrsList =
|
|
154
|
+
let attrsList = getJsxAttrs(node, (err) => {
|
|
155
|
+
this.errors.push(err)
|
|
156
|
+
})
|
|
155
157
|
|
|
156
158
|
let attrs = Object.fromEntries(attrsList)
|
|
157
159
|
return (
|
|
@@ -246,9 +248,7 @@ export class MdastToJsx {
|
|
|
246
248
|
const code = node.value
|
|
247
249
|
return (
|
|
248
250
|
<this.c.pre>
|
|
249
|
-
<this.c.code
|
|
250
|
-
{code}
|
|
251
|
-
</this.c.code>
|
|
251
|
+
<this.c.code>{code}</this.c.code>
|
|
252
252
|
</this.c.pre>
|
|
253
253
|
)
|
|
254
254
|
}
|
|
@@ -319,9 +319,14 @@ export class MdastToJsx {
|
|
|
319
319
|
return <Fragment>{this.mapMdastChildren(node)}</Fragment>
|
|
320
320
|
}
|
|
321
321
|
case 'table': {
|
|
322
|
-
const
|
|
322
|
+
const [head, ...body] = React.Children.toArray(
|
|
323
|
+
this.mapMdastChildren(node),
|
|
324
|
+
)
|
|
323
325
|
return (
|
|
324
|
-
<this.c.table>
|
|
326
|
+
<this.c.table>
|
|
327
|
+
{head && <this.c.thead>{head}</this.c.thead>}
|
|
328
|
+
{!!body?.length && <this.c.tbody>{body}</this.c.tbody>}
|
|
329
|
+
</this.c.table>
|
|
325
330
|
)
|
|
326
331
|
}
|
|
327
332
|
case 'tableRow': {
|
|
@@ -403,72 +408,78 @@ export class MdastToJsx {
|
|
|
403
408
|
}
|
|
404
409
|
}
|
|
405
410
|
}
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
export function getJsxAttrs(
|
|
414
|
+
node: MdxJsxFlowElement | MdxJsxTextElement,
|
|
415
|
+
onError: (err: { message: string }) => void = console.error,
|
|
416
|
+
) {
|
|
417
|
+
let attrsList = node.attributes
|
|
418
|
+
.map((attr) => {
|
|
419
|
+
if (attr.type === 'mdxJsxExpressionAttribute') {
|
|
420
|
+
onError({
|
|
421
|
+
message: `Expressions in jsx props are not supported (${attr.value.replace(
|
|
422
|
+
/\n+/g,
|
|
423
|
+
' ',
|
|
424
|
+
)})`,
|
|
425
|
+
})
|
|
426
|
+
return
|
|
427
|
+
}
|
|
428
|
+
if (attr.type !== 'mdxJsxAttribute') {
|
|
429
|
+
throw new Error(`non mdxJsxAttribute is not supported: ${attr}`)
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
const v = attr.value
|
|
433
|
+
if (typeof v === 'string' || typeof v === 'number') {
|
|
434
|
+
return [attr.name, v]
|
|
435
|
+
}
|
|
436
|
+
if (v === null) {
|
|
437
|
+
return [attr.name, true]
|
|
438
|
+
}
|
|
439
|
+
if (v?.type === 'mdxJsxAttributeValueExpression') {
|
|
440
|
+
if (v.value === 'true') {
|
|
441
|
+
return [attr.name, true]
|
|
417
442
|
}
|
|
418
|
-
if (
|
|
419
|
-
|
|
420
|
-
`non mdxJsxAttribute is not supported: ${attr}`,
|
|
421
|
-
)
|
|
443
|
+
if (v.value === 'false') {
|
|
444
|
+
return [attr.name, false]
|
|
422
445
|
}
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
if (typeof v === 'string' || typeof v === 'number') {
|
|
426
|
-
return [attr.name, v]
|
|
446
|
+
if (v.value === 'null') {
|
|
447
|
+
return [attr.name, null]
|
|
427
448
|
}
|
|
428
|
-
if (v ===
|
|
429
|
-
return [attr.name,
|
|
449
|
+
if (v.value === 'undefined') {
|
|
450
|
+
return [attr.name, undefined]
|
|
430
451
|
}
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
if (v.value === 'null') {
|
|
439
|
-
return [attr.name, null]
|
|
440
|
-
}
|
|
441
|
-
if (v.value === 'undefined') {
|
|
442
|
-
return [attr.name, undefined]
|
|
443
|
-
}
|
|
444
|
-
let quote = ['"', "'", '`'].find(
|
|
445
|
-
(q) => v.value.startsWith(q) && v.value.endsWith(q),
|
|
446
|
-
)
|
|
447
|
-
if (quote) {
|
|
448
|
-
let value = v.value
|
|
449
|
-
if (quote !== '"') {
|
|
450
|
-
value = v.value.replace(new RegExp(quote, 'g'), '"')
|
|
451
|
-
}
|
|
452
|
-
return [attr.name, JSON.parse(value)]
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
const number = Number(v.value)
|
|
456
|
-
if (!isNaN(number)) {
|
|
457
|
-
return [attr.name, number]
|
|
452
|
+
let quote = ['"', "'", '`'].find(
|
|
453
|
+
(q) => v.value.startsWith(q) && v.value.endsWith(q),
|
|
454
|
+
)
|
|
455
|
+
if (quote) {
|
|
456
|
+
let value = v.value
|
|
457
|
+
if (quote !== '"') {
|
|
458
|
+
value = v.value.replace(new RegExp(quote, 'g'), '"')
|
|
458
459
|
}
|
|
460
|
+
return [attr.name, JSON.parse(value)]
|
|
461
|
+
}
|
|
459
462
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
}
|
|
464
|
-
|
|
463
|
+
const number = Number(v.value)
|
|
464
|
+
if (!isNaN(number)) {
|
|
465
|
+
return [attr.name, number]
|
|
466
|
+
}
|
|
467
|
+
const parsedJson = safeJsonParse(v.value)
|
|
468
|
+
if (parsedJson) {
|
|
469
|
+
return [attr.name, parsedJson]
|
|
465
470
|
}
|
|
466
471
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
+
onError({
|
|
473
|
+
message: `Expressions in jsx props are not supported (${attr.name}={${v.value}})`,
|
|
474
|
+
})
|
|
475
|
+
} else {
|
|
476
|
+
console.log('unhandled attr', { attr }, attr.type)
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
return
|
|
480
|
+
})
|
|
481
|
+
.filter(isTruthy) as [string, any][]
|
|
482
|
+
return attrsList
|
|
472
483
|
}
|
|
473
484
|
|
|
474
485
|
function isTruthy<T>(val: T | undefined | null | false): val is T {
|
|
@@ -503,3 +514,11 @@ export function mdastBfs(
|
|
|
503
514
|
}
|
|
504
515
|
return result
|
|
505
516
|
}
|
|
517
|
+
|
|
518
|
+
function safeJsonParse(str: string) {
|
|
519
|
+
try {
|
|
520
|
+
return JSON.parse(str)
|
|
521
|
+
} catch (err) {
|
|
522
|
+
return null
|
|
523
|
+
}
|
|
524
|
+
}
|