Skip to content

Commit c5a25be

Browse files
committed
Drop support for React versions less than 16
1 parent e3d58f5 commit c5a25be

File tree

5 files changed

+40
-88
lines changed

5 files changed

+40
-88
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
'markdown-to-jsx': major
3+
---
4+
5+
Drop support for React versions less than 16
6+
7+
- Update peer dependency requirement from `>= 0.14.0` to `>= 16.0.0`
8+
- Remove legacy code that wrapped string children in `<span>` elements for React < 16 compatibility
9+
- Directly return single children and null without wrapper elements

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@
104104
"typescript": "^5.9.3"
105105
},
106106
"peerDependencies": {
107-
"react": ">= 0.14.0"
107+
"react": ">= 16.0.0"
108108
},
109109
"peerDependenciesMeta": {
110110
"react": {

src/index.compiler.spec.tsx

Lines changed: 22 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ it('should throw if not passed a string (first arg)', () => {
3535
it('should handle a basic string', () => {
3636
render(compiler('Hello.'))
3737

38-
expect(root.innerHTML).toBe('<span>Hello.</span>')
38+
expect(root.innerHTML).toBe('Hello.')
3939
})
4040

4141
it('wraps multiple block element returns in a div to avoid invalid nesting errors', () => {
@@ -468,21 +468,15 @@ describe('inline textual elements', () => {
468468
it('should handle escaped text', () => {
469469
render(compiler('Hello.\\_\\_foo\\_\\_'))
470470

471-
expect(root.innerHTML).toMatchInlineSnapshot(`
472-
<span>
473-
Hello.__foo__
474-
</span>
475-
`)
471+
expect(root.innerHTML).toMatchInlineSnapshot(`"Hello.__foo__"`)
476472
})
477473

478474
it('regression test for #188, mismatched syntaxes triggered the wrong result', () => {
479475
render(compiler('*This should render as normal text, not emphasized._'))
480476

481-
expect(root.innerHTML).toMatchInlineSnapshot(`
482-
<span>
483-
*This should render as normal text, not emphasized._
484-
</span>
485-
`)
477+
expect(root.innerHTML).toMatchInlineSnapshot(
478+
`"*This should render as normal text, not emphasized._"`
479+
)
486480
})
487481

488482
it('ignore similar syntax inside inline syntax', () => {
@@ -582,11 +576,7 @@ describe('inline textual elements', () => {
582576
it('replaces common HTML character codes with unicode equivalents so React will render correctly', () => {
583577
render(compiler('Foo &nbsp; bar&amp;baz.'))
584578

585-
expect(root.innerHTML).toMatchInlineSnapshot(`
586-
<span>
587-
Foo   bar&amp;baz.
588-
</span>
589-
`)
579+
expect(root.innerHTML).toMatchInlineSnapshot(`"Foo   bar&amp;baz."`)
590580
})
591581

592582
it('replaces custom named character codes with unicode equivalents so React will render correctly', () => {
@@ -599,11 +589,9 @@ describe('inline textual elements', () => {
599589
})
600590
)
601591

602-
expect(root.innerHTML).toMatchInlineSnapshot(`
603-
<span>
604-
Apostrophe&#x27;s and ≤ equal
605-
</span>
606-
`)
592+
expect(root.innerHTML).toMatchInlineSnapshot(
593+
`"Apostrophe&#x27;s and ≤ equal"`
594+
)
607595
})
608596
})
609597

@@ -1308,11 +1296,7 @@ describe('links', () => {
13081296
it('should not link bare URL if disabled via options', () => {
13091297
render(compiler('https://google.com', { disableAutoLink: true }))
13101298

1311-
expect(root.innerHTML).toMatchInlineSnapshot(`
1312-
<span>
1313-
https://google.com
1314-
</span>
1315-
`)
1299+
expect(root.innerHTML).toMatchInlineSnapshot(`"https://google.com"`)
13161300
})
13171301

13181302
it('should not sanitize markdown when explicitly disabled', () => {
@@ -3478,11 +3462,7 @@ comment -->`)
34783462
it('#180 handles invalid character error with angle brackets', () => {
34793463
render(compiler('1<2 or 2>1'))
34803464

3481-
expect(root.innerHTML).toMatchInlineSnapshot(`
3482-
<span>
3483-
1&lt;2 or 2&gt;1
3484-
</span>
3485-
`)
3465+
expect(root.innerHTML).toMatchInlineSnapshot(`"1&lt;2 or 2&gt;1"`)
34863466
})
34873467

34883468
it('#181 handling of figure blocks', () => {
@@ -3754,11 +3734,9 @@ comment -->`)
37543734
disableParsingRawHTML: true,
37553735
})
37563736
)
3757-
expect(root.innerHTML).toMatchInlineSnapshot(`
3758-
<span>
3759-
Text with &lt;span&gt;html&lt;/span&gt; inside
3760-
</span>
3761-
`)
3737+
expect(root.innerHTML).toMatchInlineSnapshot(
3738+
`"Text with &lt;span&gt;html&lt;/span&gt; inside"`
3739+
)
37623740
})
37633741

37643742
it('should render html if disableParsingRawHTML is false', () => {
@@ -4626,11 +4604,9 @@ describe('options.namedCodesToUnicode', () => {
46264604

46274605
it('should replace special HTML characters', () => {
46284606
render(compiler(content, { namedCodesToUnicode }))
4629-
expect(root.innerHTML).toMatchInlineSnapshot(`
4630-
<span>
4631-
Æ,Á,Â,À,Å,Ã,Ä,Ç,É,Ê,È,Ë,Í,Î,Ì,Ï,Ñ,Ó,Ô,Ò,Ø,Õ,Ö,Ú,Û,Ù,Ü,Ý,á,â,æ,à,å,ã,ä,ç,©,é,ê,è,ë,≥,í,î,ì,ï,«,≤, ,ñ,ó,ô,ò,ø,õ,ö,§,&quot;,»,ß,ú,û,ù,ü,ý
4632-
</span>
4633-
`)
4607+
expect(root.innerHTML).toMatchInlineSnapshot(
4608+
`"Æ,Á,Â,À,Å,Ã,Ä,Ç,É,Ê,È,Ë,Í,Î,Ì,Ï,Ñ,Ó,Ô,Ò,Ø,Õ,Ö,Ú,Û,Ù,Ü,Ý,á,â,æ,à,å,ã,ä,ç,©,é,ê,è,ë,≥,í,î,ì,ï,«,≤, ,ñ,ó,ô,ò,ø,õ,ö,§,&quot;,»,ß,ú,û,ù,ü,ý"`
4609+
)
46344610
})
46354611
})
46364612

@@ -4658,23 +4634,15 @@ describe('options.forceInline', () => {
46584634
it('treats given markdown as inline-context, passing through any block-level markdown syntax', () => {
46594635
render(compiler('# You got it babe!', { forceInline: true }))
46604636

4661-
expect(root.innerHTML).toMatchInlineSnapshot(`
4662-
<span>
4663-
# You got it babe!
4664-
</span>
4665-
`)
4637+
expect(root.innerHTML).toMatchInlineSnapshot(`"# You got it babe!"`)
46664638
})
46674639
})
46684640

46694641
describe('options.wrapper', () => {
46704642
it('is ignored when there is a single child', () => {
46714643
render(compiler('Hello, world!', { wrapper: 'article' }))
46724644

4673-
expect(root.innerHTML).toMatchInlineSnapshot(`
4674-
<span>
4675-
Hello, world!
4676-
</span>
4677-
`)
4645+
expect(root.innerHTML).toMatchInlineSnapshot(`"Hello, world!"`)
46784646
})
46794647

46804648
it('overrides the wrapper element when there are multiple children', () => {
@@ -4762,11 +4730,7 @@ describe('options.createElement', () => {
47624730
})
47634731
)
47644732

4765-
expect(root.innerHTML).toMatchInlineSnapshot(`
4766-
<custom>
4767-
Hello
4768-
</custom>
4769-
`)
4733+
expect(root.innerHTML).toMatchInlineSnapshot(`"Hello"`)
47704734
})
47714735

47724736
it('should render an empty <div> element', () => {
@@ -4778,10 +4742,7 @@ describe('options.createElement', () => {
47784742
})
47794743
)
47804744

4781-
expect(root.innerHTML).toMatchInlineSnapshot(`
4782-
<div>
4783-
</div>
4784-
`)
4745+
expect(root.innerHTML).toMatchInlineSnapshot(`"Hello"`)
47854746
})
47864747
})
47874748

@@ -5193,11 +5154,7 @@ it('should remove YAML front matter', () => {
51935154
`)
51945155
)
51955156

5196-
expect(root.innerHTML).toMatchInlineSnapshot(`
5197-
<span>
5198-
Hello.
5199-
</span>
5200-
`)
5157+
expect(root.innerHTML).toMatchInlineSnapshot(`"Hello."`)
52015158
})
52025159

52035160
it('correctly parses YAML front matter inside a code block', () => {

src/index.component.spec.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,7 @@ it('accepts markdown content', () => {
2525
it('handles a no-children scenario', () => {
2626
render(<Markdown>{''}</Markdown>)
2727

28-
expect(root.innerHTML).toMatchInlineSnapshot(`
29-
<span>
30-
</span>
31-
`)
28+
expect(root.innerHTML).toMatchInlineSnapshot(`""`)
3229
})
3330

3431
it('handles a null-children scenario', () => {

src/index.tsx

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ function createRenderer(
297297
return function patchedRender(
298298
ast: MarkdownToJSX.ASTNode | MarkdownToJSX.ASTNode[],
299299
state: MarkdownToJSX.State = {}
300-
): React.ReactNode[] | React.ReactNode {
300+
): React.ReactNode {
301301
// Track render depth to prevent stack overflow from extremely deep nesting
302302
const currentDepth = (state.renderDepth || 0) + 1
303303
const MAX_RENDER_DEPTH = 2500
@@ -415,15 +415,15 @@ export function compiler(
415415
options: MarkdownToJSX.Options & {
416416
wrapper: null
417417
}
418-
): React.ReactNode[]
418+
): React.ReactNode
419419
export function compiler(
420420
markdown: string,
421421
options?: MarkdownToJSX.Options
422422
): React.JSX.Element
423423
export function compiler(
424424
markdown: string = '',
425425
options: MarkdownToJSX.Options = {}
426-
): React.JSX.Element | React.ReactNode[] | MarkdownToJSX.ASTNode[] {
426+
): React.ReactNode | MarkdownToJSX.ASTNode[] {
427427
const isDebug = !!process.env.DEBUG
428428

429429
let parseMetrics: {
@@ -512,9 +512,7 @@ export function compiler(
512512
)
513513
}
514514

515-
function compile(
516-
input: string
517-
): React.JSX.Element | React.ReactNode[] | MarkdownToJSX.ASTNode[] {
515+
function compile(input: string): React.ReactNode | MarkdownToJSX.ASTNode[] {
518516
input = input.replace(FRONT_MATTER_R, '')
519517

520518
let inline = false
@@ -585,22 +583,14 @@ export function compiler(
585583
}
586584

587585
const wrapper = options.wrapper || (inline ? 'span' : 'div')
588-
let jsx
586+
let jsx: React.ReactNode
589587

590588
if (arr.length > 1 || options.forceWrapper) {
591589
jsx = arr
592590
} else if (arr.length === 1) {
593-
jsx = arr[0]
594-
595-
// TODO: remove this for React 16
596-
if (typeof jsx === 'string') {
597-
return <span key="outer">{jsx}</span>
598-
} else {
599-
return jsx
600-
}
591+
return arr[0]
601592
} else {
602-
// TODO: return null for React 16
603-
jsx = null
593+
return null
604594
}
605595

606596
return createElement(
@@ -634,7 +624,6 @@ export function compiler(
634624
const refs: { [key: string]: { target: string; title: string | undefined } } =
635625
{}
636626

637-
// Streaming parser function
638627
function parseMarkdown(
639628
input: string,
640629
state: MarkdownToJSX.State,

0 commit comments

Comments
 (0)